[FIX] Link jitsi-meet on Share Extension (#1204)

* Link jitsi-meet

* Try fix ci

* Remove realm imports
This commit is contained in:
Djorkaeff Alexandre 2019-09-18 18:44:33 -03:00 committed by Diego Mello
parent 99aea22579
commit b29a2ab216
508 changed files with 21394 additions and 8135 deletions

View File

@ -5,7 +5,7 @@ PODS:
- React
- BugsnagReactNative/Core (2.22.4):
- React
- Crashlytics (3.13.4):
- Crashlytics (3.14.0):
- Fabric (~> 1.10.2)
- DoubleConversion (1.1.6)
- EXAppLoaderProvider (6.0.0)
@ -26,24 +26,32 @@ PODS:
- EXWebBrowser (6.0.0):
- UMCore
- Fabric (1.10.2)
- Firebase/Core (6.5.0):
- Firebase/Core (6.8.1):
- Firebase/CoreOnly
- FirebaseAnalytics (= 6.0.4)
- Firebase/CoreOnly (6.5.0):
- FirebaseCore (= 6.1.0)
- FirebaseAnalytics (6.0.4):
- FirebaseCore (~> 6.1)
- FirebaseAnalytics (= 6.1.1)
- Firebase/CoreOnly (6.8.1):
- FirebaseCore (= 6.2.3)
- FirebaseAnalytics (6.1.1):
- FirebaseCore (~> 6.2)
- FirebaseInstanceID (~> 4.2)
- GoogleAppMeasurement (= 6.0.4)
- GoogleAppMeasurement (= 6.1.1)
- GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- GoogleUtilities/MethodSwizzler (~> 6.0)
- GoogleUtilities/Network (~> 6.0)
- "GoogleUtilities/NSData+zlib (~> 6.0)"
- nanopb (~> 0.3)
- FirebaseCore (6.1.0):
- GoogleUtilities/Environment (~> 6.0)
- GoogleUtilities/Logger (~> 6.0)
- FirebaseInstanceID (4.2.2):
- FirebaseCore (6.2.3):
- FirebaseCoreDiagnostics (~> 1.0)
- FirebaseCoreDiagnosticsInterop (~> 1.0)
- GoogleUtilities/Environment (~> 6.2)
- GoogleUtilities/Logger (~> 6.2)
- FirebaseCoreDiagnostics (1.0.1):
- FirebaseCoreDiagnosticsInterop (~> 1.0)
- GoogleDataTransportCCTSupport (~> 1.0)
- GoogleUtilities/Environment (~> 6.2)
- GoogleUtilities/Logger (~> 6.2)
- FirebaseCoreDiagnosticsInterop (1.0.0)
- FirebaseInstanceID (4.2.5):
- FirebaseCore (~> 6.0)
- GoogleUtilities/Environment (~> 6.0)
- GoogleUtilities/UserDefaults (~> 6.0)
@ -57,54 +65,43 @@ PODS:
- DoubleConversion
- glog
- glog (0.3.5)
- GoogleAppMeasurement (6.0.4):
- GoogleAppMeasurement (6.1.1):
- GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- GoogleUtilities/MethodSwizzler (~> 6.0)
- GoogleUtilities/Network (~> 6.0)
- "GoogleUtilities/NSData+zlib (~> 6.0)"
- nanopb (~> 0.3)
- GoogleUtilities/AppDelegateSwizzler (6.2.3):
- GoogleDataTransport (1.2.0)
- GoogleDataTransportCCTSupport (1.0.4):
- GoogleDataTransport (~> 1.2)
- nanopb
- GoogleUtilities/AppDelegateSwizzler (6.3.0):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Environment (6.2.3)
- GoogleUtilities/Logger (6.2.3):
- GoogleUtilities/Environment (6.3.0)
- GoogleUtilities/Logger (6.3.0):
- GoogleUtilities/Environment
- GoogleUtilities/MethodSwizzler (6.2.3):
- GoogleUtilities/MethodSwizzler (6.3.0):
- GoogleUtilities/Logger
- GoogleUtilities/Network (6.2.3):
- GoogleUtilities/Network (6.3.0):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (6.2.3)"
- GoogleUtilities/Reachability (6.2.3):
- "GoogleUtilities/NSData+zlib (6.3.0)"
- GoogleUtilities/Reachability (6.3.0):
- GoogleUtilities/Logger
- GoogleUtilities/UserDefaults (6.2.3):
- GoogleUtilities/UserDefaults (6.3.0):
- GoogleUtilities/Logger
- libwebp (1.0.2):
- libwebp/core (= 1.0.2)
- libwebp/dec (= 1.0.2)
- libwebp/demux (= 1.0.2)
- libwebp/dsp (= 1.0.2)
- libwebp/enc (= 1.0.2)
- libwebp/mux (= 1.0.2)
- libwebp/utils (= 1.0.2)
- libwebp/webp (= 1.0.2)
- libwebp/core (1.0.2):
- libwebp (1.0.3):
- libwebp/demux (= 1.0.3)
- libwebp/mux (= 1.0.3)
- libwebp/webp (= 1.0.3)
- libwebp/demux (1.0.3):
- libwebp/webp
- libwebp/dec (1.0.2):
- libwebp/core
- libwebp/demux (1.0.2):
- libwebp/core
- libwebp/dsp (1.0.2):
- libwebp/core
- libwebp/enc (1.0.2):
- libwebp/core
- libwebp/mux (1.0.2):
- libwebp/core
- libwebp/utils (1.0.2):
- libwebp/core
- libwebp/webp (1.0.2)
- libwebp/mux (1.0.3):
- libwebp/demux
- libwebp/webp (1.0.3)
- nanopb (0.3.901):
- nanopb/decode (= 0.3.901)
- nanopb/encode (= 0.3.901)
@ -241,10 +238,10 @@ PODS:
- RNVectorIcons (6.6.0):
- React
- RSKImageCropper (2.2.3)
- SDWebImage (5.0.6):
- SDWebImage/Core (= 5.0.6)
- SDWebImage/Core (5.0.6)
- SDWebImageWebPCoder (0.2.3):
- SDWebImage (5.1.1):
- SDWebImage/Core (= 5.1.1)
- SDWebImage/Core (5.1.1)
- SDWebImageWebPCoder (0.2.4):
- libwebp (~> 1.0)
- SDWebImage/Core (~> 5.0)
- UMBarCodeScannerInterface (3.0.0)
@ -338,8 +335,12 @@ SPEC REPOS:
- Firebase
- FirebaseAnalytics
- FirebaseCore
- FirebaseCoreDiagnostics
- FirebaseCoreDiagnosticsInterop
- FirebaseInstanceID
- GoogleAppMeasurement
- GoogleDataTransport
- GoogleDataTransportCCTSupport
- GoogleUtilities
- libwebp
- nanopb
@ -500,7 +501,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BugsnagReactNative: 2114356c3acac0a71fb4b8962d3d1afdeb35f4d9
Crashlytics: 2dfd686bcb918dc10ee0e76f7f853fe42c7bd552
Crashlytics: 540b7e5f5da5a042647227a5e3ac51d85eed06df
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
EXAppLoaderProvider: 7a8185228d8ba9e689a0e2d6d957fe9bdd49c8a0
EXAV: 7228890721d1d74779bc3154fb678a44249b1c71
@ -510,15 +511,19 @@ SPEC CHECKSUMS:
EXPermissions: 99e52dc3e5f8e55153f1958004f6df2a30a1f2f5
EXWebBrowser: def838b95aa9d396f9ce71ace4e614ee16e7ee30
Fabric: 706c8b8098fff96c33c0db69cbf81f9c551d0d74
Firebase: dedc9e48ea3f3649ad5f6b982f8a0c73508a14b5
FirebaseAnalytics: 3fb375bc9d13779add4039716f868d233a473fad
FirebaseCore: aecf02fb2274ec361b9bebeac112f5daa18273bd
FirebaseInstanceID: 662b8108a09fe9ed01aafdedba100fde8536b0f6
Firebase: 9cbe4e5b5eaafa05dc932be58b7c8c3820d71e88
FirebaseAnalytics: 843c7f64a8f9c79f0d03281197ebe7bb1d58d477
FirebaseCore: e9d9bd1dae61c1e82bc1e0e617a9d832392086a0
FirebaseCoreDiagnostics: 4c04ae09d0ab027c30179828c6bb47764df1bd13
FirebaseCoreDiagnosticsInterop: 6829da2b8d1fc795ff1bd99df751d3788035d2cb
FirebaseInstanceID: 550df9be1f99f751d8fcde3ac342a1e21a0e6c42
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
glog: 1f3da668190260b06b429bb211bfbee5cd790c28
GoogleAppMeasurement: 183bd916af7f80deb67c01888368f1108d641832
GoogleUtilities: d2b0e277a95962e09bb27f5cd42f5f0b6a506c7d
libwebp: b068a3bd7c45f7460f6715be7bed1a18fd5d6b48
GoogleAppMeasurement: 86a82f0e1f20b8eedf8e20326530138fd71409de
GoogleDataTransport: 8f9897b8e073687f24ca8d3c3a8013dec7d2d1cc
GoogleDataTransportCCTSupport: 7455d07b98851aa63e4c05a34dad356ca588479e
GoogleUtilities: 9c2c544202301110b29f7974a82e77fdcf12bf51
libwebp: 057912d6d0abfb6357d8bb05c0ea470301f5d61e
nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48
QBImagePickerController: d54cf93db6decf26baf6ed3472f336ef35cae022
React: ff7ee2ae5ee1c1d9ae2183b4111045b25294bb01
@ -562,8 +567,8 @@ SPEC CHECKSUMS:
RNUserDefaults: 8a4928443510aa99e4ccb3b53f1bf186593d690b
RNVectorIcons: 0bb4def82230be1333ddaeee9fcba45f0b288ed4
RSKImageCropper: a446db0e8444a036b34f3c43db01b2373baa4b2a
SDWebImage: 920f1a2ff1ca8296ad34f6e0510a1ef1d70ac965
SDWebImageWebPCoder: 7568737603c50f6237850afedd7e9e28e5917e6b
SDWebImage: 96d7f03415ccb28d299d765f93557ff8a617abd8
SDWebImageWebPCoder: cc72085bb20368b2f8dbb21b7e355c667e1309b7
UMBarCodeScannerInterface: 84ea2d6b58ff0dc27ef9b68bab71286be18ee020
UMCameraInterface: 26b26005d1756a0d5f4f04f1e168e39ea9154535
UMConstantsInterface: 038bacb19de12b6fd328c589122c8dc977cccf61

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,9 +0,0 @@
framework module FirebaseCoreDiagnostics {
export *
module * { export * }
link "z"
link framework "Foundation"
link framework "Security"
link framework "SystemConfiguration"
link framework "UIKit"
}

View File

@ -14,33 +14,45 @@
#include <sys/utsname.h>
#if __has_include(<UIKit/UIKit.h>)
#import <UIKit/UIKit.h>
#endif
#if __has_include(<AppKit/AppKit.h>)
#import <AppKit/AppKit.h>
#endif
#import "FIRApp.h"
#import "Private/FIRAnalyticsConfiguration.h"
#import "Private/FIRAppInternal.h"
#import "Private/FIRBundleUtil.h"
#import "Private/FIRComponentContainerInternal.h"
#import "Private/FIRConfigurationInternal.h"
#import "Private/FIRCoreDiagnosticsConnector.h"
#import "Private/FIRLibrary.h"
#import "Private/FIRLogger.h"
#import "Private/FIROptionsInternal.h"
NSString *const kFIRServiceAdMob = @"AdMob";
NSString *const kFIRServiceAuth = @"Auth";
NSString *const kFIRServiceAuthUI = @"AuthUI";
NSString *const kFIRServiceCrash = @"Crash";
NSString *const kFIRServiceDatabase = @"Database";
NSString *const kFIRServiceDynamicLinks = @"DynamicLinks";
NSString *const kFIRServiceFirestore = @"Firestore";
NSString *const kFIRServiceFunctions = @"Functions";
NSString *const kFIRServiceInstanceID = @"InstanceID";
NSString *const kFIRServiceInvites = @"Invites";
NSString *const kFIRServiceMessaging = @"Messaging";
NSString *const kFIRServiceMeasurement = @"Measurement";
NSString *const kFIRServicePerformance = @"Performance";
NSString *const kFIRServiceRemoteConfig = @"RemoteConfig";
NSString *const kFIRServiceStorage = @"Storage";
NSString *const kGGLServiceAnalytics = @"Analytics";
NSString *const kGGLServiceSignIn = @"SignIn";
// The kFIRService strings are only here while transitioning CoreDiagnostics from the Analytics
// pod to a Core dependency. These symbols are not used and should be deleted after the transition.
NSString *const kFIRServiceAdMob;
NSString *const kFIRServiceAuth;
NSString *const kFIRServiceAuthUI;
NSString *const kFIRServiceCrash;
NSString *const kFIRServiceDatabase;
NSString *const kFIRServiceDynamicLinks;
NSString *const kFIRServiceFirestore;
NSString *const kFIRServiceFunctions;
NSString *const kFIRServiceInstanceID;
NSString *const kFIRServiceInvites;
NSString *const kFIRServiceMessaging;
NSString *const kFIRServiceMeasurement;
NSString *const kFIRServicePerformance;
NSString *const kFIRServiceRemoteConfig;
NSString *const kFIRServiceStorage;
NSString *const kGGLServiceAnalytics;
NSString *const kGGLServiceSignIn;
NSString *const kFIRDefaultAppName = @"__FIRAPP_DEFAULT";
NSString *const kFIRAppReadyToConfigureSDKNotification = @"FIRAppReadyToConfigureSDKNotification";
@ -103,19 +115,6 @@ static NSMutableDictionary *sLibraryVersions;
+ (void)configure {
FIROptions *options = [FIROptions defaultOptions];
if (!options) {
// Read the Info.plist to see if the flag is set. At this point we can't check any user defaults
// since the app isn't configured at all, so only rely on the Info.plist value.
NSNumber *collectionEnabledPlistValue = [[self class] readDataCollectionSwitchFromPlist];
if (collectionEnabledPlistValue == nil || [collectionEnabledPlistValue boolValue]) {
[[NSNotificationCenter defaultCenter]
postNotificationName:kFIRAppDiagnosticsNotification
object:nil
userInfo:@{
kFIRAppDiagnosticsConfigurationTypeKey : @(FIRConfigTypeCore),
kFIRAppDiagnosticsErrorKey : [FIRApp errorForMissingOptions]
}];
}
[NSException raise:kFirebaseCoreErrorDomain
format:@"`[FIRApp configure];` (`FirebaseApp.configure()` in Swift) could not find "
@"a valid GoogleService-Info.plist in your project. Please download one "
@ -290,30 +289,17 @@ static NSMutableDictionary *sLibraryVersions;
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (BOOL)configureCore {
[self checkExpectedBundleID];
if (![self isAppIDValid]) {
if (_options.usingOptionsFromDefaultPlist && [self isDataCollectionDefaultEnabled]) {
[[NSNotificationCenter defaultCenter]
postNotificationName:kFIRAppDiagnosticsNotification
object:nil
userInfo:@{
kFIRAppDiagnosticsConfigurationTypeKey : @(FIRConfigTypeCore),
kFIRAppDiagnosticsErrorKey : [FIRApp errorForInvalidAppID],
}];
}
return NO;
}
if ([self isDataCollectionDefaultEnabled]) {
[[NSNotificationCenter defaultCenter]
postNotificationName:kFIRAppDiagnosticsNotification
object:nil
userInfo:@{
kFIRAppDiagnosticsConfigurationTypeKey : @(FIRConfigTypeCore),
kFIRAppDiagnosticsFIRAppKey : self
}];
}
[self logCoreTelemetryIfEnabled];
#if TARGET_OS_IOS
// Initialize the Analytics once there is a valid options under default app. Analytics should
@ -338,6 +324,8 @@ static NSMutableDictionary *sLibraryVersions;
}
#endif
[self subscribeForAppDidBecomeActiveNotifications];
return YES;
}
@ -809,26 +797,40 @@ static NSMutableDictionary *sLibraryVersions;
#pragma mark - Sending Logs
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
- (void)sendLogsWithServiceName:(NSString *)serviceName
version:(NSString *)version
error:(NSError *)error {
// If the user has manually turned off data collection, return and don't send logs.
if (![self isDataCollectionDefaultEnabled]) {
return;
}
// Do nothing. Please remove calls to this method.
}
#pragma clang diagnostic pop
NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:@{
kFIRAppDiagnosticsConfigurationTypeKey : @(FIRConfigTypeSDK),
kFIRAppDiagnosticsSDKNameKey : serviceName,
kFIRAppDiagnosticsSDKVersionKey : version,
kFIRAppDiagnosticsFIRAppKey : self
}];
if (error) {
userInfo[kFIRAppDiagnosticsErrorKey] = error;
#pragma mark - App Life Cycle
- (void)subscribeForAppDidBecomeActiveNotifications {
#if TARGET_OS_IOS || TARGET_OS_TV
NSNotificationName notificationName = UIApplicationDidBecomeActiveNotification;
#endif
#if TARGET_OS_OSX
NSNotificationName notificationName = NSApplicationDidBecomeActiveNotification;
#endif
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(appDidBecomeActive:)
name:notificationName
object:nil];
}
- (void)appDidBecomeActive:(NSNotification *)notification {
[self logCoreTelemetryIfEnabled];
}
- (void)logCoreTelemetryIfEnabled {
if ([self isDataCollectionDefaultEnabled]) {
[FIRCoreDiagnosticsConnector logCoreTelemetryWithOptions:_options];
}
[[NSNotificationCenter defaultCenter] postNotificationName:kFIRAppDiagnosticsNotification
object:nil
userInfo:userInfo];
}
@end

View File

@ -23,7 +23,9 @@
NS_ASSUME_NONNULL_BEGIN
@interface FIRComponentContainer ()
@interface FIRComponentContainer () {
dispatch_queue_t _containerQueue;
}
/// The dictionary of components that are registered for a particular app. The key is an NSString
/// of the protocol.
@ -67,6 +69,8 @@ static NSMutableSet<Class> *sFIRComponentRegistrants;
_app = app;
_cachedInstances = [NSMutableDictionary<NSString *, id> dictionary];
_components = [NSMutableDictionary<NSString *, FIRComponentCreationBlock> dictionary];
_containerQueue =
dispatch_queue_create("com.google.FirebaseComponentContainer", DISPATCH_QUEUE_SERIAL);
[self populateComponentsFromRegisteredClasses:allRegistrants forApp:app];
}
@ -92,7 +96,7 @@ static NSMutableSet<Class> *sFIRComponentRegistrants;
// Store the creation block for later usage.
self.components[protocolName] = component.creationBlock;
// Instantiate the
// Instantiate the instance if it has requested to be instantiated.
BOOL shouldInstantiateEager =
(component.instantiationTiming == FIRInstantiationTimingAlwaysEager);
BOOL shouldInstantiateDefaultEager =
@ -136,7 +140,9 @@ static NSMutableSet<Class> *sFIRComponentRegistrants;
// The instance is ready to be returned, but check if it should be cached first before returning.
if (shouldCache) {
dispatch_sync(_containerQueue, ^{
self.cachedInstances[protocolName] = instance;
});
}
return instance;
@ -147,7 +153,11 @@ static NSMutableSet<Class> *sFIRComponentRegistrants;
- (nullable id)instanceForProtocol:(Protocol *)protocol {
// Check if there is a cached instance, and return it if so.
NSString *protocolName = NSStringFromProtocol(protocol);
id cachedInstance = self.cachedInstances[protocolName];
__block id cachedInstance;
dispatch_sync(_containerQueue, ^{
cachedInstance = self.cachedInstances[protocolName];
});
if (cachedInstance) {
return cachedInstance;
}
@ -161,14 +171,29 @@ static NSMutableSet<Class> *sFIRComponentRegistrants;
- (void)removeAllCachedInstances {
// Loop through the cache and notify each instance that is a maintainer to clean up after itself.
for (id instance in self.cachedInstances.allValues) {
// Design note: we're getting a copy here, unlocking the cached instances, iterating over the
// copy, then locking and removing all cached instances. A race condition *could* exist where a
// new cached instance is created between the copy and the removal, but the chances are slim and
// side-effects are significantly smaller than including the entire loop in the `dispatch_sync`
// block (access to the cache from inside the block would deadlock and crash).
__block NSDictionary<NSString *, id> *instancesCopy;
dispatch_sync(_containerQueue, ^{
instancesCopy = [self.cachedInstances copy];
});
for (id instance in instancesCopy.allValues) {
if ([instance conformsToProtocol:@protocol(FIRComponentLifecycleMaintainer)] &&
[instance respondsToSelector:@selector(appWillBeDeleted:)]) {
[instance appWillBeDeleted:self.app];
}
}
instancesCopy = nil;
// Empty the cache.
dispatch_sync(_containerQueue, ^{
[self.cachedInstances removeAllObjects];
});
}
@end

View File

@ -0,0 +1,61 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "Private/FIRCoreDiagnosticsConnector.h"
#import <FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h>
#import <FirebaseCore/FIROptions.h>
#import "Private/FIRAppInternal.h"
#import "Private/FIRDiagnosticsData.h"
#import "Private/FIROptionsInternal.h"
// Define the interop class symbol declared as an extern in FIRCoreDiagnosticsInterop.
Class<FIRCoreDiagnosticsInterop> FIRCoreDiagnosticsImplementation;
@implementation FIRCoreDiagnosticsConnector
+ (void)initialize {
if (!FIRCoreDiagnosticsImplementation) {
FIRCoreDiagnosticsImplementation = NSClassFromString(@"FIRCoreDiagnostics");
if (FIRCoreDiagnosticsImplementation) {
NSAssert([FIRCoreDiagnosticsImplementation
conformsToProtocol:@protocol(FIRCoreDiagnosticsInterop)],
@"If FIRCoreDiagnostics is implemented, it must conform to the interop protocol.");
NSAssert(
[FIRCoreDiagnosticsImplementation respondsToSelector:@selector(sendDiagnosticsData:)],
@"If FIRCoreDiagnostics is implemented, it must implement +sendDiagnosticsData.");
}
}
}
+ (void)logCoreTelemetryWithOptions:(FIROptions *)options {
if (FIRCoreDiagnosticsImplementation) {
FIRDiagnosticsData *diagnosticsData = [[FIRDiagnosticsData alloc] init];
[diagnosticsData insertValue:@(YES) forKey:kFIRCDIsDataCollectionDefaultEnabledKey];
[diagnosticsData insertValue:[FIRApp firebaseUserAgent] forKey:kFIRCDFirebaseUserAgentKey];
[diagnosticsData insertValue:@(FIRConfigTypeCore) forKey:kFIRCDConfigurationTypeKey];
[diagnosticsData insertValue:options.googleAppID forKey:kFIRCDGoogleAppIDKey];
[diagnosticsData insertValue:options.bundleID forKey:kFIRCDBundleIDKey];
[diagnosticsData insertValue:@(options.usingOptionsFromDefaultPlist)
forKey:kFIRCDUsingOptionsFromDefaultPlistKey];
[diagnosticsData insertValue:options.libraryVersionID forKey:kFIRCDLibraryVersionIDKey];
[FIRCoreDiagnosticsImplementation sendDiagnosticsData:diagnosticsData];
}
}
@end

View File

@ -0,0 +1,66 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "Private/FIRDiagnosticsData.h"
#import <FirebaseCore/FIRApp.h>
#import "Private/FIRAppInternal.h"
#import "Private/FIROptionsInternal.h"
@implementation FIRDiagnosticsData {
/** Backing ivar for the diagnosticObjects property. */
NSMutableDictionary<NSString *, id> *_diagnosticObjects;
}
- (instancetype)init {
self = [super init];
if (self) {
_diagnosticObjects = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void)insertValue:(nullable id)value forKey:(NSString *)key {
if (key) {
_diagnosticObjects[key] = value;
}
}
#pragma mark - FIRCoreDiagnosticsData
- (NSDictionary<NSString *, id> *)diagnosticObjects {
if (!_diagnosticObjects[kFIRCDllAppsCountKey]) {
_diagnosticObjects[kFIRCDllAppsCountKey] = @([FIRApp allApps].count);
}
if (!_diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey]) {
_diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey] =
@([[FIRApp defaultApp] isDataCollectionDefaultEnabled]);
}
if (!_diagnosticObjects[kFIRCDFirebaseUserAgentKey]) {
_diagnosticObjects[kFIRCDFirebaseUserAgentKey] = [FIRApp firebaseUserAgent];
}
return _diagnosticObjects;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
- (void)setDiagnosticObjects:(NSDictionary<NSString *, id> *)diagnosticObjects {
NSAssert(NO, @"Please use -insertValue:forKey:");
}
#pragma clang diagnostic pop
@end

View File

@ -34,26 +34,6 @@ typedef NS_ENUM(NSInteger, FIRConfigType) {
FIRConfigTypeSDK = 2,
};
/**
* Names of services provided by Firebase.
*/
extern NSString *const kFIRServiceAdMob;
extern NSString *const kFIRServiceAuth;
extern NSString *const kFIRServiceAuthUI;
extern NSString *const kFIRServiceDatabase;
extern NSString *const kFIRServiceDynamicLinks;
extern NSString *const kFIRServiceInstanceID;
extern NSString *const kFIRServiceMessaging;
extern NSString *const kFIRServiceMeasurement;
extern NSString *const kFIRServiceRemoteConfig;
extern NSString *const kFIRServiceStorage;
/**
* Names of services provided by the Google pod, but logged by the Firebase pod.
*/
extern NSString *const kGGLServiceAnalytics;
extern NSString *const kGGLServiceSignIn;
extern NSString *const kFIRDefaultAppName;
extern NSString *const kFIRAppReadyToConfigureSDKNotification;
extern NSString *const kFIRAppDeleteNotification;
@ -160,6 +140,8 @@ extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey;
/**
* Used by each SDK to send logs about SDK configuration status to Clearcut.
*
* @note This API is a no-op, please remove calls to it.
*/
- (void)sendLogsWithServiceName:(NSString *)serviceName
version:(NSString *)version

View File

@ -0,0 +1,35 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
@class FIRDiagnosticsData;
@class FIROptions;
NS_ASSUME_NONNULL_BEGIN
/** Connects FIRCore with the CoreDiagnostics library. */
@interface FIRCoreDiagnosticsConnector : NSObject
/** Logs FirebaseCore related data.
*
* @param options The options object containing data to log.
*/
+ (void)logCoreTelemetryWithOptions:(FIROptions *)options;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,35 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h>
NS_ASSUME_NONNULL_BEGIN
/** Implements the FIRCoreDiagnosticsData protocol to log diagnostics data. */
@interface FIRDiagnosticsData : NSObject <FIRCoreDiagnosticsData>
/** Inserts values into the diagnosticObjects dictionary if the value isn't nil.
*
* @param value The value to insert if it's not nil.
* @param key The key to associate it with.
*/
- (void)insertValue:(nullable id)value forKey:(NSString *)key;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,8 +1,8 @@
# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk)
This repository contains a subset of the Firebase iOS SDK source. It currently
includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore,
FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging,
includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase,
FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging,
FirebaseInAppMessagingDisplay, FirebaseMessaging and FirebaseStorage.
The repository also includes GoogleUtilities source. The
@ -80,9 +80,8 @@ For the pod that you want to develop:
`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open`
Firestore and Functions have self contained Xcode projects. See
[Firestore/README.md](Firestore/README.md) and
[Functions/README.md](Functions/README.md).
Firestore has a self contained Xcode project. See
[Firestore/README.md](Firestore/README.md).
### Adding a New Firebase Pod
@ -179,7 +178,8 @@ very grateful! We'd like to empower as many developers as we can to be able to
participate in the Firebase community.
### macOS and tvOS
Thanks to contributions from the community, FirebaseAuth, FirebaseCore, FirebaseDatabase, FirebaseMessaging,
Thanks to contributions from the community, FirebaseABTesting, FirebaseAuth, FirebaseCore,
FirebaseDatabase, FirebaseMessaging,
FirebaseFirestore, FirebaseFunctions and FirebaseStorage now compile, run unit tests, and work on
macOS and tvOS.
@ -195,6 +195,7 @@ Note that the Firebase pod is not available for macOS and tvOS.
To install, add a subset of the following to the Podfile:
```
pod 'FirebaseABTesting'
pod 'FirebaseAuth'
pod 'FirebaseCore'
pod 'FirebaseDatabase'

View File

@ -0,0 +1,674 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <objc/runtime.h>
#include <sys/utsname.h>
#import <GoogleDataTransport/GDTConsoleLogger.h>
#import <GoogleDataTransport/GDTEvent.h>
#import <GoogleDataTransport/GDTTargets.h>
#import <GoogleDataTransport/GDTTransport.h>
#import <GoogleUtilities/GULAppEnvironmentUtil.h>
#import <GoogleUtilities/GULLogger.h>
#import <FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h>
#import <FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h>
#import <nanopb/pb.h>
#import <nanopb/pb_decode.h>
#import <nanopb/pb_encode.h>
#import "FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h"
#import "FIRCDLibrary/FIRCoreDiagnosticsDateFileStorage.h"
/** The logger service string to use when printing to the console. */
static GULLoggerService kFIRCoreDiagnostics = @"[FirebaseCoreDiagnostics/FIRCoreDiagnostics]";
#ifdef FIREBASE_BUILD_ZIP_FILE
static BOOL kUsingZipFile = YES;
#else // FIREBASE_BUILD_ZIP_FILE
static BOOL kUsingZipFile = NO;
#endif // FIREBASE_BUILD_ZIP_FILE
#ifdef FIREBASE_BUILD_CARTHAGE
#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_CARTHAGE
#elif FIREBASE_BUILD_ZIP_FILE
#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ZIP_FILE
#else
#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_COCOAPODS
#endif
static NSString *const kFIRServiceMLVisionOnDeviceAutoML = @"MLVisionOnDeviceAutoML";
static NSString *const kFIRServiceMLVisionOnDeviceFace = @"MLVisionOnDeviceFace";
static NSString *const kFIRServiceMLVisionOnDeviceBarcode = @"MLVisionOnDeviceBarcode";
static NSString *const kFIRServiceMLVisionOnDeviceText = @"MLVisionOnDeviceText";
static NSString *const kFIRServiceMLVisionOnDeviceLabel = @"MLVisionOnDeviceLabel";
static NSString *const kFIRServiceMLVisionOnDeviceObjectDetection =
@"MLVisionOnDeviceObjectDetection";
static NSString *const kFIRServiceMLModelInterpreter = @"MLModelInterpreter";
static NSString *const kFIRServiceAdMob = @"AdMob";
static NSString *const kFIRServiceAuth = @"Auth";
static NSString *const kFIRServiceAuthUI = @"AuthUI";
static NSString *const kFIRServiceCrash = @"Crash";
static NSString *const kFIRServiceDatabase = @"Database";
static NSString *const kFIRServiceDynamicLinks = @"DynamicLinks";
static NSString *const kFIRServiceFirestore = @"Firestore";
static NSString *const kFIRServiceFunctions = @"Functions";
static NSString *const kFIRServiceIAM = @"InAppMessaging";
static NSString *const kFIRServiceInstanceID = @"InstanceID";
static NSString *const kFIRServiceInvites = @"Invites";
static NSString *const kFIRServiceMessaging = @"Messaging";
static NSString *const kFIRServiceMeasurement = @"Measurement";
static NSString *const kFIRServicePerformance = @"Performance";
static NSString *const kFIRServiceRemoteConfig = @"RemoteConfig";
static NSString *const kFIRServiceStorage = @"Storage";
static NSString *const kGGLServiceAnalytics = @"Analytics";
static NSString *const kGGLServiceSignIn = @"SignIn";
static NSString *const kFIRAppDiagnosticsConfigurationTypeKey =
@"FIRAppDiagnosticsConfigurationTypeKey";
static NSString *const kFIRAppDiagnosticsFIRAppKey = @"FIRAppDiagnosticsFIRAppKey";
static NSString *const kFIRAppDiagnosticsSDKNameKey = @"FIRAppDiagnosticsSDKNameKey";
static NSString *const kFIRAppDiagnosticsSDKVersionKey = @"FIRAppDiagnosticsSDKVersionKey";
/**
* The file name to the recent heartbeat date.
*/
NSString *const kFIRCoreDiagnosticsHeartbeatDateFileName = @"FIREBASE_DIAGNOSTICS_HEARTBEAT_DATE";
/**
* @note This should implement the GDTEventDataObject protocol, but can't because of weak-linking.
*/
@interface FIRCoreDiagnosticsLog : NSObject
/** The config that will be converted to proto bytes. */
@property(nonatomic) logs_proto_mobilesdk_ios_ICoreConfiguration config;
@end
@implementation FIRCoreDiagnosticsLog
- (instancetype)initWithConfig:(logs_proto_mobilesdk_ios_ICoreConfiguration)config {
self = [super init];
if (self) {
_config = config;
}
return self;
}
// Provided and required by the GDTEventDataObject protocol.
- (NSData *)transportBytes {
pb_ostream_t sizestream = PB_OSTREAM_SIZING;
// Encode 1 time to determine the size.
if (!pb_encode(&sizestream, logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config)) {
GDTLogError(GDTMCETransportBytesError, @"Error in nanopb encoding for size: %s",
PB_GET_ERROR(&sizestream));
}
// Encode a 2nd time to actually get the bytes from it.
size_t bufferSize = sizestream.bytes_written;
CFMutableDataRef dataRef = CFDataCreateMutable(CFAllocatorGetDefault(), bufferSize);
pb_ostream_t ostream = pb_ostream_from_buffer((void *)CFDataGetBytePtr(dataRef), bufferSize);
if (!pb_encode(&ostream, logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config)) {
GDTLogError(GDTMCETransportBytesError, @"Error in nanopb encoding for bytes: %s",
PB_GET_ERROR(&ostream));
}
CFDataSetLength(dataRef, ostream.bytes_written);
return CFBridgingRelease(dataRef);
}
- (void)dealloc {
pb_release(logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config);
}
@end
NS_ASSUME_NONNULL_BEGIN
/** This class produces a protobuf containing diagnostics and usage data to be logged. */
@interface FIRCoreDiagnostics : NSObject <FIRCoreDiagnosticsInterop>
/** The queue on which all diagnostics collection will occur. */
@property(nonatomic, readonly) dispatch_queue_t diagnosticsQueue;
/** The transport object used to send data. */
@property(nonatomic, readonly) GDTTransport *transport;
/** The storage to store the date of the last sent heartbeat. */
@property(nonatomic, readonly) FIRCoreDiagnosticsDateFileStorage *heartbeatDateStorage;
@end
NS_ASSUME_NONNULL_END
@implementation FIRCoreDiagnostics
+ (instancetype)sharedInstance {
static FIRCoreDiagnostics *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[FIRCoreDiagnostics alloc] init];
});
return sharedInstance;
}
- (instancetype)init {
GDTTransport *transport = [[GDTTransport alloc] initWithMappingID:@"137"
transformers:nil
target:kGDTTargetCCT];
FIRCoreDiagnosticsDateFileStorage *dateStorage = [[FIRCoreDiagnosticsDateFileStorage alloc]
initWithFileURL:[[self class] filePathURLWithName:kFIRCoreDiagnosticsHeartbeatDateFileName]];
return [self initWithTransport:transport heartbeatDateStorage:dateStorage];
}
/** Initializer for unit tests.
*
* @param transport A `GDTTransport` instance which that be used to send event.
* @param heartbeatDateStorage An instanse of date storage to track heartbeat sending.
* @return Returns the initialized `FIRCoreDiagnostics` instance.
*/
- (instancetype)initWithTransport:(GDTTransport *)transport
heartbeatDateStorage:(FIRCoreDiagnosticsDateFileStorage *)heartbeatDateStorage {
self = [super init];
if (self) {
_diagnosticsQueue =
dispatch_queue_create("com.google.FIRCoreDiagnostics", DISPATCH_QUEUE_SERIAL);
_transport = transport;
_heartbeatDateStorage = heartbeatDateStorage;
}
return self;
}
#pragma mark - File path helpers
/** Returns the URL path of the file with name fileName under the Application Support folder for
* local logging. Creates the Application Support folder if the folder doesn't exist.
*
* @return the URL path of the file with the name fileName in Application Support.
*/
+ (NSURL *)filePathURLWithName:(NSString *)fileName {
@synchronized(self) {
NSArray<NSString *> *paths =
NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSArray<NSString *> *components = @[ paths.lastObject, @"Google/FIRApp" ];
NSString *directoryString = [NSString pathWithComponents:components];
NSURL *directoryURL = [NSURL fileURLWithPath:directoryString];
NSError *error;
if (![directoryURL checkResourceIsReachableAndReturnError:&error]) {
// If fail creating the Application Support directory, return nil.
if (![[NSFileManager defaultManager] createDirectoryAtURL:directoryURL
withIntermediateDirectories:YES
attributes:nil
error:&error]) {
GULLogWarning(kFIRCoreDiagnostics, YES, @"I-COR100001",
@"Unable to create internal state storage: %@", error);
return nil;
}
}
return [directoryURL URLByAppendingPathComponent:fileName];
}
}
#pragma mark - Metadata helpers
/** Returns the model of iOS device. Sample platform strings are @"iPhone7,1" for iPhone 6 Plus,
* @"iPhone7,2" for iPhone 6, etc. Refer to the Hardware strings at
* https://en.wikipedia.org/wiki/List_of_iOS_devices
*
* @return The device model as an NSString.
*/
+ (NSString *)deviceModel {
static NSString *deviceModel = nil;
if (deviceModel == nil) {
struct utsname systemInfo;
uname(&systemInfo);
deviceModel = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
}
return deviceModel;
}
#pragma mark - nanopb helper functions
/** Mallocs a pb_bytes_array and copies the given NSString's bytes into the bytes array.
*
* @note Memory needs to be free manually, through pb_free or pb_release.
* @param string The string to encode as pb_bytes.
*/
pb_bytes_array_t *FIREncodeString(NSString *string) {
NSData *stringBytes = [string dataUsingEncoding:NSUTF8StringEncoding];
return FIREncodeData(stringBytes);
}
/** Mallocs a pb_bytes_array and copies the given NSData bytes into the bytes array.
*
* @note Memory needs to be free manually, through pb_free or pb_release.
* @param data The data to copy into the new bytes array.
*/
pb_bytes_array_t *FIREncodeData(NSData *data) {
pb_bytes_array_t *pbBytes = malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(data.length));
memcpy(pbBytes->bytes, [data bytes], data.length);
pbBytes->size = (pb_size_t)data.length;
return pbBytes;
}
/** Maps a service string to the representative nanopb enum.
*
* @param serviceString The SDK service string to convert.
* @return The representative nanopb enum.
*/
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType FIRMapFromServiceStringToTypeEnum(
NSString *serviceString) {
static NSDictionary<NSString *, NSNumber *> *serviceStringToTypeEnum;
if (serviceStringToTypeEnum == nil) {
serviceStringToTypeEnum = @{
kFIRServiceAdMob : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ADMOB),
kFIRServiceMessaging : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MESSAGING),
kFIRServiceMeasurement :
@(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MEASUREMENT),
kFIRServiceRemoteConfig :
@(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_REMOTE_CONFIG),
kFIRServiceDatabase : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DATABASE),
kFIRServiceDynamicLinks :
@(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DYNAMIC_LINKS),
kFIRServiceAuth : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH),
kFIRServiceAuthUI : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH_UI),
kFIRServiceFirestore : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FIRESTORE),
kFIRServiceFunctions : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FUNCTIONS),
kFIRServicePerformance :
@(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_PERFORMANCE),
kFIRServiceStorage : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_STORAGE),
kFIRServiceMLVisionOnDeviceAutoML :
@(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_AUTOML),
kFIRServiceMLVisionOnDeviceFace :
@(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_FACE),
kFIRServiceMLVisionOnDeviceBarcode :
@(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_BARCODE),
kFIRServiceMLVisionOnDeviceText :
@(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_TEXT),
kFIRServiceMLVisionOnDeviceLabel :
@(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_LABEL),
kFIRServiceMLVisionOnDeviceObjectDetection : @(
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION),
kFIRServiceMLModelInterpreter :
@(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_MODEL_INTERPRETER),
kGGLServiceAnalytics : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ANALYTICS),
kGGLServiceSignIn : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SIGN_IN),
kFIRServiceIAM : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_IN_APP_MESSAGING),
};
}
if (serviceStringToTypeEnum[serviceString] != nil) {
return (int32_t)serviceStringToTypeEnum[serviceString].longLongValue;
}
return logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE;
}
#pragma mark - Proto population functions
/** Populates the given proto with data related to an SDK logDiagnostics call from the
* diagnosticObjects dictionary.
*
* @param config The proto to populate
* @param diagnosticObjects The dictionary of diagnostics objects.
*/
void FIRPopulateProtoWithInfoFromUserInfoParams(logs_proto_mobilesdk_ios_ICoreConfiguration *config,
NSDictionary<NSString *, id> *diagnosticObjects) {
NSNumber *configurationType = diagnosticObjects[kFIRCDConfigurationTypeKey];
if (configurationType != nil) {
switch (configurationType.integerValue) {
case logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE:
config->configuration_type =
logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE;
config->has_configuration_type = 1;
break;
case logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK:
config->configuration_type =
logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK;
config->has_configuration_type = 1;
break;
default:
break;
}
}
NSString *sdkName = diagnosticObjects[kFIRCDSdkNameKey];
if (sdkName) {
config->sdk_name = FIRMapFromServiceStringToTypeEnum(sdkName);
config->has_sdk_name = 1;
}
NSString *version = diagnosticObjects[kFIRCDSdkVersionKey];
if (version) {
config->sdk_version = FIREncodeString(version);
}
}
/** Populates the given proto with data from the calling FIRApp using the given
* diagnosticObjects dictionary.
*
* @param config The proto to populate
* @param diagnosticObjects The dictionary of diagnostics objects.
*/
void FIRPopulateProtoWithCommonInfoFromApp(logs_proto_mobilesdk_ios_ICoreConfiguration *config,
NSDictionary<NSString *, id> *diagnosticObjects) {
config->pod_name = logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE;
config->has_pod_name = 1;
if (!diagnosticObjects[kFIRCDllAppsCountKey]) {
GDTLogError(GDTMCEGeneralError, @"%@", @"App count is a required value in the data dict.");
}
config->app_count = (int32_t)[diagnosticObjects[kFIRCDllAppsCountKey] integerValue];
config->has_app_count = 1;
NSString *googleAppID = diagnosticObjects[kFIRCDGoogleAppIDKey];
if (googleAppID.length) {
config->app_id = FIREncodeString(googleAppID);
}
NSString *bundleID = diagnosticObjects[kFIRCDBundleIDKey];
if (bundleID.length) {
config->bundle_id = FIREncodeString(bundleID);
}
NSString *firebaseUserAgent = diagnosticObjects[kFIRCDFirebaseUserAgentKey];
if (firebaseUserAgent.length) {
config->platform_info = FIREncodeString(firebaseUserAgent);
}
NSNumber *usingOptionsFromDefaultPlist = diagnosticObjects[kFIRCDUsingOptionsFromDefaultPlistKey];
if (usingOptionsFromDefaultPlist != nil) {
config->use_default_app = [usingOptionsFromDefaultPlist boolValue];
config->has_use_default_app = 1;
}
NSString *libraryVersionID = diagnosticObjects[kFIRCDLibraryVersionIDKey];
if (libraryVersionID) {
config->icore_version = FIREncodeString(libraryVersionID);
}
NSString *deviceModel = [FIRCoreDiagnostics deviceModel];
if (deviceModel.length) {
config->device_model = FIREncodeString(deviceModel);
}
NSString *osVersion = [GULAppEnvironmentUtil systemVersion];
if (osVersion.length) {
config->os_version = FIREncodeString(osVersion);
}
config->using_zip_file = kUsingZipFile;
config->has_using_zip_file = 1;
config->deployment_type = kDeploymentType;
config->has_deployment_type = 1;
config->deployed_in_app_store = [GULAppEnvironmentUtil isFromAppStore];
config->has_deployed_in_app_store = 1;
}
/** Populates the given proto with installed services data.
*
* @param config The proto to populate
*/
void FIRPopulateProtoWithInstalledServices(logs_proto_mobilesdk_ios_ICoreConfiguration *config) {
NSMutableArray<NSNumber *> *sdkServiceInstalledArray = [NSMutableArray array];
// AdMob
if (NSClassFromString(@"GADBannerView") != nil) {
[sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAdMob))];
}
// CloudMessaging
if (NSClassFromString(@"FIRMessaging") != nil) {
[sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMessaging))];
}
// RemoteConfig
if (NSClassFromString(@"FIRRemoteConfig") != nil) {
[sdkServiceInstalledArray
addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceRemoteConfig))];
}
// Measurement/Analtyics
if (NSClassFromString(@"FIRAnalytics") != nil) {
[sdkServiceInstalledArray
addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMeasurement))];
}
// ML Vision On Device AutoML.
if (NSClassFromString(@"FIRVisionOnDeviceAutoMLImageLabelerOptions") != nil) {
[sdkServiceInstalledArray
addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceAutoML))];
}
// ML Vision On Device Face.
if (NSClassFromString(@"FIRVisionFaceDetector") != nil &&
NSClassFromString(@"GMVFaceDetector") != nil) {
[sdkServiceInstalledArray
addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceFace))];
}
// ML Vision On Device Barcode.
if (NSClassFromString(@"FIRVisionBarcodeDetector") != nil &&
NSClassFromString(@"GMVBarcodeDetector") != nil) {
[sdkServiceInstalledArray
addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceBarcode))];
}
// ML Vision On Device Text.
if (NSClassFromString(@"FIRVisionTextDetector") != nil &&
NSClassFromString(@"GMVTextDetector") != nil) {
[sdkServiceInstalledArray
addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceText))];
}
// ML Vision On Device Image Label.
if (NSClassFromString(@"FIRVisionLabelDetector") != nil &&
NSClassFromString(@"GMVLabelDetector") != nil) {
[sdkServiceInstalledArray
addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceLabel))];
}
// ML Vision On Device Object.
if (NSClassFromString(@"FIRVisionObjectDetector") != nil) {
[sdkServiceInstalledArray
addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceObjectDetection))];
}
// ML Model Interpreter
if (NSClassFromString(@"FIRCustomModelInterpreter") != nil) {
[sdkServiceInstalledArray
addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLModelInterpreter))];
}
// Database
if (NSClassFromString(@"FIRDatabase") != nil) {
[sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceDatabase))];
}
// DynamicDeepLink
if (NSClassFromString(@"FIRDynamicLinks") != nil) {
[sdkServiceInstalledArray
addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceDynamicLinks))];
}
// Auth
if (NSClassFromString(@"FIRAuth") != nil) {
[sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAuth))];
}
// AuthUI
if (NSClassFromString(@"FUIAuth") != nil) {
[sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAuthUI))];
}
// Firestore
if (NSClassFromString(@"FIRFirestore") != nil) {
[sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceFirestore))];
}
// Functions
if (NSClassFromString(@"FIRFunctions") != nil) {
[sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceFunctions))];
}
// Performance
if (NSClassFromString(@"FIRPerformance") != nil) {
[sdkServiceInstalledArray
addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServicePerformance))];
}
// Storage
if (NSClassFromString(@"FIRStorage") != nil) {
[sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceStorage))];
}
// SignIn via Google pod
if (NSClassFromString(@"GIDSignIn") != nil && NSClassFromString(@"GGLContext") != nil) {
[sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kGGLServiceSignIn))];
}
// Analytics via Google pod
if (NSClassFromString(@"GAI") != nil && NSClassFromString(@"GGLContext") != nil) {
[sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kGGLServiceAnalytics))];
}
// In-App Messaging
if (NSClassFromString(@"FIRInAppMessaging") != nil) {
[sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceIAM))];
}
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType *servicesInstalled =
malloc(sizeof(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType) *
sdkServiceInstalledArray.count);
for (NSUInteger i = 0; i < sdkServiceInstalledArray.count; i++) {
NSNumber *typeEnum = sdkServiceInstalledArray[i];
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType serviceType =
(int32_t)typeEnum.integerValue;
servicesInstalled[i] = serviceType;
}
config->sdk_service_installed = servicesInstalled;
config->sdk_service_installed_count = (int32_t)sdkServiceInstalledArray.count;
}
/** Populates the proto with the number of linked frameworks.
*
* @param config The proto to populate.
*/
void FIRPopulateProtoWithNumberOfLinkedFrameworks(
logs_proto_mobilesdk_ios_ICoreConfiguration *config) {
int numFrameworks = -1; // Subtract the app binary itself.
unsigned int numImages;
const char **imageNames = objc_copyImageNames(&numImages);
for (unsigned int i = 0; i < numImages; i++) {
NSString *imageName = [NSString stringWithUTF8String:imageNames[i]];
if ([imageName rangeOfString:@"System/Library"].length != 0 // Apple .frameworks
|| [imageName rangeOfString:@"Developer/Library"].length != 0 // Xcode debug .frameworks
|| [imageName rangeOfString:@"usr/lib"].length != 0) { // Public .dylibs
continue;
}
numFrameworks++;
}
free(imageNames);
config->dynamic_framework_count = numFrameworks;
config->has_dynamic_framework_count = 1;
}
/** Populates the proto with Info.plist values.
*
* @param config The proto to populate.
*/
void FIRPopulateProtoWithInfoPlistValues(logs_proto_mobilesdk_ios_ICoreConfiguration *config) {
NSDictionary<NSString *, id> *info = [[NSBundle mainBundle] infoDictionary];
NSString *xcodeVersion = info[@"DTXcodeBuild"] ?: @"";
NSString *sdkVersion = info[@"DTSDKBuild"] ?: @"";
NSString *combinedVersions = [NSString stringWithFormat:@"%@-%@", xcodeVersion, sdkVersion];
config->apple_framework_version = FIREncodeString(combinedVersions);
NSString *minVersion = info[@"MinimumOSVersion"];
if (minVersion) {
config->min_supported_ios_version = FIREncodeString(minVersion);
}
// Apps can turn off swizzling in the Info.plist, check if they've explicitly set the value and
// report it. It's enabled by default.
NSNumber *appDelegateSwizzledNum = info[@"FirebaseAppDelegateProxyEnabled"];
BOOL appDelegateSwizzled = YES;
if ([appDelegateSwizzledNum isKindOfClass:[NSNumber class]]) {
appDelegateSwizzled = [appDelegateSwizzledNum boolValue];
}
config->swizzling_enabled = appDelegateSwizzled;
config->has_swizzling_enabled = 1;
}
#pragma mark - FIRCoreDiagnosticsInterop
+ (void)sendDiagnosticsData:(nonnull id<FIRCoreDiagnosticsData>)diagnosticsData {
FIRCoreDiagnostics *diagnostics = [FIRCoreDiagnostics sharedInstance];
[diagnostics sendDiagnosticsData:diagnosticsData];
}
- (void)sendDiagnosticsData:(nonnull id<FIRCoreDiagnosticsData>)diagnosticsData {
dispatch_async(self.diagnosticsQueue, ^{
NSDictionary<NSString *, id> *diagnosticObjects = diagnosticsData.diagnosticObjects;
NSNumber *isDataCollectionDefaultEnabled =
diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey];
if (isDataCollectionDefaultEnabled && ![isDataCollectionDefaultEnabled boolValue]) {
return;
}
// Create the proto.
logs_proto_mobilesdk_ios_ICoreConfiguration icore_config =
logs_proto_mobilesdk_ios_ICoreConfiguration_init_default;
icore_config.using_gdt = 1;
icore_config.has_using_gdt = 1;
// Populate the proto with information.
FIRPopulateProtoWithInfoFromUserInfoParams(&icore_config, diagnosticObjects);
FIRPopulateProtoWithCommonInfoFromApp(&icore_config, diagnosticObjects);
FIRPopulateProtoWithInstalledServices(&icore_config);
FIRPopulateProtoWithNumberOfLinkedFrameworks(&icore_config);
FIRPopulateProtoWithInfoPlistValues(&icore_config);
[self setHeartbeatFlagIfNeededToConfig:&icore_config];
// This log object is capable of converting the proto to bytes.
FIRCoreDiagnosticsLog *log = [[FIRCoreDiagnosticsLog alloc] initWithConfig:icore_config];
// Send the log as a telemetry event.
GDTEvent *event = [self.transport eventForTransport];
event.dataObject = (id<GDTEventDataObject>)log;
[self.transport sendTelemetryEvent:event];
});
}
#pragma mark - Heartbeat
- (void)setHeartbeatFlagIfNeededToConfig:(logs_proto_mobilesdk_ios_ICoreConfiguration *)config {
// Check if need to send a heartbeat.
NSDate *currentDate = [NSDate date];
NSDate *lastCheckin = [self.heartbeatDateStorage date];
if (lastCheckin) {
// Ensure the previous checkin was on a different date in the past.
if ([self isDate:currentDate inSameDayOrBeforeThan:lastCheckin]) {
return;
}
}
// Update heartbeat sent date.
NSError *error;
if (![self.heartbeatDateStorage setDate:currentDate error:&error]) {
GULLogError(kFIRCoreDiagnostics, NO, @"I-COR100004", @"Unable to persist internal state: %@",
error);
}
// Set the flag.
config->sdk_name = logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ICORE;
config->has_sdk_name = 1;
}
- (BOOL)isDate:(NSDate *)date1 inSameDayOrBeforeThan:(NSDate *)date2 {
return [[NSCalendar currentCalendar] isDate:date1 inSameDayAsDate:date2] ||
[date1 compare:date2] == NSOrderedAscending;
}
@end

View File

@ -0,0 +1,47 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/// Stores a date to a specified file.
@interface FIRCoreDiagnosticsDateFileStorage : NSObject
- (instancetype)init NS_UNAVAILABLE;
/**
* Default initializer.
* @param fileURL The URL of the file to store the date. The directory must exist, the file may not
* exist, it will be created if needed.
*/
- (instancetype)initWithFileURL:(NSURL *)fileURL;
/**
* Saves the date to the specified file.
* @return YES on success, NO otherwise.
*/
- (BOOL)setDate:(nullable NSDate *)date error:(NSError **)outError;
/**
* Reads the date to the specified file.
* @return Returns date if exists, otherwise `nil`.
*/
- (nullable NSDate *)date;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,64 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRCDLibrary/FIRCoreDiagnosticsDateFileStorage.h"
@interface FIRCoreDiagnosticsDateFileStorage ()
@property(nonatomic, readonly) NSURL *fileURL;
@end
@implementation FIRCoreDiagnosticsDateFileStorage
- (instancetype)initWithFileURL:(NSURL *)fileURL {
if (fileURL == nil) {
return nil;
}
self = [super init];
if (self) {
_fileURL = fileURL;
}
return self;
}
- (BOOL)setDate:(nullable NSDate *)date error:(NSError **)outError {
NSString *stringToSave = @"";
if (date != nil) {
NSTimeInterval timestamp = [date timeIntervalSinceReferenceDate];
stringToSave = [NSString stringWithFormat:@"%f", timestamp];
}
return [stringToSave writeToURL:self.fileURL
atomically:YES
encoding:NSUTF8StringEncoding
error:outError];
}
- (nullable NSDate *)date {
NSString *timestampString = [NSString stringWithContentsOfURL:self.fileURL
encoding:NSUTF8StringEncoding
error:nil];
if (timestampString.length == 0) {
return nil;
}
NSTimeInterval timestamp = timestampString.doubleValue;
return [NSDate dateWithTimeIntervalSinceReferenceDate:timestamp];
}
@end

View File

@ -0,0 +1,72 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.3.9.2 */
#include "firebasecore.nanopb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
const pb_field_t logs_proto_mobilesdk_ios_ICoreConfiguration_fields[34] = {
PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, logs_proto_mobilesdk_ios_ICoreConfiguration, configuration_type, configuration_type, 0),
PB_FIELD( 2, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, version_name, configuration_type, 0),
PB_FIELD( 3, INT64 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, build_number, version_name, 0),
PB_FIELD( 4, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, build_type, build_number, 0),
PB_FIELD( 5, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, plist_version, build_type, 0),
PB_FIELD( 6, UENUM , REPEATED, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_service_enabled, plist_version, 0),
PB_FIELD( 7, UENUM , REPEATED, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_service_installed, sdk_service_enabled, 0),
PB_FIELD( 9, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, device_model, sdk_service_installed, 0),
PB_FIELD( 10, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, app_id, device_model, 0),
PB_FIELD( 11, INT64 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, project_number, app_id, 0),
PB_FIELD( 12, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, bundle_id, project_number, 0),
PB_FIELD( 13, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, client_id, bundle_id, 0),
PB_FIELD( 14, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, install, client_id, 0),
PB_FIELD( 16, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, pod_name, install, 0),
PB_FIELD( 18, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, icore_version, pod_name, 0),
PB_FIELD( 19, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_version, icore_version, 0),
PB_FIELD( 20, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_name, sdk_version, 0),
PB_FIELD( 21, INT32 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, app_count, sdk_name, 0),
PB_FIELD( 22, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, os_version, app_count, 0),
PB_FIELD( 23, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, itunes_id, os_version, 0),
PB_FIELD( 24, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, min_supported_ios_version, itunes_id, 0),
PB_FIELD( 25, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, use_default_app, min_supported_ios_version, 0),
PB_FIELD( 26, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, deployed_in_app_store, use_default_app, 0),
PB_FIELD( 27, INT32 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, dynamic_framework_count, deployed_in_app_store, 0),
PB_FIELD( 28, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, apple_framework_version, dynamic_framework_count, 0),
PB_FIELD( 29, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, using_zip_file, apple_framework_version, 0),
PB_FIELD( 30, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, deployment_type, using_zip_file, 0),
PB_FIELD( 31, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, platform_info, deployment_type, 0),
PB_FIELD( 32, INT64 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, app_extensions, platform_info, 0),
PB_FIELD( 33, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, swizzling_enabled, app_extensions, 0),
PB_FIELD( 34, INT32 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, log_error_count, swizzling_enabled, 0),
PB_FIELD( 35, INT32 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, log_warning_count, log_error_count, 0),
PB_FIELD( 36, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, using_gdt, log_warning_count, 0),
PB_LAST_FIELD
};
/* @@protoc_insertion_point(eof) */

View File

@ -0,0 +1,224 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Automatically generated nanopb header */
/* Generated by nanopb-0.3.9.2 */
#ifndef PB_LOGS_PROTO_MOBILESDK_IOS_FIREBASECORE_NANOPB_H_INCLUDED
#define PB_LOGS_PROTO_MOBILESDK_IOS_FIREBASECORE_NANOPB_H_INCLUDED
#include <nanopb/pb.h>
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
/* Enum definitions */
typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType {
logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_UNKNOWN_CONFIGURATION_TYPE = 0,
logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE = 1,
logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK = 2
} logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType;
#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_UNKNOWN_CONFIGURATION_TYPE
#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK
#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType)(logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK+1))
typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType {
logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_UNKNOWN_BUILD_TYPE = 0,
logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_INTERNAL = 1,
logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_EAP = 2,
logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD = 3
} logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType;
#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_UNKNOWN_BUILD_TYPE
#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD
#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType)(logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD+1))
typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType {
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE = 0,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ICORE = 1,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ADMOB = 2,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_APP_INVITE = 3,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SIGN_IN = 5,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_GCM = 6,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MAPS = 7,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SCION = 8,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ANALYTICS = 9,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_APP_INDEXING = 10,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_CONFIG = 11,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DURABLE_DEEP_LINKS = 12,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_CRASH = 13,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH = 14,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DATABASE = 15,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_STORAGE = 16,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MESSAGING = 17,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MEASUREMENT = 18,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_REMOTE_CONFIG = 19,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DYNAMIC_LINKS = 20,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_INVITES = 21,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH_UI = 22,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FIRESTORE = 23,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_PERFORMANCE = 24,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_FACE = 26,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_BARCODE = 27,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_TEXT = 28,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_LABEL = 29,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_MODEL_INTERPRETER = 30,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_IN_APP_MESSAGING = 31,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FUNCTIONS = 32,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_NATURAL_LANGUAGE = 33,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_AUTOML = 34,
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION = 35
} logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType;
#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE
#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION
#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType)(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION+1))
typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName {
logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_UNKNOWN_POD_NAME = 0,
logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_GOOGLE = 1,
logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE = 2
} logs_proto_mobilesdk_ios_ICoreConfiguration_PodName;
#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_UNKNOWN_POD_NAME
#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE
#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_PodName)(logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE+1))
typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType {
logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_UNKNOWN = 0,
logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_COCOAPODS = 1,
logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ZIP_FILE = 2,
logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_CARTHAGE = 3,
logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM = 4
} logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType;
#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_UNKNOWN
#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM
#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType)(logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM+1))
/* Struct definitions */
typedef struct _logs_proto_mobilesdk_ios_ICoreConfiguration {
bool has_configuration_type;
logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType configuration_type;
pb_bytes_array_t *version_name;
bool has_build_number;
int64_t build_number;
bool has_build_type;
logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType build_type;
pb_bytes_array_t *plist_version;
pb_size_t sdk_service_enabled_count;
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType *sdk_service_enabled;
pb_size_t sdk_service_installed_count;
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType *sdk_service_installed;
pb_bytes_array_t *device_model;
pb_bytes_array_t *app_id;
bool has_project_number;
int64_t project_number;
pb_bytes_array_t *bundle_id;
pb_bytes_array_t *client_id;
pb_bytes_array_t *install;
bool has_pod_name;
logs_proto_mobilesdk_ios_ICoreConfiguration_PodName pod_name;
pb_bytes_array_t *icore_version;
pb_bytes_array_t *sdk_version;
bool has_sdk_name;
logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType sdk_name;
bool has_app_count;
int32_t app_count;
pb_bytes_array_t *os_version;
pb_bytes_array_t *itunes_id;
pb_bytes_array_t *min_supported_ios_version;
bool has_use_default_app;
bool use_default_app;
bool has_deployed_in_app_store;
bool deployed_in_app_store;
bool has_dynamic_framework_count;
int32_t dynamic_framework_count;
pb_bytes_array_t *apple_framework_version;
bool has_using_zip_file;
bool using_zip_file;
bool has_deployment_type;
logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType deployment_type;
pb_bytes_array_t *platform_info;
bool has_app_extensions;
int64_t app_extensions;
bool has_swizzling_enabled;
bool swizzling_enabled;
bool has_log_error_count;
int32_t log_error_count;
bool has_log_warning_count;
int32_t log_warning_count;
bool has_using_gdt;
bool using_gdt;
/* @@protoc_insertion_point(struct:logs_proto_mobilesdk_ios_ICoreConfiguration) */
} logs_proto_mobilesdk_ios_ICoreConfiguration;
/* Default values for struct fields */
/* Initializer values for message structs */
#define logs_proto_mobilesdk_ios_ICoreConfiguration_init_default {false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_MIN, NULL, 0, NULL, 0, NULL, NULL, NULL, false, 0, NULL, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN, false, 0, NULL, NULL, NULL, false, 0, false, 0, false, 0, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN, NULL, false, 0, false, 0, false, 0, false, 0, false, 0}
#define logs_proto_mobilesdk_ios_ICoreConfiguration_init_zero {false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_MIN, NULL, 0, NULL, 0, NULL, NULL, NULL, false, 0, NULL, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN, false, 0, NULL, NULL, NULL, false, 0, false, 0, false, 0, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN, NULL, false, 0, false, 0, false, 0, false, 0, false, 0}
/* Field tags (for use in manual encoding/decoding) */
#define logs_proto_mobilesdk_ios_ICoreConfiguration_pod_name_tag 16
#define logs_proto_mobilesdk_ios_ICoreConfiguration_configuration_type_tag 1
#define logs_proto_mobilesdk_ios_ICoreConfiguration_version_name_tag 2
#define logs_proto_mobilesdk_ios_ICoreConfiguration_icore_version_tag 18
#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_version_tag 19
#define logs_proto_mobilesdk_ios_ICoreConfiguration_build_number_tag 3
#define logs_proto_mobilesdk_ios_ICoreConfiguration_build_type_tag 4
#define logs_proto_mobilesdk_ios_ICoreConfiguration_plist_version_tag 5
#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_service_enabled_tag 6
#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_service_installed_tag 7
#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_name_tag 20
#define logs_proto_mobilesdk_ios_ICoreConfiguration_device_model_tag 9
#define logs_proto_mobilesdk_ios_ICoreConfiguration_os_version_tag 22
#define logs_proto_mobilesdk_ios_ICoreConfiguration_app_id_tag 10
#define logs_proto_mobilesdk_ios_ICoreConfiguration_project_number_tag 11
#define logs_proto_mobilesdk_ios_ICoreConfiguration_bundle_id_tag 12
#define logs_proto_mobilesdk_ios_ICoreConfiguration_client_id_tag 13
#define logs_proto_mobilesdk_ios_ICoreConfiguration_itunes_id_tag 23
#define logs_proto_mobilesdk_ios_ICoreConfiguration_min_supported_ios_version_tag 24
#define logs_proto_mobilesdk_ios_ICoreConfiguration_install_tag 14
#define logs_proto_mobilesdk_ios_ICoreConfiguration_use_default_app_tag 25
#define logs_proto_mobilesdk_ios_ICoreConfiguration_app_count_tag 21
#define logs_proto_mobilesdk_ios_ICoreConfiguration_deployed_in_app_store_tag 26
#define logs_proto_mobilesdk_ios_ICoreConfiguration_dynamic_framework_count_tag 27
#define logs_proto_mobilesdk_ios_ICoreConfiguration_apple_framework_version_tag 28
#define logs_proto_mobilesdk_ios_ICoreConfiguration_using_zip_file_tag 29
#define logs_proto_mobilesdk_ios_ICoreConfiguration_deployment_type_tag 30
#define logs_proto_mobilesdk_ios_ICoreConfiguration_platform_info_tag 31
#define logs_proto_mobilesdk_ios_ICoreConfiguration_app_extensions_tag 32
#define logs_proto_mobilesdk_ios_ICoreConfiguration_swizzling_enabled_tag 33
#define logs_proto_mobilesdk_ios_ICoreConfiguration_log_error_count_tag 34
#define logs_proto_mobilesdk_ios_ICoreConfiguration_log_warning_count_tag 35
#define logs_proto_mobilesdk_ios_ICoreConfiguration_using_gdt_tag 36
/* Struct field encoding specification for nanopb */
extern const pb_field_t logs_proto_mobilesdk_ios_ICoreConfiguration_fields[34];
/* Maximum encoded size of messages (where known) */
/* logs_proto_mobilesdk_ios_ICoreConfiguration_size depends on runtime parameters */
/* Message IDs (where set with "msgid" option) */
#ifdef PB_MSGID
#define FIREBASECORE_MESSAGES \
#endif
/* @@protoc_insertion_point(eof) */
#endif

202
ios/Pods/FirebaseCoreDiagnostics/LICENSE generated Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

223
ios/Pods/FirebaseCoreDiagnostics/README.md generated Normal file
View File

@ -0,0 +1,223 @@
# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk)
This repository contains a subset of the Firebase iOS SDK source. It currently
includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore,
FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging,
FirebaseInAppMessagingDisplay, FirebaseMessaging and FirebaseStorage.
The repository also includes GoogleUtilities source. The
[GoogleUtilities](GoogleUtilities/README.md) pod is
a set of utilities used by Firebase and other Google products.
Firebase is an app development platform with tools to help you build, grow and
monetize your app. More information about Firebase can be found at
[https://firebase.google.com](https://firebase.google.com).
## Installation
See the three subsections for details about three different installation methods.
1. [Standard pod install](README.md#standard-pod-install)
1. [Installing from the GitHub repo](README.md#installing-from-github)
1. [Experimental Carthage](README.md#carthage-ios-only)
### Standard pod install
Go to
[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup).
### Installing from GitHub
For releases starting with 5.0.0, the source for each release is also deployed
to CocoaPods master and available via standard
[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod).
These instructions can be used to access the Firebase repo at other branches,
tags, or commits.
#### Background
See
[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod)
for instructions and options about overriding pod source locations.
#### Accessing Firebase Source Snapshots
All of the official releases are tagged in this repo and available via CocoaPods. To access a local
source snapshot or unreleased branch, use Podfile directives like the following:
To access FirebaseFirestore via a branch:
```
pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master'
pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master'
```
To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do:
```
pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk'
pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk'
```
### Carthage (iOS only)
Instructions for the experimental Carthage distribution are at
[Carthage](Carthage.md).
### Rome
Instructions for installing binary frameworks via
[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md).
## Development
To develop Firebase software in this repository, ensure that you have at least
the following software:
* Xcode 10.1 (or later)
* CocoaPods 1.7.2 (or later)
For the pod that you want to develop:
`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open`
Firestore and Functions have self contained Xcode projects. See
[Firestore/README.md](Firestore/README.md) and
[Functions/README.md](Functions/README.md).
### Adding a New Firebase Pod
See [AddNewPod.md](AddNewPod.md).
### Code Formatting
To ensure that the code is formatted consistently, run the script
[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh)
before creating a PR.
Travis will verify that any code changes are done in a style compliant way. Install
`clang-format` and `swiftformat`.
These commands will get the right versions:
```
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/773cb75d360b58f32048f5964038d09825a507c8/Formula/clang-format.rb
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/3dfea1004e0736754bbf49673cca8aaed8a94089/Formula/swiftformat.rb
```
Note: if you already have a newer version of these installed you may need to
`brew switch` to this version.
### Running Unit Tests
Select a scheme and press Command-u to build a component and run its unit tests.
#### Viewing Code Coverage
First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`.
After running the `AllUnitTests_iOS` scheme in Xcode, execute
`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output`
at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results.
### Running Sample Apps
In order to run the sample apps and integration tests, you'll need valid
`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist
files without real values, but can be replaced with real plist files. To get your own
`GoogleService-Info.plist` files:
1. Go to the [Firebase Console](https://console.firebase.google.com/)
2. Create a new Firebase project, if you don't already have one
3. For each sample app you want to test, create a new Firebase app with the sample app's bundle
identifier (e.g. `com.google.Database-Example`)
4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file
(e.g. in [Example/Database/App/](Example/Database/App/));
Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require
special Apple capabilities, and you will have to change the sample app to use a unique bundle
identifier that you can control in your own Apple Developer account.
## Specific Component Instructions
See the sections below for any special instructions for those components.
### Firebase Auth
If you're doing specific Firebase Auth development, see
[the Auth Sample README](Example/Auth/README.md) for instructions about
building and running the FirebaseAuth pod along with various samples and tests.
### Firebase Database
To run the Database Integration tests, make your database authentication rules
[public](https://firebase.google.com/docs/database/security/quickstart).
### Firebase Storage
To run the Storage Integration tests, follow the instructions in
[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m).
#### Push Notifications
Push notifications can only be delivered to specially provisioned App IDs in the developer portal.
In order to actually test receiving push notifications, you will need to:
1. Change the bundle identifier of the sample app to something you own in your Apple Developer
account, and enable that App ID for push notifications.
2. You'll also need to
[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs)
at **Project Settings > Cloud Messaging > [Your Firebase App]**.
3. Ensure your iOS device is added to your Apple Developer portal as a test device.
#### iOS Simulator
The iOS Simulator cannot register for remote notifications, and will not receive push notifications.
In order to receive push notifications, you'll have to follow the steps above and run the app on a
physical device.
## Community Supported Efforts
We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are
very grateful! We'd like to empower as many developers as we can to be able to use Firebase and
participate in the Firebase community.
### macOS and tvOS
Thanks to contributions from the community, FirebaseAuth, FirebaseCore, FirebaseDatabase, FirebaseMessaging,
FirebaseFirestore, FirebaseFunctions and FirebaseStorage now compile, run unit tests, and work on
macOS and tvOS.
For tvOS, checkout the [Sample](Example/tvOSSample).
Keep in mind that macOS and tvOS are not officially supported by Firebase, and this repository is
actively developed primarily for iOS. While we can catch basic unit test issues with Travis, there
may be some changes where the SDK no longer works as expected on macOS or tvOS. If you encounter
this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues).
Note that the Firebase pod is not available for macOS and tvOS.
To install, add a subset of the following to the Podfile:
```
pod 'FirebaseAuth'
pod 'FirebaseCore'
pod 'FirebaseDatabase'
pod 'FirebaseFirestore'
pod 'FirebaseFunctions'
pod 'FirebaseMessaging'
pod 'FirebaseStorage'
```
## Roadmap
See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source
plans and directions.
## Contributing
See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase
iOS SDK.
## License
The contents of this repository is licensed under the
[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
Your use of Firebase is governed by the
[Terms of Service for Firebase Services](https://firebase.google.com/terms/).

View File

@ -0,0 +1,63 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/** If present, is a BOOL wrapped in an NSNumber. */
static NSString *const kFIRCDIsDataCollectionDefaultEnabledKey =
@"FIRCDIsDataCollectionDefaultEnabledKey";
/** If present, is an int32_t wrapped in an NSNumber. */
static NSString *const kFIRCDConfigurationTypeKey = @"FIRCDConfigurationTypeKey";
/** If present, is an NSString. */
static NSString *const kFIRCDSdkNameKey = @"FIRCDSdkNameKey";
/** If present, is an NSString. */
static NSString *const kFIRCDSdkVersionKey = @"FIRCDSdkVersionKey";
/** If present, is an int32_t wrapped in an NSNumber. */
static NSString *const kFIRCDllAppsCountKey = @"FIRCDllAppsCountKey";
/** If present, is an NSString. */
static NSString *const kFIRCDGoogleAppIDKey = @"FIRCDGoogleAppIDKey";
/** If present, is an NSString. */
static NSString *const kFIRCDBundleIDKey = @"FIRCDBundleID";
/** If present, is a BOOL wrapped in an NSNumber. */
static NSString *const kFIRCDUsingOptionsFromDefaultPlistKey =
@"FIRCDUsingOptionsFromDefaultPlistKey";
/** If present, is an NSString. */
static NSString *const kFIRCDLibraryVersionIDKey = @"FIRCDLibraryVersionIDKey";
/** If present, is an NSString. */
static NSString *const kFIRCDFirebaseUserAgentKey = @"FIRCDFirebaseUserAgentKey";
/** Defines the interface of a data object needed to log diagnostics data. */
@protocol FIRCoreDiagnosticsData <NSObject>
@required
/** A dictionary containing data (non-exhaustive) to be logged in diagnostics. */
@property(nonatomic) NSDictionary<NSString *, id> *diagnosticObjects;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,34 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "FIRCoreDiagnosticsData.h"
NS_ASSUME_NONNULL_BEGIN
/** Allows the interoperation of FirebaseCore and FirebaseCoreDiagnostics. */
@protocol FIRCoreDiagnosticsInterop <NSObject>
/** Sends the given diagnostics data.
*
* @param diagnosticsData The diagnostics data object to send.
*/
+ (void)sendDiagnosticsData:(id<FIRCoreDiagnosticsData>)diagnosticsData;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@ -0,0 +1,223 @@
# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk)
This repository contains a subset of the Firebase iOS SDK source. It currently
includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore,
FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging,
FirebaseInAppMessagingDisplay, FirebaseMessaging and FirebaseStorage.
The repository also includes GoogleUtilities source. The
[GoogleUtilities](GoogleUtilities/README.md) pod is
a set of utilities used by Firebase and other Google products.
Firebase is an app development platform with tools to help you build, grow and
monetize your app. More information about Firebase can be found at
[https://firebase.google.com](https://firebase.google.com).
## Installation
See the three subsections for details about three different installation methods.
1. [Standard pod install](README.md#standard-pod-install)
1. [Installing from the GitHub repo](README.md#installing-from-github)
1. [Experimental Carthage](README.md#carthage-ios-only)
### Standard pod install
Go to
[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup).
### Installing from GitHub
For releases starting with 5.0.0, the source for each release is also deployed
to CocoaPods master and available via standard
[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod).
These instructions can be used to access the Firebase repo at other branches,
tags, or commits.
#### Background
See
[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod)
for instructions and options about overriding pod source locations.
#### Accessing Firebase Source Snapshots
All of the official releases are tagged in this repo and available via CocoaPods. To access a local
source snapshot or unreleased branch, use Podfile directives like the following:
To access FirebaseFirestore via a branch:
```
pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master'
pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master'
```
To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do:
```
pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk'
pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk'
```
### Carthage (iOS only)
Instructions for the experimental Carthage distribution are at
[Carthage](Carthage.md).
### Rome
Instructions for installing binary frameworks via
[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md).
## Development
To develop Firebase software in this repository, ensure that you have at least
the following software:
* Xcode 10.1 (or later)
* CocoaPods 1.7.2 (or later)
For the pod that you want to develop:
`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open`
Firestore and Functions have self contained Xcode projects. See
[Firestore/README.md](Firestore/README.md) and
[Functions/README.md](Functions/README.md).
### Adding a New Firebase Pod
See [AddNewPod.md](AddNewPod.md).
### Code Formatting
To ensure that the code is formatted consistently, run the script
[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh)
before creating a PR.
Travis will verify that any code changes are done in a style compliant way. Install
`clang-format` and `swiftformat`.
These commands will get the right versions:
```
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/773cb75d360b58f32048f5964038d09825a507c8/Formula/clang-format.rb
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/3dfea1004e0736754bbf49673cca8aaed8a94089/Formula/swiftformat.rb
```
Note: if you already have a newer version of these installed you may need to
`brew switch` to this version.
### Running Unit Tests
Select a scheme and press Command-u to build a component and run its unit tests.
#### Viewing Code Coverage
First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`.
After running the `AllUnitTests_iOS` scheme in Xcode, execute
`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output`
at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results.
### Running Sample Apps
In order to run the sample apps and integration tests, you'll need valid
`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist
files without real values, but can be replaced with real plist files. To get your own
`GoogleService-Info.plist` files:
1. Go to the [Firebase Console](https://console.firebase.google.com/)
2. Create a new Firebase project, if you don't already have one
3. For each sample app you want to test, create a new Firebase app with the sample app's bundle
identifier (e.g. `com.google.Database-Example`)
4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file
(e.g. in [Example/Database/App/](Example/Database/App/));
Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require
special Apple capabilities, and you will have to change the sample app to use a unique bundle
identifier that you can control in your own Apple Developer account.
## Specific Component Instructions
See the sections below for any special instructions for those components.
### Firebase Auth
If you're doing specific Firebase Auth development, see
[the Auth Sample README](Example/Auth/README.md) for instructions about
building and running the FirebaseAuth pod along with various samples and tests.
### Firebase Database
To run the Database Integration tests, make your database authentication rules
[public](https://firebase.google.com/docs/database/security/quickstart).
### Firebase Storage
To run the Storage Integration tests, follow the instructions in
[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m).
#### Push Notifications
Push notifications can only be delivered to specially provisioned App IDs in the developer portal.
In order to actually test receiving push notifications, you will need to:
1. Change the bundle identifier of the sample app to something you own in your Apple Developer
account, and enable that App ID for push notifications.
2. You'll also need to
[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs)
at **Project Settings > Cloud Messaging > [Your Firebase App]**.
3. Ensure your iOS device is added to your Apple Developer portal as a test device.
#### iOS Simulator
The iOS Simulator cannot register for remote notifications, and will not receive push notifications.
In order to receive push notifications, you'll have to follow the steps above and run the app on a
physical device.
## Community Supported Efforts
We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are
very grateful! We'd like to empower as many developers as we can to be able to use Firebase and
participate in the Firebase community.
### macOS and tvOS
Thanks to contributions from the community, FirebaseAuth, FirebaseCore, FirebaseDatabase, FirebaseMessaging,
FirebaseFirestore, FirebaseFunctions and FirebaseStorage now compile, run unit tests, and work on
macOS and tvOS.
For tvOS, checkout the [Sample](Example/tvOSSample).
Keep in mind that macOS and tvOS are not officially supported by Firebase, and this repository is
actively developed primarily for iOS. While we can catch basic unit test issues with Travis, there
may be some changes where the SDK no longer works as expected on macOS or tvOS. If you encounter
this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues).
Note that the Firebase pod is not available for macOS and tvOS.
To install, add a subset of the following to the Podfile:
```
pod 'FirebaseAuth'
pod 'FirebaseCore'
pod 'FirebaseDatabase'
pod 'FirebaseFirestore'
pod 'FirebaseFunctions'
pod 'FirebaseMessaging'
pod 'FirebaseStorage'
```
## Roadmap
See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source
plans and directions.
## Contributing
See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase
iOS SDK.
## License
The contents of this repository is licensed under the
[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
Your use of Firebase is governed by the
[Terms of Service for Firebase Services](https://firebase.google.com/terms/).

View File

@ -44,6 +44,8 @@ typedef NS_ENUM(NSInteger, FIRInstanceIDMessageCode) {
kFIRInstanceIDMessageCodeInstanceID014 = 3014,
kFIRInstanceIDMessageCodeInstanceID015 = 3015,
kFIRInstanceIDMessageCodeRefetchingTokenForAPNS = 3016,
kFIRInstanceIDMessageCodeInstanceID017 = 3017,
kFIRInstanceIDMessageCodeInstanceID018 = 3018,
// FIRInstanceIDAuthService.m
kFIRInstanceIDMessageCodeAuthService000 = 5000,
kFIRInstanceIDMessageCodeAuthService001 = 5001,

View File

@ -1012,6 +1012,16 @@ static FIRInstanceID *gInstanceID;
FIRInstanceID_WEAKIFY(self);
[self asyncLoadKeyPairWithHandler:^(FIRInstanceIDKeyPair *keyPair, NSError *error) {
FIRInstanceID_STRONGIFY(self);
if (self == nil) {
FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID017,
@"Instance ID shut down during token reset. Aborting");
return;
}
if (self.apnsTokenData == nil) {
FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID018,
@"apnsTokenData was set to nil during token reset. Aborting");
return;
}
NSMutableDictionary *tokenOptions = [@{
kFIRInstanceIDTokenOptionsAPNSKey : self.apnsTokenData,

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
#import "FIRInstanceIDCheckinPreferences.h"
#import <FirebaseInstanceID/FIRInstanceIDCheckinPreferences.h>
@interface FIRInstanceIDCheckinPreferences (Internal)

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
#import "FIRInstanceIDCheckinPreferences.h"
#import <FirebaseInstanceID/FIRInstanceIDCheckinPreferences.h>
/** Checkin refresh interval. **/
FOUNDATION_EXPORT const NSTimeInterval kFIRInstanceIDDefaultCheckinInterval;

View File

@ -16,6 +16,7 @@
#import <Foundation/Foundation.h>
#import <FirebaseInstanceID/FIRInstanceID+Private.h>
#import "FIRInstanceIDUtilities.h"
NS_ASSUME_NONNULL_BEGIN
@ -31,20 +32,6 @@ FOUNDATION_EXPORT NSString *const kFIRInstanceIDDeviceDataVersionKey;
@class FIRInstanceIDCheckinPreferences;
/**
* @related FIRInstanceIDCheckinService
*
* The completion handler invoked once the fetch from Checkin server finishes.
* For successful fetches we returned checkin information by the checkin service
* and `nil` error, else we return the appropriate error object as reported by the
* Checkin Service.
*
* @param checkinPreferences The checkin preferences as fetched from the server.
* @param error The error object which fetching GServices data.
*/
typedef void (^FIRInstanceIDDeviceCheckinCompletion)(
FIRInstanceIDCheckinPreferences *_Nullable checkinPreferences, NSError *_Nullable error);
/**
* Register the device with Checkin Service and get back the `authID`, `secret
* token` etc. for the client. Checkin results are cached in the

View File

@ -14,14 +14,26 @@
* limitations under the License.
*/
#import "FIRInstanceID.h"
#import "FIRInstanceIDCheckinService.h"
#import <FirebaseInstanceID/FIRInstanceID.h>
#import <FirebaseInstanceID/FIRInstanceIDCheckinPreferences.h>
/**
* Internal API used by Firebase SDK teams by calling in reflection or internal teams.
* @related FIRInstanceIDCheckinService
*
* The completion handler invoked once the fetch from Checkin server finishes.
* For successful fetches we returned checkin information by the checkin service
* and `nil` error, else we return the appropriate error object as reported by the
* Checkin Service.
*
* @param checkinPreferences The checkin preferences as fetched from the server.
* @param error The error object which fetching GServices data.
*/
typedef void (^FIRInstanceIDDeviceCheckinCompletion)(
FIRInstanceIDCheckinPreferences *_Nullable checkinPreferences, NSError *_Nullable error);
/**
* Private API used by Firebase SDK teams by calling in reflection or internal teams.
*/
// TODO(chliangGoogle) Rename this to Internal.
@interface FIRInstanceID (Private)
/**

View File

@ -1,8 +1,8 @@
# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk)
This repository contains a subset of the Firebase iOS SDK source. It currently
includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore,
FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging,
includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase,
FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging,
FirebaseInAppMessagingDisplay, FirebaseMessaging and FirebaseStorage.
The repository also includes GoogleUtilities source. The
@ -80,9 +80,8 @@ For the pod that you want to develop:
`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open`
Firestore and Functions have self contained Xcode projects. See
[Firestore/README.md](Firestore/README.md) and
[Functions/README.md](Functions/README.md).
Firestore has a self contained Xcode project. See
[Firestore/README.md](Firestore/README.md).
### Adding a New Firebase Pod
@ -179,7 +178,8 @@ very grateful! We'd like to empower as many developers as we can to be able to
participate in the Firebase community.
### macOS and tvOS
Thanks to contributions from the community, FirebaseAuth, FirebaseCore, FirebaseDatabase, FirebaseMessaging,
Thanks to contributions from the community, FirebaseABTesting, FirebaseAuth, FirebaseCore,
FirebaseDatabase, FirebaseMessaging,
FirebaseFirestore, FirebaseFunctions and FirebaseStorage now compile, run unit tests, and work on
macOS and tvOS.
@ -195,6 +195,7 @@ Note that the Firebase pod is not available for macOS and tvOS.
To install, add a subset of the following to the Podfile:
```
pod 'FirebaseABTesting'
pod 'FirebaseAuth'
pod 'FirebaseCore'
pod 'FirebaseDatabase'

View File

@ -0,0 +1,36 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "GDTLibrary/Public/GDTAssert.h"
GDTAssertionBlock GDTAssertionBlockToRunInstead(void) {
// This class is only compiled in by unit tests, and this should fail quickly in optimized builds.
Class GDTAssertClass = NSClassFromString(@"GDTAssertHelper");
if (__builtin_expect(!!GDTAssertClass, 0)) {
SEL assertionBlockSEL = NSSelectorFromString(@"assertionBlock");
if (assertionBlockSEL) {
IMP assertionBlockIMP = [GDTAssertClass methodForSelector:assertionBlockSEL];
if (assertionBlockIMP) {
GDTAssertionBlock assertionBlock =
((GDTAssertionBlock(*)(id, SEL))assertionBlockIMP)(GDTAssertClass, assertionBlockSEL);
if (assertionBlock) {
return assertionBlock;
}
}
}
}
return NULL;
}

View File

@ -0,0 +1,164 @@
/*
* 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 "GDTLibrary/Public/GDTClock.h"
#import <sys/sysctl.h>
// Using a monotonic clock is necessary because CFAbsoluteTimeGetCurrent(), NSDate, and related all
// are subject to drift. That it to say, multiple consecutive calls do not always result in a
// time that is in the future. Clocks may be adjusted by the user, NTP, or any number of external
// factors. This class attempts to determine the wall-clock time at the time of the event by
// capturing the kernel start and time since boot to determine a wallclock time in UTC.
//
// Timezone offsets at the time of a snapshot are also captured in order to provide local-time
// details. Other classes in this library depend on comparing times at some time in the future to
// a time captured in the past, and this class needs to provide a mechanism to do that.
//
// TL;DR: This class attempts to accomplish two things: 1. Provide accurate event times. 2. Provide
// a monotonic clock mechanism to accurately check if some clock snapshot was before or after
// by using a shared reference point (kernel boot time).
//
// Note: Much of the mach time stuff doesn't work properly in the simulator. So this class can be
// difficult to unit test.
/** Returns the kernel boottime property from sysctl.
*
* Inspired by https://stackoverflow.com/a/40497811
*
* @return The KERN_BOOTTIME property from sysctl, in nanoseconds.
*/
static int64_t KernelBootTimeInNanoseconds() {
// Caching the result is not possible because clock drift would not be accounted for.
struct timeval boottime;
int mib[2] = {CTL_KERN, KERN_BOOTTIME};
size_t size = sizeof(boottime);
int rc = sysctl(mib, 2, &boottime, &size, NULL, 0);
if (rc != 0) {
return 0;
}
return (int64_t)boottime.tv_sec * NSEC_PER_MSEC + (int64_t)boottime.tv_usec;
}
/** Returns value of gettimeofday, in nanoseconds.
*
* Inspired by https://stackoverflow.com/a/40497811
*
* @return The value of gettimeofday, in nanoseconds.
*/
static int64_t UptimeInNanoseconds() {
int64_t before_now;
int64_t after_now;
struct timeval now;
before_now = KernelBootTimeInNanoseconds();
// Addresses a race condition in which the system time has updated, but the boottime has not.
do {
gettimeofday(&now, NULL);
after_now = KernelBootTimeInNanoseconds();
} while (after_now != before_now);
return (int64_t)now.tv_sec * NSEC_PER_MSEC + (int64_t)now.tv_usec - before_now;
}
// TODO: Consider adding a 'trustedTime' property that can be populated by the response from a BE.
@implementation GDTClock
- (instancetype)init {
self = [super init];
if (self) {
_kernelBootTime = KernelBootTimeInNanoseconds();
_uptime = UptimeInNanoseconds();
_timeMillis =
(int64_t)((CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) * NSEC_PER_USEC);
CFTimeZoneRef timeZoneRef = CFTimeZoneCopySystem();
_timezoneOffsetSeconds = CFTimeZoneGetSecondsFromGMT(timeZoneRef, 0);
CFRelease(timeZoneRef);
}
return self;
}
+ (GDTClock *)snapshot {
return [[GDTClock alloc] init];
}
+ (instancetype)clockSnapshotInTheFuture:(uint64_t)millisInTheFuture {
GDTClock *snapshot = [self snapshot];
snapshot->_timeMillis += millisInTheFuture;
return snapshot;
}
- (BOOL)isAfter:(GDTClock *)otherClock {
// These clocks are trivially comparable when they share a kernel boot time.
if (_kernelBootTime == otherClock->_kernelBootTime) {
int64_t timeDiff = (_timeMillis + _timezoneOffsetSeconds) -
(otherClock->_timeMillis + otherClock->_timezoneOffsetSeconds);
return timeDiff > 0;
} else {
int64_t kernelBootTimeDiff = otherClock->_kernelBootTime - _kernelBootTime;
// This isn't a great solution, but essentially, if the other clock's boot time is 'later', NO
// is returned. This can be altered by changing the system time and rebooting.
return kernelBootTimeDiff < 0 ? YES : NO;
}
}
- (NSUInteger)hash {
return [@(_kernelBootTime) hash] ^ [@(_uptime) hash] ^ [@(_timeMillis) hash] ^
[@(_timezoneOffsetSeconds) hash];
}
- (BOOL)isEqual:(id)object {
return [self hash] == [object hash];
}
#pragma mark - NSSecureCoding
/** NSKeyedCoder key for timeMillis property. */
static NSString *const kGDTClockTimeMillisKey = @"GDTClockTimeMillis";
/** NSKeyedCoder key for timezoneOffsetMillis property. */
static NSString *const kGDTClockTimezoneOffsetSeconds = @"GDTClockTimezoneOffsetSeconds";
/** NSKeyedCoder key for _kernelBootTime ivar. */
static NSString *const kGDTClockKernelBootTime = @"GDTClockKernelBootTime";
/** NSKeyedCoder key for _uptime ivar. */
static NSString *const kGDTClockUptime = @"GDTClockUptime";
+ (BOOL)supportsSecureCoding {
return YES;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
// TODO: If the kernelBootTime is more recent, we need to change the kernel boot time and
// uptimeMillis ivars
_timeMillis = [aDecoder decodeInt64ForKey:kGDTClockTimeMillisKey];
_timezoneOffsetSeconds = [aDecoder decodeInt64ForKey:kGDTClockTimezoneOffsetSeconds];
_kernelBootTime = [aDecoder decodeInt64ForKey:kGDTClockKernelBootTime];
_uptime = [aDecoder decodeInt64ForKey:kGDTClockUptime];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeInt64:_timeMillis forKey:kGDTClockTimeMillisKey];
[aCoder encodeInt64:_timezoneOffsetSeconds forKey:kGDTClockTimezoneOffsetSeconds];
[aCoder encodeInt64:_kernelBootTime forKey:kGDTClockKernelBootTime];
[aCoder encodeInt64:_uptime forKey:kGDTClockUptime];
}
@end

View File

@ -0,0 +1,36 @@
/*
* 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 "GDTLibrary/Public/GDTConsoleLogger.h"
/** The console logger prefix. */
static NSString *kGDTConsoleLogger = @"[GoogleDataTransport]";
NSString *GDTMessageCodeEnumToString(GDTMessageCode code) {
return [[NSString alloc] initWithFormat:@"I-GDT%06ld", (long)code];
}
void GDTLog(GDTMessageCode code, NSString *format, ...) {
// Don't log anything in not debug builds.
#ifndef NDEBUG
NSString *logFormat = [NSString
stringWithFormat:@"%@[%@] %@", kGDTConsoleLogger, GDTMessageCodeEnumToString(code), format];
va_list args;
va_start(args, format);
NSLogv(logFormat, args);
va_end(args);
#endif // NDEBUG
}

View File

@ -0,0 +1,64 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <GoogleDataTransport/GDTDataFuture.h>
@implementation GDTDataFuture
- (instancetype)initWithFileURL:(NSURL *)fileURL {
self = [super init];
if (self) {
_fileURL = fileURL;
}
return self;
}
- (BOOL)isEqual:(id)object {
return [self hash] == [object hash];
}
- (NSUInteger)hash {
// In reality, only one of these should be populated.
return [_fileURL hash] ^ [_originalData hash];
}
#pragma mark - NSSecureCoding
/** Coding key for _fileURL ivar. */
static NSString *kGDTDataFutureFileURLKey = @"GDTDataFutureFileURLKey";
/** Coding key for _data ivar. */
static NSString *kGDTDataFutureDataKey = @"GDTDataFutureDataKey";
+ (BOOL)supportsSecureCoding {
return YES;
}
- (void)encodeWithCoder:(nonnull NSCoder *)aCoder {
[aCoder encodeObject:_fileURL forKey:kGDTDataFutureFileURLKey];
[aCoder encodeObject:_originalData forKey:kGDTDataFutureDataKey];
}
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
self = [self init];
if (self) {
_fileURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:kGDTDataFutureFileURLKey];
_originalData = [aDecoder decodeObjectOfClass:[NSData class] forKey:kGDTDataFutureDataKey];
}
return self;
}
@end

View File

@ -0,0 +1,119 @@
/*
* 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 <GoogleDataTransport/GDTEvent.h>
#import <GoogleDataTransport/GDTAssert.h>
#import <GoogleDataTransport/GDTStoredEvent.h>
#import "GDTLibrary/Private/GDTEvent_Private.h"
@implementation GDTEvent
- (instancetype)initWithMappingID:(NSString *)mappingID target:(NSInteger)target {
GDTAssert(mappingID.length > 0, @"Please give a valid mapping ID");
GDTAssert(target > 0, @"A target cannot be negative or 0");
if (mappingID == nil || mappingID.length == 0 || target <= 0) {
return nil;
}
self = [super init];
if (self) {
_mappingID = mappingID;
_target = target;
_qosTier = GDTEventQosDefault;
}
return self;
}
- (instancetype)copy {
GDTEvent *copy = [[GDTEvent alloc] initWithMappingID:_mappingID target:_target];
copy.dataObject = _dataObject;
copy.dataObjectTransportBytes = _dataObjectTransportBytes;
copy.qosTier = _qosTier;
copy.clockSnapshot = _clockSnapshot;
copy.customPrioritizationParams = _customPrioritizationParams;
return copy;
}
- (NSUInteger)hash {
// This loses some precision, but it's probably fine.
NSUInteger mappingIDHash = [_mappingID hash];
NSUInteger timeHash = [_clockSnapshot hash];
NSUInteger dataObjectTransportBytesHash = [_dataObjectTransportBytes hash];
return mappingIDHash ^ _target ^ dataObjectTransportBytesHash ^ _qosTier ^ timeHash;
}
- (BOOL)isEqual:(id)object {
return [self hash] == [object hash];
}
- (void)setDataObject:(id<GDTEventDataObject>)dataObject {
// If you're looking here because of a performance issue in -transportBytes slowing the assignment
// of -dataObject, one way to address this is to add a queue to this class,
// dispatch_(barrier_ if concurrent)async here, and implement the getter with a dispatch_sync.
if (dataObject != _dataObject) {
_dataObject = dataObject;
_dataObjectTransportBytes = [dataObject transportBytes];
}
}
- (GDTStoredEvent *)storedEventWithDataFuture:(GDTDataFuture *)dataFuture {
return [[GDTStoredEvent alloc] initWithEvent:self dataFuture:dataFuture];
}
#pragma mark - NSSecureCoding and NSCoding Protocols
/** NSCoding key for mappingID property. */
static NSString *mappingIDKey = @"_mappingID";
/** NSCoding key for target property. */
static NSString *targetKey = @"_target";
/** NSCoding key for dataObjectTransportBytes property. */
static NSString *dataObjectTransportBytesKey = @"_dataObjectTransportBytesKey";
/** NSCoding key for qosTier property. */
static NSString *qosTierKey = @"_qosTier";
/** NSCoding key for clockSnapshot property. */
static NSString *clockSnapshotKey = @"_clockSnapshot";
+ (BOOL)supportsSecureCoding {
return YES;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
NSString *mappingID = [aDecoder decodeObjectOfClass:[NSObject class] forKey:mappingIDKey];
NSInteger target = [aDecoder decodeIntegerForKey:targetKey];
self = [self initWithMappingID:mappingID target:target];
if (self) {
_dataObjectTransportBytes = [aDecoder decodeObjectOfClass:[NSData class]
forKey:dataObjectTransportBytesKey];
_qosTier = [aDecoder decodeIntegerForKey:qosTierKey];
_clockSnapshot = [aDecoder decodeObjectOfClass:[GDTClock class] forKey:clockSnapshotKey];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:_mappingID forKey:mappingIDKey];
[aCoder encodeInteger:_target forKey:targetKey];
[aCoder encodeObject:_dataObjectTransportBytes forKey:dataObjectTransportBytesKey];
[aCoder encodeInteger:_qosTier forKey:qosTierKey];
[aCoder encodeObject:_clockSnapshot forKey:clockSnapshotKey];
}
@end

View File

@ -0,0 +1,119 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "GDTLibrary/Public/GDTLifecycle.h"
#import <GoogleDataTransport/GDTEvent.h>
#import "GDTLibrary/Private/GDTRegistrar_Private.h"
#import "GDTLibrary/Private/GDTStorage_Private.h"
#import "GDTLibrary/Private/GDTTransformer_Private.h"
#import "GDTLibrary/Private/GDTUploadCoordinator.h"
@implementation GDTLifecycle
+ (void)load {
[self sharedInstance];
}
/** Creates/returns the singleton instance of this class.
*
* @return The singleton instance of this class.
*/
+ (instancetype)sharedInstance {
static GDTLifecycle *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[GDTLifecycle alloc] init];
});
return sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:@selector(applicationDidEnterBackground:)
name:kGDTApplicationDidEnterBackgroundNotification
object:nil];
[notificationCenter addObserver:self
selector:@selector(applicationWillEnterForeground:)
name:kGDTApplicationWillEnterForegroundNotification
object:nil];
NSString *name = kGDTApplicationWillTerminateNotification;
[notificationCenter addObserver:self
selector:@selector(applicationWillTerminate:)
name:name
object:nil];
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)applicationDidEnterBackground:(NSNotification *)notification {
GDTApplication *application = [GDTApplication sharedApplication];
if ([[GDTTransformer sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
[[GDTTransformer sharedInstance] appWillBackground:application];
}
if ([[GDTStorage sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
[[GDTStorage sharedInstance] appWillBackground:application];
}
if ([[GDTUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
[[GDTUploadCoordinator sharedInstance] appWillBackground:application];
}
if ([[GDTRegistrar sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
[[GDTRegistrar sharedInstance] appWillBackground:application];
}
}
- (void)applicationWillEnterForeground:(NSNotification *)notification {
GDTApplication *application = [GDTApplication sharedApplication];
if ([[GDTTransformer sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
[[GDTTransformer sharedInstance] appWillForeground:application];
}
if ([[GDTStorage sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
[[GDTStorage sharedInstance] appWillForeground:application];
}
if ([[GDTUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
[[GDTUploadCoordinator sharedInstance] appWillForeground:application];
}
if ([[GDTRegistrar sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
[[GDTRegistrar sharedInstance] appWillForeground:application];
}
}
- (void)applicationWillTerminate:(NSNotification *)notification {
GDTApplication *application = [GDTApplication sharedApplication];
if ([[GDTTransformer sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
[[GDTTransformer sharedInstance] appWillTerminate:application];
}
if ([[GDTStorage sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
[[GDTStorage sharedInstance] appWillTerminate:application];
}
if ([[GDTUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
[[GDTUploadCoordinator sharedInstance] appWillTerminate:application];
}
if ([[GDTRegistrar sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
[[GDTRegistrar sharedInstance] appWillTerminate:application];
}
}
@end

View File

@ -0,0 +1,175 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <GoogleDataTransport/GDTPlatform.h>
#import <GoogleDataTransport/GDTAssert.h>
const GDTBackgroundIdentifier GDTBackgroundIdentifierInvalid = 0;
NSString *const kGDTApplicationDidEnterBackgroundNotification =
@"GDTApplicationDidEnterBackgroundNotification";
NSString *const kGDTApplicationWillEnterForegroundNotification =
@"GDTApplicationWillEnterForegroundNotification";
NSString *const kGDTApplicationWillTerminateNotification =
@"GDTApplicationWillTerminateNotification";
BOOL GDTReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) {
#if TARGET_OS_IOS
return (flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN;
#else
return NO;
#endif // TARGET_OS_IOS
}
@implementation GDTApplication
+ (void)load {
#if TARGET_OS_IOS || TARGET_OS_TV
// If this asserts, please file a bug at https://github.com/firebase/firebase-ios-sdk/issues.
GDTFatalAssert(GDTBackgroundIdentifierInvalid == UIBackgroundTaskInvalid,
@"GDTBackgroundIdentifierInvalid and UIBackgroundTaskInvalid should be the same.");
#endif
[self sharedApplication];
}
+ (nullable GDTApplication *)sharedApplication {
static GDTApplication *application;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
application = [[GDTApplication alloc] init];
});
return application;
}
- (instancetype)init {
self = [super init];
if (self) {
#if TARGET_OS_IOS || TARGET_OS_TV
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:@selector(iOSApplicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[notificationCenter addObserver:self
selector:@selector(iOSApplicationWillEnterForeground:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
NSString *name = UIApplicationWillTerminateNotification;
[notificationCenter addObserver:self
selector:@selector(iOSApplicationWillTerminate:)
name:name
object:nil];
#if defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13, tvOS 13.0, *)) {
[notificationCenter addObserver:self
selector:@selector(iOSApplicationWillEnterForeground:)
name:UISceneWillEnterForegroundNotification
object:nil];
[notificationCenter addObserver:self
selector:@selector(iOSApplicationDidEnterBackground:)
name:UISceneWillDeactivateNotification
object:nil];
}
#endif // defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
#elif TARGET_OS_OSX
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:@selector(macOSApplicationWillTerminate:)
name:NSApplicationWillTerminateNotification
object:nil];
#endif // TARGET_OS_IOS || TARGET_OS_TV
}
return self;
}
- (GDTBackgroundIdentifier)beginBackgroundTaskWithExpirationHandler:(void (^)(void))handler {
return
[[self sharedApplicationForBackgroundTask] beginBackgroundTaskWithExpirationHandler:handler];
}
- (void)endBackgroundTask:(GDTBackgroundIdentifier)bgID {
if (bgID != GDTBackgroundIdentifierInvalid) {
[[self sharedApplicationForBackgroundTask] endBackgroundTask:bgID];
}
}
#pragma mark - App environment helpers
- (BOOL)isAppExtension {
#if TARGET_OS_IOS || TARGET_OS_TV
BOOL appExtension = [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"];
return appExtension;
#elif TARGET_OS_OSX
return NO;
#endif
}
/** Returns a UIApplication instance if on the appropriate platform.
*
* @return The shared UIApplication if on the appropriate platform.
*/
#if TARGET_OS_IOS || TARGET_OS_TV
- (nullable UIApplication *)sharedApplicationForBackgroundTask {
#else
- (nullable id)sharedApplicationForBackgroundTask {
#endif
if ([self isAppExtension]) {
return nil;
}
id sharedApplication = nil;
Class uiApplicationClass = NSClassFromString(@"UIApplication");
if (uiApplicationClass &&
[uiApplicationClass respondsToSelector:(NSSelectorFromString(@"sharedApplication"))]) {
sharedApplication = [uiApplicationClass sharedApplication];
}
return sharedApplication;
}
#pragma mark - UIApplicationDelegate
#if TARGET_OS_IOS || TARGET_OS_TV
- (void)iOSApplicationDidEnterBackground:(NSNotification *)notif {
NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
[notifCenter postNotificationName:kGDTApplicationDidEnterBackgroundNotification object:nil];
}
- (void)iOSApplicationWillEnterForeground:(NSNotification *)notif {
NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
[notifCenter postNotificationName:kGDTApplicationWillEnterForegroundNotification object:nil];
}
- (void)iOSApplicationWillTerminate:(NSNotification *)notif {
NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
[notifCenter postNotificationName:kGDTApplicationWillTerminateNotification object:nil];
}
#endif // TARGET_OS_IOS || TARGET_OS_TV
#pragma mark - NSApplicationDelegate
#if TARGET_OS_OSX
- (void)macOSApplicationWillTerminate:(NSNotification *)notif {
NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
[notifCenter postNotificationName:kGDTApplicationWillTerminateNotification object:nil];
}
#endif // TARGET_OS_OSX
@end

View File

@ -0,0 +1,110 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "GDTLibrary/Private/GDTReachability.h"
#import "GDTLibrary/Private/GDTReachability_Private.h"
#import <GoogleDataTransport/GDTConsoleLogger.h>
#import <netinet/in.h>
/** Sets the _callbackFlag ivar whenever the network changes.
*
* @param reachability The reachability object calling back.
* @param flags The new flag values.
* @param info Any data that might be passed in by the callback.
*/
static void GDTReachabilityCallback(SCNetworkReachabilityRef reachability,
SCNetworkReachabilityFlags flags,
void *info);
@implementation GDTReachability {
/** The reachability object. */
SCNetworkReachabilityRef _reachabilityRef;
/** The queue on which callbacks and all work will occur. */
dispatch_queue_t _reachabilityQueue;
/** Flags specified by reachability callbacks. */
SCNetworkConnectionFlags _callbackFlags;
}
+ (void)load {
[self sharedInstance];
}
+ (instancetype)sharedInstance {
static GDTReachability *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[GDTReachability alloc] init];
});
return sharedInstance;
}
+ (SCNetworkReachabilityFlags)currentFlags {
__block SCNetworkReachabilityFlags currentFlags;
dispatch_sync([GDTReachability sharedInstance] -> _reachabilityQueue, ^{
GDTReachability *reachability = [GDTReachability sharedInstance];
currentFlags = reachability->_flags ? reachability->_flags : reachability->_callbackFlags;
});
return currentFlags;
}
- (instancetype)init {
self = [super init];
if (self) {
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
_reachabilityQueue = dispatch_queue_create("com.google.GDTReachability", DISPATCH_QUEUE_SERIAL);
_reachabilityRef = SCNetworkReachabilityCreateWithAddress(
kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress);
Boolean success = SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, _reachabilityQueue);
if (!success) {
GDTLogWarning(GDTMCWReachabilityFailed, @"%@", @"The reachability queue wasn't set.");
}
success = SCNetworkReachabilitySetCallback(_reachabilityRef, GDTReachabilityCallback, NULL);
if (!success) {
GDTLogWarning(GDTMCWReachabilityFailed, @"%@", @"The reachability callback wasn't set.");
}
// Get the initial set of flags.
dispatch_async(_reachabilityQueue, ^{
Boolean valid = SCNetworkReachabilityGetFlags(self->_reachabilityRef, &self->_flags);
if (!valid) {
self->_flags = 0;
}
});
}
return self;
}
- (void)setCallbackFlags:(SCNetworkReachabilityFlags)flags {
if (_callbackFlags != flags) {
self->_callbackFlags = flags;
}
}
@end
static void GDTReachabilityCallback(SCNetworkReachabilityRef reachability,
SCNetworkReachabilityFlags flags,
void *info) {
[[GDTReachability sharedInstance] setCallbackFlags:flags];
}

View File

@ -0,0 +1,139 @@
/*
* 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 "GDTLibrary/Public/GDTRegistrar.h"
#import "GDTLibrary/Private/GDTRegistrar_Private.h"
@implementation GDTRegistrar {
/** Backing ivar for targetToUploader property. */
NSMutableDictionary<NSNumber *, id<GDTUploader>> *_targetToUploader;
/** Backing ivar for targetToPrioritizer property. */
NSMutableDictionary<NSNumber *, id<GDTPrioritizer>> *_targetToPrioritizer;
}
+ (instancetype)sharedInstance {
static GDTRegistrar *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[GDTRegistrar alloc] init];
});
return sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
_registrarQueue = dispatch_queue_create("com.google.GDTRegistrar", DISPATCH_QUEUE_CONCURRENT);
_targetToPrioritizer = [[NSMutableDictionary alloc] init];
_targetToUploader = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void)registerUploader:(id<GDTUploader>)backend target:(GDTTarget)target {
__weak GDTRegistrar *weakSelf = self;
dispatch_barrier_async(_registrarQueue, ^{
GDTRegistrar *strongSelf = weakSelf;
if (strongSelf) {
strongSelf->_targetToUploader[@(target)] = backend;
}
});
}
- (void)registerPrioritizer:(id<GDTPrioritizer>)prioritizer target:(GDTTarget)target {
__weak GDTRegistrar *weakSelf = self;
dispatch_barrier_async(_registrarQueue, ^{
GDTRegistrar *strongSelf = weakSelf;
if (strongSelf) {
strongSelf->_targetToPrioritizer[@(target)] = prioritizer;
}
});
}
- (NSMutableDictionary<NSNumber *, id<GDTUploader>> *)targetToUploader {
__block NSMutableDictionary<NSNumber *, id<GDTUploader>> *targetToUploader;
__weak GDTRegistrar *weakSelf = self;
dispatch_sync(_registrarQueue, ^{
GDTRegistrar *strongSelf = weakSelf;
if (strongSelf) {
targetToUploader = strongSelf->_targetToUploader;
}
});
return targetToUploader;
}
- (NSMutableDictionary<NSNumber *, id<GDTPrioritizer>> *)targetToPrioritizer {
__block NSMutableDictionary<NSNumber *, id<GDTPrioritizer>> *targetToPrioritizer;
__weak GDTRegistrar *weakSelf = self;
dispatch_sync(_registrarQueue, ^{
GDTRegistrar *strongSelf = weakSelf;
if (strongSelf) {
targetToPrioritizer = strongSelf->_targetToPrioritizer;
}
});
return targetToPrioritizer;
}
#pragma mark - GDTLifecycleProtocol
- (void)appWillBackground:(nonnull GDTApplication *)app {
dispatch_async(_registrarQueue, ^{
for (id<GDTUploader> uploader in [self->_targetToUploader allValues]) {
if ([uploader respondsToSelector:@selector(appWillBackground:)]) {
[uploader appWillBackground:app];
}
}
for (id<GDTPrioritizer> prioritizer in [self->_targetToPrioritizer allValues]) {
if ([prioritizer respondsToSelector:@selector(appWillBackground:)]) {
[prioritizer appWillBackground:app];
}
}
});
}
- (void)appWillForeground:(nonnull GDTApplication *)app {
dispatch_async(_registrarQueue, ^{
for (id<GDTUploader> uploader in [self->_targetToUploader allValues]) {
if ([uploader respondsToSelector:@selector(appWillForeground:)]) {
[uploader appWillForeground:app];
}
}
for (id<GDTPrioritizer> prioritizer in [self->_targetToPrioritizer allValues]) {
if ([prioritizer respondsToSelector:@selector(appWillForeground:)]) {
[prioritizer appWillForeground:app];
}
}
});
}
- (void)appWillTerminate:(nonnull GDTApplication *)app {
dispatch_sync(_registrarQueue, ^{
for (id<GDTUploader> uploader in [self->_targetToUploader allValues]) {
if ([uploader respondsToSelector:@selector(appWillTerminate:)]) {
[uploader appWillTerminate:app];
}
}
for (id<GDTPrioritizer> prioritizer in [self->_targetToPrioritizer allValues]) {
if ([prioritizer respondsToSelector:@selector(appWillTerminate:)]) {
[prioritizer appWillTerminate:app];
}
}
});
}
@end

View File

@ -0,0 +1,321 @@
/*
* 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 "GDTLibrary/Private/GDTStorage.h"
#import "GDTLibrary/Private/GDTStorage_Private.h"
#import <GoogleDataTransport/GDTAssert.h>
#import <GoogleDataTransport/GDTConsoleLogger.h>
#import <GoogleDataTransport/GDTLifecycle.h>
#import <GoogleDataTransport/GDTPrioritizer.h>
#import <GoogleDataTransport/GDTStoredEvent.h>
#import "GDTLibrary/Private/GDTEvent_Private.h"
#import "GDTLibrary/Private/GDTRegistrar_Private.h"
#import "GDTLibrary/Private/GDTUploadCoordinator.h"
/** Creates and/or returns a singleton NSString that is the shared storage path.
*
* @return The SDK event storage path.
*/
static NSString *GDTStoragePath() {
static NSString *storagePath;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString *cachePath =
NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
storagePath = [NSString stringWithFormat:@"%@/google-sdks-events", cachePath];
});
return storagePath;
}
@implementation GDTStorage
+ (NSString *)archivePath {
static NSString *archivePath;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
archivePath = [GDTStoragePath() stringByAppendingPathComponent:@"GDTStorageArchive"];
});
return archivePath;
}
+ (instancetype)sharedInstance {
static GDTStorage *sharedStorage;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedStorage = [[GDTStorage alloc] init];
});
return sharedStorage;
}
- (instancetype)init {
self = [super init];
if (self) {
_storageQueue = dispatch_queue_create("com.google.GDTStorage", DISPATCH_QUEUE_SERIAL);
_targetToEventSet = [[NSMutableDictionary alloc] init];
_storedEvents = [[NSMutableOrderedSet alloc] init];
_uploadCoordinator = [GDTUploadCoordinator sharedInstance];
}
return self;
}
- (void)storeEvent:(GDTEvent *)event {
if (event == nil) {
return;
}
[self createEventDirectoryIfNotExists];
__block GDTBackgroundIdentifier bgID = GDTBackgroundIdentifierInvalid;
if (_runningInBackground) {
bgID = [[GDTApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
if (bgID != GDTBackgroundIdentifierInvalid) {
[[GDTApplication sharedApplication] endBackgroundTask:bgID];
bgID = GDTBackgroundIdentifierInvalid;
}
}];
}
dispatch_async(_storageQueue, ^{
// Check that a backend implementation is available for this target.
NSInteger target = event.target;
// Check that a prioritizer is available for this target.
id<GDTPrioritizer> prioritizer = [GDTRegistrar sharedInstance].targetToPrioritizer[@(target)];
GDTAssert(prioritizer, @"There's no prioritizer registered for the given target.");
// Write the transport bytes to disk, get a filename.
GDTAssert(event.dataObjectTransportBytes, @"The event should have been serialized to bytes");
NSURL *eventFile = [self saveEventBytesToDisk:event.dataObjectTransportBytes
eventHash:event.hash];
GDTDataFuture *dataFuture = [[GDTDataFuture alloc] initWithFileURL:eventFile];
GDTStoredEvent *storedEvent = [event storedEventWithDataFuture:dataFuture];
// Add event to tracking collections.
[self addEventToTrackingCollections:storedEvent];
// Have the prioritizer prioritize the event.
[prioritizer prioritizeEvent:storedEvent];
// Check the QoS, if it's high priority, notify the target that it has a high priority event.
if (event.qosTier == GDTEventQoSFast) {
[self.uploadCoordinator forceUploadForTarget:target];
}
// Write state to disk.
if (self->_runningInBackground) {
if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self
requiringSecureCoding:YES
error:nil];
[data writeToFile:[GDTStorage archivePath] atomically:YES];
} else {
#if !defined(TARGET_OS_MACCATALYST)
[NSKeyedArchiver archiveRootObject:self toFile:[GDTStorage archivePath]];
#endif
}
}
// If running in the background, save state to disk and end the associated background task.
if (bgID != GDTBackgroundIdentifierInvalid) {
[[GDTApplication sharedApplication] endBackgroundTask:bgID];
bgID = GDTBackgroundIdentifierInvalid;
}
});
}
- (void)removeEvents:(NSSet<GDTStoredEvent *> *)events {
NSSet<GDTStoredEvent *> *eventsToRemove = [events copy];
dispatch_async(_storageQueue, ^{
for (GDTStoredEvent *event in eventsToRemove) {
// Remove from disk, first and foremost.
NSError *error;
if (event.dataFuture.fileURL) {
NSURL *fileURL = event.dataFuture.fileURL;
[[NSFileManager defaultManager] removeItemAtURL:fileURL error:&error];
GDTAssert(error == nil, @"There was an error removing an event file: %@", error);
}
// Remove from the tracking collections.
[self.storedEvents removeObject:event];
[self.targetToEventSet[event.target] removeObject:event];
}
});
}
#pragma mark - Private helper methods
/** Creates the storage directory if it does not exist. */
- (void)createEventDirectoryIfNotExists {
NSError *error;
BOOL result = [[NSFileManager defaultManager] createDirectoryAtPath:GDTStoragePath()
withIntermediateDirectories:YES
attributes:0
error:&error];
if (!result || error) {
GDTLogError(GDTMCEDirectoryCreationError, @"Error creating the directory: %@", error);
}
}
/** Saves the event's dataObjectTransportBytes to a file using NSData mechanisms.
*
* @note This method should only be called from a method within a block on _storageQueue to maintain
* thread safety.
*
* @param transportBytes The transport bytes of the event.
* @param eventHash The hash value of the event.
* @return The filename
*/
- (NSURL *)saveEventBytesToDisk:(NSData *)transportBytes eventHash:(NSUInteger)eventHash {
NSString *storagePath = GDTStoragePath();
NSString *event = [NSString stringWithFormat:@"event-%lu", (unsigned long)eventHash];
NSURL *eventFilePath = [NSURL fileURLWithPath:[storagePath stringByAppendingPathComponent:event]];
GDTAssert(![[NSFileManager defaultManager] fileExistsAtPath:eventFilePath.path],
@"An event shouldn't already exist at this path: %@", eventFilePath.path);
BOOL writingSuccess = [transportBytes writeToURL:eventFilePath atomically:YES];
if (!writingSuccess) {
GDTLogError(GDTMCEFileWriteError, @"An event file could not be written: %@", eventFilePath);
}
return eventFilePath;
}
/** Adds the event to internal tracking collections.
*
* @note This method should only be called from a method within a block on _storageQueue to maintain
* thread safety.
*
* @param event The event to track.
*/
- (void)addEventToTrackingCollections:(GDTStoredEvent *)event {
[_storedEvents addObject:event];
NSMutableSet<GDTStoredEvent *> *events = self.targetToEventSet[event.target];
events = events ? events : [[NSMutableSet alloc] init];
[events addObject:event];
_targetToEventSet[event.target] = events;
}
#pragma mark - GDTLifecycleProtocol
- (void)appWillForeground:(GDTApplication *)app {
if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
NSData *data = [NSData dataWithContentsOfFile:[GDTStorage archivePath]];
[NSKeyedUnarchiver unarchivedObjectOfClass:[GDTStorage class] fromData:data error:nil];
} else {
#if !defined(TARGET_OS_MACCATALYST)
[NSKeyedUnarchiver unarchiveObjectWithFile:[GDTStorage archivePath]];
#endif
}
}
- (void)appWillBackground:(GDTApplication *)app {
self->_runningInBackground = YES;
dispatch_async(_storageQueue, ^{
if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self
requiringSecureCoding:YES
error:nil];
[data writeToFile:[GDTStorage archivePath] atomically:YES];
} else {
#if !defined(TARGET_OS_MACCATALYST)
[NSKeyedArchiver archiveRootObject:self toFile:[GDTStorage archivePath]];
#endif
}
});
// Create an immediate background task to run until the end of the current queue of work.
__block GDTBackgroundIdentifier bgID = [app beginBackgroundTaskWithExpirationHandler:^{
if (bgID != GDTBackgroundIdentifierInvalid) {
[app endBackgroundTask:bgID];
bgID = GDTBackgroundIdentifierInvalid;
}
}];
dispatch_async(_storageQueue, ^{
if (bgID != GDTBackgroundIdentifierInvalid) {
[app endBackgroundTask:bgID];
bgID = GDTBackgroundIdentifierInvalid;
}
});
}
- (void)appWillTerminate:(GDTApplication *)application {
if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self
requiringSecureCoding:YES
error:nil];
[data writeToFile:[GDTStorage archivePath] atomically:YES];
} else {
#if !defined(TARGET_OS_MACCATALYST)
[NSKeyedArchiver archiveRootObject:self toFile:[GDTStorage archivePath]];
#endif
}
}
#pragma mark - NSSecureCoding
/** The NSKeyedCoder key for the storedEvents property. */
static NSString *const kGDTStorageStoredEventsKey = @"GDTStorageStoredEventsKey";
/** The NSKeyedCoder key for the targetToEventSet property. */
static NSString *const kGDTStorageTargetToEventSetKey = @"GDTStorageTargetToEventSetKey";
/** The NSKeyedCoder key for the uploadCoordinator property. */
static NSString *const kGDTStorageUploadCoordinatorKey = @"GDTStorageUploadCoordinatorKey";
+ (BOOL)supportsSecureCoding {
return YES;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
// Create the singleton and populate its ivars.
GDTStorage *sharedInstance = [self.class sharedInstance];
dispatch_sync(sharedInstance.storageQueue, ^{
NSSet *classes =
[NSSet setWithObjects:[NSMutableOrderedSet class], [GDTStoredEvent class], nil];
sharedInstance->_storedEvents = [aDecoder decodeObjectOfClasses:classes
forKey:kGDTStorageStoredEventsKey];
classes = [NSSet setWithObjects:[NSMutableDictionary class], [NSMutableSet class],
[GDTStoredEvent class], nil];
sharedInstance->_targetToEventSet =
[aDecoder decodeObjectOfClasses:classes forKey:kGDTStorageTargetToEventSetKey];
sharedInstance->_uploadCoordinator =
[aDecoder decodeObjectOfClass:[GDTUploadCoordinator class]
forKey:kGDTStorageUploadCoordinatorKey];
});
return sharedInstance;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
GDTStorage *sharedInstance = [self.class sharedInstance];
NSMutableOrderedSet<GDTStoredEvent *> *storedEvents = sharedInstance->_storedEvents;
if (storedEvents) {
[aCoder encodeObject:storedEvents forKey:kGDTStorageStoredEventsKey];
}
NSMutableDictionary<NSNumber *, NSMutableSet<GDTStoredEvent *> *> *targetToEventSet =
sharedInstance->_targetToEventSet;
if (targetToEventSet) {
[aCoder encodeObject:targetToEventSet forKey:kGDTStorageTargetToEventSetKey];
}
GDTUploadCoordinator *uploadCoordinator = sharedInstance->_uploadCoordinator;
if (uploadCoordinator) {
[aCoder encodeObject:uploadCoordinator forKey:kGDTStorageUploadCoordinatorKey];
}
}
@end

View File

@ -0,0 +1,94 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <GoogleDataTransport/GDTStoredEvent.h>
#import <GoogleDataTransport/GDTClock.h>
#import "GDTLibrary/Private/GDTStorage_Private.h"
@implementation GDTStoredEvent
- (instancetype)initWithEvent:(GDTEvent *)event dataFuture:(nonnull GDTDataFuture *)dataFuture {
self = [super init];
if (self) {
_dataFuture = dataFuture;
_mappingID = event.mappingID;
_target = @(event.target);
_qosTier = event.qosTier;
_clockSnapshot = event.clockSnapshot;
_customPrioritizationParams = event.customPrioritizationParams;
}
return self;
}
#pragma mark - NSSecureCoding
/** Coding key for the dataFuture ivar. */
static NSString *kDataFutureKey = @"GDTStoredEventDataFutureKey";
/** Coding key for mappingID ivar. */
static NSString *kMappingIDKey = @"GDTStoredEventMappingIDKey";
/** Coding key for target ivar. */
static NSString *kTargetKey = @"GDTStoredEventTargetKey";
/** Coding key for qosTier ivar. */
static NSString *kQosTierKey = @"GDTStoredEventQosTierKey";
/** Coding key for clockSnapshot ivar. */
static NSString *kClockSnapshotKey = @"GDTStoredEventClockSnapshotKey";
/** Coding key for customPrioritizationParams ivar. */
static NSString *kCustomPrioritizationParamsKey = @"GDTStoredEventcustomPrioritizationParamsKey";
+ (BOOL)supportsSecureCoding {
return YES;
}
- (void)encodeWithCoder:(nonnull NSCoder *)aCoder {
[aCoder encodeObject:_dataFuture forKey:kDataFutureKey];
[aCoder encodeObject:_mappingID forKey:kMappingIDKey];
[aCoder encodeObject:_target forKey:kTargetKey];
[aCoder encodeObject:@(_qosTier) forKey:kQosTierKey];
[aCoder encodeObject:_clockSnapshot forKey:kClockSnapshotKey];
[aCoder encodeObject:_customPrioritizationParams forKey:kCustomPrioritizationParamsKey];
}
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
self = [self init];
if (self) {
_dataFuture = [aDecoder decodeObjectOfClass:[GDTDataFuture class] forKey:kDataFutureKey];
_mappingID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kMappingIDKey];
_target = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:kTargetKey];
NSNumber *qosTier = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:kQosTierKey];
_qosTier = [qosTier intValue];
_clockSnapshot = [aDecoder decodeObjectOfClass:[GDTClock class] forKey:kClockSnapshotKey];
_customPrioritizationParams = [aDecoder decodeObjectOfClass:[NSDictionary class]
forKey:kCustomPrioritizationParamsKey];
}
return self;
}
- (BOOL)isEqual:(GDTStoredEvent *)other {
return [self hash] == [other hash];
}
- (NSUInteger)hash {
return [_dataFuture hash] ^ [_mappingID hash] ^ [_target hash] ^ [_clockSnapshot hash] ^ _qosTier;
}
@end

View File

@ -0,0 +1,112 @@
/*
* 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 "GDTLibrary/Private/GDTTransformer.h"
#import "GDTLibrary/Private/GDTTransformer_Private.h"
#import <GoogleDataTransport/GDTAssert.h>
#import <GoogleDataTransport/GDTConsoleLogger.h>
#import <GoogleDataTransport/GDTEventTransformer.h>
#import <GoogleDataTransport/GDTLifecycle.h>
#import "GDTLibrary/Private/GDTStorage.h"
@implementation GDTTransformer
+ (instancetype)sharedInstance {
static GDTTransformer *eventTransformer;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
eventTransformer = [[self alloc] init];
});
return eventTransformer;
}
- (instancetype)init {
self = [super init];
if (self) {
_eventWritingQueue = dispatch_queue_create("com.google.GDTTransformer", DISPATCH_QUEUE_SERIAL);
_storageInstance = [GDTStorage sharedInstance];
}
return self;
}
- (void)transformEvent:(GDTEvent *)event
withTransformers:(NSArray<id<GDTEventTransformer>> *)transformers {
GDTAssert(event, @"You can't write a nil event");
__block GDTBackgroundIdentifier bgID = GDTBackgroundIdentifierInvalid;
if (_runningInBackground) {
bgID = [[GDTApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
if (bgID != GDTBackgroundIdentifierInvalid) {
[[GDTApplication sharedApplication] endBackgroundTask:bgID];
bgID = GDTBackgroundIdentifierInvalid;
}
}];
}
dispatch_async(_eventWritingQueue, ^{
GDTEvent *transformedEvent = event;
for (id<GDTEventTransformer> transformer in transformers) {
if ([transformer respondsToSelector:@selector(transform:)]) {
transformedEvent = [transformer transform:transformedEvent];
if (!transformedEvent) {
return;
}
} else {
GDTLogError(GDTMCETransformerDoesntImplementTransform,
@"Transformer doesn't implement transform: %@", transformer);
return;
}
}
[self.storageInstance storeEvent:transformedEvent];
if (self->_runningInBackground) {
[[GDTApplication sharedApplication] endBackgroundTask:bgID];
bgID = GDTBackgroundIdentifierInvalid;
}
});
}
#pragma mark - GDTLifecycleProtocol
- (void)appWillForeground:(GDTApplication *)app {
dispatch_async(_eventWritingQueue, ^{
self->_runningInBackground = NO;
});
}
- (void)appWillBackground:(GDTApplication *)app {
// Create an immediate background task to run until the end of the current queue of work.
__block GDTBackgroundIdentifier bgID = [app beginBackgroundTaskWithExpirationHandler:^{
if (bgID != GDTBackgroundIdentifierInvalid) {
[app endBackgroundTask:bgID];
bgID = GDTBackgroundIdentifierInvalid;
}
}];
dispatch_async(_eventWritingQueue, ^{
if (bgID != GDTBackgroundIdentifierInvalid) {
[app endBackgroundTask:bgID];
bgID = GDTBackgroundIdentifierInvalid;
}
});
}
- (void)appWillTerminate:(GDTApplication *)application {
// Flush the queue immediately.
dispatch_sync(_eventWritingQueue, ^{
});
}
@end

View File

@ -0,0 +1,68 @@
/*
* 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 <GoogleDataTransport/GDTTransport.h>
#import "GDTLibrary/Private/GDTTransport_Private.h"
#import <GoogleDataTransport/GDTAssert.h>
#import <GoogleDataTransport/GDTClock.h>
#import <GoogleDataTransport/GDTEvent.h>
#import "GDTLibrary/Private/GDTTransformer.h"
@implementation GDTTransport
- (instancetype)initWithMappingID:(NSString *)mappingID
transformers:(nullable NSArray<id<GDTEventTransformer>> *)transformers
target:(NSInteger)target {
GDTAssert(mappingID.length > 0, @"A mapping ID cannot be nil or empty");
GDTAssert(target > 0, @"A target cannot be negative or 0");
if (mappingID == nil || mappingID.length == 0 || target <= 0) {
return nil;
}
self = [super init];
if (self) {
_mappingID = mappingID;
_transformers = transformers;
_target = target;
_transformerInstance = [GDTTransformer sharedInstance];
}
return self;
}
- (void)sendTelemetryEvent:(GDTEvent *)event {
// TODO: Determine if sending an event before registration is allowed.
GDTAssert(event, @"You can't send a nil event");
GDTEvent *copiedEvent = [event copy];
copiedEvent.qosTier = GDTEventQoSTelemetry;
copiedEvent.clockSnapshot = [GDTClock snapshot];
[self.transformerInstance transformEvent:copiedEvent withTransformers:_transformers];
}
- (void)sendDataEvent:(GDTEvent *)event {
// TODO: Determine if sending an event before registration is allowed.
GDTAssert(event, @"You can't send a nil event");
GDTAssert(event.qosTier != GDTEventQoSTelemetry, @"Use -sendTelemetryEvent, please.");
GDTEvent *copiedEvent = [event copy];
copiedEvent.clockSnapshot = [GDTClock snapshot];
[self.transformerInstance transformEvent:copiedEvent withTransformers:_transformers];
}
- (GDTEvent *)eventForTransport {
return [[GDTEvent alloc] initWithMappingID:_mappingID target:_target];
}
@end

View File

@ -0,0 +1,274 @@
/*
* 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 "GDTLibrary/Private/GDTUploadCoordinator.h"
#import <GoogleDataTransport/GDTAssert.h>
#import <GoogleDataTransport/GDTClock.h>
#import <GoogleDataTransport/GDTConsoleLogger.h>
#import "GDTLibrary/Private/GDTReachability.h"
#import "GDTLibrary/Private/GDTRegistrar_Private.h"
#import "GDTLibrary/Private/GDTStorage.h"
@implementation GDTUploadCoordinator
+ (instancetype)sharedInstance {
static GDTUploadCoordinator *sharedUploader;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedUploader = [[GDTUploadCoordinator alloc] init];
[sharedUploader startTimer];
});
return sharedUploader;
}
- (instancetype)init {
self = [super init];
if (self) {
_coordinationQueue =
dispatch_queue_create("com.google.GDTUploadCoordinator", DISPATCH_QUEUE_SERIAL);
_registrar = [GDTRegistrar sharedInstance];
_timerInterval = 30 * NSEC_PER_SEC;
_timerLeeway = 5 * NSEC_PER_SEC;
_targetToInFlightPackages = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void)forceUploadForTarget:(GDTTarget)target {
dispatch_async(_coordinationQueue, ^{
GDTUploadConditions conditions = [self uploadConditions];
conditions |= GDTUploadConditionHighPriority;
[self uploadTargets:@[ @(target) ] conditions:conditions];
});
}
#pragma mark - Property overrides
// GDTStorage and GDTUploadCoordinator +sharedInstance methods call each other, so this breaks
// the loop.
- (GDTStorage *)storage {
if (!_storage) {
_storage = [GDTStorage sharedInstance];
}
return _storage;
}
#pragma mark - Private helper methods
/** Starts a timer that checks whether or not events can be uploaded at regular intervals. It will
* check the next-upload clocks of all targets to determine if an upload attempt can be made.
*/
- (void)startTimer {
dispatch_sync(_coordinationQueue, ^{
self->_timer =
dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self->_coordinationQueue);
dispatch_source_set_timer(self->_timer, DISPATCH_TIME_NOW, self->_timerInterval,
self->_timerLeeway);
dispatch_source_set_event_handler(self->_timer, ^{
if (!self->_runningInBackground) {
GDTUploadConditions conditions = [self uploadConditions];
[self uploadTargets:[self.registrar.targetToUploader allKeys] conditions:conditions];
}
});
dispatch_resume(self->_timer);
});
}
/** Stops the currently running timer. */
- (void)stopTimer {
if (_timer) {
dispatch_source_cancel(_timer);
}
}
/** Triggers the uploader implementations for the given targets to upload.
*
* @param targets An array of targets to trigger.
* @param conditions The set of upload conditions.
*/
- (void)uploadTargets:(NSArray<NSNumber *> *)targets conditions:(GDTUploadConditions)conditions {
dispatch_async(_coordinationQueue, ^{
if ((conditions & GDTUploadConditionNoNetwork) == GDTUploadConditionNoNetwork) {
return;
}
for (NSNumber *target in targets) {
// Don't trigger uploads for targets that have an in-flight package already.
if (self->_targetToInFlightPackages[target]) {
continue;
}
// Ask the uploader if they can upload and do so, if it can.
id<GDTUploader> uploader = self.registrar.targetToUploader[target];
if ([uploader readyToUploadWithConditions:conditions]) {
id<GDTPrioritizer> prioritizer = self.registrar.targetToPrioritizer[target];
GDTUploadPackage *package = [prioritizer uploadPackageWithConditions:conditions];
if (package.events.count) {
self->_targetToInFlightPackages[target] = package;
[uploader uploadPackage:package];
} else {
[package completeDelivery];
}
}
}
});
}
/** Returns the current upload conditions after making determinations about the network connection.
*
* @return The current upload conditions.
*/
- (GDTUploadConditions)uploadConditions {
SCNetworkReachabilityFlags currentFlags = [GDTReachability currentFlags];
BOOL reachable =
(currentFlags & kSCNetworkReachabilityFlagsReachable) == kSCNetworkReachabilityFlagsReachable;
BOOL connectionRequired = (currentFlags & kSCNetworkReachabilityFlagsConnectionRequired) ==
kSCNetworkReachabilityFlagsConnectionRequired;
BOOL networkConnected = reachable && !connectionRequired;
if (!networkConnected) {
return GDTUploadConditionNoNetwork;
}
BOOL isWWAN = GDTReachabilityFlagsContainWWAN(currentFlags);
if (isWWAN) {
return GDTUploadConditionMobileData;
} else {
return GDTUploadConditionWifiData;
}
}
#pragma mark - NSSecureCoding support
/** The NSKeyedCoder key for the targetToInFlightPackages property. */
static NSString *const ktargetToInFlightPackagesKey =
@"GDTUploadCoordinatortargetToInFlightPackages";
+ (BOOL)supportsSecureCoding {
return YES;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
GDTUploadCoordinator *sharedCoordinator = [GDTUploadCoordinator sharedInstance];
@try {
sharedCoordinator->_targetToInFlightPackages =
[aDecoder decodeObjectOfClass:[NSMutableDictionary class]
forKey:ktargetToInFlightPackagesKey];
} @catch (NSException *exception) {
sharedCoordinator->_targetToInFlightPackages = [NSMutableDictionary dictionary];
}
return sharedCoordinator;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
// All packages that have been given to uploaders need to be tracked so that their expiration
// timers can be called.
if (_targetToInFlightPackages.count > 0) {
[aCoder encodeObject:_targetToInFlightPackages forKey:ktargetToInFlightPackagesKey];
}
}
#pragma mark - GDTLifecycleProtocol
- (void)appWillForeground:(GDTApplication *)app {
// Not entirely thread-safe, but it should be fine.
self->_runningInBackground = NO;
[self startTimer];
}
- (void)appWillBackground:(GDTApplication *)app {
// Not entirely thread-safe, but it should be fine.
self->_runningInBackground = YES;
// Should be thread-safe. If it ends up not being, put this in a dispatch_sync.
[self stopTimer];
// Create an immediate background task to run until the end of the current queue of work.
__block GDTBackgroundIdentifier bgID = [app beginBackgroundTaskWithExpirationHandler:^{
if (bgID != GDTBackgroundIdentifierInvalid) {
[app endBackgroundTask:bgID];
bgID = GDTBackgroundIdentifierInvalid;
}
}];
dispatch_async(_coordinationQueue, ^{
if (bgID != GDTBackgroundIdentifierInvalid) {
[app endBackgroundTask:bgID];
bgID = GDTBackgroundIdentifierInvalid;
}
});
}
- (void)appWillTerminate:(GDTApplication *)application {
dispatch_sync(_coordinationQueue, ^{
[self stopTimer];
});
}
#pragma mark - GDTUploadPackageProtocol
- (void)packageDelivered:(GDTUploadPackage *)package successful:(BOOL)successful {
if (!_coordinationQueue) {
return;
}
dispatch_async(_coordinationQueue, ^{
NSNumber *targetNumber = @(package.target);
NSMutableDictionary<NSNumber *, GDTUploadPackage *> *targetToInFlightPackages =
self->_targetToInFlightPackages;
GDTRegistrar *registrar = self->_registrar;
if (targetToInFlightPackages) {
[targetToInFlightPackages removeObjectForKey:targetNumber];
}
if (registrar) {
id<GDTPrioritizer> prioritizer = registrar.targetToPrioritizer[targetNumber];
if (!prioritizer) {
GDTLogError(GDTMCEPrioritizerError,
@"A prioritizer should be registered for this target: %@", targetNumber);
}
if ([prioritizer respondsToSelector:@selector(packageDelivered:successful:)]) {
[prioritizer packageDelivered:package successful:successful];
}
}
[self.storage removeEvents:package.events];
});
}
- (void)packageExpired:(GDTUploadPackage *)package {
if (!_coordinationQueue) {
return;
}
dispatch_async(_coordinationQueue, ^{
NSNumber *targetNumber = @(package.target);
NSMutableDictionary<NSNumber *, GDTUploadPackage *> *targetToInFlightPackages =
self->_targetToInFlightPackages;
GDTRegistrar *registrar = self->_registrar;
if (targetToInFlightPackages) {
[targetToInFlightPackages removeObjectForKey:targetNumber];
}
if (registrar) {
id<GDTPrioritizer> prioritizer = registrar.targetToPrioritizer[targetNumber];
id<GDTUploader> uploader = registrar.targetToUploader[targetNumber];
if ([prioritizer respondsToSelector:@selector(packageExpired:)]) {
[prioritizer packageExpired:package];
}
if ([uploader respondsToSelector:@selector(packageExpired:)]) {
[uploader packageExpired:package];
}
}
});
}
@end

View File

@ -0,0 +1,154 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <GoogleDataTransport/GDTUploadPackage.h>
#import <GoogleDataTransport/GDTClock.h>
#import <GoogleDataTransport/GDTConsoleLogger.h>
#import <GoogleDataTransport/GDTStoredEvent.h>
#import "GDTLibrary/Private/GDTStorage_Private.h"
#import "GDTLibrary/Private/GDTUploadCoordinator.h"
#import "GDTLibrary/Private/GDTUploadPackage_Private.h"
@implementation GDTUploadPackage {
/** If YES, the package's -completeDelivery method has been called. */
BOOL _isDelivered;
/** If YES, is being handled by the handler. */
BOOL _isHandled;
/** A timer that will regularly check to see whether this package has expired or not. */
NSTimer *_expirationTimer;
}
- (instancetype)initWithTarget:(GDTTarget)target {
self = [super init];
if (self) {
_target = target;
_storage = [GDTStorage sharedInstance];
_deliverByTime = [GDTClock clockSnapshotInTheFuture:180000];
_handler = [GDTUploadCoordinator sharedInstance];
_expirationTimer = [NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:@selector(checkIfPackageIsExpired:)
userInfo:nil
repeats:YES];
}
return self;
}
- (instancetype)copy {
GDTUploadPackage *newPackage = [[GDTUploadPackage alloc] initWithTarget:_target];
newPackage->_events = [_events copy];
return newPackage;
}
- (NSUInteger)hash {
return [_events hash];
}
- (BOOL)isEqual:(id)object {
return [self hash] == [object hash];
}
- (void)dealloc {
[_expirationTimer invalidate];
}
- (void)setStorage:(GDTStorage *)storage {
if (storage != _storage) {
_storage = storage;
}
}
- (void)completeDelivery {
if (_isDelivered) {
GDTLogError(GDTMCEDeliverTwice, @"%@",
@"It's an API violation to call -completeDelivery twice.");
}
_isDelivered = YES;
if (!_isHandled && _handler &&
[_handler respondsToSelector:@selector(packageDelivered:successful:)]) {
[_expirationTimer invalidate];
_isHandled = YES;
[_handler packageDelivered:self successful:YES];
}
}
- (void)retryDeliveryInTheFuture {
if (!_isHandled && _handler &&
[_handler respondsToSelector:@selector(packageDelivered:successful:)]) {
[_expirationTimer invalidate];
_isHandled = YES;
[_handler packageDelivered:self successful:NO];
}
}
- (void)checkIfPackageIsExpired:(NSTimer *)timer {
if ([[GDTClock snapshot] isAfter:_deliverByTime]) {
if (_handler && [_handler respondsToSelector:@selector(packageExpired:)]) {
_isHandled = YES;
[_expirationTimer invalidate];
[_handler packageExpired:self];
}
}
}
#pragma mark - NSSecureCoding
/** The keyed archiver key for the events property. */
static NSString *const kEventsKey = @"GDTUploadPackageEventsKey";
/** The keyed archiver key for the _isHandled property. */
static NSString *const kDeliverByTimeKey = @"GDTUploadPackageDeliveryByTimeKey";
/** The keyed archiver key for the _isHandled ivar. */
static NSString *const kIsHandledKey = @"GDTUploadPackageIsHandledKey";
/** The keyed archiver key for the handler property. */
static NSString *const kHandlerKey = @"GDTUploadPackageHandlerKey";
/** The keyed archiver key for the target property. */
static NSString *const kTargetKey = @"GDTUploadPackageTargetKey";
+ (BOOL)supportsSecureCoding {
return YES;
}
- (void)encodeWithCoder:(nonnull NSCoder *)aCoder {
[aCoder encodeObject:_events forKey:kEventsKey];
[aCoder encodeObject:_deliverByTime forKey:kDeliverByTimeKey];
[aCoder encodeBool:_isHandled forKey:kIsHandledKey];
[aCoder encodeObject:_handler forKey:kHandlerKey];
[aCoder encodeInteger:_target forKey:kTargetKey];
}
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
GDTTarget target = [aDecoder decodeIntegerForKey:kTargetKey];
self = [self initWithTarget:target];
if (self) {
NSSet *classes = [NSSet setWithObjects:[NSSet class], [GDTStoredEvent class], nil];
_events = [aDecoder decodeObjectOfClasses:classes forKey:kEventsKey];
_deliverByTime = [aDecoder decodeObjectOfClass:[GDTClock class] forKey:kDeliverByTimeKey];
_isHandled = [aDecoder decodeBoolForKey:kIsHandledKey];
// _handler isn't technically NSSecureCoding, because we don't know the class of this object.
// but it gets decoded anyway.
}
return self;
}
@end

View File

@ -0,0 +1,30 @@
/*
* 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 <GoogleDataTransport/GDTEvent.h>
#import <GoogleDataTransport/GDTClock.h>
NS_ASSUME_NONNULL_BEGIN
@interface GDTEvent ()
/** The serialized bytes of the event data object. */
@property(nonatomic) NSData *dataObjectTransportBytes;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,31 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <SystemConfiguration/SCNetworkReachability.h>
NS_ASSUME_NONNULL_BEGIN
/** This class helps determine upload conditions by determining connectivity. */
@interface GDTReachability : NSObject
/** The current set flags indicating network conditions */
+ (SCNetworkReachabilityFlags)currentFlags;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,30 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "GDTLibrary/Private/GDTReachability.h"
@interface GDTReachability ()
/** Allows manually setting the flags for testing purposes. */
@property(nonatomic, readwrite) SCNetworkReachabilityFlags flags;
/** Creates/returns the singleton instance of this class.
*
* @return The singleton instance of this class.
*/
+ (instancetype)sharedInstance;
@end

View File

@ -0,0 +1,35 @@
/*
* 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 <GoogleDataTransport/GDTRegistrar.h>
@interface GDTRegistrar ()
NS_ASSUME_NONNULL_BEGIN
/** The concurrent queue on which all registration occurs. */
@property(nonatomic, readonly) dispatch_queue_t registrarQueue;
/** A map of targets to backend implementations. */
@property(atomic, readonly) NSMutableDictionary<NSNumber *, id<GDTUploader>> *targetToUploader;
/** A map of targets to prioritizer implementations. */
@property(atomic, readonly)
NSMutableDictionary<NSNumber *, id<GDTPrioritizer>> *targetToPrioritizer;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,50 @@
/*
* 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 <GoogleDataTransport/GDTLifecycle.h>
@class GDTEvent;
@class GDTStoredEvent;
NS_ASSUME_NONNULL_BEGIN
/** Manages the storage of events. This class is thread-safe. */
@interface GDTStorage : NSObject <NSSecureCoding, GDTLifecycleProtocol>
/** Creates and/or returns the storage singleton.
*
* @return The storage singleton.
*/
+ (instancetype)sharedInstance;
/** Stores event.dataObjectTransportBytes into a shared on-device folder and tracks the event via
* a GDTStoredEvent instance.
*
* @param event The event to store.
*/
- (void)storeEvent:(GDTEvent *)event;
/** Removes a set of events from storage specified by their hash.
*
* @param events The set of stored events to remove.
*/
- (void)removeEvents:(NSSet<GDTStoredEvent *> *)events;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,51 @@
/*
* 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 "GDTLibrary/Private/GDTStorage.h"
@class GDTUploadCoordinator;
NS_ASSUME_NONNULL_BEGIN
@interface GDTStorage ()
/** The queue on which all storage work will occur. */
@property(nonatomic) dispatch_queue_t storageQueue;
/** A map of targets to a set of stored events. */
@property(nonatomic)
NSMutableDictionary<NSNumber *, NSMutableSet<GDTStoredEvent *> *> *targetToEventSet;
/** All the events that have been stored. */
@property(readonly, nonatomic) NSMutableOrderedSet<GDTStoredEvent *> *storedEvents;
/** The upload coordinator instance used by this storage instance. */
@property(nonatomic) GDTUploadCoordinator *uploadCoordinator;
/** If YES, every call to -storeLog results in background task and serializes the singleton to disk.
*/
@property(nonatomic) BOOL runningInBackground;
/** Returns the path to the keyed archive of the singleton. This is where the singleton is saved
* to disk during certain app lifecycle events.
*
* @return File path to serialized singleton.
*/
+ (NSString *)archivePath;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,54 @@
/*
* 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 <GoogleDataTransport/GDTLifecycle.h>
@class GDTEvent;
@protocol GDTEventTransformer;
NS_ASSUME_NONNULL_BEGIN
/** Manages the transforming of events. It's desirable for this to be its own class
* because running all events through a single instance ensures that transformers are thread-safe.
* Having a per-transport queue to run on isn't sufficient because transformer objects could
* maintain state (or at least, there's nothing to stop them from doing that) and the same instances
* may be used across multiple instances.
*/
@interface GDTTransformer : NSObject <GDTLifecycleProtocol>
/** Instantiates or returns the event transformer singleton.
*
* @return The singleton instance of the event transformer.
*/
+ (instancetype)sharedInstance;
/** Writes the result of applying the given transformers' -transform method on the given event.
*
* @note If the app is suspended, a background task will be created to complete work in-progress,
* but this method will not send any further events until the app is resumed.
*
* @param event The event to apply transformers on.
* @param transformers The list of transformers to apply.
*/
- (void)transformEvent:(GDTEvent *)event
withTransformers:(nullable NSArray<id<GDTEventTransformer>> *)transformers;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,36 @@
/*
* 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 "GDTLibrary/Private/GDTTransformer.h"
@class GDTStorage;
NS_ASSUME_NONNULL_BEGIN
@interface GDTTransformer ()
/** The queue on which all work will occur. */
@property(nonatomic) dispatch_queue_t eventWritingQueue;
/** The storage instance used to store events. Should only be used to inject a testing fake. */
@property(nonatomic) GDTStorage *storageInstance;
/** If YES, every call to -transformEvent will result in a background task. */
@property(nonatomic, readonly) BOOL runningInBackground;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,39 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <GoogleDataTransport/GDTTransport.h>
@class GDTTransformer;
NS_ASSUME_NONNULL_BEGIN
@interface GDTTransport ()
/** The mapping identifier that the target backend will use to map the transport bytes to proto. */
@property(nonatomic) NSString *mappingID;
/** The transformers that will operate on events sent by this transport. */
@property(nonatomic) NSArray<id<GDTEventTransformer>> *transformers;
/** The target backend of this transport. */
@property(nonatomic) NSInteger target;
/** The transformer instance to used to transform events. Allows injecting a fake during testing. */
@property(nonatomic) GDTTransformer *transformerInstance;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,80 @@
/*
* 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 <GoogleDataTransport/GDTLifecycle.h>
#import <GoogleDataTransport/GDTRegistrar.h>
#import "GDTLibrary/Private/GDTUploadPackage_Private.h"
@class GDTClock;
@class GDTStorage;
NS_ASSUME_NONNULL_BEGIN
/** This class connects storage and uploader implementations, providing events to an uploader
* and informing the storage what events were successfully uploaded or not.
*/
@interface GDTUploadCoordinator
: NSObject <NSSecureCoding, GDTLifecycleProtocol, GDTUploadPackageProtocol>
/** The queue on which all upload coordination will occur. Also used by a dispatch timer. */
/** Creates and/or returrns the singleton.
*
* @return The singleton instance of this class.
*/
+ (instancetype)sharedInstance;
@property(nonatomic, readonly) dispatch_queue_t coordinationQueue;
/** A timer that will causes regular checks for events to upload. */
@property(nonatomic, readonly) dispatch_source_t timer;
/** The interval the timer will fire. */
@property(nonatomic, readonly) uint64_t timerInterval;
/** Some leeway given to libdispatch for the timer interval event. */
@property(nonatomic, readonly) uint64_t timerLeeway;
/** The map of targets to in-flight packages. */
@property(nonatomic, readonly)
NSMutableDictionary<NSNumber *, GDTUploadPackage *> *targetToInFlightPackages;
/** The storage object the coordinator will use. Generally used for testing. */
@property(nonatomic) GDTStorage *storage;
/** The registrar object the coordinator will use. Generally used for testing. */
@property(nonatomic) GDTRegistrar *registrar;
/** If YES, completion and other operations will result in serializing the singleton to disk. */
@property(nonatomic, readonly) BOOL runningInBackground;
/** Forces the backend specified by the target to upload the provided set of events. This should
* only ever happen when the QoS tier of an event requires it.
*
* @param target The target that should force an upload.
*/
- (void)forceUploadForTarget:(GDTTarget)target;
/** Starts the upload timer. */
- (void)startTimer;
/** Stops the upload timer from running. */
- (void)stopTimer;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,29 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <GoogleDataTransport/GDTUploadPackage.h>
@class GDTStorage;
@interface GDTUploadPackage ()
/** The storage object this upload package will use to resolve event hashes to files. */
@property(nonatomic) GDTStorage *storage;
/** A handler that will receive callbacks for certain events. */
@property(nonatomic) id<NSSecureCoding, GDTUploadPackageProtocol> handler;
@end

View File

@ -0,0 +1,91 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <GoogleDataTransport/GDTConsoleLogger.h>
/** A block type that could be run instead of normal assertion logging. No return type, no params.
*/
typedef void (^GDTAssertionBlock)(void);
/** Returns the result of executing a soft-linked method present in unit tests that allows a block
* to be run instead of normal assertion logging. This helps ameliorate issues with catching
* exceptions that occur on a dispatch_queue.
*
* @return A block that can be run instead of normal assert printing.
*/
FOUNDATION_EXPORT GDTAssertionBlock _Nullable GDTAssertionBlockToRunInstead(void);
#if defined(NS_BLOCK_ASSERTIONS)
#define GDTAssert(condition, ...) \
do { \
} while (0);
#define GDTFatalAssert(condition, ...) \
do { \
} while (0);
#else // defined(NS_BLOCK_ASSERTIONS)
/** Asserts using a console log, unless a block was specified to be run instead.
*
* @param condition The condition you'd expect to be YES.
*/
#define GDTAssert(condition, ...) \
do { \
if (__builtin_expect(!(condition), 0)) { \
GDTAssertionBlock assertionBlock = GDTAssertionBlockToRunInstead(); \
if (assertionBlock) { \
assertionBlock(); \
} else { \
__PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \
NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; \
__assert_file__ = __assert_file__ ? __assert_file__ : @"<Unknown File>"; \
GDTLogError(GDTMCEGeneralError, @"Assertion failed (%@:%d): %s,", __assert_file__, \
__LINE__, ##__VA_ARGS__); \
__PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \
} \
} \
} while (0);
/** Asserts by logging to the console and throwing an exception if NS_BLOCK_ASSERTIONS is not
* defined.
*
* @param condition The condition you'd expect to be YES.
*/
#define GDTFatalAssert(condition, ...) \
do { \
__PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \
if (__builtin_expect(!(condition), 0)) { \
NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; \
__assert_file__ = __assert_file__ ? __assert_file__ : @"<Unknown File>"; \
GDTLogError(GDTMCEFatalAssertion, \
@"Fatal assertion encountered, please open an issue at " \
"https://github.com/firebase/firebase-ios-sdk/issues " \
"(%@:%d): %s,", \
__assert_file__, __LINE__, ##__VA_ARGS__); \
[[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd \
object:self \
file:__assert_file__ \
lineNumber:__LINE__ \
description:@"%@", ##__VA_ARGS__]; \
} \
__PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \
} while (0);
#endif // defined(NS_BLOCK_ASSERTIONS)

View File

@ -0,0 +1,57 @@
/*
* 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>
NS_ASSUME_NONNULL_BEGIN
/** This class manages the device clock and produces snapshots of the current time. */
@interface GDTClock : NSObject <NSSecureCoding>
/** The wallclock time, UTC, in milliseconds. */
@property(nonatomic, readonly) int64_t timeMillis;
/** The offset from UTC in seconds. */
@property(nonatomic, readonly) int64_t timezoneOffsetSeconds;
/** The kernel boot time when this clock was created. */
@property(nonatomic, readonly) int64_t kernelBootTime;
/** The device uptime when this clock was created. */
@property(nonatomic, readonly) int64_t uptime;
/** Creates a GDTClock object using the current time and offsets.
*
* @return A new GDTClock object representing the current time state.
*/
+ (instancetype)snapshot;
/** Creates a GDTClock object representing a time in the future, relative to now.
*
* @param millisInTheFuture The millis in the future from now this clock should represent.
* @return An instance representing a future time.
*/
+ (instancetype)clockSnapshotInTheFuture:(uint64_t)millisInTheFuture;
/** Compares one clock with another, returns YES if the caller is after the parameter.
*
* @return YES if the calling clock's time is after the given clock's time.
*/
- (BOOL)isAfter:(GDTClock *)otherClock;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,84 @@
/*
* 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>
/** A list of message codes to print in the logger that help to correspond printed messages with
* code locations.
*
* Prefixes:
* - MCW => MessageCodeWarning
* - MCE => MessageCodeError
*/
typedef NS_ENUM(NSInteger, GDTMessageCode) {
/** For warning messages concerning transportBytes: not being implemented by a data object. */
GDTMCWDataObjectMissingBytesImpl = 1,
/** For warning messages concerning a failed event upload. */
GDTMCWUploadFailed = 2,
/** For warning messages concerning a forced event upload. */
GDTMCWForcedUpload = 3,
/** For warning messages concerning a failed reachability call. */
GDTMCWReachabilityFailed = 4,
/** For error messages concerning transform: not being implemented by an event transformer. */
GDTMCETransformerDoesntImplementTransform = 1000,
/** For error messages concerning the creation of a directory failing. */
GDTMCEDirectoryCreationError = 1001,
/** For error messages concerning the writing of a event file. */
GDTMCEFileWriteError = 1002,
/** For error messages concerning the lack of a prioritizer for a given backend. */
GDTMCEPrioritizerError = 1003,
/** For error messages concerning a package delivery API violation. */
GDTMCEDeliverTwice = 1004,
/** For error messages concerning an error in an implementation of -transportBytes. */
GDTMCETransportBytesError = 1005,
/** For general purpose error messages in a dependency. */
GDTMCEGeneralError = 1006,
/** For fatal errors. Please go to https://github.com/firebase/firebase-ios-sdk/issues and open
* an issue if you encounter an error with this code.
*/
GDTMCEFatalAssertion = 1007
};
/** */
FOUNDATION_EXPORT
void GDTLog(GDTMessageCode code, NSString *_Nonnull format, ...);
/** Returns the string that represents some message code.
*
* @param code The code to convert to a string.
* @return The string representing the message code.
*/
FOUNDATION_EXPORT NSString *_Nonnull GDTMessageCodeEnumToString(GDTMessageCode code);
// A define to wrap GULLogWarning with slightly more convenient usage.
#define GDTLogWarning(MESSAGE_CODE, MESSAGE_FORMAT, ...) \
GDTLog(MESSAGE_CODE, MESSAGE_FORMAT, __VA_ARGS__);
// A define to wrap GULLogError with slightly more convenient usage and a failing assert.
#define GDTLogError(MESSAGE_CODE, MESSAGE_FORMAT, ...) \
GDTLog(MESSAGE_CODE, MESSAGE_FORMAT, __VA_ARGS__);

View File

@ -0,0 +1,42 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/** This class represents a future data object, determined at instantiation time. */
@interface GDTDataFuture : NSObject <NSSecureCoding>
/** The data, computed on-demand, depending on the initializer. */
@property(nullable, readonly, nonatomic) NSData *data;
/** If not nil, this data future was instantiated with this file URL. */
@property(nullable, readonly, nonatomic) NSURL *fileURL;
/** If not nil, this data future was instantiated with this NSData instance. */
@property(nullable, readonly, nonatomic) NSData *originalData;
/** Initializes an instance with the given the fileURL.
*
* @param fileURL The fileURL containing the data to return in -data.
* @return An instance of this class.
*/
- (instancetype)initWithFileURL:(NSURL *)fileURL;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,94 @@
/*
* 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 <GoogleDataTransport/GDTEventDataObject.h>
@class GDTClock;
@class GDTDataFuture;
@class GDTStoredEvent;
NS_ASSUME_NONNULL_BEGIN
/** The different possible quality of service specifiers. High values indicate high priority. */
typedef NS_ENUM(NSInteger, GDTEventQoS) {
/** The QoS tier wasn't set, and won't ever be sent. */
GDTEventQoSUnknown = 0,
/** This event is internal telemetry data that should not be sent on its own if possible. */
GDTEventQoSTelemetry = 1,
/** This event should be sent, but in a batch only roughly once per day. */
GDTEventQoSDaily = 2,
/** This event should be sent when requested by the uploader. */
GDTEventQosDefault = 3,
/** This event should be sent immediately along with any other data that can be batched. */
GDTEventQoSFast = 4,
/** This event should only be uploaded on wifi. */
GDTEventQoSWifiOnly = 5,
};
@interface GDTEvent : NSObject <NSSecureCoding>
/** The mapping identifier, to allow backends to map the transport bytes to a proto. */
@property(readonly, nonatomic) NSString *mappingID;
/** The identifier for the backend this event will eventually be sent to. */
@property(readonly, nonatomic) NSInteger target;
/** The data object encapsulated in the transport of your choice, as long as it implements
* the GDTEventDataObject protocol. */
@property(nullable, nonatomic) id<GDTEventDataObject> dataObject;
/** The quality of service tier this event belongs to. */
@property(nonatomic) GDTEventQoS qosTier;
/** The clock snapshot at the time of the event. */
@property(nonatomic) GDTClock *clockSnapshot;
/** A dictionary provided to aid prioritizers by allowing the passing of arbitrary data. It will be
* retained by a copy in -copy, but not used for -hash.
*
* @note Ensure that classes contained therein implement NSSecureCoding to prevent loss of data.
*/
@property(nullable, nonatomic) NSDictionary *customPrioritizationParams;
// Please use the designated initializer.
- (instancetype)init NS_UNAVAILABLE;
/** Initializes an instance using the given mappingID.
*
* @param mappingID The mapping identifier.
* @param target The event's target identifier.
* @return An instance of this class.
*/
- (instancetype)initWithMappingID:(NSString *)mappingID
target:(NSInteger)target NS_DESIGNATED_INITIALIZER;
/** Returns the GDTStoredEvent equivalent of self.
*
* @param dataFuture The data future representing the transport bytes of the original event.
* @return An equivalent GDTStoredEvent.
*/
- (GDTStoredEvent *)storedEventWithDataFuture:(GDTDataFuture *)dataFuture;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,36 @@
/*
* 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>
NS_ASSUME_NONNULL_BEGIN
/** This protocol defines the common interface that event protos should implement regardless of the
* underlying transport technology (protobuf, nanopb, etc).
*/
@protocol GDTEventDataObject <NSObject>
@required
/** Returns the serialized proto bytes of the implementing event proto.
*
* @return the serialized proto bytes of the implementing event proto.
*/
- (NSData *)transportBytes;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,38 @@
/*
* 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>
@class GDTEvent;
NS_ASSUME_NONNULL_BEGIN
/** Defines the API that event transformers must adopt. */
@protocol GDTEventTransformer <NSObject>
@required
/** Transforms an event by applying some logic to it. Events returned can be nil, for example, in
* instances where the event should be sampled.
*
* @param event The event to transform.
* @return A transformed event, or nil if the transformation dropped the event.
*/
- (GDTEvent *)transform:(GDTEvent *)event;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,63 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <GoogleDataTransport/GDTPlatform.h>
@class GDTEvent;
NS_ASSUME_NONNULL_BEGIN
/** A protocol defining the lifecycle events objects in the library must respond to immediately. */
@protocol GDTLifecycleProtocol <NSObject>
@optional
/** Indicates an imminent app termination in the rare occurrence when -applicationWillTerminate: has
* been called.
*
* @param app The GDTApplication instance.
*/
- (void)appWillTerminate:(GDTApplication *)app;
/** Indicates that the app is moving to background and eventual suspension or the current UIScene is
* deactivating.
*
* @param app The GDTApplication instance.
*/
- (void)appWillBackground:(GDTApplication *)app;
/** Indicates that the app is resuming operation or a UIScene is activating.
*
* @param app The GDTApplication instance.
*/
- (void)appWillForeground:(GDTApplication *)app;
@end
/** This class manages the library's response to app lifecycle events.
*
* When backgrounding, the library doesn't stop processing events, it's just that several background
* tasks will end up being created for every event that's sent, and the stateful objects of the
* library (GDTStorage and GDTUploadCoordinator singletons) will deserialize themselves from and to
* disk before and after every operation, respectively.
*/
@interface GDTLifecycle : NSObject <GDTApplicationDelegate>
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,87 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
#if TARGET_OS_IOS || TARGET_OS_TV
#import <UIKit/UIKit.h>
#elif TARGET_OS_OSX
#import <AppKit/AppKit.h>
#endif // TARGET_OS_IOS || TARGET_OS_TV
NS_ASSUME_NONNULL_BEGIN
/** A notification sent out if the app is backgrounding. */
FOUNDATION_EXPORT NSString *const kGDTApplicationDidEnterBackgroundNotification;
/** A notification sent out if the app is foregrounding. */
FOUNDATION_EXPORT NSString *const kGDTApplicationWillEnterForegroundNotification;
/** A notification sent out if the app is terminating. */
FOUNDATION_EXPORT NSString *const kGDTApplicationWillTerminateNotification;
/** Compares flags with the WWAN reachability flag, if available, and returns YES if present.
*
* @param flags The set of reachability flags.
* @return YES if the WWAN flag is set, NO otherwise.
*/
BOOL GDTReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags);
/** A typedef identify background identifiers. */
typedef volatile NSUInteger GDTBackgroundIdentifier;
/** A background task's invalid sentinel value. */
FOUNDATION_EXPORT const GDTBackgroundIdentifier GDTBackgroundIdentifierInvalid;
#if TARGET_OS_IOS || TARGET_OS_TV
/** A protocol that wraps UIApplicationDelegate or NSObject protocol, depending on the platform. */
@protocol GDTApplicationDelegate <UIApplicationDelegate>
#elif TARGET_OS_OSX
@protocol GDTApplicationDelegate <NSApplicationDelegate>
#else
@protocol GDTApplicationDelegate <NSObject>
#endif // TARGET_OS_IOS || TARGET_OS_TV
@end
/** A cross-platform application class. */
@interface GDTApplication : NSObject <GDTApplicationDelegate>
/** Creates and/or returns the shared application instance.
*
* @return The shared application instance.
*/
+ (nullable GDTApplication *)sharedApplication;
/** Creates a background task with the returned identifier if on a suitable platform.
*
* @param handler The handler block that is called if the background task expires.
* @return An identifier for the background task, or GDTBackgroundIdentifierInvalid if one couldn't
* be created.
*/
- (GDTBackgroundIdentifier)beginBackgroundTaskWithExpirationHandler:
(void (^__nullable)(void))handler;
/** Ends the background task if the identifier is valid.
*
* @param bgID The background task to end.
*/
- (void)endBackgroundTask:(GDTBackgroundIdentifier)bgID;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,73 @@
/*
* 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 <GoogleDataTransport/GDTLifecycle.h>
#import <GoogleDataTransport/GDTUploadPackage.h>
@class GDTStoredEvent;
NS_ASSUME_NONNULL_BEGIN
/** Options that define a set of upload conditions. This is used to help minimize end user data
* consumption impact.
*/
typedef NS_OPTIONS(NSInteger, GDTUploadConditions) {
/** An upload shouldn't be attempted, because there's no network. */
GDTUploadConditionNoNetwork = 1 << 0,
/** An upload would likely use mobile data. */
GDTUploadConditionMobileData = 1 << 1,
/** An upload would likely use wifi data. */
GDTUploadConditionWifiData = 1 << 2,
/** An upload uses some sort of network connection, but it's unclear which. */
GDTUploadConditionUnclearConnection = 1 << 3,
/** A high priority event has occurred. */
GDTUploadConditionHighPriority = 1 << 4,
};
/** This protocol defines the common interface of event prioritization. Prioritizers are
* stateful objects that prioritize events upon insertion into storage and remain prepared to return
* a set of filenames to the storage system.
*/
@protocol GDTPrioritizer <NSObject, GDTLifecycleProtocol, GDTUploadPackageProtocol>
@required
/** Accepts an event and uses the event metadata to make choices on how to prioritize the event.
* This method exists as a way to help prioritize which events should be sent, which is dependent on
* the request proto structure of your backend.
*
* @param event The event to prioritize.
*/
- (void)prioritizeEvent:(GDTStoredEvent *)event;
/** Returns a set of events to upload given a set of conditions.
*
* @param conditions A bit mask specifying the current upload conditions.
* @return An object to be used by the uploader to determine file URLs to upload with respect to the
* current conditions.
*/
- (GDTUploadPackage *)uploadPackageWithConditions:(GDTUploadConditions)conditions;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,50 @@
/*
* 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 <GoogleDataTransport/GDTPrioritizer.h>
#import <GoogleDataTransport/GDTTargets.h>
#import <GoogleDataTransport/GDTUploader.h>
NS_ASSUME_NONNULL_BEGIN
/** Manages the registration of targets with the transport SDK. */
@interface GDTRegistrar : NSObject <GDTLifecycleProtocol>
/** Creates and/or returns the singleton instance.
*
* @return The singleton instance of this class.
*/
+ (instancetype)sharedInstance;
/** Registers a backend implementation with the GoogleDataTransport infrastructure.
*
* @param backend The backend object to register.
* @param target The target this backend object will be responsible for.
*/
- (void)registerUploader:(id<GDTUploader>)backend target:(GDTTarget)target;
/** Registers a event prioritizer implementation with the GoogleDataTransport infrastructure.
*
* @param prioritizer The prioritizer object to register.
* @param target The target this prioritizer object will be responsible for.
*/
- (void)registerPrioritizer:(id<GDTPrioritizer>)prioritizer target:(GDTTarget)target;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,58 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <GoogleDataTransport/GDTDataFuture.h>
#import <GoogleDataTransport/GDTEvent.h>
@class GDTEvent;
NS_ASSUME_NONNULL_BEGIN
@interface GDTStoredEvent : NSObject <NSSecureCoding>
/** The data future representing the original event's transport bytes. */
@property(readonly, nonatomic) GDTDataFuture *dataFuture;
/** The mapping identifier, to allow backends to map the transport bytes to a proto. */
@property(readonly, nonatomic) NSString *mappingID;
/** The identifier for the backend this event will eventually be sent to. */
@property(readonly, nonatomic) NSNumber *target;
/** The quality of service tier this event belongs to. */
@property(readonly, nonatomic) GDTEventQoS qosTier;
/** The clock snapshot at the time of the event. */
@property(readonly, nonatomic) GDTClock *clockSnapshot;
/** A dictionary provided to aid prioritizers by allowing the passing of arbitrary data.
*
* @note Ensure that custom classes in this dict implement NSSecureCoding to prevent loss of data.
*/
@property(readonly, nullable, nonatomic) NSDictionary *customPrioritizationParams;
/** Initializes a stored event with the given URL and event.
*
* @param event The event this stored event represents.
* @param dataFuture The dataFuture this event represents.
* @return An instance of this class.
*/
- (instancetype)initWithEvent:(GDTEvent *)event dataFuture:(GDTDataFuture *)dataFuture;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,29 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
/** The list of targets supported by the shared transport infrastructure. If adding a new target,
* please use the previous value +1.
*/
typedef NS_ENUM(NSInteger, GDTTarget) {
/** A target only used in testing. */
kGDTTargetTest = 999,
/** The CCT target. */
kGDTTargetCCT = 1000,
};

View File

@ -0,0 +1,68 @@
/*
* 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 <GoogleDataTransport/GDTEventTransformer.h>
@class GDTEvent;
NS_ASSUME_NONNULL_BEGIN
@interface GDTTransport : NSObject
// Please use the designated initializer.
- (instancetype)init NS_UNAVAILABLE;
/** Initializes a new transport that will send events to the given target backend.
*
* @param mappingID The mapping identifier used by the backend to map the data object transport
* bytes to a proto.
* @param transformers A list of transformers to be applied to events that are sent.
* @param target The target backend of this transport.
* @return A transport that will send events.
*/
- (instancetype)initWithMappingID:(NSString *)mappingID
transformers:(nullable NSArray<id<GDTEventTransformer>> *)transformers
target:(NSInteger)target NS_DESIGNATED_INITIALIZER;
/** Copies and sends an internal telemetry event. Events sent using this API are lower in priority,
* and sometimes won't be sent on their own.
*
* @note This will convert the event's data object to data and release the original event.
*
* @param event The event to send.
*/
- (void)sendTelemetryEvent:(GDTEvent *)event;
/** Copies and sends an SDK service data event. Events send using this API are higher in priority,
* and will cause a network request at some point in the relative near future.
*
* @note This will convert the event's data object to data and release the original event.
*
* @param event The event to send.
*/
- (void)sendDataEvent:(GDTEvent *)event;
/** Creates an event for use by this transport.
*
* @return An event that is suited for use by this transport.
*/
- (GDTEvent *)eventForTransport;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,80 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <GoogleDataTransport/GDTTargets.h>
@class GDTClock;
@class GDTStoredEvent;
@class GDTUploadPackage;
/** A protocol that allows a handler to respond to package lifecycle events. */
@protocol GDTUploadPackageProtocol <NSObject>
@optional
/** Indicates that the package has expired.
*
* @note Package expiration will only be checked every 5 seconds.
*
* @param package The package that has expired.
*/
- (void)packageExpired:(GDTUploadPackage *)package;
/** Indicates that the package was successfully delivered.
*
* @param package The package that was delivered.
*/
- (void)packageDelivered:(GDTUploadPackage *)package successful:(BOOL)successful;
@end
/** This class is a container that's handed off to uploaders. */
@interface GDTUploadPackage : NSObject <NSSecureCoding>
/** The set of stored events in this upload package. */
@property(nonatomic) NSSet<GDTStoredEvent *> *events;
/** The expiration time. If [[GDTClock snapshot] isAfter:deliverByTime] this package has expired.
*
* @note By default, the expiration time will be 3 minutes from creation.
*/
@property(nonatomic) GDTClock *deliverByTime;
/** The target of this package. */
@property(nonatomic, readonly) GDTTarget target;
/** Initializes a package instance.
*
* @param target The target/destination of this package.
* @return An instance of this class.
*/
- (instancetype)initWithTarget:(GDTTarget)target NS_DESIGNATED_INITIALIZER;
// Please use the designated initializer.
- (instancetype)init NS_UNAVAILABLE;
/** Completes delivery of the package.
*
* @note This *needs* to be called by an uploader for the package to not expire.
*/
- (void)completeDelivery;
/** Sends the package back, indicating that delivery should be attempted again in the future. */
- (void)retryDeliveryInTheFuture;
@end

View File

@ -0,0 +1,47 @@
/*
* 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 <GoogleDataTransport/GDTClock.h>
#import <GoogleDataTransport/GDTLifecycle.h>
#import <GoogleDataTransport/GDTPrioritizer.h>
#import <GoogleDataTransport/GDTTargets.h>
#import <GoogleDataTransport/GDTUploadPackage.h>
NS_ASSUME_NONNULL_BEGIN
/** This protocol defines the common interface for uploader implementations. */
@protocol GDTUploader <NSObject, GDTLifecycleProtocol, GDTUploadPackageProtocol>
@required
/** Returns YES if the uploader can make an upload attempt, NO otherwise.
*
* @param conditions The conditions that the upload attempt is likely to occur under.
* @return YES if the uploader can make an upload attempt, NO otherwise.
*/
- (BOOL)readyToUploadWithConditions:(GDTUploadConditions)conditions;
/** Uploads events to the backend using this specific backend's chosen format.
*
* @param package The event package to upload. Make sure to call -completeDelivery.
*/
- (void)uploadPackage:(GDTUploadPackage *)package;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,30 @@
/*
* 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 "GDTClock.h"
#import "GDTConsoleLogger.h"
#import "GDTDataFuture.h"
#import "GDTEvent.h"
#import "GDTEventDataObject.h"
#import "GDTEventTransformer.h"
#import "GDTLifecycle.h"
#import "GDTPrioritizer.h"
#import "GDTRegistrar.h"
#import "GDTStoredEvent.h"
#import "GDTTargets.h"
#import "GDTTransport.h"
#import "GDTUploadPackage.h"
#import "GDTUploader.h"

202
ios/Pods/GoogleDataTransport/LICENSE generated Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

224
ios/Pods/GoogleDataTransport/README.md generated Normal file
View File

@ -0,0 +1,224 @@
# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk)
This repository contains a subset of the Firebase iOS SDK source. It currently
includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase,
FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging,
FirebaseInAppMessagingDisplay, FirebaseMessaging and FirebaseStorage.
The repository also includes GoogleUtilities source. The
[GoogleUtilities](GoogleUtilities/README.md) pod is
a set of utilities used by Firebase and other Google products.
Firebase is an app development platform with tools to help you build, grow and
monetize your app. More information about Firebase can be found at
[https://firebase.google.com](https://firebase.google.com).
## Installation
See the three subsections for details about three different installation methods.
1. [Standard pod install](README.md#standard-pod-install)
1. [Installing from the GitHub repo](README.md#installing-from-github)
1. [Experimental Carthage](README.md#carthage-ios-only)
### Standard pod install
Go to
[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup).
### Installing from GitHub
For releases starting with 5.0.0, the source for each release is also deployed
to CocoaPods master and available via standard
[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod).
These instructions can be used to access the Firebase repo at other branches,
tags, or commits.
#### Background
See
[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod)
for instructions and options about overriding pod source locations.
#### Accessing Firebase Source Snapshots
All of the official releases are tagged in this repo and available via CocoaPods. To access a local
source snapshot or unreleased branch, use Podfile directives like the following:
To access FirebaseFirestore via a branch:
```
pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master'
pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master'
```
To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do:
```
pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk'
pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk'
```
### Carthage (iOS only)
Instructions for the experimental Carthage distribution are at
[Carthage](Carthage.md).
### Rome
Instructions for installing binary frameworks via
[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md).
## Development
To develop Firebase software in this repository, ensure that you have at least
the following software:
* Xcode 10.1 (or later)
* CocoaPods 1.7.2 (or later)
For the pod that you want to develop:
`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open`
Firestore has a self contained Xcode project. See
[Firestore/README.md](Firestore/README.md).
### Adding a New Firebase Pod
See [AddNewPod.md](AddNewPod.md).
### Code Formatting
To ensure that the code is formatted consistently, run the script
[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh)
before creating a PR.
Travis will verify that any code changes are done in a style compliant way. Install
`clang-format` and `swiftformat`.
These commands will get the right versions:
```
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/773cb75d360b58f32048f5964038d09825a507c8/Formula/clang-format.rb
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/3dfea1004e0736754bbf49673cca8aaed8a94089/Formula/swiftformat.rb
```
Note: if you already have a newer version of these installed you may need to
`brew switch` to this version.
### Running Unit Tests
Select a scheme and press Command-u to build a component and run its unit tests.
#### Viewing Code Coverage
First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`.
After running the `AllUnitTests_iOS` scheme in Xcode, execute
`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output`
at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results.
### Running Sample Apps
In order to run the sample apps and integration tests, you'll need valid
`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist
files without real values, but can be replaced with real plist files. To get your own
`GoogleService-Info.plist` files:
1. Go to the [Firebase Console](https://console.firebase.google.com/)
2. Create a new Firebase project, if you don't already have one
3. For each sample app you want to test, create a new Firebase app with the sample app's bundle
identifier (e.g. `com.google.Database-Example`)
4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file
(e.g. in [Example/Database/App/](Example/Database/App/));
Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require
special Apple capabilities, and you will have to change the sample app to use a unique bundle
identifier that you can control in your own Apple Developer account.
## Specific Component Instructions
See the sections below for any special instructions for those components.
### Firebase Auth
If you're doing specific Firebase Auth development, see
[the Auth Sample README](Example/Auth/README.md) for instructions about
building and running the FirebaseAuth pod along with various samples and tests.
### Firebase Database
To run the Database Integration tests, make your database authentication rules
[public](https://firebase.google.com/docs/database/security/quickstart).
### Firebase Storage
To run the Storage Integration tests, follow the instructions in
[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m).
#### Push Notifications
Push notifications can only be delivered to specially provisioned App IDs in the developer portal.
In order to actually test receiving push notifications, you will need to:
1. Change the bundle identifier of the sample app to something you own in your Apple Developer
account, and enable that App ID for push notifications.
2. You'll also need to
[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs)
at **Project Settings > Cloud Messaging > [Your Firebase App]**.
3. Ensure your iOS device is added to your Apple Developer portal as a test device.
#### iOS Simulator
The iOS Simulator cannot register for remote notifications, and will not receive push notifications.
In order to receive push notifications, you'll have to follow the steps above and run the app on a
physical device.
## Community Supported Efforts
We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are
very grateful! We'd like to empower as many developers as we can to be able to use Firebase and
participate in the Firebase community.
### macOS and tvOS
Thanks to contributions from the community, FirebaseABTesting, FirebaseAuth, FirebaseCore,
FirebaseDatabase, FirebaseMessaging,
FirebaseFirestore, FirebaseFunctions and FirebaseStorage now compile, run unit tests, and work on
macOS and tvOS.
For tvOS, checkout the [Sample](Example/tvOSSample).
Keep in mind that macOS and tvOS are not officially supported by Firebase, and this repository is
actively developed primarily for iOS. While we can catch basic unit test issues with Travis, there
may be some changes where the SDK no longer works as expected on macOS or tvOS. If you encounter
this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues).
Note that the Firebase pod is not available for macOS and tvOS.
To install, add a subset of the following to the Podfile:
```
pod 'FirebaseABTesting'
pod 'FirebaseAuth'
pod 'FirebaseCore'
pod 'FirebaseDatabase'
pod 'FirebaseFirestore'
pod 'FirebaseFunctions'
pod 'FirebaseMessaging'
pod 'FirebaseStorage'
```
## Roadmap
See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source
plans and directions.
## Contributing
See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase
iOS SDK.
## License
The contents of this repository is licensed under the
[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
Your use of Firebase is governed by the
[Terms of Service for Firebase Services](https://firebase.google.com/terms/).

View File

@ -0,0 +1,188 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h"
#if TARGET_OS_IOS || TARGET_OS_TV
#import <UIKit/UIKit.h>
#elif TARGET_OS_OSX
#import <AppKit/AppKit.h>
#endif // TARGET_OS_IOS || TARGET_OS_TV
#import <GoogleDataTransport/GDTConsoleLogger.h>
#import <nanopb/pb.h>
#import <nanopb/pb_decode.h>
#import <nanopb/pb_encode.h>
#import "GDTCCTLibrary/Private/GDTCCTPrioritizer.h"
#pragma mark - General purpose encoders
pb_bytes_array_t *GDTCCTEncodeString(NSString *string) {
NSData *stringBytes = [string dataUsingEncoding:NSUTF8StringEncoding];
return GDTCCTEncodeData(stringBytes);
}
pb_bytes_array_t *GDTCCTEncodeData(NSData *data) {
pb_bytes_array_t *pbBytes = malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(data.length));
memcpy(pbBytes->bytes, [data bytes], data.length);
pbBytes->size = (pb_size_t)data.length;
return pbBytes;
}
#pragma mark - CCT object constructors
NSData *_Nullable GDTCCTEncodeBatchedLogRequest(gdt_cct_BatchedLogRequest *batchedLogRequest) {
pb_ostream_t sizestream = PB_OSTREAM_SIZING;
// Encode 1 time to determine the size.
if (!pb_encode(&sizestream, gdt_cct_BatchedLogRequest_fields, batchedLogRequest)) {
GDTLogError(GDTMCEGeneralError, @"Error in nanopb encoding for size: %s",
PB_GET_ERROR(&sizestream));
}
// Encode a 2nd time to actually get the bytes from it.
size_t bufferSize = sizestream.bytes_written;
CFMutableDataRef dataRef = CFDataCreateMutable(CFAllocatorGetDefault(), bufferSize);
pb_ostream_t ostream = pb_ostream_from_buffer((void *)CFDataGetBytePtr(dataRef), bufferSize);
if (!pb_encode(&ostream, gdt_cct_BatchedLogRequest_fields, batchedLogRequest)) {
GDTLogError(GDTMCEGeneralError, @"Error in nanopb encoding for bytes: %s",
PB_GET_ERROR(&ostream));
}
CFDataSetLength(dataRef, ostream.bytes_written);
return CFBridgingRelease(dataRef);
}
gdt_cct_BatchedLogRequest GDTCCTConstructBatchedLogRequest(
NSDictionary<NSString *, NSSet<GDTStoredEvent *> *> *logMappingIDToLogSet) {
gdt_cct_BatchedLogRequest batchedLogRequest = gdt_cct_BatchedLogRequest_init_default;
NSUInteger numberOfLogRequests = logMappingIDToLogSet.count;
gdt_cct_LogRequest *logRequests = malloc(sizeof(gdt_cct_LogRequest) * numberOfLogRequests);
__block int i = 0;
[logMappingIDToLogSet enumerateKeysAndObjectsUsingBlock:^(
NSString *_Nonnull logMappingID,
NSSet<GDTStoredEvent *> *_Nonnull logSet, BOOL *_Nonnull stop) {
int32_t logSource = [logMappingID intValue];
gdt_cct_LogRequest logRequest = GDTCCTConstructLogRequest(logSource, logSet);
logRequests[i] = logRequest;
i++;
}];
batchedLogRequest.log_request = logRequests;
batchedLogRequest.log_request_count = (pb_size_t)numberOfLogRequests;
return batchedLogRequest;
}
gdt_cct_LogRequest GDTCCTConstructLogRequest(int32_t logSource,
NSSet<GDTStoredEvent *> *_Nonnull logSet) {
if (logSet.count == 0) {
GDTLogError(GDTMCEGeneralError, @"%@", @"An empty event set can't be serialized to proto.");
gdt_cct_LogRequest logRequest = gdt_cct_LogRequest_init_default;
return logRequest;
}
gdt_cct_LogRequest logRequest = gdt_cct_LogRequest_init_default;
logRequest.log_source = logSource;
logRequest.has_log_source = 1;
logRequest.client_info = GDTCCTConstructClientInfo();
logRequest.has_client_info = 1;
logRequest.log_event = malloc(sizeof(gdt_cct_LogEvent) * logSet.count);
int i = 0;
for (GDTStoredEvent *log in logSet) {
gdt_cct_LogEvent logEvent = GDTCCTConstructLogEvent(log);
logRequest.log_event[i] = logEvent;
i++;
}
logRequest.log_event_count = (pb_size_t)logSet.count;
return logRequest;
}
gdt_cct_LogEvent GDTCCTConstructLogEvent(GDTStoredEvent *event) {
gdt_cct_LogEvent logEvent = gdt_cct_LogEvent_init_default;
logEvent.event_time_ms = event.clockSnapshot.timeMillis;
logEvent.has_event_time_ms = 1;
logEvent.event_uptime_ms = event.clockSnapshot.uptime;
logEvent.has_event_uptime_ms = 1;
logEvent.timezone_offset_seconds = event.clockSnapshot.timezoneOffsetSeconds;
logEvent.has_timezone_offset_seconds = 1;
// TODO: Read network_connection_info from the custom params dict.
NSError *error;
NSData *extensionBytes = [NSData dataWithContentsOfURL:event.dataFuture.fileURL
options:0
error:&error];
if (error) {
GDTLogError(GDTMCEGeneralError, @"There was an error reading extension bytes from disk: %@",
error);
return logEvent;
}
logEvent.source_extension = GDTCCTEncodeData(extensionBytes); // read bytes from the file.
return logEvent;
}
gdt_cct_ClientInfo GDTCCTConstructClientInfo() {
gdt_cct_ClientInfo clientInfo = gdt_cct_ClientInfo_init_default;
clientInfo.client_type = gdt_cct_ClientInfo_ClientType_IOS_FIREBASE;
clientInfo.has_client_type = 1;
#if TARGET_OS_IOS || TARGET_OS_TV
clientInfo.ios_client_info = GDTCCTConstructiOSClientInfo();
clientInfo.has_ios_client_info = 1;
#elif TARGET_OS_OSX
// TODO(mikehaney24): Expand the proto to include macOS client info.
#endif
return clientInfo;
}
gdt_cct_IosClientInfo GDTCCTConstructiOSClientInfo() {
gdt_cct_IosClientInfo iOSClientInfo = gdt_cct_IosClientInfo_init_default;
#if TARGET_OS_IOS || TARGET_OS_TV
UIDevice *device = [UIDevice currentDevice];
NSBundle *bundle = [NSBundle mainBundle];
NSLocale *locale = [NSLocale currentLocale];
iOSClientInfo.os_full_version = GDTCCTEncodeString(device.systemVersion);
NSArray *versionComponents = [device.systemVersion componentsSeparatedByString:@"."];
iOSClientInfo.os_major_version = GDTCCTEncodeString(versionComponents[0]);
NSString *version = [bundle objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
if (version) {
iOSClientInfo.application_build = GDTCCTEncodeString(version);
}
iOSClientInfo.country = GDTCCTEncodeString([locale objectForKey:NSLocaleCountryCode]);
iOSClientInfo.model = GDTCCTEncodeString(device.model);
NSString *languageCode = bundle.preferredLocalizations.firstObject;
iOSClientInfo.language_code =
languageCode ? GDTCCTEncodeString(languageCode) : GDTCCTEncodeString(@"en");
iOSClientInfo.application_bundle_id = GDTCCTEncodeString(bundle.bundleIdentifier);
#endif
return iOSClientInfo;
}
#pragma mark - CCT Object decoders
gdt_cct_LogResponse GDTCCTDecodeLogResponse(NSData *data, NSError **error) {
gdt_cct_LogResponse response = gdt_cct_LogResponse_init_default;
pb_istream_t istream = pb_istream_from_buffer([data bytes], [data length]);
if (!pb_decode(&istream, gdt_cct_LogResponse_fields, &response)) {
NSString *nanopb_error = [NSString stringWithFormat:@"%s", PB_GET_ERROR(&istream)];
NSDictionary *userInfo = @{@"nanopb error:" : nanopb_error};
if (error != NULL) {
*error = [NSError errorWithDomain:NSURLErrorDomain code:-1 userInfo:userInfo];
}
response = (gdt_cct_LogResponse)gdt_cct_LogResponse_init_default;
}
return response;
}

View File

@ -0,0 +1,188 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "GDTCCTLibrary/Private/GDTCCTPrioritizer.h"
#import <GoogleDataTransport/GDTEvent.h>
#import <GoogleDataTransport/GDTRegistrar.h>
#import <GoogleDataTransport/GDTStoredEvent.h>
#import <GoogleDataTransport/GDTTargets.h>
const static int64_t kMillisPerDay = 8.64e+7;
@implementation GDTCCTPrioritizer
+ (void)load {
GDTCCTPrioritizer *prioritizer = [GDTCCTPrioritizer sharedInstance];
[[GDTRegistrar sharedInstance] registerPrioritizer:prioritizer target:kGDTTargetCCT];
}
+ (instancetype)sharedInstance {
static GDTCCTPrioritizer *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[GDTCCTPrioritizer alloc] init];
});
return sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
_queue = dispatch_queue_create("com.google.GDTCCTPrioritizer", DISPATCH_QUEUE_SERIAL);
_events = [[NSMutableSet alloc] init];
}
return self;
}
#pragma mark - GDTPrioritizer Protocol
- (void)prioritizeEvent:(GDTStoredEvent *)event {
dispatch_async(_queue, ^{
[self.events addObject:event];
});
}
- (GDTUploadPackage *)uploadPackageWithConditions:(GDTUploadConditions)conditions {
GDTUploadPackage *package = [[GDTUploadPackage alloc] initWithTarget:kGDTTargetCCT];
dispatch_sync(_queue, ^{
NSSet<GDTStoredEvent *> *logEventsThatWillBeSent;
// A high priority event effectively flushes all events to be sent.
if ((conditions & GDTUploadConditionHighPriority) == GDTUploadConditionHighPriority) {
package.events = self.events;
return;
}
// If on wifi, upload logs that are ok to send on wifi.
if ((conditions & GDTUploadConditionWifiData) == GDTUploadConditionWifiData) {
logEventsThatWillBeSent = [self logEventsOkToSendOnWifi];
} else {
logEventsThatWillBeSent = [self logEventsOkToSendOnMobileData];
}
// If it's been > 24h since the last daily upload, upload logs with the daily QoS.
if (self.timeOfLastDailyUpload) {
int64_t millisSinceLastUpload =
[GDTClock snapshot].timeMillis - self.timeOfLastDailyUpload.timeMillis;
if (millisSinceLastUpload > kMillisPerDay) {
logEventsThatWillBeSent =
[logEventsThatWillBeSent setByAddingObjectsFromSet:[self logEventsOkToSendDaily]];
}
} else {
self.timeOfLastDailyUpload = [GDTClock snapshot];
logEventsThatWillBeSent =
[logEventsThatWillBeSent setByAddingObjectsFromSet:[self logEventsOkToSendDaily]];
}
package.events = logEventsThatWillBeSent;
});
return package;
}
#pragma mark - Private helper methods
/** The different possible quality of service specifiers. High values indicate high priority. */
typedef NS_ENUM(NSInteger, GDTCCTQoSTier) {
/** The QoS tier wasn't set, and won't ever be sent. */
GDTCCTQoSDefault = 0,
/** This event is internal telemetry data that should not be sent on its own if possible. */
GDTCCTQoSTelemetry = 1,
/** This event should be sent, but in a batch only roughly once per day. */
GDTCCTQoSDaily = 2,
/** This event should only be uploaded on wifi. */
GDTCCTQoSWifiOnly = 5,
};
/** Converts a GDTEventQoS to a GDTCCTQoS tier.
*
* @param qosTier The GDTEventQoS value.
* @return A static NSNumber that represents the CCT QoS tier.
*/
FOUNDATION_STATIC_INLINE
NSNumber *GDTCCTQosTierFromGDTEventQosTier(GDTEventQoS qosTier) {
switch (qosTier) {
case GDTEventQoSWifiOnly:
return @(GDTCCTQoSWifiOnly);
break;
case GDTEventQoSTelemetry:
// falls through.
case GDTEventQoSDaily:
return @(GDTCCTQoSDaily);
break;
default:
return @(GDTCCTQoSDefault);
break;
}
}
/** Returns a set of logs that are ok to upload whilst on mobile data.
*
* @note This should be called from a thread safe method.
* @return A set of logs that are ok to upload whilst on mobile data.
*/
- (NSSet<GDTStoredEvent *> *)logEventsOkToSendOnMobileData {
return
[self.events objectsPassingTest:^BOOL(GDTStoredEvent *_Nonnull event, BOOL *_Nonnull stop) {
return [GDTCCTQosTierFromGDTEventQosTier(event.qosTier) isEqual:@(GDTCCTQoSDefault)];
}];
}
/** Returns a set of logs that are ok to upload whilst on wifi.
*
* @note This should be called from a thread safe method.
* @return A set of logs that are ok to upload whilst on wifi.
*/
- (NSSet<GDTStoredEvent *> *)logEventsOkToSendOnWifi {
return
[self.events objectsPassingTest:^BOOL(GDTStoredEvent *_Nonnull event, BOOL *_Nonnull stop) {
NSNumber *qosTier = GDTCCTQosTierFromGDTEventQosTier(event.qosTier);
return [qosTier isEqual:@(GDTCCTQoSDefault)] || [qosTier isEqual:@(GDTCCTQoSWifiOnly)] ||
[qosTier isEqual:@(GDTCCTQoSDaily)];
}];
}
/** Returns a set of logs that only should have a single upload attempt per day.
*
* @note This should be called from a thread safe method.
* @return A set of logs that are ok to upload only once per day.
*/
- (NSSet<GDTStoredEvent *> *)logEventsOkToSendDaily {
return
[self.events objectsPassingTest:^BOOL(GDTStoredEvent *_Nonnull event, BOOL *_Nonnull stop) {
return [GDTCCTQosTierFromGDTEventQosTier(event.qosTier) isEqual:@(GDTCCTQoSDaily)];
}];
}
#pragma mark - GDTUploadPackageProtocol
- (void)packageDelivered:(GDTUploadPackage *)package successful:(BOOL)successful {
dispatch_async(_queue, ^{
NSSet<GDTStoredEvent *> *events = [package.events copy];
for (GDTStoredEvent *event in events) {
[self.events removeObject:event];
}
});
}
- (void)packageExpired:(GDTUploadPackage *)package {
[self packageDelivered:package successful:YES];
}
@end

View File

@ -0,0 +1,227 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "GDTCCTLibrary/Private/GDTCCTUploader.h"
#import <GoogleDataTransport/GDTConsoleLogger.h>
#import <GoogleDataTransport/GDTPlatform.h>
#import <GoogleDataTransport/GDTRegistrar.h>
#import <nanopb/pb.h>
#import <nanopb/pb_decode.h>
#import <nanopb/pb_encode.h>
#import "GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h"
#import "GDTCCTLibrary/Private/GDTCCTPrioritizer.h"
#import "GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h"
@interface GDTCCTUploader ()
// Redeclared as readwrite.
@property(nullable, nonatomic, readwrite) NSURLSessionUploadTask *currentTask;
/** If running in the background, the current background ID. */
@property(nonatomic) BOOL runningInBackground;
@end
@implementation GDTCCTUploader
+ (void)load {
GDTCCTUploader *uploader = [GDTCCTUploader sharedInstance];
[[GDTRegistrar sharedInstance] registerUploader:uploader target:kGDTTargetCCT];
}
+ (instancetype)sharedInstance {
static GDTCCTUploader *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[GDTCCTUploader alloc] init];
});
return sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
_uploaderQueue = dispatch_queue_create("com.google.GDTCCTUploader", DISPATCH_QUEUE_SERIAL);
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_uploaderSession = [NSURLSession sessionWithConfiguration:config];
}
return self;
}
- (NSURL *)defaultServerURL {
static NSURL *defaultServerURL;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// These strings should be interleaved to construct the real URL. This is just to (hopefully)
// fool github URL scanning bots.
const char *p1 = "hts/frbslgiggolai.o/0clgbth";
const char *p2 = "tp:/ieaeogn.ogepscmvc/o/ac";
const char defaultURL[54] = {
p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], p1[4], p2[4], p1[5],
p2[5], p1[6], p2[6], p1[7], p2[7], p1[8], p2[8], p1[9], p2[9], p1[10], p2[10],
p1[11], p2[11], p1[12], p2[12], p1[13], p2[13], p1[14], p2[14], p1[15], p2[15], p1[16],
p2[16], p1[17], p2[17], p1[18], p2[18], p1[19], p2[19], p1[20], p2[20], p1[21], p2[21],
p1[22], p2[22], p1[23], p2[23], p1[24], p2[24], p1[25], p2[25], p1[26], '\0'};
defaultServerURL = [NSURL URLWithString:[NSString stringWithUTF8String:defaultURL]];
});
return defaultServerURL;
}
- (void)uploadPackage:(GDTUploadPackage *)package {
GDTBackgroundIdentifier bgID = GDTBackgroundIdentifierInvalid;
if (_runningInBackground) {
bgID = [[GDTApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
if (bgID != GDTBackgroundIdentifierInvalid) {
[[GDTApplication sharedApplication] endBackgroundTask:bgID];
}
}];
}
dispatch_async(_uploaderQueue, ^{
if (self->_currentTask || self->_currentUploadPackage) {
GDTLogWarning(GDTMCWUploadFailed, @"%@",
@"An upload shouldn't be initiated with another in progress.");
return;
}
NSURL *serverURL = self.serverURL ? self.serverURL : [self defaultServerURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:serverURL];
request.HTTPMethod = @"POST";
id completionHandler =
^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {
if (error) {
GDTLogWarning(GDTMCWUploadFailed, @"There was an error uploading events: %@", error);
}
NSError *decodingError;
gdt_cct_LogResponse logResponse = GDTCCTDecodeLogResponse(data, &decodingError);
if (!decodingError && logResponse.has_next_request_wait_millis) {
self->_nextUploadTime =
[GDTClock clockSnapshotInTheFuture:logResponse.next_request_wait_millis];
} else {
// 15 minutes from now.
self->_nextUploadTime = [GDTClock clockSnapshotInTheFuture:15 * 60 * 1000];
}
pb_release(gdt_cct_LogResponse_fields, &logResponse);
[package completeDelivery];
// End the background task if there was one.
if (bgID != GDTBackgroundIdentifierInvalid) {
[[GDTApplication sharedApplication] endBackgroundTask:bgID];
}
self.currentTask = nil;
self.currentUploadPackage = nil;
};
self->_currentUploadPackage = package;
NSData *requestProtoData = [self constructRequestProtoFromPackage:(GDTUploadPackage *)package];
self.currentTask = [self.uploaderSession uploadTaskWithRequest:request
fromData:requestProtoData
completionHandler:completionHandler];
[self.currentTask resume];
});
}
- (BOOL)readyToUploadWithConditions:(GDTUploadConditions)conditions {
__block BOOL result = NO;
dispatch_sync(_uploaderQueue, ^{
if (self->_currentUploadPackage) {
result = NO;
return;
}
if (self->_currentTask) {
result = NO;
return;
}
if ((conditions & GDTUploadConditionHighPriority) == GDTUploadConditionHighPriority) {
result = YES;
return;
} else if (self->_nextUploadTime) {
result = [[GDTClock snapshot] isAfter:self->_nextUploadTime];
return;
}
result = YES;
});
return result;
}
#pragma mark - Private helper methods
/** Constructs data given an upload package.
*
* @param package The upload package used to construct the request proto bytes.
* @return Proto bytes representing a gdt_cct_LogRequest object.
*/
- (nonnull NSData *)constructRequestProtoFromPackage:(GDTUploadPackage *)package {
// Segment the log events by log type.
NSMutableDictionary<NSString *, NSMutableSet<GDTStoredEvent *> *> *logMappingIDToLogSet =
[[NSMutableDictionary alloc] init];
[package.events
enumerateObjectsUsingBlock:^(GDTStoredEvent *_Nonnull event, BOOL *_Nonnull stop) {
NSMutableSet *logSet = logMappingIDToLogSet[event.mappingID];
logSet = logSet ? logSet : [[NSMutableSet alloc] init];
[logSet addObject:event];
logMappingIDToLogSet[event.mappingID] = logSet;
}];
gdt_cct_BatchedLogRequest batchedLogRequest =
GDTCCTConstructBatchedLogRequest(logMappingIDToLogSet);
NSData *data = GDTCCTEncodeBatchedLogRequest(&batchedLogRequest);
pb_release(gdt_cct_BatchedLogRequest_fields, &batchedLogRequest);
return data ? data : [[NSData alloc] init];
}
#pragma mark - GDTUploadPackageProtocol
- (void)packageExpired:(GDTUploadPackage *)package {
dispatch_async(_uploaderQueue, ^{
[self.currentTask cancel];
self.currentTask = nil;
self.currentUploadPackage = nil;
});
}
#pragma mark - GDTLifecycleProtocol
- (void)appWillBackground:(GDTApplication *)app {
_runningInBackground = YES;
__block GDTBackgroundIdentifier bgID = [app beginBackgroundTaskWithExpirationHandler:^{
if (bgID != GDTBackgroundIdentifierInvalid) {
[app endBackgroundTask:bgID];
}
}];
if (bgID != GDTBackgroundIdentifierInvalid) {
dispatch_async(_uploaderQueue, ^{
[[GDTApplication sharedApplication] endBackgroundTask:bgID];
});
}
}
- (void)appWillForeground:(GDTApplication *)app {
_runningInBackground = NO;
}
- (void)appWillTerminate:(GDTApplication *)application {
dispatch_sync(_uploaderQueue, ^{
[self.currentTask cancel];
[self.currentUploadPackage completeDelivery];
});
}
@end

View File

@ -0,0 +1,112 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <GoogleDataTransport/GDTStoredEvent.h>
#import "GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h"
NS_ASSUME_NONNULL_BEGIN
#pragma mark - General purpose encoders
/** Converts an NSString* to a pb_bytes_array_t*.
*
* @note malloc is called in this method. Ensure that pb_release is called on this or the parent.
*
* @param string The string to convert.
* @return A newly allocated array of bytes representing the UTF8 encoding of the string.
*/
pb_bytes_array_t *GDTCCTEncodeString(NSString *string);
/** Converts an NSData to a pb_bytes_array_t*.
*
* @note malloc is called in this method. Ensure that pb_release is called on this or the parent.
*
* @param data The data to convert.
* @return A newly allocated array of bytes with [data bytes] copied into it.
*/
pb_bytes_array_t *GDTCCTEncodeData(NSData *data);
#pragma mark - CCT object constructors
/** Encodes a batched log request.
*
* @note Ensure that pb_release is called on the batchedLogRequest param.
*
* @param batchedLogRequest A pointer to the log batch to encode to bytes.
* @return An NSData object representing the bytes of the log request batch.
*/
FOUNDATION_EXPORT
NSData *GDTCCTEncodeBatchedLogRequest(gdt_cct_BatchedLogRequest *batchedLogRequest);
/** Constructs a gdt_cct_BatchedLogRequest given sets of events segemented by mapping ID.
*
* @note malloc is called in this method. Ensure that pb_release is called on this or the parent.
*
* @param logMappingIDToLogSet A map of mapping IDs to sets of events to convert into a batch.
* @return A newly created gdt_cct_BatchedLogRequest.
*/
FOUNDATION_EXPORT
gdt_cct_BatchedLogRequest GDTCCTConstructBatchedLogRequest(
NSDictionary<NSString *, NSSet<GDTStoredEvent *> *> *logMappingIDToLogSet);
/** Constructs a log request given a log source and a set of events.
*
* @note malloc is called in this method. Ensure that pb_release is called on this or the parent.
* @param logSource The CCT log source to put into the log request.
* @param logSet The set of events to send in this log request.
*/
FOUNDATION_EXPORT
gdt_cct_LogRequest GDTCCTConstructLogRequest(int32_t logSource, NSSet<GDTStoredEvent *> *logSet);
/** Constructs a gdt_cct_LogEvent given a GDTStoredEvent*.
*
* @param event The GDTStoredEvent to convert.
* @return The new gdt_cct_LogEvent object.
*/
FOUNDATION_EXPORT
gdt_cct_LogEvent GDTCCTConstructLogEvent(GDTStoredEvent *event);
/** Constructs a gdt_cct_ClientInfo representing the client device.
*
* @return The new gdt_cct_ClientInfo object.
*/
FOUNDATION_EXPORT
gdt_cct_ClientInfo GDTCCTConstructClientInfo(void);
/** Constructs a gdt_cct_IosClientInfo representing the client device.
*
* @return The new gdt_cct_IosClientInfo object.
*/
FOUNDATION_EXPORT
gdt_cct_IosClientInfo GDTCCTConstructiOSClientInfo(void);
#pragma mark - CCT object decoders
/** Decodes a gdt_cct_LogResponse given proto bytes.
*
* @note malloc is called in this method. Ensure that pb_release is called on the return value.
*
* @param data The proto bytes of the gdt_cct_LogResponse.
* @param error An error that will be populated if something went wrong during decoding.
* @return A newly allocated gdt_cct_LogResponse from the data, if the bytes decoded properly.
*/
FOUNDATION_EXPORT
gdt_cct_LogResponse GDTCCTDecodeLogResponse(NSData *data, NSError **error);
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,44 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <GoogleDataTransport/GDTClock.h>
#import <GoogleDataTransport/GDTPrioritizer.h>
NS_ASSUME_NONNULL_BEGIN
/** Manages the prioritization of events from GoogleDataTransport. */
@interface GDTCCTPrioritizer : NSObject <GDTPrioritizer>
/** The queue on which this prioritizer operates. */
@property(nonatomic) dispatch_queue_t queue;
/** All log events that have been processed by this prioritizer. */
@property(nonatomic) NSMutableSet<GDTStoredEvent *> *events;
/** The most recent attempted upload of daily uploaded logs. */
@property(nonatomic) GDTClock *timeOfLastDailyUpload;
/** Creates and/or returns the singleton instance of this class.
*
* @return The singleton instance of this class.
*/
+ (instancetype)sharedInstance;
NS_ASSUME_NONNULL_END
@end

View File

@ -0,0 +1,52 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <GoogleDataTransport/GDTUploader.h>
NS_ASSUME_NONNULL_BEGIN
/** Class capable of uploading events to the CCT backend. */
@interface GDTCCTUploader : NSObject <GDTUploader>
/** The queue on which all CCT uploading will occur. */
@property(nonatomic, readonly) dispatch_queue_t uploaderQueue;
/** The server URL to upload to. Look at .m for the default value. */
@property(nonatomic) NSURL *serverURL;
/** The URL session that will attempt upload. */
@property(nonatomic, readonly) NSURLSession *uploaderSession;
/** The current upload task. */
@property(nullable, nonatomic, readonly) NSURLSessionUploadTask *currentTask;
/** Current upload package. */
@property(nullable, nonatomic) GDTUploadPackage *currentUploadPackage;
/** The next upload time. */
@property(nullable, nonatomic) GDTClock *nextUploadTime;
/** Creates and/or returns the singleton instance of this class.
*
* @return The singleton instance of this class.
*/
+ (instancetype)sharedInstance;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,128 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.3.9.2 */
#include "cct.nanopb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
const gdt_cct_NetworkConnectionInfo_NetworkType gdt_cct_NetworkConnectionInfo_network_type_default = gdt_cct_NetworkConnectionInfo_NetworkType_NONE;
const gdt_cct_NetworkConnectionInfo_MobileSubtype gdt_cct_NetworkConnectionInfo_mobile_subtype_default = gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE;
const gdt_cct_QosTierConfiguration_QosTier gdt_cct_LogRequest_qos_tier_default = gdt_cct_QosTierConfiguration_QosTier_DEFAULT;
const int32_t gdt_cct_QosTierConfiguration_log_source_default = 0;
const pb_field_t gdt_cct_LogEvent_fields[7] = {
PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, gdt_cct_LogEvent, event_time_ms, event_time_ms, 0),
PB_FIELD( 6, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_LogEvent, source_extension, event_time_ms, 0),
PB_FIELD( 11, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, event_code, source_extension, 0),
PB_FIELD( 15, SINT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, timezone_offset_seconds, event_code, 0),
PB_FIELD( 17, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, event_uptime_ms, timezone_offset_seconds, 0),
PB_FIELD( 23, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, network_connection_info, event_uptime_ms, &gdt_cct_NetworkConnectionInfo_fields),
PB_LAST_FIELD
};
const pb_field_t gdt_cct_NetworkConnectionInfo_fields[3] = {
PB_FIELD( 1, ENUM , OPTIONAL, STATIC , FIRST, gdt_cct_NetworkConnectionInfo, network_type, network_type, &gdt_cct_NetworkConnectionInfo_network_type_default),
PB_FIELD( 2, UENUM , OPTIONAL, STATIC , OTHER, gdt_cct_NetworkConnectionInfo, mobile_subtype, network_type, &gdt_cct_NetworkConnectionInfo_mobile_subtype_default),
PB_LAST_FIELD
};
const pb_field_t gdt_cct_IosClientInfo_fields[8] = {
PB_FIELD( 3, BYTES , OPTIONAL, POINTER , FIRST, gdt_cct_IosClientInfo, os_major_version, os_major_version, 0),
PB_FIELD( 4, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, os_full_version, os_major_version, 0),
PB_FIELD( 5, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, application_build, os_full_version, 0),
PB_FIELD( 6, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, country, application_build, 0),
PB_FIELD( 7, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, model, country, 0),
PB_FIELD( 8, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, language_code, model, 0),
PB_FIELD( 11, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, application_bundle_id, language_code, 0),
PB_LAST_FIELD
};
const pb_field_t gdt_cct_ClientInfo_fields[3] = {
PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, gdt_cct_ClientInfo, client_type, client_type, 0),
PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_ClientInfo, ios_client_info, client_type, &gdt_cct_IosClientInfo_fields),
PB_LAST_FIELD
};
const pb_field_t gdt_cct_BatchedLogRequest_fields[2] = {
PB_FIELD( 1, MESSAGE , REPEATED, POINTER , FIRST, gdt_cct_BatchedLogRequest, log_request, log_request, &gdt_cct_LogRequest_fields),
PB_LAST_FIELD
};
const pb_field_t gdt_cct_LogRequest_fields[7] = {
PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, gdt_cct_LogRequest, client_info, client_info, &gdt_cct_ClientInfo_fields),
PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, log_source, client_info, 0),
PB_FIELD( 3, MESSAGE , REPEATED, POINTER , OTHER, gdt_cct_LogRequest, log_event, log_source, &gdt_cct_LogEvent_fields),
PB_FIELD( 4, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, request_time_ms, log_event, 0),
PB_FIELD( 8, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, request_uptime_ms, request_time_ms, 0),
PB_FIELD( 9, UENUM , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, qos_tier, request_uptime_ms, &gdt_cct_LogRequest_qos_tier_default),
PB_LAST_FIELD
};
const pb_field_t gdt_cct_QosTierConfiguration_fields[3] = {
PB_FIELD( 2, UENUM , OPTIONAL, STATIC , FIRST, gdt_cct_QosTierConfiguration, qos_tier, qos_tier, 0),
PB_FIELD( 3, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_QosTierConfiguration, log_source, qos_tier, &gdt_cct_QosTierConfiguration_log_source_default),
PB_LAST_FIELD
};
const pb_field_t gdt_cct_QosTiersOverride_fields[3] = {
PB_FIELD( 1, MESSAGE , REPEATED, POINTER , FIRST, gdt_cct_QosTiersOverride, qos_tier_configuration, qos_tier_configuration, &gdt_cct_QosTierConfiguration_fields),
PB_FIELD( 2, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_QosTiersOverride, qos_tier_fingerprint, qos_tier_configuration, 0),
PB_LAST_FIELD
};
const pb_field_t gdt_cct_LogResponse_fields[3] = {
PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, gdt_cct_LogResponse, next_request_wait_millis, next_request_wait_millis, 0),
PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_LogResponse, qos_tier, next_request_wait_millis, &gdt_cct_QosTiersOverride_fields),
PB_LAST_FIELD
};
/* Check that field information fits in pb_field_t */
#if !defined(PB_FIELD_32BIT)
/* If you get an error here, it means that you need to define PB_FIELD_32BIT
* compile-time option. You can do that in pb.h or on compiler command line.
*
* The reason you need to do this is that some of your messages contain tag
* numbers or field sizes that are larger than what can fit in 8 or 16 bit
* field descriptors.
*/
PB_STATIC_ASSERT((pb_membersize(gdt_cct_LogEvent, network_connection_info) < 65536 && pb_membersize(gdt_cct_ClientInfo, ios_client_info) < 65536 && pb_membersize(gdt_cct_LogRequest, client_info) < 65536 && pb_membersize(gdt_cct_LogResponse, qos_tier) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_gdt_cct_LogEvent_gdt_cct_NetworkConnectionInfo_gdt_cct_IosClientInfo_gdt_cct_ClientInfo_gdt_cct_BatchedLogRequest_gdt_cct_LogRequest_gdt_cct_QosTierConfiguration_gdt_cct_QosTiersOverride_gdt_cct_LogResponse)
#endif
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
/* If you get an error here, it means that you need to define PB_FIELD_16BIT
* compile-time option. You can do that in pb.h or on compiler command line.
*
* The reason you need to do this is that some of your messages contain tag
* numbers or field sizes that are larger than what can fit in the default
* 8 bit descriptors.
*/
PB_STATIC_ASSERT((pb_membersize(gdt_cct_LogEvent, network_connection_info) < 256 && pb_membersize(gdt_cct_ClientInfo, ios_client_info) < 256 && pb_membersize(gdt_cct_LogRequest, client_info) < 256 && pb_membersize(gdt_cct_LogResponse, qos_tier) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_gdt_cct_LogEvent_gdt_cct_NetworkConnectionInfo_gdt_cct_IosClientInfo_gdt_cct_ClientInfo_gdt_cct_BatchedLogRequest_gdt_cct_LogRequest_gdt_cct_QosTierConfiguration_gdt_cct_QosTiersOverride_gdt_cct_LogResponse)
#endif
/* @@protoc_insertion_point(eof) */

View File

@ -0,0 +1,281 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Automatically generated nanopb header */
/* Generated by nanopb-0.3.9.2 */
#ifndef PB_GDT_CCT_CCT_NANOPB_H_INCLUDED
#define PB_GDT_CCT_CCT_NANOPB_H_INCLUDED
#include <nanopb/pb.h>
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
/* Enum definitions */
typedef enum _gdt_cct_NetworkConnectionInfo_NetworkType {
gdt_cct_NetworkConnectionInfo_NetworkType_NONE = -1,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE = 0,
gdt_cct_NetworkConnectionInfo_NetworkType_WIFI = 1,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_MMS = 2,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_SUPL = 3,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_DUN = 4,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_HIPRI = 5,
gdt_cct_NetworkConnectionInfo_NetworkType_WIMAX = 6,
gdt_cct_NetworkConnectionInfo_NetworkType_BLUETOOTH = 7,
gdt_cct_NetworkConnectionInfo_NetworkType_DUMMY = 8,
gdt_cct_NetworkConnectionInfo_NetworkType_ETHERNET = 9,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_FOTA = 10,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_IMS = 11,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_CBS = 12,
gdt_cct_NetworkConnectionInfo_NetworkType_WIFI_P2P = 13,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_IA = 14,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_EMERGENCY = 15,
gdt_cct_NetworkConnectionInfo_NetworkType_PROXY = 16,
gdt_cct_NetworkConnectionInfo_NetworkType_VPN = 17
} gdt_cct_NetworkConnectionInfo_NetworkType;
#define _gdt_cct_NetworkConnectionInfo_NetworkType_MIN gdt_cct_NetworkConnectionInfo_NetworkType_NONE
#define _gdt_cct_NetworkConnectionInfo_NetworkType_MAX gdt_cct_NetworkConnectionInfo_NetworkType_VPN
#define _gdt_cct_NetworkConnectionInfo_NetworkType_ARRAYSIZE ((gdt_cct_NetworkConnectionInfo_NetworkType)(gdt_cct_NetworkConnectionInfo_NetworkType_VPN+1))
typedef enum _gdt_cct_NetworkConnectionInfo_MobileSubtype {
gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE = 0,
gdt_cct_NetworkConnectionInfo_MobileSubtype_GPRS = 1,
gdt_cct_NetworkConnectionInfo_MobileSubtype_EDGE = 2,
gdt_cct_NetworkConnectionInfo_MobileSubtype_UMTS = 3,
gdt_cct_NetworkConnectionInfo_MobileSubtype_CDMA = 4,
gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_0 = 5,
gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_A = 6,
gdt_cct_NetworkConnectionInfo_MobileSubtype_RTT = 7,
gdt_cct_NetworkConnectionInfo_MobileSubtype_HSDPA = 8,
gdt_cct_NetworkConnectionInfo_MobileSubtype_HSUPA = 9,
gdt_cct_NetworkConnectionInfo_MobileSubtype_HSPA = 10,
gdt_cct_NetworkConnectionInfo_MobileSubtype_IDEN = 11,
gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_B = 12,
gdt_cct_NetworkConnectionInfo_MobileSubtype_LTE = 13,
gdt_cct_NetworkConnectionInfo_MobileSubtype_EHRPD = 14,
gdt_cct_NetworkConnectionInfo_MobileSubtype_HSPAP = 15,
gdt_cct_NetworkConnectionInfo_MobileSubtype_GSM = 16,
gdt_cct_NetworkConnectionInfo_MobileSubtype_TD_SCDMA = 17,
gdt_cct_NetworkConnectionInfo_MobileSubtype_IWLAN = 18,
gdt_cct_NetworkConnectionInfo_MobileSubtype_LTE_CA = 19,
gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED = 100
} gdt_cct_NetworkConnectionInfo_MobileSubtype;
#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_MIN gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE
#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_MAX gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED
#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_ARRAYSIZE ((gdt_cct_NetworkConnectionInfo_MobileSubtype)(gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED+1))
typedef enum _gdt_cct_ClientInfo_ClientType {
gdt_cct_ClientInfo_ClientType_CLIENT_UNKNOWN = 0,
gdt_cct_ClientInfo_ClientType_IOS_FIREBASE = 15
} gdt_cct_ClientInfo_ClientType;
#define _gdt_cct_ClientInfo_ClientType_MIN gdt_cct_ClientInfo_ClientType_CLIENT_UNKNOWN
#define _gdt_cct_ClientInfo_ClientType_MAX gdt_cct_ClientInfo_ClientType_IOS_FIREBASE
#define _gdt_cct_ClientInfo_ClientType_ARRAYSIZE ((gdt_cct_ClientInfo_ClientType)(gdt_cct_ClientInfo_ClientType_IOS_FIREBASE+1))
typedef enum _gdt_cct_QosTierConfiguration_QosTier {
gdt_cct_QosTierConfiguration_QosTier_DEFAULT = 0,
gdt_cct_QosTierConfiguration_QosTier_UNMETERED_ONLY = 1,
gdt_cct_QosTierConfiguration_QosTier_UNMETERED_OR_DAILY = 2,
gdt_cct_QosTierConfiguration_QosTier_FAST_IF_RADIO_AWAKE = 3,
gdt_cct_QosTierConfiguration_QosTier_NEVER = 4
} gdt_cct_QosTierConfiguration_QosTier;
#define _gdt_cct_QosTierConfiguration_QosTier_MIN gdt_cct_QosTierConfiguration_QosTier_DEFAULT
#define _gdt_cct_QosTierConfiguration_QosTier_MAX gdt_cct_QosTierConfiguration_QosTier_NEVER
#define _gdt_cct_QosTierConfiguration_QosTier_ARRAYSIZE ((gdt_cct_QosTierConfiguration_QosTier)(gdt_cct_QosTierConfiguration_QosTier_NEVER+1))
/* Struct definitions */
typedef struct _gdt_cct_BatchedLogRequest {
pb_size_t log_request_count;
struct _gdt_cct_LogRequest *log_request;
/* @@protoc_insertion_point(struct:gdt_cct_BatchedLogRequest) */
} gdt_cct_BatchedLogRequest;
typedef struct _gdt_cct_IosClientInfo {
pb_bytes_array_t *os_major_version;
pb_bytes_array_t *os_full_version;
pb_bytes_array_t *application_build;
pb_bytes_array_t *country;
pb_bytes_array_t *model;
pb_bytes_array_t *language_code;
pb_bytes_array_t *application_bundle_id;
/* @@protoc_insertion_point(struct:gdt_cct_IosClientInfo) */
} gdt_cct_IosClientInfo;
typedef struct _gdt_cct_ClientInfo {
bool has_client_type;
gdt_cct_ClientInfo_ClientType client_type;
bool has_ios_client_info;
gdt_cct_IosClientInfo ios_client_info;
/* @@protoc_insertion_point(struct:gdt_cct_ClientInfo) */
} gdt_cct_ClientInfo;
typedef struct _gdt_cct_NetworkConnectionInfo {
bool has_network_type;
gdt_cct_NetworkConnectionInfo_NetworkType network_type;
bool has_mobile_subtype;
gdt_cct_NetworkConnectionInfo_MobileSubtype mobile_subtype;
/* @@protoc_insertion_point(struct:gdt_cct_NetworkConnectionInfo) */
} gdt_cct_NetworkConnectionInfo;
typedef struct _gdt_cct_QosTierConfiguration {
bool has_qos_tier;
gdt_cct_QosTierConfiguration_QosTier qos_tier;
bool has_log_source;
int32_t log_source;
/* @@protoc_insertion_point(struct:gdt_cct_QosTierConfiguration) */
} gdt_cct_QosTierConfiguration;
typedef struct _gdt_cct_QosTiersOverride {
pb_size_t qos_tier_configuration_count;
struct _gdt_cct_QosTierConfiguration *qos_tier_configuration;
bool has_qos_tier_fingerprint;
int64_t qos_tier_fingerprint;
/* @@protoc_insertion_point(struct:gdt_cct_QosTiersOverride) */
} gdt_cct_QosTiersOverride;
typedef struct _gdt_cct_LogEvent {
bool has_event_time_ms;
int64_t event_time_ms;
pb_bytes_array_t *source_extension;
bool has_event_code;
int32_t event_code;
bool has_timezone_offset_seconds;
int64_t timezone_offset_seconds;
bool has_event_uptime_ms;
int64_t event_uptime_ms;
bool has_network_connection_info;
gdt_cct_NetworkConnectionInfo network_connection_info;
/* @@protoc_insertion_point(struct:gdt_cct_LogEvent) */
} gdt_cct_LogEvent;
typedef struct _gdt_cct_LogRequest {
bool has_client_info;
gdt_cct_ClientInfo client_info;
bool has_log_source;
int32_t log_source;
pb_size_t log_event_count;
struct _gdt_cct_LogEvent *log_event;
bool has_request_time_ms;
int64_t request_time_ms;
bool has_request_uptime_ms;
int64_t request_uptime_ms;
bool has_qos_tier;
gdt_cct_QosTierConfiguration_QosTier qos_tier;
/* @@protoc_insertion_point(struct:gdt_cct_LogRequest) */
} gdt_cct_LogRequest;
typedef struct _gdt_cct_LogResponse {
bool has_next_request_wait_millis;
int64_t next_request_wait_millis;
bool has_qos_tier;
gdt_cct_QosTiersOverride qos_tier;
/* @@protoc_insertion_point(struct:gdt_cct_LogResponse) */
} gdt_cct_LogResponse;
/* Default values for struct fields */
extern const gdt_cct_NetworkConnectionInfo_NetworkType gdt_cct_NetworkConnectionInfo_network_type_default;
extern const gdt_cct_NetworkConnectionInfo_MobileSubtype gdt_cct_NetworkConnectionInfo_mobile_subtype_default;
extern const gdt_cct_QosTierConfiguration_QosTier gdt_cct_LogRequest_qos_tier_default;
extern const int32_t gdt_cct_QosTierConfiguration_log_source_default;
/* Initializer values for message structs */
#define gdt_cct_LogEvent_init_default {false, 0, NULL, false, 0, false, 0, false, 0, false, gdt_cct_NetworkConnectionInfo_init_default}
#define gdt_cct_NetworkConnectionInfo_init_default {false, gdt_cct_NetworkConnectionInfo_NetworkType_NONE, false, gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE}
#define gdt_cct_IosClientInfo_init_default {NULL, NULL, NULL, NULL, NULL, NULL, NULL}
#define gdt_cct_ClientInfo_init_default {false, _gdt_cct_ClientInfo_ClientType_MIN, false, gdt_cct_IosClientInfo_init_default}
#define gdt_cct_BatchedLogRequest_init_default {0, NULL}
#define gdt_cct_LogRequest_init_default {false, gdt_cct_ClientInfo_init_default, false, 0, 0, NULL, false, 0, false, 0, false, gdt_cct_QosTierConfiguration_QosTier_DEFAULT}
#define gdt_cct_QosTierConfiguration_init_default {false, _gdt_cct_QosTierConfiguration_QosTier_MIN, false, 0}
#define gdt_cct_QosTiersOverride_init_default {0, NULL, false, 0}
#define gdt_cct_LogResponse_init_default {false, 0, false, gdt_cct_QosTiersOverride_init_default}
#define gdt_cct_LogEvent_init_zero {false, 0, NULL, false, 0, false, 0, false, 0, false, gdt_cct_NetworkConnectionInfo_init_zero}
#define gdt_cct_NetworkConnectionInfo_init_zero {false, _gdt_cct_NetworkConnectionInfo_NetworkType_MIN, false, _gdt_cct_NetworkConnectionInfo_MobileSubtype_MIN}
#define gdt_cct_IosClientInfo_init_zero {NULL, NULL, NULL, NULL, NULL, NULL, NULL}
#define gdt_cct_ClientInfo_init_zero {false, _gdt_cct_ClientInfo_ClientType_MIN, false, gdt_cct_IosClientInfo_init_zero}
#define gdt_cct_BatchedLogRequest_init_zero {0, NULL}
#define gdt_cct_LogRequest_init_zero {false, gdt_cct_ClientInfo_init_zero, false, 0, 0, NULL, false, 0, false, 0, false, _gdt_cct_QosTierConfiguration_QosTier_MIN}
#define gdt_cct_QosTierConfiguration_init_zero {false, _gdt_cct_QosTierConfiguration_QosTier_MIN, false, 0}
#define gdt_cct_QosTiersOverride_init_zero {0, NULL, false, 0}
#define gdt_cct_LogResponse_init_zero {false, 0, false, gdt_cct_QosTiersOverride_init_zero}
/* Field tags (for use in manual encoding/decoding) */
#define gdt_cct_BatchedLogRequest_log_request_tag 1
#define gdt_cct_IosClientInfo_os_major_version_tag 3
#define gdt_cct_IosClientInfo_os_full_version_tag 4
#define gdt_cct_IosClientInfo_application_build_tag 5
#define gdt_cct_IosClientInfo_country_tag 6
#define gdt_cct_IosClientInfo_model_tag 7
#define gdt_cct_IosClientInfo_language_code_tag 8
#define gdt_cct_IosClientInfo_application_bundle_id_tag 11
#define gdt_cct_ClientInfo_client_type_tag 1
#define gdt_cct_ClientInfo_ios_client_info_tag 4
#define gdt_cct_NetworkConnectionInfo_network_type_tag 1
#define gdt_cct_NetworkConnectionInfo_mobile_subtype_tag 2
#define gdt_cct_QosTierConfiguration_qos_tier_tag 2
#define gdt_cct_QosTierConfiguration_log_source_tag 3
#define gdt_cct_QosTiersOverride_qos_tier_configuration_tag 1
#define gdt_cct_QosTiersOverride_qos_tier_fingerprint_tag 2
#define gdt_cct_LogEvent_event_time_ms_tag 1
#define gdt_cct_LogEvent_event_code_tag 11
#define gdt_cct_LogEvent_event_uptime_ms_tag 17
#define gdt_cct_LogEvent_source_extension_tag 6
#define gdt_cct_LogEvent_timezone_offset_seconds_tag 15
#define gdt_cct_LogEvent_network_connection_info_tag 23
#define gdt_cct_LogRequest_request_time_ms_tag 4
#define gdt_cct_LogRequest_request_uptime_ms_tag 8
#define gdt_cct_LogRequest_client_info_tag 1
#define gdt_cct_LogRequest_log_source_tag 2
#define gdt_cct_LogRequest_log_event_tag 3
#define gdt_cct_LogRequest_qos_tier_tag 9
#define gdt_cct_LogResponse_next_request_wait_millis_tag 1
#define gdt_cct_LogResponse_qos_tier_tag 3
/* Struct field encoding specification for nanopb */
extern const pb_field_t gdt_cct_LogEvent_fields[7];
extern const pb_field_t gdt_cct_NetworkConnectionInfo_fields[3];
extern const pb_field_t gdt_cct_IosClientInfo_fields[8];
extern const pb_field_t gdt_cct_ClientInfo_fields[3];
extern const pb_field_t gdt_cct_BatchedLogRequest_fields[2];
extern const pb_field_t gdt_cct_LogRequest_fields[7];
extern const pb_field_t gdt_cct_QosTierConfiguration_fields[3];
extern const pb_field_t gdt_cct_QosTiersOverride_fields[3];
extern const pb_field_t gdt_cct_LogResponse_fields[3];
/* Maximum encoded size of messages (where known) */
/* gdt_cct_LogEvent_size depends on runtime parameters */
#define gdt_cct_NetworkConnectionInfo_size 13
/* gdt_cct_IosClientInfo_size depends on runtime parameters */
/* gdt_cct_ClientInfo_size depends on runtime parameters */
/* gdt_cct_BatchedLogRequest_size depends on runtime parameters */
/* gdt_cct_LogRequest_size depends on runtime parameters */
#define gdt_cct_QosTierConfiguration_size 13
/* gdt_cct_QosTiersOverride_size depends on runtime parameters */
/* gdt_cct_LogResponse_size depends on runtime parameters */
/* Message IDs (where set with "msgid" option) */
#ifdef PB_MSGID
#define CCT_MESSAGES \
#endif
/* @@protoc_insertion_point(eof) */
#endif

View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@ -0,0 +1,224 @@
# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk)
This repository contains a subset of the Firebase iOS SDK source. It currently
includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase,
FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging,
FirebaseInAppMessagingDisplay, FirebaseMessaging and FirebaseStorage.
The repository also includes GoogleUtilities source. The
[GoogleUtilities](GoogleUtilities/README.md) pod is
a set of utilities used by Firebase and other Google products.
Firebase is an app development platform with tools to help you build, grow and
monetize your app. More information about Firebase can be found at
[https://firebase.google.com](https://firebase.google.com).
## Installation
See the three subsections for details about three different installation methods.
1. [Standard pod install](README.md#standard-pod-install)
1. [Installing from the GitHub repo](README.md#installing-from-github)
1. [Experimental Carthage](README.md#carthage-ios-only)
### Standard pod install
Go to
[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup).
### Installing from GitHub
For releases starting with 5.0.0, the source for each release is also deployed
to CocoaPods master and available via standard
[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod).
These instructions can be used to access the Firebase repo at other branches,
tags, or commits.
#### Background
See
[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod)
for instructions and options about overriding pod source locations.
#### Accessing Firebase Source Snapshots
All of the official releases are tagged in this repo and available via CocoaPods. To access a local
source snapshot or unreleased branch, use Podfile directives like the following:
To access FirebaseFirestore via a branch:
```
pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master'
pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master'
```
To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do:
```
pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk'
pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk'
```
### Carthage (iOS only)
Instructions for the experimental Carthage distribution are at
[Carthage](Carthage.md).
### Rome
Instructions for installing binary frameworks via
[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md).
## Development
To develop Firebase software in this repository, ensure that you have at least
the following software:
* Xcode 10.1 (or later)
* CocoaPods 1.7.2 (or later)
For the pod that you want to develop:
`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open`
Firestore has a self contained Xcode project. See
[Firestore/README.md](Firestore/README.md).
### Adding a New Firebase Pod
See [AddNewPod.md](AddNewPod.md).
### Code Formatting
To ensure that the code is formatted consistently, run the script
[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh)
before creating a PR.
Travis will verify that any code changes are done in a style compliant way. Install
`clang-format` and `swiftformat`.
These commands will get the right versions:
```
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/773cb75d360b58f32048f5964038d09825a507c8/Formula/clang-format.rb
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/3dfea1004e0736754bbf49673cca8aaed8a94089/Formula/swiftformat.rb
```
Note: if you already have a newer version of these installed you may need to
`brew switch` to this version.
### Running Unit Tests
Select a scheme and press Command-u to build a component and run its unit tests.
#### Viewing Code Coverage
First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`.
After running the `AllUnitTests_iOS` scheme in Xcode, execute
`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output`
at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results.
### Running Sample Apps
In order to run the sample apps and integration tests, you'll need valid
`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist
files without real values, but can be replaced with real plist files. To get your own
`GoogleService-Info.plist` files:
1. Go to the [Firebase Console](https://console.firebase.google.com/)
2. Create a new Firebase project, if you don't already have one
3. For each sample app you want to test, create a new Firebase app with the sample app's bundle
identifier (e.g. `com.google.Database-Example`)
4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file
(e.g. in [Example/Database/App/](Example/Database/App/));
Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require
special Apple capabilities, and you will have to change the sample app to use a unique bundle
identifier that you can control in your own Apple Developer account.
## Specific Component Instructions
See the sections below for any special instructions for those components.
### Firebase Auth
If you're doing specific Firebase Auth development, see
[the Auth Sample README](Example/Auth/README.md) for instructions about
building and running the FirebaseAuth pod along with various samples and tests.
### Firebase Database
To run the Database Integration tests, make your database authentication rules
[public](https://firebase.google.com/docs/database/security/quickstart).
### Firebase Storage
To run the Storage Integration tests, follow the instructions in
[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m).
#### Push Notifications
Push notifications can only be delivered to specially provisioned App IDs in the developer portal.
In order to actually test receiving push notifications, you will need to:
1. Change the bundle identifier of the sample app to something you own in your Apple Developer
account, and enable that App ID for push notifications.
2. You'll also need to
[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs)
at **Project Settings > Cloud Messaging > [Your Firebase App]**.
3. Ensure your iOS device is added to your Apple Developer portal as a test device.
#### iOS Simulator
The iOS Simulator cannot register for remote notifications, and will not receive push notifications.
In order to receive push notifications, you'll have to follow the steps above and run the app on a
physical device.
## Community Supported Efforts
We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are
very grateful! We'd like to empower as many developers as we can to be able to use Firebase and
participate in the Firebase community.
### macOS and tvOS
Thanks to contributions from the community, FirebaseABTesting, FirebaseAuth, FirebaseCore,
FirebaseDatabase, FirebaseMessaging,
FirebaseFirestore, FirebaseFunctions and FirebaseStorage now compile, run unit tests, and work on
macOS and tvOS.
For tvOS, checkout the [Sample](Example/tvOSSample).
Keep in mind that macOS and tvOS are not officially supported by Firebase, and this repository is
actively developed primarily for iOS. While we can catch basic unit test issues with Travis, there
may be some changes where the SDK no longer works as expected on macOS or tvOS. If you encounter
this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues).
Note that the Firebase pod is not available for macOS and tvOS.
To install, add a subset of the following to the Podfile:
```
pod 'FirebaseABTesting'
pod 'FirebaseAuth'
pod 'FirebaseCore'
pod 'FirebaseDatabase'
pod 'FirebaseFirestore'
pod 'FirebaseFunctions'
pod 'FirebaseMessaging'
pod 'FirebaseStorage'
```
## Roadmap
See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source
plans and directions.
## Contributing
See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase
iOS SDK.
## License
The contents of this repository is licensed under the
[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
Your use of Firebase is governed by the
[Terms of Service for Firebase Services](https://firebase.google.com/terms/).

View File

@ -195,28 +195,6 @@ typedef NS_ENUM(NSInteger, GULUDMessageCode) {
#pragma mark - Private methods
/// Removes all values from the search list entry specified by 'domainName', the current user, and
/// any host. The change is persistent. Equivalent to -removePersistentDomainForName: of
/// NSUserDefaults.
- (void)clearAllData {
// On macOS, using `kCFPreferencesCurrentHost` will not set all the keys necessary to match
// `NSUserDefaults`.
#if TARGET_OS_OSX
CFStringRef host = kCFPreferencesAnyHost;
#else
CFStringRef host = kCFPreferencesCurrentHost;
#endif // TARGET_OS_OSX
CFArrayRef keyList = CFPreferencesCopyKeyList(_appNameRef, kCFPreferencesCurrentUser, host);
if (!keyList) {
return;
}
CFPreferencesSetMultiple(NULL, keyList, _appNameRef, kCFPreferencesCurrentUser, host);
CFRelease(keyList);
[self scheduleSynchronize];
}
- (void)scheduleSynchronize {
// Synchronize data using a timer so that multiple set... calls can be coalesced under one
// synchronize.

View File

@ -1,9 +1,10 @@
# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk)
This repository contains a subset of the Firebase iOS SDK source. It currently
includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore,
FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging,
FirebaseInAppMessagingDisplay, FirebaseMessaging and FirebaseStorage.
includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase,
FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging,
FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and
FirebaseStorage.
The repository also includes GoogleUtilities source. The
[GoogleUtilities](GoogleUtilities/README.md) pod is
@ -70,19 +71,22 @@ Instructions for installing binary frameworks via
## Development
Follow the subsequent instructions to develop, debug, unit test, run integration
tests, and try out reference samples:
To develop Firebase software in this repository, ensure that you have at least
the following software:
```
$ git clone git@github.com:firebase/firebase-ios-sdk.git
$ cd firebase-ios-sdk/Example
$ pod update
$ open Firebase.xcworkspace
```
* Xcode 10.1 (or later)
* CocoaPods 1.7.2 (or later)
Firestore and Functions have self contained Xcode projects. See
[Firestore/README.md](Firestore/README.md) and
[Functions/README.md](Functions/README.md).
For the pod that you want to develop:
`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open`
Firestore has a self contained Xcode project. See
[Firestore/README.md](Firestore/README.md).
### Adding a New Firebase Pod
See [AddNewPod.md](AddNewPod.md).
### Code Formatting
@ -95,13 +99,17 @@ Travis will verify that any code changes are done in a style compliant way. Inst
These commands will get the right versions:
```
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/773cb75d360b58f32048f5964038d09825a507c8/Formula/clang-format.rb
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/3dfea1004e0736754bbf49673cca8aaed8a94089/Formula/swiftformat.rb
brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb
brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb
```
Note: if you already have a newer version of these installed you may need to
`brew switch` to this version.
To update this section, find the versions of clang-format and swiftformat.rb to
match the versions in the CI failure logs
[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula).
### Running Unit Tests
Select a scheme and press Command-u to build a component and run its unit tests.
@ -175,8 +183,9 @@ very grateful! We'd like to empower as many developers as we can to be able to
participate in the Firebase community.
### macOS and tvOS
Thanks to contributions from the community, FirebaseAuth, FirebaseCore, FirebaseDatabase, FirebaseMessaging,
FirebaseFirestore, FirebaseFunctions and FirebaseStorage now compile, run unit tests, and work on
Thanks to contributions from the community, FirebaseABTesting, FirebaseAuth, FirebaseCore,
FirebaseDatabase, FirebaseMessaging, FirebaseFirestore,
FirebaseFunctions, FirebaseRemoteConfig, and FirebaseStorage now compile, run unit tests, and work on
macOS and tvOS.
For tvOS, checkout the [Sample](Example/tvOSSample).
@ -191,12 +200,14 @@ Note that the Firebase pod is not available for macOS and tvOS.
To install, add a subset of the following to the Podfile:
```
pod 'FirebaseABTesting'
pod 'FirebaseAuth'
pod 'FirebaseCore'
pod 'FirebaseDatabase'
pod 'FirebaseFirestore' # Only iOS and macOS
pod 'FirebaseFirestore'
pod 'FirebaseFunctions'
pod 'FirebaseMessaging' # Only iOS and tvOS
pod 'FirebaseMessaging'
pod 'FirebaseRemoteConfig'
pod 'FirebaseStorage'
```

View File

@ -0,0 +1 @@
../../../FirebaseCore/Firebase/Core/Private/FIRCoreDiagnosticsConnector.h

View File

@ -0,0 +1 @@
../../../FirebaseCore/Firebase/Core/Private/FIRDiagnosticsData.h

View File

@ -0,0 +1 @@
../../../FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnosticsDateFileStorage.h

View File

@ -0,0 +1 @@
../../../FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h

View File

@ -0,0 +1 @@
../../../FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h

View File

@ -0,0 +1 @@
../../../FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h

View File

@ -1 +1 @@
../../../FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.h
../../../FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID+Private.h

Some files were not shown because too many files have changed in this diff Show More