Configured colours and added additional images to ready app for iOS 13 dark mode

This commit is contained in:
Deniz Duezgoeren
2019-10-08 21:37:42 +02:00
parent b7bc097664
commit 85efe3955d
310 changed files with 6512 additions and 4492 deletions
+4 -5
View File
@@ -85,7 +85,7 @@ In order to keep Alamofire focused specifically on core networking implementatio
$ gem install cocoapods
```
> CocoaPods 1.1+ is required to build Alamofire 4.0+.
> CocoaPods 1.7+ is required to build Alamofire 4.9+.
To integrate Alamofire into your Xcode project using CocoaPods, specify it in your `Podfile`:
@@ -95,7 +95,7 @@ platform :ios, '10.0'
use_frameworks!
target '<Your Target Name>' do
pod 'Alamofire', '~> 4.7'
pod 'Alamofire', '~> 4.9'
end
```
@@ -112,14 +112,13 @@ $ pod install
You can install Carthage with [Homebrew](https://brew.sh/) using the following command:
```bash
$ brew update
$ brew install carthage
```
To integrate Alamofire into your Xcode project using Carthage, specify it in your `Cartfile`:
```ogdl
github "Alamofire/Alamofire" ~> 4.7
github "Alamofire/Alamofire" ~> 4.9
```
Run `carthage update` to build the framework and drag the built `Alamofire.framework` into your Xcode project.
@@ -142,7 +141,7 @@ dependencies: [
```swift
dependencies: [
.package(url: "https://github.com/Alamofire/Alamofire.git", from: "4.0.0")
.package(url: "https://github.com/Alamofire/Alamofire.git", from: "4.9.0")
]
```
+3
View File
@@ -159,7 +159,10 @@ open class NetworkReachabilityManager {
let queueEnabled = SCNetworkReachabilitySetDispatchQueue(reachability, listenerQueue)
listenerQueue.async {
self.previousFlags = SCNetworkReachabilityFlags(rawValue: 1 << 30)
guard let flags = self.flags else { return }
self.notifyListener(flags)
}
+13 -2
View File
@@ -497,8 +497,19 @@ open class DownloadRequest: Request {
// MARK: State
/// Cancels the request.
open override func cancel() {
downloadDelegate.downloadTask.cancel { self.downloadDelegate.resumeData = $0 }
override open func cancel() {
cancel(createResumeData: true)
}
/// Cancels the request.
///
/// - parameter createResumeData: Determines whether resume data is created via the underlying download task or not.
open func cancel(createResumeData: Bool) {
if createResumeData {
downloadDelegate.downloadTask.cancel { self.downloadDelegate.resumeData = $0 }
} else {
downloadDelegate.downloadTask.cancel()
}
NotificationCenter.default.post(
name: Notification.Name.Task.DidCancel,
+8 -2
View File
@@ -219,7 +219,10 @@ extension DataRequest {
/// - returns: The request.
@discardableResult
public func validate() -> Self {
return validate(statusCode: self.acceptableStatusCodes).validate(contentType: self.acceptableContentTypes)
let contentTypes = { [unowned self] in
self.acceptableContentTypes
}
return validate(statusCode: acceptableStatusCodes).validate(contentType: contentTypes())
}
}
@@ -310,6 +313,9 @@ extension DownloadRequest {
/// - returns: The request.
@discardableResult
public func validate() -> Self {
return validate(statusCode: self.acceptableStatusCodes).validate(contentType: self.acceptableContentTypes)
let contentTypes = { [unowned self] in
self.acceptableContentTypes
}
return validate(statusCode: acceptableStatusCodes).validate(contentType: contentTypes())
}
}
@@ -20,6 +20,9 @@
NS_ASSUME_NONNULL_BEGIN
/// Block typedef callback parameter to getUserPropertiesWithCallback:.
typedef void (^FIRAInteropUserPropertiesCallback)(NSDictionary<NSString *, id> *userProperties);
/// Connector for bridging communication between Firebase SDKs and FirebaseAnalytics API.
@protocol FIRAnalyticsInterop
@@ -40,6 +43,9 @@ NS_ASSUME_NONNULL_BEGIN
/// Returns the maximum number of user properties.
- (NSInteger)maxUserProperties:(NSString *)origin;
/// Returns the user properties to a callback function.
- (void)getUserPropertiesWithCallback:(FIRAInteropUserPropertiesCallback)callback;
/// Logs events.
- (void)logEventWithOrigin:(NSString *)origin
name:(NSString *)name
+7 -6
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'
+1 -1
View File
@@ -352,7 +352,7 @@ static NSMutableDictionary *sLibraryVersions;
}
// Check if the Analytics flag is explicitly set. If so, no further actions are necessary.
if ([self.options isAnalyticsCollectionExpicitlySet]) {
if ([self.options isAnalyticsCollectionExplicitlySet]) {
return;
}
+31 -6
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) {
self.cachedInstances[protocolName] = instance;
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];
}
}
[self.cachedInstances removeAllObjects];
instancesCopy = nil;
// Empty the cache.
dispatch_sync(_containerQueue, ^{
[self.cachedInstances removeAllObjects];
});
}
@end
+1 -1
View File
@@ -399,7 +399,7 @@ static NSDictionary *sDefaultOptionsDictionary = nil;
return [value boolValue];
}
- (BOOL)isAnalyticsCollectionExpicitlySet {
- (BOOL)isAnalyticsCollectionExplicitlySet {
// If it's de-activated, it classifies as explicity set. If not, it's not a good enough indication
// that the developer wants FirebaseAnalytics enabled so continue checking.
if (self.isAnalyticsCollectionDeactivated) {
@@ -65,7 +65,7 @@ extern NSString *const kServiceInfoFileType;
* Indicates whether or not Analytics collection was explicitly enabled via a plist flag or at
* runtime.
*/
@property(nonatomic, readonly) BOOL isAnalyticsCollectionExpicitlySet;
@property(nonatomic, readonly) BOOL isAnalyticsCollectionExplicitlySet;
/**
* Whether or not Analytics Collection was enabled. Analytics Collection is enabled unless
+17 -10
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
@@ -80,9 +81,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
@@ -99,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.
@@ -179,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).
@@ -195,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'
pod 'FirebaseFunctions'
pod 'FirebaseMessaging'
pod 'FirebaseRemoteConfig'
pod 'FirebaseStorage'
```
@@ -17,10 +17,10 @@
#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 <GoogleDataTransport/GDTCORConsoleLogger.h>
#import <GoogleDataTransport/GDTCOREvent.h>
#import <GoogleDataTransport/GDTCORTargets.h>
#import <GoogleDataTransport/GDTCORTransport.h>
#import <GoogleUtilities/GULAppEnvironmentUtil.h>
#import <GoogleUtilities/GULLogger.h>
@@ -92,7 +92,8 @@ static NSString *const kFIRAppDiagnosticsSDKVersionKey = @"FIRAppDiagnosticsSDKV
NSString *const kFIRCoreDiagnosticsHeartbeatDateFileName = @"FIREBASE_DIAGNOSTICS_HEARTBEAT_DATE";
/**
* @note This should implement the GDTEventDataObject protocol, but can't because of weak-linking.
* @note This should implement the GDTCOREventDataObject protocol, but can't because of
* weak-linking.
*/
@interface FIRCoreDiagnosticsLog : NSObject
@@ -111,14 +112,14 @@ NSString *const kFIRCoreDiagnosticsHeartbeatDateFileName = @"FIREBASE_DIAGNOSTIC
return self;
}
// Provided and required by the GDTEventDataObject protocol.
// Provided and required by the GDTCOREventDataObject 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));
GDTCORLogError(GDTCORMCETransportBytesError, @"Error in nanopb encoding for size: %s",
PB_GET_ERROR(&sizestream));
}
// Encode a 2nd time to actually get the bytes from it.
@@ -126,8 +127,8 @@ NSString *const kFIRCoreDiagnosticsHeartbeatDateFileName = @"FIREBASE_DIAGNOSTIC
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));
GDTCORLogError(GDTCORMCETransportBytesError, @"Error in nanopb encoding for bytes: %s",
PB_GET_ERROR(&ostream));
}
CFDataSetLength(dataRef, ostream.bytes_written);
@@ -149,7 +150,7 @@ NS_ASSUME_NONNULL_BEGIN
@property(nonatomic, readonly) dispatch_queue_t diagnosticsQueue;
/** The transport object used to send data. */
@property(nonatomic, readonly) GDTTransport *transport;
@property(nonatomic, readonly) GDTCORTransport *transport;
/** The storage to store the date of the last sent heartbeat. */
@property(nonatomic, readonly) FIRCoreDiagnosticsDateFileStorage *heartbeatDateStorage;
@@ -170,9 +171,9 @@ NS_ASSUME_NONNULL_END
}
- (instancetype)init {
GDTTransport *transport = [[GDTTransport alloc] initWithMappingID:@"137"
transformers:nil
target:kGDTTargetCCT];
GDTCORTransport *transport = [[GDTCORTransport alloc] initWithMappingID:@"137"
transformers:nil
target:kGDTCORTargetCCT];
FIRCoreDiagnosticsDateFileStorage *dateStorage = [[FIRCoreDiagnosticsDateFileStorage alloc]
initWithFileURL:[[self class] filePathURLWithName:kFIRCoreDiagnosticsHeartbeatDateFileName]];
@@ -182,11 +183,11 @@ NS_ASSUME_NONNULL_END
/** Initializer for unit tests.
*
* @param transport A `GDTTransport` instance which that be used to send event.
* @param transport A `GDTCORTransport` 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
- (instancetype)initWithTransport:(GDTCORTransport *)transport
heartbeatDateStorage:(FIRCoreDiagnosticsDateFileStorage *)heartbeatDateStorage {
self = [super init];
if (self) {
@@ -374,7 +375,8 @@ void FIRPopulateProtoWithCommonInfoFromApp(logs_proto_mobilesdk_ios_ICoreConfigu
config->has_pod_name = 1;
if (!diagnosticObjects[kFIRCDllAppsCountKey]) {
GDTLogError(GDTMCEGeneralError, @"%@", @"App count is a required value in the data dict.");
GDTCORLogError(GDTCORMCEGeneralError, @"%@",
@"App count is a required value in the data dict.");
}
config->app_count = (int32_t)[diagnosticObjects[kFIRCDllAppsCountKey] integerValue];
config->has_app_count = 1;
@@ -635,8 +637,8 @@ void FIRPopulateProtoWithInfoPlistValues(logs_proto_mobilesdk_ios_ICoreConfigura
FIRCoreDiagnosticsLog *log = [[FIRCoreDiagnosticsLog alloc] initWithConfig:icore_config];
// Send the log as a telemetry event.
GDTEvent *event = [self.transport eventForTransport];
event.dataObject = (id<GDTEventDataObject>)log;
GDTCOREvent *event = [self.transport eventForTransport];
event.dataObject = (id<GDTCOREventDataObject>)log;
[self.transport sendTelemetryEvent:event];
});
}
@@ -26,28 +26,19 @@
const pb_field_t logs_proto_mobilesdk_ios_ICoreConfiguration_fields[34] = {
const pb_field_t logs_proto_mobilesdk_ios_ICoreConfiguration_fields[22] = {
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( 7, UENUM , REPEATED, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_service_installed, configuration_type, 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( 12, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, bundle_id, app_id, 0),
PB_FIELD( 16, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, pod_name, bundle_id, 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( 24, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, min_supported_ios_version, os_version, 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),
@@ -55,11 +46,8 @@ const pb_field_t logs_proto_mobilesdk_ios_ICoreConfiguration_fields[34] = {
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_FIELD( 33, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, swizzling_enabled, platform_info, 0),
PB_FIELD( 36, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, using_gdt, swizzling_enabled, 0),
PB_LAST_FIELD
};
@@ -111,23 +111,11 @@ typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType {
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;
@@ -137,7 +125,6 @@ typedef struct _logs_proto_mobilesdk_ios_ICoreConfiguration {
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;
@@ -151,14 +138,8 @@ typedef struct _logs_proto_mobilesdk_ios_ICoreConfiguration {
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) */
@@ -167,30 +148,21 @@ typedef struct _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}
#define logs_proto_mobilesdk_ios_ICoreConfiguration_init_default {false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN, 0, NULL, 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, false, 0, false, 0, false, 0, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN, NULL, false, 0, false, 0}
#define logs_proto_mobilesdk_ios_ICoreConfiguration_init_zero {false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN, 0, NULL, 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, false, 0, false, 0, false, 0, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN, NULL, 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
@@ -199,14 +171,11 @@ typedef struct _logs_proto_mobilesdk_ios_ICoreConfiguration {
#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];
extern const pb_field_t logs_proto_mobilesdk_ios_ICoreConfiguration_fields[22];
/* Maximum encoded size of messages (where known) */
/* logs_proto_mobilesdk_ios_ICoreConfiguration_size depends on runtime parameters */
+17 -10
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
@@ -80,9 +81,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
@@ -99,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.
@@ -179,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).
@@ -195,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'
pod 'FirebaseFunctions'
pod 'FirebaseMessaging'
pod 'FirebaseRemoteConfig'
pod 'FirebaseStorage'
```
@@ -14,7 +14,7 @@
* limitations under the License.
*/
#import "FIRInstanceIDCheckinPreferences.h"
#import <FirebaseInstanceID/FIRInstanceIDCheckinPreferences.h>
@interface FIRInstanceIDCheckinPreferences (Internal)
@@ -14,7 +14,7 @@
* limitations under the License.
*/
#import "FIRInstanceIDCheckinPreferences.h"
#import <FirebaseInstanceID/FIRInstanceIDCheckinPreferences.h>
/** Checkin refresh interval. **/
FOUNDATION_EXPORT const NSTimeInterval kFIRInstanceIDDefaultCheckinInterval;
@@ -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
@@ -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)
/**
+7 -6
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'
@@ -47,6 +47,7 @@ typedef NS_ENUM(NSInteger, FIRMessagingMessageCode) {
kFIRMessagingMessageCodeTokenDelegateMethodsNotImplemented = 2023, // I-FCM002023
kFIRMessagingMessageCodeTopicFormatIsDeprecated = 2024,
kFIRMessagingMessageCodeDirectChannelConnectionFailed = 2025,
kFIRMessagingMessageCodeInvalidClient = 2026,
// FIRMessagingClient.m
kFIRMessagingMessageCodeClient000 = 4000, // I-FCM004000
kFIRMessagingMessageCodeClient001 = 4001, // I-FCM004001
@@ -60,6 +61,9 @@ typedef NS_ENUM(NSInteger, FIRMessagingMessageCode) {
kFIRMessagingMessageCodeClient009 = 4009, // I-FCM004009
kFIRMessagingMessageCodeClient010 = 4010, // I-FCM004010
kFIRMessagingMessageCodeClient011 = 4011, // I-FCM004011
kFIRMessagingMessageCodeClientInvalidState = 4012,
kFIRMessagingMessageCodeClientInvalidStateTimeout = 4013,
// FIRMessagingConnection.m
kFIRMessagingMessageCodeConnection000 = 5000, // I-FCM005000
kFIRMessagingMessageCodeConnection001 = 5001, // I-FCM005001
@@ -106,6 +110,8 @@ typedef NS_ENUM(NSInteger, FIRMessagingMessageCode) {
kFIRMessagingMessageCodeDataMessageManager010 = 7010, // I-FCM007010
kFIRMessagingMessageCodeDataMessageManager011 = 7011, // I-FCM007011
kFIRMessagingMessageCodeDataMessageManager012 = 7012, // I-FCM007012
kFIRMessagingMessageCodeDataMessageManager013 = 7013,
// FIRMessagingPendingTopicsList.m
kFIRMessagingMessageCodePendingTopicsList000 = 8000, // I-FCM008000
// FIRMessagingPubSub.m
@@ -196,4 +202,7 @@ typedef NS_ENUM(NSInteger, FIRMessagingMessageCode) {
kFIRMessagingServiceExtensionLocalFileNotCreated = 20002,
kFIRMessagingServiceExtensionImageNotAttached = 20003,
// FIRMessagingCodedInputStream.m
kFIRMessagingCodeInputStreamInvalidParameters = 21000,
};
+60 -58
View File
@@ -18,26 +18,6 @@
#error FIRMessagingLib should be compiled with ARC.
#endif
#import "FIRMessaging.h"
#import "FIRMessaging_Private.h"
#import "FIRMessagingAnalytics.h"
#import "FIRMessagingClient.h"
#import "FIRMessagingConstants.h"
#import "FIRMessagingContextManagerService.h"
#import "FIRMessagingDataMessageManager.h"
#import "FIRMessagingDefines.h"
#import "FIRMessagingExtensionHelper.h"
#import "FIRMessagingLogger.h"
#import "FIRMessagingPubSub.h"
#import "FIRMessagingReceiver.h"
#import "FIRMessagingRemoteNotificationsProxy.h"
#import "FIRMessagingRmqManager.h"
#import "FIRMessagingSyncMessageManager.h"
#import "FIRMessagingUtilities.h"
#import "FIRMessagingVersionUtilities.h"
#import "FIRMessaging_Private.h"
#import <FirebaseAnalyticsInterop/FIRAnalyticsInterop.h>
#import <FirebaseCore/FIRAppInternal.h>
#import <FirebaseCore/FIRComponent.h>
@@ -46,11 +26,28 @@
#import <FirebaseCore/FIRLibrary.h>
#import <FirebaseInstanceID/FirebaseInstanceID.h>
#import <FirebaseInstanceID/FIRInstanceID_Private.h>
#import <FirebaseMessaging/FIRMessaging.h>
#import <FirebaseMessaging/FIRMessagingExtensionHelper.h>
#import <GoogleUtilities/GULReachabilityChecker.h>
#import <GoogleUtilities/GULUserDefaults.h>
#import <GoogleUtilities/GULAppDelegateSwizzler.h>
#import "NSError+FIRMessaging.h"
#import "Firebase/Messaging/FIRMessagingAnalytics.h"
#import "Firebase/Messaging/FIRMessagingClient.h"
#import "Firebase/Messaging/FIRMessagingConstants.h"
#import "Firebase/Messaging/FIRMessagingContextManagerService.h"
#import "Firebase/Messaging/FIRMessagingDataMessageManager.h"
#import "Firebase/Messaging/FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMessagingPubSub.h"
#import "Firebase/Messaging/FIRMessagingReceiver.h"
#import "Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.h"
#import "Firebase/Messaging/FIRMessagingRmqManager.h"
#import "Firebase/Messaging/FIRMessagingSyncMessageManager.h"
#import "Firebase/Messaging/FIRMessagingUtilities.h"
#import "Firebase/Messaging/FIRMessagingVersionUtilities.h"
#import "Firebase/Messaging/FIRMessaging_Private.h"
#import "Firebase/Messaging/NSError+FIRMessaging.h"
static NSString *const kFIRMessagingMessageViaAPNSRootKey = @"aps";
static NSString *const kFIRMessagingReachabilityHostname = @"www.google.com";
@@ -89,6 +86,20 @@ NSString *const kFIRMessagingAPNSTokenType = @"APNSTokenType"; // APNS Token typ
NSString *const kFIRMessagingPlistAutoInitEnabled =
@"FirebaseMessagingAutoInitEnabled"; // Auto Init Enabled key stored in Info.plist
const BOOL FIRMessagingIsAPNSSyncMessage(NSDictionary *message) {
if ([message[kFIRMessagingMessageViaAPNSRootKey] isKindOfClass:[NSDictionary class]]) {
NSDictionary *aps = message[kFIRMessagingMessageViaAPNSRootKey];
if (aps && [aps isKindOfClass:[NSDictionary class]]) {
return [aps[kFIRMessagingMessageAPNSContentAvailableKey] boolValue];
}
}
return NO;
}
BOOL FIRMessagingIsContextManagerMessage(NSDictionary *message) {
return [FIRMessagingContextManagerService isContextManagerMessage:message];
}
@interface FIRMessagingMessageInfo ()
@property(nonatomic, readwrite, assign) FIRMessagingMessageStatus status;
@@ -170,13 +181,7 @@ NSString *const kFIRMessagingPlistAutoInitEnabled =
FIR_COMPONENT(FIRMessagingInstanceProvider, defaultApp.container);
// We know the instance coming from the container is a FIRMessaging instance, cast it and move on.
FIRMessaging *messaging = (FIRMessaging *)instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[messaging start];
});
return messaging;
return (FIRMessaging *)instance;
}
+ (FIRMessagingExtensionHelper *)extensionHelper {
@@ -223,9 +228,12 @@ NSString *const kFIRMessagingPlistAutoInitEnabled =
// Ensure it's cached so it returns the same instance every time messaging is called.
*isCacheable = YES;
id<FIRAnalyticsInterop> analytics = FIR_COMPONENT(FIRAnalyticsInterop, container);
return [[FIRMessaging alloc] initWithAnalytics:analytics
withInstanceID:[FIRInstanceID instanceID]
withUserDefaults:[GULUserDefaults standardUserDefaults]];
FIRMessaging *messaging =
[[FIRMessaging alloc] initWithAnalytics:analytics
withInstanceID:[FIRInstanceID instanceID]
withUserDefaults:[GULUserDefaults standardUserDefaults]];
[messaging start];
return messaging;
};
FIRComponent *messagingProvider =
[FIRComponent componentWithProtocol:@protocol(FIRMessagingInstanceProvider)
@@ -348,7 +356,9 @@ NSString *const kFIRMessagingPlistAutoInitEnabled =
}
- (void)setupTopics {
_FIRMessagingDevAssert(self.client, @"Invalid nil client before init pubsub.");
if (!self.client) {
FIRMessagingLoggerWarn(kFIRMessagingMessageCodeInvalidClient, @"Invalid nil client before init pubsub.");
}
self.pubsub = [[FIRMessagingPubSub alloc] initWithClient:self.client];
}
@@ -367,8 +377,6 @@ NSString *const kFIRMessagingPlistAutoInitEnabled =
}
- (void)teardown {
_FIRMessagingDevAssert([NSThread isMainThread],
@"FIRMessaging should be called from main thread only.");
[self.client teardown];
self.pubsub = nil;
self.syncMessageManager = nil;
@@ -390,21 +398,25 @@ NSString *const kFIRMessagingPlistAutoInitEnabled =
// the message to the device.
BOOL isOldMessage = NO;
NSString *messageID = message[kFIRMessagingMessageIDKey];
if ([messageID length]) {
if (messageID.length) {
[self.rmq2Manager saveS2dMessageWithRmqId:messageID];
BOOL isSyncMessage = [[self class] isAPNSSyncMessage:message];
BOOL isSyncMessage = FIRMessagingIsAPNSSyncMessage(message);
if (isSyncMessage) {
isOldMessage = [self.syncMessageManager didReceiveAPNSSyncMessage:message];
}
}
// Prevent duplicates by keeping a cache of all the logged messages during each session.
// The duplicates only happen when the 3P app calls `appDidReceiveMessage:` along with
// us swizzling their implementation to call the same method implicitly.
if (!isOldMessage && messageID.length) {
isOldMessage = [self.loggedMessageIDs containsObject:messageID];
if (!isOldMessage) {
[self.loggedMessageIDs addObject:messageID];
// Prevent duplicates by keeping a cache of all the logged messages during each session.
// The duplicates only happen when the 3P app calls `appDidReceiveMessage:` along with
// us swizzling their implementation to call the same method implicitly.
// We need to rule out the contextual message because it shares the same message ID
// as the local notification it will schedule. And because it is also a APNSSync message
// its duplication is already checked previously.
if (!isOldMessage && !FIRMessagingIsContextManagerMessage(message)) {
isOldMessage = [self.loggedMessageIDs containsObject:messageID];
if (!isOldMessage) {
[self.loggedMessageIDs addObject:messageID];
}
}
}
@@ -417,20 +429,12 @@ NSString *const kFIRMessagingPlistAutoInitEnabled =
}
- (BOOL)handleContextManagerMessage:(NSDictionary *)message {
if ([FIRMessagingContextManagerService isContextManagerMessage:message]) {
if (FIRMessagingIsContextManagerMessage(message)) {
return [FIRMessagingContextManagerService handleContextManagerMessage:message];
}
return NO;
}
+ (BOOL)isAPNSSyncMessage:(NSDictionary *)message {
if ([message[kFIRMessagingMessageViaAPNSRootKey] isKindOfClass:[NSDictionary class]]) {
NSDictionary *aps = message[kFIRMessagingMessageViaAPNSRootKey];
return [aps[kFIRMessagingMessageAPNSContentAvailableKey] boolValue];
}
return NO;
}
- (void)handleIncomingLinkIfNeededFromMessage:(NSDictionary *)message {
#if TARGET_OS_IOS || TARGET_OS_TV
NSURL *url = [self linkURLFromMessage:message];
@@ -826,15 +830,13 @@ NSString *const kFIRMessagingPlistAutoInitEnabled =
to:(NSString *)to
withMessageID:(NSString *)messageID
timeToLive:(int64_t)ttl {
_FIRMessagingDevAssert([to length] != 0, @"Invalid receiver id for FIRMessaging-message");
NSMutableDictionary *fcmMessage = [[self class] createFIRMessagingMessageWithMessage:message
to:to
withID:messageID
timeToLive:ttl
delay:0];
FIRMessagingLoggerInfo(kFIRMessagingMessageCodeMessaging013, @"Sending message: %@ with id: %@",
message, messageID);
FIRMessagingLoggerInfo(kFIRMessagingMessageCodeMessaging013, @"Sending message: %@ with id: %@ to %@.",
message, messageID, to);
[self.dataMessageManager sendDataMessageStanza:fcmMessage];
}
@@ -872,7 +874,7 @@ NSString *const kFIRMessagingPlistAutoInitEnabled =
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
[self.delegate messaging:self didReceiveMessage:remoteMessage];
#pragma pop
#pragma clang diagnostic pop
} else {
// Delegate methods weren't implemented, so messages are being dropped, log a warning
FIRMessagingLoggerWarn(kFIRMessagingMessageCodeRemoteMessageDelegateMethodNotImplemented,
@@ -14,14 +14,16 @@
* limitations under the License.
*/
#import "FIRMessagingAnalytics.h"
#import "FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMessagingAnalytics.h"
#import <FirebaseAnalyticsInterop/FIRInteropEventNames.h>
#import <FirebaseAnalyticsInterop/FIRInteropParameterNames.h>
#import <GoogleUtilities/GULAppEnvironmentUtil.h>
#import <GoogleUtilities/GULAppDelegateSwizzler.h>
#import "Firebase/Messaging/FIRMessagingLogger.h"
static NSString *const kLogTag = @"FIRMessagingAnalytics";
// aps Key
@@ -14,7 +14,7 @@
* limitations under the License.
*/
#import "FIRMessaging.h"
#import <FirebaseMessaging/FIRMessaging.h>
@class GULReachabilityChecker;
@class GPBMessage;
+32 -33
View File
@@ -14,22 +14,22 @@
* limitations under the License.
*/
#import "FIRMessagingClient.h"
#import "Firebase/Messaging/FIRMessagingClient.h"
#import <FirebaseInstanceID/FIRInstanceID_Private.h>
#import <FirebaseMessaging/FIRMessaging.h>
#import <GoogleUtilities/GULReachabilityChecker.h>
#import "FIRMessaging.h"
#import "FIRMessagingConnection.h"
#import "FIRMessagingConstants.h"
#import "FIRMessagingDataMessageManager.h"
#import "FIRMessagingDefines.h"
#import "FIRMessagingLogger.h"
#import "FIRMessagingRmqManager.h"
#import "FIRMessagingTopicsCommon.h"
#import "FIRMessagingUtilities.h"
#import "NSError+FIRMessaging.h"
#import "FIRMessagingPubSubRegistrar.h"
#import "Firebase/Messaging/FIRMessagingConnection.h"
#import "Firebase/Messaging/FIRMessagingConstants.h"
#import "Firebase/Messaging/FIRMessagingDataMessageManager.h"
#import "Firebase/Messaging/FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMessagingRmqManager.h"
#import "Firebase/Messaging/FIRMessagingTopicsCommon.h"
#import "Firebase/Messaging/FIRMessagingUtilities.h"
#import "Firebase/Messaging/NSError+FIRMessaging.h"
#import "Firebase/Messaging/FIRMessagingPubSubRegistrar.h"
static const NSTimeInterval kConnectTimeoutInterval = 40.0;
static const NSTimeInterval kReconnectDelayInSeconds = 2 * 60; // 2 minutes
@@ -131,7 +131,9 @@ static NSUInteger FIRMessagingServerPort() {
}
- (void)teardown {
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient000, @"");
if (![NSThread isMainThread]) {
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeClient000, @"FIRMessagingClient should be called from main thread only.");
}
self.stayConnected = NO;
// Clear all the handlers
@@ -140,9 +142,8 @@ static NSUInteger FIRMessagingServerPort() {
[self.connection teardown];
// Stop all subscription requests
[self.registrar stopAllSubscriptionRequests];
[self.registrar stopAllSubscriptionRequests];
_FIRMessagingDevAssert(self.connection.state == kFIRMessagingConnectionNotConnected, @"Did not disconnect");
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[[NSNotificationCenter defaultCenter] removeObserver:self];
@@ -166,10 +167,7 @@ static NSUInteger FIRMessagingServerPort() {
options:(NSDictionary *)options
shouldDelete:(BOOL)shouldDelete
handler:(FIRMessagingTopicOperationCompletion)handler {
_FIRMessagingDevAssert(handler != nil, @"Invalid handler to FIRMessaging subscribe");
FIRMessagingTopicOperationCompletion completion = ^void(NSError *error) {
FIRMessagingTopicOperationCompletion completion = ^void(NSError *error) {
if (error) {
FIRMessagingLoggerError(kFIRMessagingMessageCodeClient001, @"Failed to subscribe to topic %@",
error);
@@ -182,7 +180,9 @@ static NSUInteger FIRMessagingServerPort() {
@"Successfully subscribed to topic %@", topic);
}
}
handler(error);
if (handler) {
handler(error);
}
};
if ([[FIRInstanceID instanceID] tryToLoadValidCheckinInfo]) {
@@ -316,8 +316,6 @@ static NSUInteger FIRMessagingServerPort() {
self.stayConnected = tryToConnectLater;
[self.connection signOut];
_FIRMessagingDevAssert(self.connection.state == kFIRMessagingConnectionNotConnected,
@"FIRMessaging connection did not disconnect");
// since we can disconnect while still trying to establish the connection it's required to
// cancel all performSelectors else the object might be retained
@@ -421,8 +419,6 @@ static NSUInteger FIRMessagingServerPort() {
- (void)setupConnection {
NSString *host = FIRMessagingServerHost();
NSUInteger port = FIRMessagingServerPort();
_FIRMessagingDevAssert([host length] > 0 && port != 0, @"Invalid port or host");
if (self.connection != nil) {
// if there is an old connection, explicitly sign it off.
[self.connection signOut];
@@ -447,17 +443,20 @@ static NSUInteger FIRMessagingServerPort() {
[NSObject cancelPreviousPerformRequestsWithTarget:self
selector:@selector(tryToConnect)
object:nil];
NSString *deviceAuthID = [FIRInstanceID instanceID].deviceAuthID;
NSString *secretToken = [FIRInstanceID instanceID].secretToken;
if (deviceAuthID.length == 0 || secretToken.length == 0 ||
!self.connection) {
FIRMessagingLoggerWarn(kFIRMessagingMessageCodeClientInvalidState,
@"Invalid state to connect, deviceAuthID: %@, secretToken: %@, connection state: %ld",
deviceAuthID, secretToken, (long)self.connection.state);
return;
}
// Do not re-sign in if there is already a connection in progress.
if (self.connection.state != kFIRMessagingConnectionNotConnected) {
return;
}
_FIRMessagingDevAssert([FIRInstanceID instanceID].deviceAuthID.length > 0 &&
[FIRInstanceID instanceID].secretToken.length > 0 &&
self.connection != nil,
@"Invalid state cannot connect");
self.connectRetryCount = MIN(kMaxRetryExponent, self.connectRetryCount + 1);
[self performSelector:@selector(didConnectTimeout)
withObject:nil
@@ -466,9 +465,9 @@ static NSUInteger FIRMessagingServerPort() {
}
- (void)didConnectTimeout {
_FIRMessagingDevAssert(self.connection.state != kFIRMessagingConnectionSignedIn,
@"Invalid state for MCS connection");
if (self.connection.state == kFIRMessagingConnectionSignedIn) {
FIRMessagingLoggerWarn(kFIRMessagingMessageCodeClientInvalidStateTimeout, @"Invalid state for connection timeout.");
}
if (self.stayConnected) {
[self.connection signOut];
[self scheduleConnectRetry];
@@ -14,8 +14,10 @@
* limitations under the License.
*/
#import "FIRMessagingCodedInputStream.h"
#import "FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingCodedInputStream.h"
#import "Firebase/Messaging/FIRMMessageCode.h"
#import "Firebase/Messaging/FIRMessagingLogger.h"
typedef struct {
const void *bytes;
@@ -32,9 +34,10 @@ static BOOL CheckSize(BufferState *state, size_t size) {
}
static BOOL ReadRawByte(BufferState *state, int8_t *output) {
_FIRMessagingDevAssert(output != NULL && state != NULL, @"Invalid parameters");
if (CheckSize(state, sizeof(int8_t))) {
if (state == NULL || output == NULL) {
FIRMessagingLoggerDebug(kFIRMessagingCodeInputStreamInvalidParameters, @"Invalid parameters.");
}
if (output != nil && CheckSize(state, sizeof(int8_t))) {
*output = ((int8_t *)state->bytes)[state->bufferPos++];
return YES;
}
@@ -42,8 +45,10 @@ static BOOL ReadRawByte(BufferState *state, int8_t *output) {
}
static BOOL ReadRawVarInt32(BufferState *state, int32_t *output) {
_FIRMessagingDevAssert(output != NULL && state != NULL, @"Invalid parameters");
if (state == NULL || output == NULL) {
FIRMessagingLoggerDebug(kFIRMessagingCodeInputStreamInvalidParameters, @"Invalid parameters.");
return NO;
}
int8_t tmp = 0;
if (!ReadRawByte(state, &tmp)) {
return NO;
@@ -14,20 +14,21 @@
* limitations under the License.
*/
#import "FIRMessagingConnection.h"
#import "Firebase/Messaging/FIRMessagingConnection.h"
#import "Protos/GtalkCore.pbobjc.h"
#import "Protos/GtalkExtensions.pbobjc.h"
#import <FirebaseMessaging/FIRMessaging.h>
#import "FIRMessaging.h"
#import "FIRMessagingDataMessageManager.h"
#import "FIRMessagingDefines.h"
#import "FIRMessagingLogger.h"
#import "FIRMessagingRmqManager.h"
#import "FIRMessagingSecureSocket.h"
#import "FIRMessagingUtilities.h"
#import "FIRMessagingVersionUtilities.h"
#import "FIRMessaging_Private.h"
#import "Firebase/Messaging/Protos/GtalkCore.pbobjc.h"
#import "Firebase/Messaging/Protos/GtalkExtensions.pbobjc.h"
#import "Firebase/Messaging/FIRMessagingDataMessageManager.h"
#import "Firebase/Messaging/FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMessagingRmqManager.h"
#import "Firebase/Messaging/FIRMessagingSecureSocket.h"
#import "Firebase/Messaging/FIRMessagingUtilities.h"
#import "Firebase/Messaging/FIRMessagingVersionUtilities.h"
#import "Firebase/Messaging/FIRMessaging_Private.h"
static NSInteger const kIqSelectiveAck = 12;
static NSInteger const kIqStreamAck = 13;
@@ -144,7 +145,6 @@ static NSString *const kRemoteFromAddress = @"from";
}
- (void)signIn {
_FIRMessagingDevAssert(self.state == kFIRMessagingConnectionNotConnected, @"Invalid connection state.");
if (self.state != kFIRMessagingConnectionNotConnected) {
return;
}
@@ -200,11 +200,8 @@ static NSString *const kRemoteFromAddress = @"from";
}
- (void)didDisconnectWithSecureSocket:(FIRMessagingSecureSocket *)socket {
_FIRMessagingDevAssert(self.socket == socket, @"Invalid socket");
_FIRMessagingDevAssert(self.socket.state == kFIRMessagingSecureSocketClosed, @"Socket already closed");
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection002,
@"Secure socket disconnected from FIRMessaging service.");
@"Secure socket disconnected from FIRMessaging service. %ld", (long)self.socket.state);
[self disconnect];
[self.delegate connection:self didCloseForReason:kFIRMessagingConnectionCloseReasonSocketDisconnected];
}
@@ -294,7 +291,6 @@ static NSString *const kRemoteFromAddress = @"from";
return;
}
_FIRMessagingDevAssert(self.socket != nil, @"Socket shouldn't be nil");
if (self.socket == nil) {
return;
}
@@ -438,10 +434,6 @@ static NSString *const kRemoteFromAddress = @"from";
return;
}
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeConnection012, @"Logged onto MCS service.");
// We sent the persisted list of unack'd messages with login so we can assume they have been ack'd
// by the server.
_FIRMessagingDevAssert(self.unackedS2dIds.count == 0, @"No ids present");
_FIRMessagingDevAssert(self.outStreamId == 1, @"Login should be the first stream id");
self.state = kFIRMessagingConnectionSignedIn;
self.lastLoginServerTimestamp = loginResponse.serverTimestamp;
@@ -659,7 +651,6 @@ static NSString *const kRemoteFromAddress = @"from";
}
- (void)disconnect {
_FIRMessagingDevAssert(self.state != kFIRMessagingConnectionNotConnected, @"Connection already not connected");
// cancel pending timeout tasks.
[self cancelConnectionTimeoutTask];
// cancel pending heartbeat.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
#import "FIRMessagingConstants.h"
#import "Firebase/Messaging/FIRMessagingConstants.h"
NSString *const kFIRMessagingRawDataKey = @"rawData";
NSString *const kFIRMessagingCollapseKey = @"collapse_key";
@@ -14,11 +14,11 @@
* limitations under the License.
*/
#import "FIRMessagingContextManagerService.h"
#import "Firebase/Messaging/FIRMessagingContextManagerService.h"
#import "FIRMessagingDefines.h"
#import "FIRMessagingLogger.h"
#import "FIRMessagingUtilities.h"
#import "Firebase/Messaging/FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMessagingUtilities.h"
#import <GoogleUtilities/GULAppDelegateSwizzler.h>
@@ -44,6 +44,7 @@ NSString *const kFIRMessagingContextManagerCategoryKey =
NSString *const kFIRMessagingContextManagerSoundKey = kFIRMessagingContextManagerNotificationKeyPrefix @"sound";
NSString *const kFIRMessagingContextManagerContentAvailableKey =
kFIRMessagingContextManagerNotificationKeyPrefix @"content-available";
static NSString *const kFIRMessagingAPNSPayloadKey = @"aps";
typedef NS_ENUM(NSUInteger, FIRMessagingContextManagerMessageType) {
FIRMessagingContextManagerMessageTypeNone,
@@ -77,19 +78,16 @@ typedef NS_ENUM(NSUInteger, FIRMessagingContextManagerMessageType) {
+ (BOOL)handleContextManagerLocalTimeMessage:(NSDictionary *)message {
NSString *startTimeString = message[kFIRMessagingContextManagerLocalTimeStart];
if (!startTimeString) {
FIRMessagingLoggerError(kFIRMessagingMessageCodeContextManagerService002,
@"Invalid local start date format %@. Message dropped",
startTimeString);
return NO;
}
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
[dateFormatter setDateFormat:kLocalTimeFormatString];
NSDate *startDate = [dateFormatter dateFromString:startTimeString];
_FIRMessagingDevAssert(startDate, @"Invalid local start date format %@", startTimeString);
if (!startTimeString) {
FIRMessagingLoggerError(kFIRMessagingMessageCodeContextManagerService002,
@"Invalid local start date format %@. Message dropped",
startTimeString);
return NO;
}
NSDate *currentDate = [NSDate date];
if ([currentDate compare:startDate] == NSOrderedAscending) {
@@ -106,8 +104,6 @@ typedef NS_ENUM(NSUInteger, FIRMessagingContextManagerMessageType) {
}
NSDate *endDate = [dateFormatter dateFromString:endTimeString];
_FIRMessagingDevAssert(endDate, @"Invalid local end date format %@", endTimeString);
if (!endTimeString) {
FIRMessagingLoggerError(kFIRMessagingMessageCodeContextManagerService004,
@"Invalid local end date format %@. Message dropped", endTimeString);
@@ -153,7 +149,7 @@ typedef NS_ENUM(NSUInteger, FIRMessagingContextManagerMessageType) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
notification.alertTitle = apsDictionary[kFIRMessagingContextManagerTitleKey];
#pragma pop
#pragma clang diagnostic pop
}
}
@@ -179,7 +175,10 @@ typedef NS_ENUM(NSUInteger, FIRMessagingContextManagerMessageType) {
if (!application) {
return;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[application scheduleLocalNotification:notification];
#pragma clang diagnostic pop
#endif
}
@@ -192,6 +191,11 @@ typedef NS_ENUM(NSUInteger, FIRMessagingContextManagerMessageType) {
continue;
} else if ([keyString hasPrefix:kContextManagerPrefixKey]) {
continue;
} else if ([keyString isEqualToString:kFIRMessagingAPNSPayloadKey]) {
// Local timezone message is scheduled with FCM payload. APNS payload with
// content_available should be ignored and not passed to the scheduled
// messages.
continue;
}
}
data[[key copy]] = message[key];
@@ -14,22 +14,22 @@
* limitations under the License.
*/
#import "FIRMessagingDataMessageManager.h"
#import "Firebase/Messaging/FIRMessagingDataMessageManager.h"
#import "Protos/GtalkCore.pbobjc.h"
#import "Firebase/Messaging/Protos/GtalkCore.pbobjc.h"
#import "FIRMessagingClient.h"
#import "FIRMessagingConnection.h"
#import "FIRMessagingConstants.h"
#import "FIRMessagingDefines.h"
#import "FIRMessagingDelayedMessageQueue.h"
#import "FIRMessagingLogger.h"
#import "FIRMessagingReceiver.h"
#import "FIRMessagingRmqManager.h"
#import "FIRMessaging_Private.h"
#import "FIRMessagingSyncMessageManager.h"
#import "FIRMessagingUtilities.h"
#import "NSError+FIRMessaging.h"
#import "Firebase/Messaging/FIRMessagingClient.h"
#import "Firebase/Messaging/FIRMessagingConnection.h"
#import "Firebase/Messaging/FIRMessagingConstants.h"
#import "Firebase/Messaging/FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingDelayedMessageQueue.h"
#import "Firebase/Messaging/FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMessagingReceiver.h"
#import "Firebase/Messaging/FIRMessagingRmqManager.h"
#import "Firebase/Messaging/FIRMessaging_Private.h"
#import "Firebase/Messaging/FIRMessagingSyncMessageManager.h"
#import "Firebase/Messaging/FIRMessagingUtilities.h"
#import "Firebase/Messaging/NSError+FIRMessaging.h"
static const int kMaxAppDataSizeDefault = 4 * 1024; // 4k
static const int kMinDelaySeconds = 1; // 1 second
@@ -96,8 +96,9 @@ typedef NS_ENUM(int8_t, UpstreamForceReconnect) {
}
- (void)setDeviceAuthID:(NSString *)deviceAuthID secretToken:(NSString *)secretToken {
_FIRMessagingDevAssert([deviceAuthID length] && [secretToken length],
@"Invalid credentials for FIRMessaging");
if (deviceAuthID.length == 0 || secretToken.length == 0) {
FIRMessagingLoggerWarn(kFIRMessagingMessageCodeDataMessageManager013, @"Invalid credentials: deviceAuthID: %@, secrectToken: %@", deviceAuthID, secretToken);
}
self.deviceAuthID = deviceAuthID;
self.secretToken = secretToken;
}
@@ -135,31 +136,29 @@ typedef NS_ENUM(int8_t, UpstreamForceReconnect) {
- (NSDictionary *)parseDataMessage:(GtalkDataMessageStanza *)dataMessage {
NSMutableDictionary *message = [NSMutableDictionary dictionary];
NSString *from = [dataMessage from];
if ([from length]) {
if (from.length) {
message[kFIRMessagingFromKey] = from;
}
// raw data
NSData *rawData = [dataMessage rawData];
if ([rawData length]) {
if (rawData.length) {
message[kFIRMessagingRawDataKey] = rawData;
}
NSString *token = [dataMessage token];
if ([token length]) {
if (token.length) {
message[kFIRMessagingCollapseKey] = token;
}
// Add the persistent_id. This would be removed later before sending the message to the device.
NSString *persistentID = [dataMessage persistentId];
_FIRMessagingDevAssert([persistentID length], @"Invalid MCS message without persistentID");
if ([persistentID length]) {
if (persistentID.length) {
message[kFIRMessagingMessageIDKey] = persistentID;
}
// third-party data
for (GtalkAppData *item in dataMessage.appDataArray) {
_FIRMessagingDevAssert(item.hasKey && item.hasValue, @"Invalid AppData");
// do not process the "from" key -- is not useful
if ([kFIRMessagingFromKey isEqualToString:item.key]) {
@@ -175,7 +174,6 @@ typedef NS_ENUM(int8_t, UpstreamForceReconnect) {
}
message[kDataMessageNotificationKey][key] = item.value;
} else {
_FIRMessagingDevAssert([key length], @"Invalid key in MCS message: %@", key);
FIRMessagingLoggerError(kFIRMessagingMessageCodeDataMessageManager001,
@"Invalid key in MCS message: %@", key);
}
@@ -17,16 +17,6 @@
#ifndef FIRMessaging_xcodeproj_FIRMessagingDefines_h
#define FIRMessaging_xcodeproj_FIRMessagingDefines_h
#define _FIRMessaging_VERBOSE_LOGGING 1
// Verbose Logging
#if (_FIRMessaging_VERBOSE_LOGGING)
#define FIRMessaging_DEV_VERBOSE_LOG(...) NSLog(__VA_ARGS__)
#else
#define FIRMessaging_DEV_VERBOSE_LOG(...) do { } while (0)
#endif // FIRMessaging_VERBOSE_LOGGING
// WEAKIFY & STRONGIFY
// Helper macro.
#define _FIRMessaging_WEAKNAME(VAR) VAR ## _weak_
@@ -40,45 +30,18 @@ __strong __typeof__(VAR) VAR = _FIRMessaging_WEAKNAME(VAR); \
_Pragma("clang diagnostic pop")
// Type Conversions (used for NSInteger etc)
#ifndef _FIRMessaging_L
#define _FIRMessaging_L(v) (long)(v)
#endif
#ifndef _FIRMessaging_UL
#define _FIRMessaging_UL(v) (unsigned long)(v)
#endif
#endif
// Debug Assert
#ifndef _FIRMessagingDevAssert
// we directly invoke the NSAssert handler so we can pass on the varargs
// (NSAssert doesn't have a macro we can use that takes varargs)
#ifdef DEBUG
#define _FIRMessagingDevAssert(condition, ...) \
do { \
if (!(condition)) { \
[[NSAssertionHandler currentHandler] \
handleFailureInFunction:(NSString *) \
[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \
file:(NSString *)[NSString stringWithUTF8String:__FILE__] \
lineNumber:__LINE__ \
description:__VA_ARGS__]; \
} \
} while(0)
#else // !defined(DEBUG)
#define _FIRMessagingDevAssert(condition, ...) do { } while (0)
#endif // !defined(DEBUG)
#endif // _FIRMessagingDevAssert
// Invalidates the initializer from which it's called.
#ifndef FIRMessagingInvalidateInitializer
#define FIRMessagingInvalidateInitializer() \
do { \
[self class]; /* Avoid warning of dead store to |self|. */ \
_FIRMessagingDevAssert(NO, @"Invalid initializer."); \
NSAssert(NO, @"Invalid initializer."); \
return nil; \
} while (0)
#endif
@@ -14,13 +14,13 @@
* limitations under the License.
*/
#import "FIRMessagingDelayedMessageQueue.h"
#import "Firebase/Messaging/FIRMessagingDelayedMessageQueue.h"
#import "Protos/GtalkCore.pbobjc.h"
#import "Firebase/Messaging/Protos/GtalkCore.pbobjc.h"
#import "FIRMessagingDefines.h"
#import "FIRMessagingRmqManager.h"
#import "FIRMessagingUtilities.h"
#import "Firebase/Messaging/FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingRmqManager.h"
#import "Firebase/Messaging/FIRMessagingUtilities.h"
static const int kMaxQueuedMessageCount = 10;
@@ -49,7 +49,6 @@ static const int kMaxQueuedMessageCount = 10;
- (instancetype)initWithRmqScanner:(id<FIRMessagingRmqScanner>)rmqScanner
sendDelayedMessagesHandler:(FIRMessagingSendDelayedMessagesHandler)sendDelayedMessagesHandler {
_FIRMessagingDevAssert(sendDelayedMessagesHandler, @"Invalid nil callback for delayed messages");
self = [super init];
if (self) {
_rmqScanner = rmqScanner;
@@ -14,10 +14,10 @@
* limitations under the License.
*/
#import "FIRMessagingExtensionHelper.h"
#import <FirebaseMessaging/FIRMessagingExtensionHelper.h>
#import "FIRMMessageCode.h"
#import "FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMMessageCode.h"
#import "Firebase/Messaging/FIRMessagingLogger.h"
static NSString *const kPayloadOptionsName = @"fcm_options";
static NSString *const kPayloadOptionsImageURLName = @"image";
@@ -14,7 +14,7 @@
* limitations under the License.
*/
#import "FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMessagingLogger.h"
#import <FirebaseCore/FIRLogger.h>
@@ -14,9 +14,9 @@
* limitations under the License.
*/
#import "FIRMessagingPacketQueue.h"
#import "Firebase/Messaging/FIRMessagingPacketQueue.h"
#import "FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingDefines.h"
@interface FIRMessagingPacket ()
@@ -16,8 +16,9 @@
#import <Foundation/Foundation.h>
#import "FIRMessaging.h"
#import "FIRMessagingTopicsCommon.h"
#import <FirebaseMessaging/FIRMessaging.h>
#import "Firebase/Messaging/FIRMessagingTopicsCommon.h"
NS_ASSUME_NONNULL_BEGIN
@@ -14,13 +14,13 @@
* limitations under the License.
*/
#import "FIRMessagingPendingTopicsList.h"
#import "Firebase/Messaging/FIRMessagingPendingTopicsList.h"
#import "FIRMessaging_Private.h"
#import "FIRMessagingLogger.h"
#import "FIRMessagingPubSub.h"
#import "Firebase/Messaging/FIRMessaging_Private.h"
#import "Firebase/Messaging/FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMessagingPubSub.h"
#import "FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingDefines.h"
NSString *const kPendingTopicBatchActionKey = @"action";
NSString *const kPendingTopicBatchTopicsKey = @"topics";
@@ -14,9 +14,9 @@
* limitations under the License.
*/
#import "FIRMessagingPersistentSyncMessage.h"
#import "Firebase/Messaging/FIRMessagingPersistentSyncMessage.h"
#import "FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingDefines.h"
@interface FIRMessagingPersistentSyncMessage ()
@@ -14,7 +14,7 @@
* limitations under the License.
*/
#import "FIRMessaging.h"
#import <FirebaseMessaging/FIRMessaging.h>
NS_ASSUME_NONNULL_BEGIN
+10 -16
View File
@@ -14,19 +14,19 @@
* limitations under the License.
*/
#import "FIRMessagingPubSub.h"
#import "Firebase/Messaging/FIRMessagingPubSub.h"
#import <GoogleUtilities/GULUserDefaults.h>
#import <FirebaseMessaging/FIRMessaging.h>
#import "FIRMessaging.h"
#import "FIRMessagingClient.h"
#import "FIRMessagingDefines.h"
#import "FIRMessagingLogger.h"
#import "FIRMessagingPendingTopicsList.h"
#import "FIRMessagingUtilities.h"
#import "FIRMessaging_Private.h"
#import "NSDictionary+FIRMessaging.h"
#import "NSError+FIRMessaging.h"
#import "Firebase/Messaging/FIRMessagingClient.h"
#import "Firebase/Messaging/FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMessagingPendingTopicsList.h"
#import "Firebase/Messaging/FIRMessagingUtilities.h"
#import "Firebase/Messaging/FIRMessaging_Private.h"
#import "Firebase/Messaging/NSDictionary+FIRMessaging.h"
#import "Firebase/Messaging/NSError+FIRMessaging.h"
static NSString *const kPendingSubscriptionsListKey =
@"com.firebase.messaging.pending-subscriptions";
@@ -59,8 +59,6 @@ static NSString *const kPendingSubscriptionsListKey =
topic:(NSString *)topic
options:(NSDictionary *)options
handler:(FIRMessagingTopicOperationCompletion)handler {
_FIRMessagingDevAssert([token length], @"FIRMessaging error no token specified");
_FIRMessagingDevAssert([topic length], @"FIRMessaging error Invalid empty topic specified");
if (!self.client) {
handler([NSError errorWithFCMErrorCode:kFIRMessagingErrorCodePubSubFIRMessagingNotSetup]);
return;
@@ -102,14 +100,10 @@ static NSString *const kPendingSubscriptionsListKey =
topic:(NSString *)topic
options:(NSDictionary *)options
handler:(FIRMessagingTopicOperationCompletion)handler {
_FIRMessagingDevAssert([token length], @"FIRMessaging error no token specified");
_FIRMessagingDevAssert([topic length], @"FIRMessaging error Invalid empty topic specified");
if (!self.client) {
handler([NSError errorWithFCMErrorCode:kFIRMessagingErrorCodePubSubFIRMessagingNotSetup]);
return;
}
token = [token copy];
topic = [topic copy];
if (![options count]) {
@@ -14,7 +14,7 @@
* limitations under the License.
*/
#import "FIRMessagingTopicOperation.h"
#import "Firebase/Messaging/FIRMessagingTopicOperation.h"
@interface FIRMessagingPubSubRegistrar : NSObject
@@ -14,12 +14,12 @@
* limitations under the License.
*/
#import "FIRMessagingPubSubRegistrar.h"
#import "Firebase/Messaging/FIRMessagingPubSubRegistrar.h"
#import "FIRMessagingDefines.h"
#import "FIRMessagingPubSubRegistrar.h"
#import "FIRMessagingTopicsCommon.h"
#import "NSError+FIRMessaging.h"
#import "Firebase/Messaging/FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingPubSubRegistrar.h"
#import "Firebase/Messaging/FIRMessagingTopicsCommon.h"
#import "Firebase/Messaging/NSError+FIRMessaging.h"
@interface FIRMessagingPubSubRegistrar ()
@@ -14,8 +14,8 @@
* limitations under the License.
*/
#import "FIRMessagingDataMessageManager.h"
#import "FIRMessaging.h"
#import <FirebaseMessaging/FIRMessaging.h>
#import "Firebase/Messaging/FIRMessagingDataMessageManager.h"
NS_ASSUME_NONNULL_BEGIN
@@ -14,12 +14,13 @@
* limitations under the License.
*/
#import "FIRMessagingReceiver.h"
#import "Firebase/Messaging/FIRMessagingReceiver.h"
#import "FIRMessaging.h"
#import "FIRMessagingLogger.h"
#import "FIRMessagingUtilities.h"
#import "FIRMessaging_Private.h"
#import <FirebaseMessaging/FIRMessaging.h>
#import "Firebase/Messaging/FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMessagingUtilities.h"
#import "Firebase/Messaging/FIRMessaging_Private.h"
static NSString *const kUpstreamMessageIDUserInfoKey = @"messageID";
static NSString *const kUpstreamErrorUserInfoKey = @"error";
@@ -14,14 +14,14 @@
* limitations under the License.
*/
#import "FIRMessagingRemoteNotificationsProxy.h"
#import "Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.h"
#import <objc/runtime.h>
#import "FIRMessagingConstants.h"
#import "FIRMessagingLogger.h"
#import "FIRMessagingUtilities.h"
#import "FIRMessaging_Private.h"
#import "Firebase/Messaging/FIRMessagingConstants.h"
#import "Firebase/Messaging/FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMessagingUtilities.h"
#import "Firebase/Messaging/FIRMessaging_Private.h"
#import <GoogleUtilities/GULAppDelegateSwizzler.h>
static void * UserNotificationObserverContext = &UserNotificationObserverContext;
@@ -93,9 +93,9 @@ static NSString *kUserNotificationDidReceiveResponseSelectorString =
Class notificationCenterClass = NSClassFromString(@"UNUserNotificationCenter");
if (notificationCenterClass) {
// We are linked against iOS 10 SDK or above
id notificationCenter = getNamedPropertyFromObject(notificationCenterClass,
@"currentNotificationCenter",
notificationCenterClass);
id notificationCenter = FIRMessagingPropertyNameFromObject(notificationCenterClass,
@"currentNotificationCenter",
notificationCenterClass);
if (notificationCenter) {
[self listenForDelegateChangesInUserNotificationCenter:notificationCenter];
}
@@ -125,7 +125,7 @@ static NSString *kUserNotificationDidReceiveResponseSelectorString =
if (![notificationCenter isKindOfClass:notificationCenterClass]) {
return;
}
id delegate = getNamedPropertyFromObject(notificationCenter, @"delegate", nil);
id delegate = FIRMessagingPropertyNameFromObject(notificationCenter, @"delegate", nil);
Protocol *delegateProtocol = NSProtocolFromString(@"UNUserNotificationCenterDelegate");
if ([delegate conformsToProtocol:delegateProtocol]) {
// Swizzle this object now, if available
@@ -156,7 +156,7 @@ static NSString *kUserNotificationDidReceiveResponseSelectorString =
if ([delegate respondsToSelector:willPresentNotificationSelector]) {
[self swizzleSelector:willPresentNotificationSelector
inClass:[delegate class]
withImplementation:(IMP)FCM_swizzle_willPresentNotificationWithHandler
withImplementation:(IMP)FCMSwizzleWillPresentNotificationWithHandler
inProtocol:userNotificationCenterProtocol];
}
SEL didReceiveNotificationResponseSelector =
@@ -164,7 +164,7 @@ static NSString *kUserNotificationDidReceiveResponseSelectorString =
if ([delegate respondsToSelector:didReceiveNotificationResponseSelector]) {
[self swizzleSelector:didReceiveNotificationResponseSelector
inClass:[delegate class]
withImplementation:(IMP)FCM_swizzle_didReceiveNotificationResponseWithHandler
withImplementation:(IMP)FCMSwizzleDidReceiveNotificationResponseWithHandler
inProtocol:userNotificationCenterProtocol];
}
self.currentUserNotificationCenterDelegate = delegate;
@@ -263,13 +263,13 @@ static NSString *kUserNotificationDidReceiveResponseSelectorString =
- (IMP)originalImplementationForSelector:(SEL)selector {
NSString *selectorString = NSStringFromSelector(selector);
NSValue *implementation_value = self.originalAppDelegateImps[selectorString];
if (!implementation_value) {
NSValue *implementationValue = self.originalAppDelegateImps[selectorString];
if (!implementationValue) {
return nil;
}
IMP imp;
[implementation_value getValue:&imp];
[implementationValue getValue:&imp];
return imp;
}
@@ -300,27 +300,27 @@ static NSString *kUserNotificationDidReceiveResponseSelectorString =
// This class implements this method, so replace the original implementation
// with our new implementation and save the old implementation.
IMP __original_method_implementation =
IMP originalMethodImplementation =
method_setImplementation(originalMethod, swizzledImplementation);
IMP __nonexistant_method_implementation = [self nonExistantMethodImplementationForClass:klass];
IMP nonexistantMethodImplementation = [self nonExistantMethodImplementationForClass:klass];
if (__original_method_implementation &&
__original_method_implementation != __nonexistant_method_implementation &&
__original_method_implementation != swizzledImplementation) {
[self saveOriginalImplementation:__original_method_implementation
if (originalMethodImplementation &&
originalMethodImplementation != nonexistantMethodImplementation &&
originalMethodImplementation != swizzledImplementation) {
[self saveOriginalImplementation:originalMethodImplementation
forSelector:originalSelector];
}
} else {
// The class doesn't have this method, so add our swizzled implementation as the
// original implementation of the original method.
struct objc_method_description method_description =
struct objc_method_description methodDescription =
protocol_getMethodDescription(protocol, originalSelector, NO, YES);
BOOL methodAdded = class_addMethod(klass,
originalSelector,
swizzledImplementation,
method_description.types);
methodDescription.types);
if (!methodAdded) {
FIRMessagingLoggerError(kFIRMessagingMessageCodeRemoteNotificationsProxyMethodNotAdded,
@"Could not add method for %@ to class %@",
@@ -339,10 +339,10 @@ static NSString *kUserNotificationDidReceiveResponseSelectorString =
return;
}
IMP original_imp = [self originalImplementationForSelector:selector];
if (original_imp) {
IMP originalImp = [self originalImplementationForSelector:selector];
if (originalImp) {
// Restore the original implementation as the current implementation
method_setImplementation(swizzledMethod, original_imp);
method_setImplementation(swizzledMethod, originalImp);
[self removeImplementationForSelector:selector];
} else {
// This class originally did not have an implementation for this selector.
@@ -369,7 +369,7 @@ static NSString *kUserNotificationDidReceiveResponseSelectorString =
}
// A safe, non-leaky way return a property object by its name
id getNamedPropertyFromObject(id object, NSString *propertyName, Class klass) {
id FIRMessagingPropertyNameFromObject(id object, NSString *propertyName, Class klass) {
SEL selector = NSSelectorFromString(propertyName);
if (![object respondsToSelector:selector]) {
return nil;
@@ -433,16 +433,16 @@ didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
* In order to make FCM SDK compile and compatible with iOS SDKs before iOS 10, hide the
* parameter types from the swizzling implementation.
*/
void FCM_swizzle_willPresentNotificationWithHandler(
id self, SEL _cmd, id center, id notification, void (^handler)(NSUInteger)) {
static void FCMSwizzleWillPresentNotificationWithHandler(
id self, SEL cmd, id center, id notification, void (^handler)(NSUInteger)) {
FIRMessagingRemoteNotificationsProxy *proxy = [FIRMessagingRemoteNotificationsProxy sharedProxy];
IMP original_imp = [proxy originalImplementationForSelector:_cmd];
IMP originalImp = [proxy originalImplementationForSelector:cmd];
void (^callOriginalMethodIfAvailable)(void) = ^{
if (original_imp) {
((void (*)(id, SEL, id, id, void (^)(NSUInteger)))original_imp)(
self, _cmd, center, notification, handler);
if (originalImp) {
((void (*)(id, SEL, id, id, void (^)(NSUInteger)))originalImp)(
self, cmd, center, notification, handler);
}
return;
};
@@ -476,7 +476,7 @@ void FCM_swizzle_willPresentNotificationWithHandler(
}
// Attempt to access the user info
id notificationUserInfo = userInfoFromNotification(notification);
id notificationUserInfo = FIRMessagingUserInfoFromNotification(notification);
if (!notificationUserInfo) {
// Could not access notification.request.content.userInfo.
@@ -498,16 +498,16 @@ void FCM_swizzle_willPresentNotificationWithHandler(
* In order to make FCM SDK compile and compatible with iOS SDKs before iOS 10, hide the
* parameter types from the swizzling implementation.
*/
void FCM_swizzle_didReceiveNotificationResponseWithHandler(
id self, SEL _cmd, id center, id response, void (^handler)(void)) {
static void FCMSwizzleDidReceiveNotificationResponseWithHandler(
id self, SEL cmd, id center, id response, void (^handler)(void)) {
FIRMessagingRemoteNotificationsProxy *proxy = [FIRMessagingRemoteNotificationsProxy sharedProxy];
IMP original_imp = [proxy originalImplementationForSelector:_cmd];
IMP originalImp = [proxy originalImplementationForSelector:cmd];
void (^callOriginalMethodIfAvailable)(void) = ^{
if (original_imp) {
((void (*)(id, SEL, id, id, void (^)(void)))original_imp)(
self, _cmd, center, response, handler);
if (originalImp) {
((void (*)(id, SEL, id, id, void (^)(void)))originalImp)(
self, cmd, center, response, handler);
}
return;
};
@@ -543,11 +543,11 @@ void FCM_swizzle_didReceiveNotificationResponseWithHandler(
return;
}
id notificationClass = NSClassFromString(@"UNNotification");
id notification = getNamedPropertyFromObject(response, @"notification", notificationClass);
id notification = FIRMessagingPropertyNameFromObject(response, @"notification", notificationClass);
// With a notification object, use the common code to reach deep into notification
// (notification.request.content.userInfo)
id notificationUserInfo = userInfoFromNotification(notification);
id notificationUserInfo = FIRMessagingUserInfoFromNotification(notification);
if (!notificationUserInfo) {
// Could not access notification.request.content.userInfo.
callOriginalMethodIfAvailable();
@@ -559,7 +559,7 @@ void FCM_swizzle_didReceiveNotificationResponseWithHandler(
callOriginalMethodIfAvailable();
}
id userInfoFromNotification(id notification) {
static id FIRMessagingUserInfoFromNotification(id notification) {
// Select the userInfo field from UNNotification.request.content.userInfo.
SEL requestSelector = NSSelectorFromString(@"request");
@@ -568,7 +568,7 @@ id userInfoFromNotification(id notification) {
return nil;
}
Class requestClass = NSClassFromString(@"UNNotificationRequest");
id notificationRequest = getNamedPropertyFromObject(notification, @"request", requestClass);
id notificationRequest = FIRMessagingPropertyNameFromObject(notification, @"request", requestClass);
SEL notificationContentSelector = NSSelectorFromString(@"content");
if (!notificationRequest
@@ -577,9 +577,9 @@ id userInfoFromNotification(id notification) {
return nil;
}
Class contentClass = NSClassFromString(@"UNNotificationContent");
id notificationContent = getNamedPropertyFromObject(notificationRequest,
@"content",
contentClass);
id notificationContent = FIRMessagingPropertyNameFromObject(notificationRequest,
@"content",
contentClass);
SEL notificationUserInfoSelector = NSSelectorFromString(@"userInfo");
if (!notificationContent
@@ -587,9 +587,9 @@ id userInfoFromNotification(id notification) {
// Cannot access the userInfo property.
return nil;
}
id notificationUserInfo = getNamedPropertyFromObject(notificationContent,
@"userInfo",
[NSDictionary class]);
id notificationUserInfo = FIRMessagingPropertyNameFromObject(notificationContent,
@"userInfo",
[NSDictionary class]);
if (!notificationUserInfo) {
// This is not the expected notification handler.
@@ -14,17 +14,17 @@
* limitations under the License.
*/
#import "FIRMessagingRmq2PersistentStore.h"
#import "Firebase/Messaging/FIRMessagingRmq2PersistentStore.h"
#import <sqlite3.h>
#import "FIRMessagingConstants.h"
#import "FIRMessagingDefines.h"
#import "FIRMessagingLogger.h"
#import "FIRMessagingPersistentSyncMessage.h"
#import "FIRMessagingUtilities.h"
#import "NSError+FIRMessaging.h"
#import "Protos/GtalkCore.pbobjc.h"
#import "Firebase/Messaging/FIRMessagingConstants.h"
#import "Firebase/Messaging/FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMessagingPersistentSyncMessage.h"
#import "Firebase/Messaging/FIRMessagingUtilities.h"
#import "Firebase/Messaging/NSError+FIRMessaging.h"
#import "Firebase/Messaging/Protos/GtalkCore.pbobjc.h"
#ifndef _FIRMessagingRmqLogAndExit
#define _FIRMessagingRmqLogAndExit(stmt, return_value) \
@@ -106,7 +106,7 @@ NSString * _Nonnull FIRMessagingStringFromSQLiteResult(int result) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
const char *errorStr = sqlite3_errstr(result);
#pragma pop
#pragma clang diagnostic pop
NSString *errorString = [NSString stringWithFormat:@"%d - %s", result, errorStr];
return errorString;
}
@@ -395,12 +395,6 @@ NSString * _Nonnull FIRMessagingStringFromSQLiteResult(int result) {
- (int)deleteMessagesFromTable:(NSString *)tableName
withRmqIds:(NSArray *)rmqIds {
_FIRMessagingDevAssert([tableName isEqualToString:kTableOutgoingRmqMessages] ||
[tableName isEqualToString:kTableLastRmqId] ||
[tableName isEqualToString:kTableS2DRmqIds] ||
[tableName isEqualToString:kTableSyncMessages],
@"%@: Invalid Table Name %@", kFCMRmqStoreTag, tableName);
BOOL isRmqIDString = NO;
// RmqID is a string only for outgoing messages
if ([tableName isEqualToString:kTableS2DRmqIds] ||
@@ -592,9 +586,7 @@ NSString * _Nonnull FIRMessagingStringFromSQLiteResult(int result) {
int8_t type = sqlite3_column_int(statement, typeColumnNumber);
const void *bytes = sqlite3_column_blob(statement, dataColumnNumber);
int length = sqlite3_column_bytes(statement, dataColumnNumber);
_FIRMessagingDevAssert(bytes != NULL,
@"%@ Message with no data being stored in Rmq",
kFCMRmqStoreTag);
NSData *data = [NSData dataWithBytes:bytes length:length];
handler(rmqId, type, data);
}
@@ -604,8 +596,6 @@ NSString * _Nonnull FIRMessagingStringFromSQLiteResult(int result) {
#pragma mark - Sync Messages
- (FIRMessagingPersistentSyncMessage *)querySyncMessageWithRmqID:(NSString *)rmqID {
_FIRMessagingDevAssert([rmqID length], @"Invalid rmqID key %@ to search in SYNC_RMQ", rmqID);
NSString *queryFormat = @"SELECT %@ FROM %@ WHERE %@ = '%@'";
NSString *query = [NSString stringWithFormat:queryFormat,
kSyncMessagesColumns, // SELECT (rmq_id, expiration_ts, apns_recv, mcs_recv)
@@ -645,12 +635,10 @@ NSString * _Nonnull FIRMessagingStringFromSQLiteResult(int result) {
}
sqlite3_finalize(stmt);
_FIRMessagingDevAssert(count <= 1, @"Found multiple messages in %@ with same RMQ ID", kTableSyncMessages);
return persistentMessage;
}
- (BOOL)deleteSyncMessageWithRmqID:(NSString *)rmqID {
_FIRMessagingDevAssert([rmqID length], @"Invalid rmqID key %@ to delete in SYNC_RMQ", rmqID);
return [self deleteMessagesFromTable:kTableSyncMessages withRmqIds:@[rmqID]] > 0;
}
@@ -695,8 +683,6 @@ NSString * _Nonnull FIRMessagingStringFromSQLiteResult(int result) {
apnsReceived:(BOOL)apnsReceived
mcsReceived:(BOOL)mcsReceived
error:(NSError **)error {
_FIRMessagingDevAssert([rmqID length], @"Invalid nil message to persist to SYNC_RMQ");
NSString *insertFormat = @"INSERT INTO %@ (%@, %@, %@, %@) VALUES (?, ?, ?, ?)";
NSString *insertSQL = [NSString stringWithFormat:insertFormat,
kTableSyncMessages, // Table name
@@ -759,9 +745,6 @@ NSString * _Nonnull FIRMessagingStringFromSQLiteResult(int result) {
column:(NSString *)column
value:(BOOL)value
error:(NSError **)error {
_FIRMessagingDevAssert([column isEqualToString:kSyncMessageAPNSReceivedColumn] ||
[column isEqualToString:kSyncMessageMCSReceivedColumn],
@"Invalid column name %@ for SYNC_RMQ", column);
NSString *queryFormat = @"UPDATE %@ " // Table name
@"SET %@ = %d " // column=value
@"WHERE %@ = ?"; // condition
@@ -14,15 +14,15 @@
* limitations under the License.
*/
#import "FIRMessagingRmqManager.h"
#import "Firebase/Messaging/FIRMessagingRmqManager.h"
#import <sqlite3.h>
#import "FIRMessagingDefines.h"
#import "FIRMessagingLogger.h"
#import "FIRMessagingRmq2PersistentStore.h"
#import "FIRMessagingUtilities.h"
#import "Protos/GtalkCore.pbobjc.h"
#import "Firebase/Messaging/FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMessagingRmq2PersistentStore.h"
#import "Firebase/Messaging/FIRMessagingUtilities.h"
#import "Firebase/Messaging/Protos/GtalkCore.pbobjc.h"
#ifndef _FIRMessagingRmqLogAndExit
#define _FIRMessagingRmqLogAndExit(stmt, return_value) \
@@ -51,7 +51,6 @@ static NSString *const kFCMRmqTag = @"FIRMessagingRmq:";
- (instancetype)initWithDatabaseName:(NSString *)databaseName {
self = [super init];
if (self) {
_FIRMessagingDevAssert([databaseName length] > 0, @"RMQ: Invalid rmq db name");
_rmq2Store = [[FIRMessagingRmq2PersistentStore alloc] initWithDatabaseName:databaseName];
_outstandingMessages = [NSMutableDictionary dictionaryWithCapacity:2];
_rmqId = -1;
@@ -14,16 +14,16 @@
* limitations under the License.
*/
#import "FIRMessagingSecureSocket.h"
#import "Firebase/Messaging/FIRMessagingSecureSocket.h"
#import <Protobuf/GPBMessage.h>
#import <Protobuf/GPBCodedOutputStream.h>
#import <Protobuf/GPBUtilities.h>
#import "FIRMessagingCodedInputStream.h"
#import "FIRMessagingDefines.h"
#import "FIRMessagingLogger.h"
#import "FIRMessagingPacketQueue.h"
#import "Firebase/Messaging/FIRMessagingCodedInputStream.h"
#import "Firebase/Messaging/FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMessagingPacketQueue.h"
static const NSUInteger kMaxBufferLength = 1024 * 1024; // 1M
static const NSUInteger kBufferLengthIncrement = 16 * 1024; // 16k
@@ -97,10 +97,6 @@ static NSUInteger SerializedSize(int32_t value) {
- (void)connectToHost:(NSString *)host
port:(NSUInteger)port
onRunLoop:(NSRunLoop *)runLoop {
_FIRMessagingDevAssert(host != nil, @"Invalid host");
_FIRMessagingDevAssert(runLoop != nil, @"Invalid runloop");
_FIRMessagingDevAssert(self.state == kFIRMessagingSecureSocketNotOpen, @"Socket is already connected");
if (!host || self.state != kFIRMessagingSecureSocketNotOpen) {
return;
}
@@ -140,8 +136,6 @@ static NSUInteger SerializedSize(int32_t value) {
if (!self.inStream && !self.outStream) {
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket002,
@"The socket is not open or already closed.");
_FIRMessagingDevAssert(self.state == kFIRMessagingSecureSocketClosed || self.state == kFIRMessagingSecureSocketNotOpen,
@"Socket is already disconnected.");
return;
}
@@ -175,7 +169,6 @@ static NSUInteger SerializedSize(int32_t value) {
@"Try to read from socket that is not opened");
return;
}
_FIRMessagingDevAssert(stream == self.inStream, @"Incorrect stream");
if (![self performRead]) {
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket004,
@"Error occurred when reading incoming stream");
@@ -218,7 +211,6 @@ static NSUInteger SerializedSize(int32_t value) {
@"Try to write to socket that is not opened");
return;
}
_FIRMessagingDevAssert(stream == self.outStream, @"Incorrect stream");
[self performWrite];
break;
default:
@@ -229,11 +221,7 @@ static NSUInteger SerializedSize(int32_t value) {
#pragma mark - Private
- (void)openStream:(NSStream *)stream isVOIPStream:(BOOL)isVOIPStream {
_FIRMessagingDevAssert(stream != nil, @"Invalid stream");
_FIRMessagingDevAssert(self.runLoop != nil, @"Invalid runloop");
if (stream) {
_FIRMessagingDevAssert([stream streamStatus] == NSStreamStatusNotOpen, @"Stream already open");
if ([stream streamStatus] != NSStreamStatusNotOpen) {
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket009,
@"stream should not be open.");
@@ -252,9 +240,6 @@ static NSUInteger SerializedSize(int32_t value) {
}
- (void)closeStream:(NSStream *)stream {
_FIRMessagingDevAssert(stream != nil, @"Invalid stream");
_FIRMessagingDevAssert(self.runLoop != nil, @"Invalid runloop");
if (stream) {
[stream close];
[stream removeFromRunLoop:self.runLoop forMode:NSDefaultRunLoopMode];
@@ -263,8 +248,6 @@ static NSUInteger SerializedSize(int32_t value) {
}
- (BOOL)performRead {
_FIRMessagingDevAssert(self.state == kFIRMessagingSecureSocketOpen, @"Socket should be open");
if (!self.isVersionReceived) {
self.isVersionReceived = YES;
uint8_t versionByte = 0;
@@ -279,11 +262,6 @@ static NSUInteger SerializedSize(int32_t value) {
while (YES) {
BOOL isInputBufferValid = [self.inputBuffer length] > 0;
_FIRMessagingDevAssert(isInputBufferValid,
@"Invalid input buffer size %lu. Used bytes length %lu, buffer content: %@",
_FIRMessaging_UL([self.inputBuffer length]),
_FIRMessaging_UL(self.inputBufferLength),
self.inputBuffer);
if (!isInputBufferValid) {
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket011,
@"Input buffer is not valid.");
@@ -323,12 +301,9 @@ static NSUInteger SerializedSize(int32_t value) {
_FIRMessaging_UL(self.inputBufferLength),
_FIRMessaging_UL([self.inputBuffer length]));
[self.inputBuffer increaseLengthBy:kBufferLengthIncrement];
_FIRMessagingDevAssert([self.inputBuffer length] > self.inputBufferLength, @"Invalid buffer size");
}
while (self.inputBufferLength > 0 && [self.inputBuffer length] > 0) {
_FIRMessagingDevAssert([self.inputBuffer length] >= self.inputBufferLength,
@"Buffer longer than length");
NSRange inputRange = NSMakeRange(0, self.inputBufferLength);
size_t protoBytes = 0;
// read the actual proto data coming in
@@ -342,7 +317,6 @@ static NSUInteger SerializedSize(int32_t value) {
} else if (readResult == kFIRMessagingSecureSocketReadResultIncomplete) {
break;
}
_FIRMessagingDevAssert(self.inputBufferLength >= protoBytes, @"More bytes than buffer can handle");
// we have read (0, protoBytes) of data in the inputBuffer
if (protoBytes == self.inputBufferLength) {
// did completely read the buffer data can be reset for further processing
@@ -354,12 +328,6 @@ static NSUInteger SerializedSize(int32_t value) {
[self.inputBuffer replaceBytesInRange:NSMakeRange(0, protoBytes) withBytes:NULL length:0];
// reallocate more data
[self.inputBuffer increaseLengthBy:protoBytes];
_FIRMessagingDevAssert([self.inputBuffer length] == prevLength,
@"Invalid input buffer size %lu. Used bytes length %lu, "
@"buffer content: %@",
_FIRMessaging_UL([self.inputBuffer length]),
_FIRMessaging_UL(self.inputBufferLength),
self.inputBuffer);
self.inputBufferLength -= protoBytes;
}
}
@@ -381,7 +349,6 @@ static NSUInteger SerializedSize(int32_t value) {
return kFIRMessagingSecureSocketReadResultIncomplete;
}
// NOTE tag can be zero for |HeartbeatPing|, and length can be zero for |Close| proto
_FIRMessagingDevAssert(rawTag >= 0 && length >= 0, @"Invalid tag or length");
if (rawTag < 0 || length < 0) {
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeSecureSocket015, @"Buffer data corrupted.");
return kFIRMessagingSecureSocketReadResultCorrupt;
@@ -399,8 +366,6 @@ static NSUInteger SerializedSize(int32_t value) {
}
- (void)performWrite {
_FIRMessagingDevAssert(self.state == kFIRMessagingSecureSocketOpen, @"Invalid socket state");
if (!self.isVersionSent) {
self.isVersionSent = YES;
uint8_t versionByte = kVersion;
@@ -14,14 +14,14 @@
* limitations under the License.
*/
#import "FIRMessagingSyncMessageManager.h"
#import "Firebase/Messaging/FIRMessagingSyncMessageManager.h"
#import "FIRMessagingConstants.h"
#import "FIRMessagingDefines.h"
#import "FIRMessagingLogger.h"
#import "FIRMessagingPersistentSyncMessage.h"
#import "FIRMessagingRmqManager.h"
#import "FIRMessagingUtilities.h"
#import "Firebase/Messaging/FIRMessagingConstants.h"
#import "Firebase/Messaging/FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMessagingPersistentSyncMessage.h"
#import "Firebase/Messaging/FIRMessagingRmqManager.h"
#import "Firebase/Messaging/FIRMessagingUtilities.h"
static const int64_t kDefaultSyncMessageTTL = 4 * 7 * 24 * 60 * 60; // 4 weeks
// 4 MB of free space is required to persist Sync messages
@@ -40,7 +40,6 @@ static const uint64_t kMinFreeDiskSpaceInMB = 1;
}
- (instancetype)initWithRmqManager:(FIRMessagingRmqManager *)rmqManager {
_FIRMessagingDevAssert(rmqManager, @"Invalid nil rmq manager while initalizing sync message manager");
self = [super init];
if (self) {
_rmqManager = rmqManager;
@@ -72,7 +71,6 @@ static const uint64_t kMinFreeDiskSpaceInMB = 1;
viaAPNS:(BOOL)viaAPNS
viaMCS:(BOOL)viaMCS {
NSString *rmqID = message[kFIRMessagingMessageIDKey];
_FIRMessagingDevAssert([rmqID length], @"Invalid nil rmqID for message");
if (![rmqID length]) {
FIRMessagingLoggerError(kFIRMessagingMessageCodeSyncMessageManager002,
@"Invalid nil rmqID for sync message.");
@@ -16,8 +16,9 @@
#import <Foundation/Foundation.h>
#import "FIRMessaging.h"
#import "FIRMessagingTopicsCommon.h"
#import <FirebaseMessaging/FIRMessaging.h>
#import "Firebase/Messaging/FIRMessagingTopicsCommon.h"
NS_ASSUME_NONNULL_BEGIN
@@ -14,14 +14,14 @@
* limitations under the License.
*/
#import "FIRMessagingTopicOperation.h"
#import "Firebase/Messaging/FIRMessagingTopicOperation.h"
#import <FirebaseInstanceID/FIRInstanceID_Private.h>
#import "FIRMessagingDefines.h"
#import "FIRMessagingLogger.h"
#import "FIRMessagingUtilities.h"
#import "NSError+FIRMessaging.h"
#import "Firebase/Messaging/FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMessagingUtilities.h"
#import "Firebase/Messaging/NSError+FIRMessaging.h"
#define DEBUG_LOG_SUBSCRIPTION_OPERATION_DURATIONS 0
@@ -217,7 +217,7 @@ NSString *FIRMessagingSubscriptionsServer() {
}
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeTopicOption001,
@"Device registration HTTP fetch error. Error Code: %ld",
_FIRMessaging_L(error.code));
(long)error.code);
[self finishWithError:error];
return;
}
@@ -229,7 +229,6 @@ NSString *FIRMessagingSubscriptionsServer() {
return;
}
NSArray *parts = [response componentsSeparatedByString:@"="];
_FIRMessagingDevAssert(parts.count, @"Invalid registration response");
if (![parts[0] isEqualToString:@"token"] || parts.count <= 1) {
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeTopicOption002,
@"Invalid registration response %@", response);
@@ -14,11 +14,11 @@
* limitations under the License.
*/
#import "FIRMessagingUtilities.h"
#import "Firebase/Messaging/FIRMessagingUtilities.h"
#import "Protos/GtalkCore.pbobjc.h"
#import "Firebase/Messaging/Protos/GtalkCore.pbobjc.h"
#import "FIRMessagingLogger.h"
#import "Firebase/Messaging/FIRMessagingLogger.h"
#import <GoogleUtilities/GULAppEnvironmentUtil.h>
@@ -14,9 +14,9 @@
* limitations under the License.
*/
#import "FIRMessagingVersionUtilities.h"
#import "Firebase/Messaging/FIRMessagingVersionUtilities.h"
#import "FIRMessagingDefines.h"
#import "Firebase/Messaging/FIRMessagingDefines.h"
// Convert the macro to a string
#define STR_EXPAND(x) #x
@@ -39,7 +39,6 @@ void FIRMessagingParseCurrentLibraryVersion(void) {
// Parse versions
// major, minor, patch[-beta#]
allVersions = [daylightVersion componentsSeparatedByString:kSemanticVersioningSeparator];
_FIRMessagingDevAssert(allVersions.count == 3, @"Invalid versioning of FIRMessaging library");
if (allVersions.count == 3) {
majorVersion = [allVersions[0] intValue];
minorVersion = [allVersions[1] intValue];
@@ -47,7 +46,6 @@ void FIRMessagingParseCurrentLibraryVersion(void) {
// Parse patch and beta versions
NSArray *patchAndBetaVersion =
[allVersions[2] componentsSeparatedByString:kBetaVersionPrefix];
_FIRMessagingDevAssert(patchAndBetaVersion.count <= 2, @"Invalid versioning of FIRMessaging library");
if (patchAndBetaVersion.count == 2) {
patchVersion = [patchAndBetaVersion[0] intValue];
betaVersion = [patchAndBetaVersion[1] intValue];
@@ -14,7 +14,7 @@
* limitations under the License.
*/
#import "FIRMessaging.h"
#import <FirebaseMessaging/FIRMessaging.h>
@class FIRMessagingClient;
@class FIRMessagingPubSub;
@@ -14,4 +14,4 @@
* limitations under the License.
*/
#import "FIRMessaging.h"
#import <FirebaseMessaging/FIRMessaging.h>
@@ -1,30 +0,0 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/// @file FIRMessagingInternalUtilities.h
///
/// Internal Class Names and Methods that other libs can query at runtime.
/// FIRMessaging Class that responds to the FIRMessaging SDK version selector.
/// Verify at runtime if the class exists and implements the
/// required method.
static NSString *const kFIRMessagingSDKClassString = @"FIRMessaging";
/// FIRMessaging selector that returns the current FIRMessaging library version.
static NSString *const kFIRMessagingSDKVersionSelectorString = @"FIRMessagingSDKVersion";
/// FIRMessaging selector that returns the current device locale.
static NSString *const kFIRMessagingSDKLocaleSelectorString = @"FIRMessagingSDKCurrentLocale";
@@ -21,6 +21,10 @@
NS_ASSUME_NONNULL_BEGIN
/// This class is used to automatically populate a notification with an image if it is
/// specified in the notification body via the `image` parameter. Images and other
/// rich content can be populated manually without the use of this class. See the
/// `UNNotificationServiceExtension` type for more details.
__IOS_AVAILABLE(10.0) __OSX_AVAILABLE(10.14)
@interface FIRMessagingExtensionHelper : NSObject
@@ -14,5 +14,5 @@
* limitations under the License.
*/
#import "FIRMessaging.h"
#import "FIRMessagingExtensionHelper.h"
#import <FirebaseMessaging/FIRMessaging.h>
#import <FirebaseMessaging/FIRMessagingExtensionHelper.h>
+17 -10
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
@@ -80,9 +81,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
@@ -99,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.
@@ -179,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).
@@ -195,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'
pod 'FirebaseFunctions'
pod 'FirebaseMessaging'
pod 'FirebaseRemoteConfig'
pod 'FirebaseStorage'
```
@@ -14,18 +14,18 @@
* limitations under the License.
*/
#import "GDTLibrary/Private/GDTAssert.h"
#import "GDTCORLibrary/Public/GDTCORAssert.h"
GDTAssertionBlock GDTAssertionBlockToRunInsteadOfNSAssert(void) {
GDTCORAssertionBlock GDTCORAssertionBlockToRunInstead(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)) {
Class GDTCORAssertClass = NSClassFromString(@"GDTCORAssertHelper");
if (__builtin_expect(!!GDTCORAssertClass, 0)) {
SEL assertionBlockSEL = NSSelectorFromString(@"assertionBlock");
if (assertionBlockSEL) {
IMP assertionBlockIMP = [GDTAssertClass methodForSelector:assertionBlockSEL];
IMP assertionBlockIMP = [GDTCORAssertClass methodForSelector:assertionBlockSEL];
if (assertionBlockIMP) {
GDTAssertionBlock assertionBlock =
((GDTAssertionBlock(*)(id, SEL))assertionBlockIMP)(GDTAssertClass, assertionBlockSEL);
GDTCORAssertionBlock assertionBlock = ((GDTCORAssertionBlock(*)(id, SEL))assertionBlockIMP)(
GDTCORAssertClass, assertionBlockSEL);
if (assertionBlock) {
return assertionBlock;
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
#import "GDTLibrary/Public/GDTClock.h"
#import "GDTCORLibrary/Public/GDTCORClock.h"
#import <sys/sysctl.h>
@@ -74,7 +74,7 @@ static int64_t UptimeInNanoseconds() {
}
// TODO: Consider adding a 'trustedTime' property that can be populated by the response from a BE.
@implementation GDTClock
@implementation GDTCORClock
- (instancetype)init {
self = [super init];
@@ -90,17 +90,17 @@ static int64_t UptimeInNanoseconds() {
return self;
}
+ (GDTClock *)snapshot {
return [[GDTClock alloc] init];
+ (GDTCORClock *)snapshot {
return [[GDTCORClock alloc] init];
}
+ (instancetype)clockSnapshotInTheFuture:(uint64_t)millisInTheFuture {
GDTClock *snapshot = [self snapshot];
GDTCORClock *snapshot = [self snapshot];
snapshot->_timeMillis += millisInTheFuture;
return snapshot;
}
- (BOOL)isAfter:(GDTClock *)otherClock {
- (BOOL)isAfter:(GDTCORClock *)otherClock {
// These clocks are trivially comparable when they share a kernel boot time.
if (_kernelBootTime == otherClock->_kernelBootTime) {
int64_t timeDiff = (_timeMillis + _timezoneOffsetSeconds) -
@@ -126,16 +126,16 @@ static int64_t UptimeInNanoseconds() {
#pragma mark - NSSecureCoding
/** NSKeyedCoder key for timeMillis property. */
static NSString *const kGDTClockTimeMillisKey = @"GDTClockTimeMillis";
static NSString *const kGDTCORClockTimeMillisKey = @"GDTCORClockTimeMillis";
/** NSKeyedCoder key for timezoneOffsetMillis property. */
static NSString *const kGDTClockTimezoneOffsetSeconds = @"GDTClockTimezoneOffsetSeconds";
static NSString *const kGDTCORClockTimezoneOffsetSeconds = @"GDTCORClockTimezoneOffsetSeconds";
/** NSKeyedCoder key for _kernelBootTime ivar. */
static NSString *const kGDTClockKernelBootTime = @"GDTClockKernelBootTime";
static NSString *const kGDTCORClockKernelBootTime = @"GDTCORClockKernelBootTime";
/** NSKeyedCoder key for _uptime ivar. */
static NSString *const kGDTClockUptime = @"GDTClockUptime";
static NSString *const kGDTCORClockUptime = @"GDTCORClockUptime";
+ (BOOL)supportsSecureCoding {
return YES;
@@ -146,19 +146,19 @@ static NSString *const kGDTClockUptime = @"GDTClockUptime";
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];
_timeMillis = [aDecoder decodeInt64ForKey:kGDTCORClockTimeMillisKey];
_timezoneOffsetSeconds = [aDecoder decodeInt64ForKey:kGDTCORClockTimezoneOffsetSeconds];
_kernelBootTime = [aDecoder decodeInt64ForKey:kGDTCORClockKernelBootTime];
_uptime = [aDecoder decodeInt64ForKey:kGDTCORClockUptime];
}
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];
[aCoder encodeInt64:_timeMillis forKey:kGDTCORClockTimeMillisKey];
[aCoder encodeInt64:_timezoneOffsetSeconds forKey:kGDTCORClockTimezoneOffsetSeconds];
[aCoder encodeInt64:_kernelBootTime forKey:kGDTCORClockKernelBootTime];
[aCoder encodeInt64:_uptime forKey:kGDTCORClockUptime];
}
@end
@@ -14,20 +14,20 @@
* limitations under the License.
*/
#import "GDTLibrary/Public/GDTConsoleLogger.h"
#import "GDTCORLibrary/Public/GDTCORConsoleLogger.h"
/** The console logger prefix. */
static NSString *kGDTConsoleLogger = @"[GoogleDataTransport]";
static NSString *kGDTCORConsoleLogger = @"[GoogleDataTransport]";
NSString *GDTMessageCodeEnumToString(GDTMessageCode code) {
return [[NSString alloc] initWithFormat:@"I-GDT%06ld", (long)code];
NSString *GDTCORMessageCodeEnumToString(GDTCORMessageCode code) {
return [[NSString alloc] initWithFormat:@"I-GDTCOR%06ld", (long)code];
}
void GDTLog(GDTMessageCode code, NSString *format, ...) {
void GDTCORLog(GDTCORMessageCode code, NSString *format, ...) {
// Don't log anything in not debug builds.
#ifndef NDEBUG
NSString *logFormat = [NSString
stringWithFormat:@"%@[%@] %@", kGDTConsoleLogger, GDTMessageCodeEnumToString(code), format];
NSString *logFormat = [NSString stringWithFormat:@"%@[%@] %@", kGDTCORConsoleLogger,
GDTCORMessageCodeEnumToString(code), format];
va_list args;
va_start(args, format);
NSLogv(logFormat, args);
@@ -14,9 +14,9 @@
* limitations under the License.
*/
#import <GoogleDataTransport/GDTDataFuture.h>
#import <GoogleDataTransport/GDTCORDataFuture.h>
@implementation GDTDataFuture
@implementation GDTCORDataFuture
- (instancetype)initWithFileURL:(NSURL *)fileURL {
self = [super init];
@@ -38,25 +38,25 @@
#pragma mark - NSSecureCoding
/** Coding key for _fileURL ivar. */
static NSString *kGDTDataFutureFileURLKey = @"GDTDataFutureFileURLKey";
static NSString *kGDTCORDataFutureFileURLKey = @"GDTCORDataFutureFileURLKey";
/** Coding key for _data ivar. */
static NSString *kGDTDataFutureDataKey = @"GDTDataFutureDataKey";
static NSString *kGDTCORDataFutureDataKey = @"GDTCORDataFutureDataKey";
+ (BOOL)supportsSecureCoding {
return YES;
}
- (void)encodeWithCoder:(nonnull NSCoder *)aCoder {
[aCoder encodeObject:_fileURL forKey:kGDTDataFutureFileURLKey];
[aCoder encodeObject:_originalData forKey:kGDTDataFutureDataKey];
[aCoder encodeObject:_fileURL forKey:kGDTCORDataFutureFileURLKey];
[aCoder encodeObject:_originalData forKey:kGDTCORDataFutureDataKey];
}
- (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];
_fileURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:kGDTCORDataFutureFileURLKey];
_originalData = [aDecoder decodeObjectOfClass:[NSData class] forKey:kGDTCORDataFutureDataKey];
}
return self;
}
@@ -14,29 +14,32 @@
* limitations under the License.
*/
#import <GoogleDataTransport/GDTEvent.h>
#import <GoogleDataTransport/GDTCOREvent.h>
#import <GoogleDataTransport/GDTStoredEvent.h>
#import <GoogleDataTransport/GDTCORAssert.h>
#import <GoogleDataTransport/GDTCORStoredEvent.h>
#import "GDTLibrary/Private/GDTAssert.h"
#import "GDTLibrary/Private/GDTEvent_Private.h"
#import "GDTCORLibrary/Private/GDTCOREvent_Private.h"
@implementation GDTEvent
@implementation GDTCOREvent
- (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");
GDTCORAssert(mappingID.length > 0, @"Please give a valid mapping ID");
GDTCORAssert(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;
_qosTier = GDTCOREventQosDefault;
}
return self;
}
- (instancetype)copy {
GDTEvent *copy = [[GDTEvent alloc] initWithMappingID:_mappingID target:_target];
GDTCOREvent *copy = [[GDTCOREvent alloc] initWithMappingID:_mappingID target:_target];
copy.dataObject = _dataObject;
copy.dataObjectTransportBytes = _dataObjectTransportBytes;
copy.qosTier = _qosTier;
@@ -57,7 +60,7 @@
return [self hash] == [object hash];
}
- (void)setDataObject:(id<GDTEventDataObject>)dataObject {
- (void)setDataObject:(id<GDTCOREventDataObject>)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.
@@ -67,8 +70,8 @@
}
}
- (GDTStoredEvent *)storedEventWithDataFuture:(GDTDataFuture *)dataFuture {
return [[GDTStoredEvent alloc] initWithEvent:self dataFuture:dataFuture];
- (GDTCORStoredEvent *)storedEventWithDataFuture:(GDTCORDataFuture *)dataFuture {
return [[GDTCORStoredEvent alloc] initWithEvent:self dataFuture:dataFuture];
}
#pragma mark - NSSecureCoding and NSCoding Protocols
@@ -100,7 +103,7 @@ static NSString *clockSnapshotKey = @"_clockSnapshot";
_dataObjectTransportBytes = [aDecoder decodeObjectOfClass:[NSData class]
forKey:dataObjectTransportBytesKey];
_qosTier = [aDecoder decodeIntegerForKey:qosTierKey];
_clockSnapshot = [aDecoder decodeObjectOfClass:[GDTClock class] forKey:clockSnapshotKey];
_clockSnapshot = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:clockSnapshotKey];
}
return self;
}
@@ -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 "GDTCORLibrary/Public/GDTCORLifecycle.h"
#import <GoogleDataTransport/GDTCOREvent.h>
#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h"
#import "GDTCORLibrary/Private/GDTCORStorage_Private.h"
#import "GDTCORLibrary/Private/GDTCORTransformer_Private.h"
#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h"
@implementation GDTCORLifecycle
+ (void)load {
[self sharedInstance];
}
/** Creates/returns the singleton instance of this class.
*
* @return The singleton instance of this class.
*/
+ (instancetype)sharedInstance {
static GDTCORLifecycle *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[GDTCORLifecycle alloc] init];
});
return sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:@selector(applicationDidEnterBackground:)
name:kGDTCORApplicationDidEnterBackgroundNotification
object:nil];
[notificationCenter addObserver:self
selector:@selector(applicationWillEnterForeground:)
name:kGDTCORApplicationWillEnterForegroundNotification
object:nil];
NSString *name = kGDTCORApplicationWillTerminateNotification;
[notificationCenter addObserver:self
selector:@selector(applicationWillTerminate:)
name:name
object:nil];
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)applicationDidEnterBackground:(NSNotification *)notification {
GDTCORApplication *application = [GDTCORApplication sharedApplication];
if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
[[GDTCORTransformer sharedInstance] appWillBackground:application];
}
if ([[GDTCORStorage sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
[[GDTCORStorage sharedInstance] appWillBackground:application];
}
if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
[[GDTCORUploadCoordinator sharedInstance] appWillBackground:application];
}
if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
[[GDTCORRegistrar sharedInstance] appWillBackground:application];
}
}
- (void)applicationWillEnterForeground:(NSNotification *)notification {
GDTCORApplication *application = [GDTCORApplication sharedApplication];
if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
[[GDTCORTransformer sharedInstance] appWillForeground:application];
}
if ([[GDTCORStorage sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
[[GDTCORStorage sharedInstance] appWillForeground:application];
}
if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
[[GDTCORUploadCoordinator sharedInstance] appWillForeground:application];
}
if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
[[GDTCORRegistrar sharedInstance] appWillForeground:application];
}
}
- (void)applicationWillTerminate:(NSNotification *)notification {
GDTCORApplication *application = [GDTCORApplication sharedApplication];
if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
[[GDTCORTransformer sharedInstance] appWillTerminate:application];
}
if ([[GDTCORStorage sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
[[GDTCORStorage sharedInstance] appWillTerminate:application];
}
if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
[[GDTCORUploadCoordinator sharedInstance] appWillTerminate:application];
}
if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
[[GDTCORRegistrar sharedInstance] appWillTerminate:application];
}
}
@end
@@ -14,20 +14,22 @@
* limitations under the License.
*/
#import <GoogleDataTransport/GDTPlatform.h>
#import <GoogleDataTransport/GDTCORPlatform.h>
const GDTBackgroundIdentifier GDTBackgroundIdentifierInvalid = 0;
#import <GoogleDataTransport/GDTCORAssert.h>
NSString *const kGDTApplicationDidEnterBackgroundNotification =
@"GDTApplicationDidEnterBackgroundNotification";
const GDTCORBackgroundIdentifier GDTCORBackgroundIdentifierInvalid = 0;
NSString *const kGDTApplicationWillEnterForegroundNotification =
@"GDTApplicationWillEnterForegroundNotification";
NSString *const kGDTCORApplicationDidEnterBackgroundNotification =
@"GDTCORApplicationDidEnterBackgroundNotification";
NSString *const kGDTApplicationWillTerminateNotification =
@"GDTApplicationWillTerminateNotification";
NSString *const kGDTCORApplicationWillEnterForegroundNotification =
@"GDTCORApplicationWillEnterForegroundNotification";
BOOL GDTReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) {
NSString *const kGDTCORApplicationWillTerminateNotification =
@"GDTCORApplicationWillTerminateNotification";
BOOL GDTCORReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) {
#if TARGET_OS_IOS
return (flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN;
#else
@@ -35,22 +37,23 @@ BOOL GDTReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) {
#endif // TARGET_OS_IOS
}
@implementation GDTApplication
@implementation GDTCORApplication
+ (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.
NSAssert(GDTBackgroundIdentifierInvalid == UIBackgroundTaskInvalid,
@"GDTBackgroundIdentifierInvalid and UIBackgroundTaskInvalid should be the same.");
GDTCORFatalAssert(
GDTCORBackgroundIdentifierInvalid == UIBackgroundTaskInvalid,
@"GDTCORBackgroundIdentifierInvalid and UIBackgroundTaskInvalid should be the same.");
#endif
[self sharedApplication];
}
+ (nullable GDTApplication *)sharedApplication {
static GDTApplication *application;
+ (nullable GDTCORApplication *)sharedApplication {
static GDTCORApplication *application;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
application = [[GDTApplication alloc] init];
application = [[GDTCORApplication alloc] init];
});
return application;
}
@@ -74,6 +77,20 @@ BOOL GDTReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) {
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
@@ -85,13 +102,15 @@ BOOL GDTReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) {
return self;
}
- (GDTBackgroundIdentifier)beginBackgroundTaskWithExpirationHandler:(void (^)(void))handler {
- (GDTCORBackgroundIdentifier)beginBackgroundTaskWithExpirationHandler:(void (^)(void))handler {
return
[[self sharedApplicationForBackgroundTask] beginBackgroundTaskWithExpirationHandler:handler];
}
- (void)endBackgroundTask:(GDTBackgroundIdentifier)bgID {
[[self sharedApplicationForBackgroundTask] endBackgroundTask:bgID];
- (void)endBackgroundTask:(GDTCORBackgroundIdentifier)bgID {
if (bgID != GDTCORBackgroundIdentifierInvalid) {
[[self sharedApplicationForBackgroundTask] endBackgroundTask:bgID];
}
}
#pragma mark - App environment helpers
@@ -131,17 +150,17 @@ BOOL GDTReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) {
#if TARGET_OS_IOS || TARGET_OS_TV
- (void)iOSApplicationDidEnterBackground:(NSNotification *)notif {
NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
[notifCenter postNotificationName:kGDTApplicationDidEnterBackgroundNotification object:nil];
[notifCenter postNotificationName:kGDTCORApplicationDidEnterBackgroundNotification object:nil];
}
- (void)iOSApplicationWillEnterForeground:(NSNotification *)notif {
NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
[notifCenter postNotificationName:kGDTApplicationWillEnterForegroundNotification object:nil];
[notifCenter postNotificationName:kGDTCORApplicationWillEnterForegroundNotification object:nil];
}
- (void)iOSApplicationWillTerminate:(NSNotification *)notif {
NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
[notifCenter postNotificationName:kGDTApplicationWillTerminateNotification object:nil];
[notifCenter postNotificationName:kGDTCORApplicationWillTerminateNotification object:nil];
}
#endif // TARGET_OS_IOS || TARGET_OS_TV
@@ -150,7 +169,7 @@ BOOL GDTReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) {
#if TARGET_OS_OSX
- (void)macOSApplicationWillTerminate:(NSNotification *)notif {
NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
[notifCenter postNotificationName:kGDTApplicationWillTerminateNotification object:nil];
[notifCenter postNotificationName:kGDTCORApplicationWillTerminateNotification object:nil];
}
#endif // TARGET_OS_OSX
@@ -14,10 +14,10 @@
* limitations under the License.
*/
#import "GDTLibrary/Private/GDTReachability.h"
#import "GDTLibrary/Private/GDTReachability_Private.h"
#import "GDTCORLibrary/Private/GDTCORReachability.h"
#import "GDTCORLibrary/Private/GDTCORReachability_Private.h"
#import <GoogleDataTransport/GDTConsoleLogger.h>
#import <GoogleDataTransport/GDTCORConsoleLogger.h>
#import <netinet/in.h>
@@ -27,11 +27,11 @@
* @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);
static void GDTCORReachabilityCallback(SCNetworkReachabilityRef reachability,
SCNetworkReachabilityFlags flags,
void *info);
@implementation GDTReachability {
@implementation GDTCORReachability {
/** The reachability object. */
SCNetworkReachabilityRef _reachabilityRef;
@@ -47,18 +47,18 @@ static void GDTReachabilityCallback(SCNetworkReachabilityRef reachability,
}
+ (instancetype)sharedInstance {
static GDTReachability *sharedInstance;
static GDTCORReachability *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[GDTReachability alloc] init];
sharedInstance = [[GDTCORReachability alloc] init];
});
return sharedInstance;
}
+ (SCNetworkReachabilityFlags)currentFlags {
__block SCNetworkReachabilityFlags currentFlags;
dispatch_sync([GDTReachability sharedInstance] -> _reachabilityQueue, ^{
GDTReachability *reachability = [GDTReachability sharedInstance];
dispatch_sync([GDTCORReachability sharedInstance] -> _reachabilityQueue, ^{
GDTCORReachability *reachability = [GDTCORReachability sharedInstance];
currentFlags = reachability->_flags ? reachability->_flags : reachability->_callbackFlags;
});
return currentFlags;
@@ -72,16 +72,18 @@ static void GDTReachabilityCallback(SCNetworkReachabilityRef reachability,
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
_reachabilityQueue = dispatch_queue_create("com.google.GDTReachability", DISPATCH_QUEUE_SERIAL);
_reachabilityQueue =
dispatch_queue_create("com.google.GDTCORReachability", 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.");
GDTCORLogWarning(GDTCORMCWReachabilityFailed, @"%@", @"The reachability queue wasn't set.");
}
success = SCNetworkReachabilitySetCallback(_reachabilityRef, GDTReachabilityCallback, NULL);
success = SCNetworkReachabilitySetCallback(_reachabilityRef, GDTCORReachabilityCallback, NULL);
if (!success) {
GDTLogWarning(GDTMCWReachabilityFailed, @"%@", @"The reachability callback wasn't set.");
GDTCORLogWarning(GDTCORMCWReachabilityFailed, @"%@",
@"The reachability callback wasn't set.");
}
// Get the initial set of flags.
@@ -103,8 +105,8 @@ static void GDTReachabilityCallback(SCNetworkReachabilityRef reachability,
@end
static void GDTReachabilityCallback(SCNetworkReachabilityRef reachability,
SCNetworkReachabilityFlags flags,
void *info) {
[[GDTReachability sharedInstance] setCallbackFlags:flags];
static void GDTCORReachabilityCallback(SCNetworkReachabilityRef reachability,
SCNetworkReachabilityFlags flags,
void *info) {
[[GDTCORReachability sharedInstance] setCallbackFlags:flags];
}
@@ -14,23 +14,23 @@
* limitations under the License.
*/
#import "GDTLibrary/Public/GDTRegistrar.h"
#import "GDTCORLibrary/Public/GDTCORRegistrar.h"
#import "GDTLibrary/Private/GDTRegistrar_Private.h"
#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h"
@implementation GDTRegistrar {
@implementation GDTCORRegistrar {
/** Backing ivar for targetToUploader property. */
NSMutableDictionary<NSNumber *, id<GDTUploader>> *_targetToUploader;
NSMutableDictionary<NSNumber *, id<GDTCORUploader>> *_targetToUploader;
/** Backing ivar for targetToPrioritizer property. */
NSMutableDictionary<NSNumber *, id<GDTPrioritizer>> *_targetToPrioritizer;
NSMutableDictionary<NSNumber *, id<GDTCORPrioritizer>> *_targetToPrioritizer;
}
+ (instancetype)sharedInstance {
static GDTRegistrar *sharedInstance;
static GDTCORRegistrar *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[GDTRegistrar alloc] init];
sharedInstance = [[GDTCORRegistrar alloc] init];
});
return sharedInstance;
}
@@ -38,38 +38,39 @@
- (instancetype)init {
self = [super init];
if (self) {
_registrarQueue = dispatch_queue_create("com.google.GDTRegistrar", DISPATCH_QUEUE_CONCURRENT);
_registrarQueue =
dispatch_queue_create("com.google.GDTCORRegistrar", 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;
- (void)registerUploader:(id<GDTCORUploader>)backend target:(GDTCORTarget)target {
__weak GDTCORRegistrar *weakSelf = self;
dispatch_barrier_async(_registrarQueue, ^{
GDTRegistrar *strongSelf = weakSelf;
GDTCORRegistrar *strongSelf = weakSelf;
if (strongSelf) {
strongSelf->_targetToUploader[@(target)] = backend;
}
});
}
- (void)registerPrioritizer:(id<GDTPrioritizer>)prioritizer target:(GDTTarget)target {
__weak GDTRegistrar *weakSelf = self;
- (void)registerPrioritizer:(id<GDTCORPrioritizer>)prioritizer target:(GDTCORTarget)target {
__weak GDTCORRegistrar *weakSelf = self;
dispatch_barrier_async(_registrarQueue, ^{
GDTRegistrar *strongSelf = weakSelf;
GDTCORRegistrar *strongSelf = weakSelf;
if (strongSelf) {
strongSelf->_targetToPrioritizer[@(target)] = prioritizer;
}
});
}
- (NSMutableDictionary<NSNumber *, id<GDTUploader>> *)targetToUploader {
__block NSMutableDictionary<NSNumber *, id<GDTUploader>> *targetToUploader;
__weak GDTRegistrar *weakSelf = self;
- (NSMutableDictionary<NSNumber *, id<GDTCORUploader>> *)targetToUploader {
__block NSMutableDictionary<NSNumber *, id<GDTCORUploader>> *targetToUploader;
__weak GDTCORRegistrar *weakSelf = self;
dispatch_sync(_registrarQueue, ^{
GDTRegistrar *strongSelf = weakSelf;
GDTCORRegistrar *strongSelf = weakSelf;
if (strongSelf) {
targetToUploader = strongSelf->_targetToUploader;
}
@@ -77,11 +78,11 @@
return targetToUploader;
}
- (NSMutableDictionary<NSNumber *, id<GDTPrioritizer>> *)targetToPrioritizer {
__block NSMutableDictionary<NSNumber *, id<GDTPrioritizer>> *targetToPrioritizer;
__weak GDTRegistrar *weakSelf = self;
- (NSMutableDictionary<NSNumber *, id<GDTCORPrioritizer>> *)targetToPrioritizer {
__block NSMutableDictionary<NSNumber *, id<GDTCORPrioritizer>> *targetToPrioritizer;
__weak GDTCORRegistrar *weakSelf = self;
dispatch_sync(_registrarQueue, ^{
GDTRegistrar *strongSelf = weakSelf;
GDTCORRegistrar *strongSelf = weakSelf;
if (strongSelf) {
targetToPrioritizer = strongSelf->_targetToPrioritizer;
}
@@ -89,16 +90,16 @@
return targetToPrioritizer;
}
#pragma mark - GDTLifecycleProtocol
#pragma mark - GDTCORLifecycleProtocol
- (void)appWillBackground:(nonnull GDTApplication *)app {
- (void)appWillBackground:(nonnull GDTCORApplication *)app {
dispatch_async(_registrarQueue, ^{
for (id<GDTUploader> uploader in [self->_targetToUploader allValues]) {
for (id<GDTCORUploader> uploader in [self->_targetToUploader allValues]) {
if ([uploader respondsToSelector:@selector(appWillBackground:)]) {
[uploader appWillBackground:app];
}
}
for (id<GDTPrioritizer> prioritizer in [self->_targetToPrioritizer allValues]) {
for (id<GDTCORPrioritizer> prioritizer in [self->_targetToPrioritizer allValues]) {
if ([prioritizer respondsToSelector:@selector(appWillBackground:)]) {
[prioritizer appWillBackground:app];
}
@@ -106,14 +107,14 @@
});
}
- (void)appWillForeground:(nonnull GDTApplication *)app {
- (void)appWillForeground:(nonnull GDTCORApplication *)app {
dispatch_async(_registrarQueue, ^{
for (id<GDTUploader> uploader in [self->_targetToUploader allValues]) {
for (id<GDTCORUploader> uploader in [self->_targetToUploader allValues]) {
if ([uploader respondsToSelector:@selector(appWillForeground:)]) {
[uploader appWillForeground:app];
}
}
for (id<GDTPrioritizer> prioritizer in [self->_targetToPrioritizer allValues]) {
for (id<GDTCORPrioritizer> prioritizer in [self->_targetToPrioritizer allValues]) {
if ([prioritizer respondsToSelector:@selector(appWillForeground:)]) {
[prioritizer appWillForeground:app];
}
@@ -121,14 +122,14 @@
});
}
- (void)appWillTerminate:(nonnull GDTApplication *)app {
- (void)appWillTerminate:(nonnull GDTCORApplication *)app {
dispatch_sync(_registrarQueue, ^{
for (id<GDTUploader> uploader in [self->_targetToUploader allValues]) {
for (id<GDTCORUploader> uploader in [self->_targetToUploader allValues]) {
if ([uploader respondsToSelector:@selector(appWillTerminate:)]) {
[uploader appWillTerminate:app];
}
}
for (id<GDTPrioritizer> prioritizer in [self->_targetToPrioritizer allValues]) {
for (id<GDTCORPrioritizer> prioritizer in [self->_targetToPrioritizer allValues]) {
if ([prioritizer respondsToSelector:@selector(appWillTerminate:)]) {
[prioritizer appWillTerminate:app];
}
@@ -0,0 +1,323 @@
/*
* 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 "GDTCORLibrary/Private/GDTCORStorage.h"
#import "GDTCORLibrary/Private/GDTCORStorage_Private.h"
#import <GoogleDataTransport/GDTCORAssert.h>
#import <GoogleDataTransport/GDTCORConsoleLogger.h>
#import <GoogleDataTransport/GDTCORLifecycle.h>
#import <GoogleDataTransport/GDTCORPrioritizer.h>
#import <GoogleDataTransport/GDTCORStoredEvent.h>
#import "GDTCORLibrary/Private/GDTCOREvent_Private.h"
#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h"
#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h"
/** Creates and/or returns a singleton NSString that is the shared storage path.
*
* @return The SDK event storage path.
*/
static NSString *GDTCORStoragePath() {
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 GDTCORStorage
+ (NSString *)archivePath {
static NSString *archivePath;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
archivePath = [GDTCORStoragePath() stringByAppendingPathComponent:@"GDTCORStorageArchive"];
});
return archivePath;
}
+ (instancetype)sharedInstance {
static GDTCORStorage *sharedStorage;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedStorage = [[GDTCORStorage alloc] init];
});
return sharedStorage;
}
- (instancetype)init {
self = [super init];
if (self) {
_storageQueue = dispatch_queue_create("com.google.GDTCORStorage", DISPATCH_QUEUE_SERIAL);
_targetToEventSet = [[NSMutableDictionary alloc] init];
_storedEvents = [[NSMutableOrderedSet alloc] init];
_uploadCoordinator = [GDTCORUploadCoordinator sharedInstance];
}
return self;
}
- (void)storeEvent:(GDTCOREvent *)event {
if (event == nil) {
return;
}
[self createEventDirectoryIfNotExists];
__block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid;
if (_runningInBackground) {
bgID = [[GDTCORApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
if (bgID != GDTCORBackgroundIdentifierInvalid) {
[[GDTCORApplication sharedApplication] endBackgroundTask:bgID];
bgID = GDTCORBackgroundIdentifierInvalid;
}
}];
}
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<GDTCORPrioritizer> prioritizer =
[GDTCORRegistrar sharedInstance].targetToPrioritizer[@(target)];
GDTCORAssert(prioritizer, @"There's no prioritizer registered for the given target.");
// Write the transport bytes to disk, get a filename.
GDTCORAssert(event.dataObjectTransportBytes, @"The event should have been serialized to bytes");
NSURL *eventFile = [self saveEventBytesToDisk:event.dataObjectTransportBytes
eventHash:event.hash];
GDTCORDataFuture *dataFuture = [[GDTCORDataFuture alloc] initWithFileURL:eventFile];
GDTCORStoredEvent *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 == GDTCOREventQoSFast) {
[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:[GDTCORStorage archivePath] atomically:YES];
} else {
#if !defined(TARGET_OS_MACCATALYST)
[NSKeyedArchiver archiveRootObject:self toFile:[GDTCORStorage archivePath]];
#endif
}
}
// If running in the background, save state to disk and end the associated background task.
if (bgID != GDTCORBackgroundIdentifierInvalid) {
[[GDTCORApplication sharedApplication] endBackgroundTask:bgID];
bgID = GDTCORBackgroundIdentifierInvalid;
}
});
}
- (void)removeEvents:(NSSet<GDTCORStoredEvent *> *)events {
NSSet<GDTCORStoredEvent *> *eventsToRemove = [events copy];
dispatch_async(_storageQueue, ^{
for (GDTCORStoredEvent *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];
GDTCORAssert(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:GDTCORStoragePath()
withIntermediateDirectories:YES
attributes:0
error:&error];
if (!result || error) {
GDTCORLogError(GDTCORMCEDirectoryCreationError, @"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 = GDTCORStoragePath();
NSString *event = [NSString stringWithFormat:@"event-%lu", (unsigned long)eventHash];
NSURL *eventFilePath = [NSURL fileURLWithPath:[storagePath stringByAppendingPathComponent:event]];
GDTCORAssert(![[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) {
GDTCORLogError(GDTCORMCEFileWriteError, @"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:(GDTCORStoredEvent *)event {
[_storedEvents addObject:event];
NSMutableSet<GDTCORStoredEvent *> *events = self.targetToEventSet[event.target];
events = events ? events : [[NSMutableSet alloc] init];
[events addObject:event];
_targetToEventSet[event.target] = events;
}
#pragma mark - GDTCORLifecycleProtocol
- (void)appWillForeground:(GDTCORApplication *)app {
if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
NSData *data = [NSData dataWithContentsOfFile:[GDTCORStorage archivePath]];
[NSKeyedUnarchiver unarchivedObjectOfClass:[GDTCORStorage class] fromData:data error:nil];
} else {
#if !defined(TARGET_OS_MACCATALYST)
[NSKeyedUnarchiver unarchiveObjectWithFile:[GDTCORStorage archivePath]];
#endif
}
}
- (void)appWillBackground:(GDTCORApplication *)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:[GDTCORStorage archivePath] atomically:YES];
} else {
#if !defined(TARGET_OS_MACCATALYST)
[NSKeyedArchiver archiveRootObject:self toFile:[GDTCORStorage archivePath]];
#endif
}
});
// Create an immediate background task to run until the end of the current queue of work.
__block GDTCORBackgroundIdentifier bgID = [app beginBackgroundTaskWithExpirationHandler:^{
if (bgID != GDTCORBackgroundIdentifierInvalid) {
[app endBackgroundTask:bgID];
bgID = GDTCORBackgroundIdentifierInvalid;
}
}];
dispatch_async(_storageQueue, ^{
if (bgID != GDTCORBackgroundIdentifierInvalid) {
[app endBackgroundTask:bgID];
bgID = GDTCORBackgroundIdentifierInvalid;
}
});
}
- (void)appWillTerminate:(GDTCORApplication *)application {
if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self
requiringSecureCoding:YES
error:nil];
[data writeToFile:[GDTCORStorage archivePath] atomically:YES];
} else {
#if !defined(TARGET_OS_MACCATALYST)
[NSKeyedArchiver archiveRootObject:self toFile:[GDTCORStorage archivePath]];
#endif
}
}
#pragma mark - NSSecureCoding
/** The NSKeyedCoder key for the storedEvents property. */
static NSString *const kGDTCORStorageStoredEventsKey = @"GDTCORStorageStoredEventsKey";
/** The NSKeyedCoder key for the targetToEventSet property. */
static NSString *const kGDTCORStorageTargetToEventSetKey = @"GDTCORStorageTargetToEventSetKey";
/** The NSKeyedCoder key for the uploadCoordinator property. */
static NSString *const kGDTCORStorageUploadCoordinatorKey = @"GDTCORStorageUploadCoordinatorKey";
+ (BOOL)supportsSecureCoding {
return YES;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
// Create the singleton and populate its ivars.
GDTCORStorage *sharedInstance = [self.class sharedInstance];
dispatch_sync(sharedInstance.storageQueue, ^{
NSSet *classes =
[NSSet setWithObjects:[NSMutableOrderedSet class], [GDTCORStoredEvent class], nil];
sharedInstance->_storedEvents = [aDecoder decodeObjectOfClasses:classes
forKey:kGDTCORStorageStoredEventsKey];
classes = [NSSet setWithObjects:[NSMutableDictionary class], [NSMutableSet class],
[GDTCORStoredEvent class], nil];
sharedInstance->_targetToEventSet =
[aDecoder decodeObjectOfClasses:classes forKey:kGDTCORStorageTargetToEventSetKey];
sharedInstance->_uploadCoordinator =
[aDecoder decodeObjectOfClass:[GDTCORUploadCoordinator class]
forKey:kGDTCORStorageUploadCoordinatorKey];
});
return sharedInstance;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
GDTCORStorage *sharedInstance = [self.class sharedInstance];
NSMutableOrderedSet<GDTCORStoredEvent *> *storedEvents = sharedInstance->_storedEvents;
if (storedEvents) {
[aCoder encodeObject:storedEvents forKey:kGDTCORStorageStoredEventsKey];
}
NSMutableDictionary<NSNumber *, NSMutableSet<GDTCORStoredEvent *> *> *targetToEventSet =
sharedInstance->_targetToEventSet;
if (targetToEventSet) {
[aCoder encodeObject:targetToEventSet forKey:kGDTCORStorageTargetToEventSetKey];
}
GDTCORUploadCoordinator *uploadCoordinator = sharedInstance->_uploadCoordinator;
if (uploadCoordinator) {
[aCoder encodeObject:uploadCoordinator forKey:kGDTCORStorageUploadCoordinatorKey];
}
}
@end
@@ -14,15 +14,16 @@
* limitations under the License.
*/
#import <GoogleDataTransport/GDTStoredEvent.h>
#import <GoogleDataTransport/GDTCORStoredEvent.h>
#import <GoogleDataTransport/GDTClock.h>
#import <GoogleDataTransport/GDTCORClock.h>
#import "GDTLibrary/Private/GDTStorage_Private.h"
#import "GDTCORLibrary/Private/GDTCORStorage_Private.h"
@implementation GDTStoredEvent
@implementation GDTCORStoredEvent
- (instancetype)initWithEvent:(GDTEvent *)event dataFuture:(nonnull GDTDataFuture *)dataFuture {
- (instancetype)initWithEvent:(GDTCOREvent *)event
dataFuture:(nonnull GDTCORDataFuture *)dataFuture {
self = [super init];
if (self) {
_dataFuture = dataFuture;
@@ -38,22 +39,22 @@
#pragma mark - NSSecureCoding
/** Coding key for the dataFuture ivar. */
static NSString *kDataFutureKey = @"GDTStoredEventDataFutureKey";
static NSString *kDataFutureKey = @"GDTCORStoredEventDataFutureKey";
/** Coding key for mappingID ivar. */
static NSString *kMappingIDKey = @"GDTStoredEventMappingIDKey";
static NSString *kMappingIDKey = @"GDTCORStoredEventMappingIDKey";
/** Coding key for target ivar. */
static NSString *kTargetKey = @"GDTStoredEventTargetKey";
static NSString *kTargetKey = @"GDTCORStoredEventTargetKey";
/** Coding key for qosTier ivar. */
static NSString *kQosTierKey = @"GDTStoredEventQosTierKey";
static NSString *kQosTierKey = @"GDTCORStoredEventQosTierKey";
/** Coding key for clockSnapshot ivar. */
static NSString *kClockSnapshotKey = @"GDTStoredEventClockSnapshotKey";
static NSString *kClockSnapshotKey = @"GDTCORStoredEventClockSnapshotKey";
/** Coding key for customPrioritizationParams ivar. */
static NSString *kCustomPrioritizationParamsKey = @"GDTStoredEventcustomPrioritizationParamsKey";
static NSString *kCustomPrioritizationParamsKey = @"GDTCORStoredEventcustomPrioritizationParamsKey";
+ (BOOL)supportsSecureCoding {
return YES;
@@ -71,19 +72,19 @@ static NSString *kCustomPrioritizationParamsKey = @"GDTStoredEventcustomPrioriti
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
self = [self init];
if (self) {
_dataFuture = [aDecoder decodeObjectOfClass:[GDTDataFuture class] forKey:kDataFutureKey];
_dataFuture = [aDecoder decodeObjectOfClass:[GDTCORDataFuture 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];
_clockSnapshot = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:kClockSnapshotKey];
_customPrioritizationParams = [aDecoder decodeObjectOfClass:[NSDictionary class]
forKey:kCustomPrioritizationParamsKey];
}
return self;
}
- (BOOL)isEqual:(GDTStoredEvent *)other {
- (BOOL)isEqual:(GDTCORStoredEvent *)other {
return [self hash] == [other hash];
}
@@ -0,0 +1,113 @@
/*
* 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 "GDTCORLibrary/Private/GDTCORTransformer.h"
#import "GDTCORLibrary/Private/GDTCORTransformer_Private.h"
#import <GoogleDataTransport/GDTCORAssert.h>
#import <GoogleDataTransport/GDTCORConsoleLogger.h>
#import <GoogleDataTransport/GDTCOREventTransformer.h>
#import <GoogleDataTransport/GDTCORLifecycle.h>
#import "GDTCORLibrary/Private/GDTCORStorage.h"
@implementation GDTCORTransformer
+ (instancetype)sharedInstance {
static GDTCORTransformer *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.GDTCORTransformer", DISPATCH_QUEUE_SERIAL);
_storageInstance = [GDTCORStorage sharedInstance];
}
return self;
}
- (void)transformEvent:(GDTCOREvent *)event
withTransformers:(NSArray<id<GDTCOREventTransformer>> *)transformers {
GDTCORAssert(event, @"You can't write a nil event");
__block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid;
if (_runningInBackground) {
bgID = [[GDTCORApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
if (bgID != GDTCORBackgroundIdentifierInvalid) {
[[GDTCORApplication sharedApplication] endBackgroundTask:bgID];
bgID = GDTCORBackgroundIdentifierInvalid;
}
}];
}
dispatch_async(_eventWritingQueue, ^{
GDTCOREvent *transformedEvent = event;
for (id<GDTCOREventTransformer> transformer in transformers) {
if ([transformer respondsToSelector:@selector(transform:)]) {
transformedEvent = [transformer transform:transformedEvent];
if (!transformedEvent) {
return;
}
} else {
GDTCORLogError(GDTCORMCETransformerDoesntImplementTransform,
@"Transformer doesn't implement transform: %@", transformer);
return;
}
}
[self.storageInstance storeEvent:transformedEvent];
if (self->_runningInBackground) {
[[GDTCORApplication sharedApplication] endBackgroundTask:bgID];
bgID = GDTCORBackgroundIdentifierInvalid;
}
});
}
#pragma mark - GDTCORLifecycleProtocol
- (void)appWillForeground:(GDTCORApplication *)app {
dispatch_async(_eventWritingQueue, ^{
self->_runningInBackground = NO;
});
}
- (void)appWillBackground:(GDTCORApplication *)app {
// Create an immediate background task to run until the end of the current queue of work.
__block GDTCORBackgroundIdentifier bgID = [app beginBackgroundTaskWithExpirationHandler:^{
if (bgID != GDTCORBackgroundIdentifierInvalid) {
[app endBackgroundTask:bgID];
bgID = GDTCORBackgroundIdentifierInvalid;
}
}];
dispatch_async(_eventWritingQueue, ^{
if (bgID != GDTCORBackgroundIdentifierInvalid) {
[app endBackgroundTask:bgID];
bgID = GDTCORBackgroundIdentifierInvalid;
}
});
}
- (void)appWillTerminate:(GDTCORApplication *)application {
// Flush the queue immediately.
dispatch_sync(_eventWritingQueue, ^{
});
}
@end
@@ -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/GDTCORTransport.h>
#import "GDTCORLibrary/Private/GDTCORTransport_Private.h"
#import <GoogleDataTransport/GDTCORAssert.h>
#import <GoogleDataTransport/GDTCORClock.h>
#import <GoogleDataTransport/GDTCOREvent.h>
#import "GDTCORLibrary/Private/GDTCORTransformer.h"
@implementation GDTCORTransport
- (instancetype)initWithMappingID:(NSString *)mappingID
transformers:(nullable NSArray<id<GDTCOREventTransformer>> *)transformers
target:(NSInteger)target {
GDTCORAssert(mappingID.length > 0, @"A mapping ID cannot be nil or empty");
GDTCORAssert(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 = [GDTCORTransformer sharedInstance];
}
return self;
}
- (void)sendTelemetryEvent:(GDTCOREvent *)event {
// TODO: Determine if sending an event before registration is allowed.
GDTCORAssert(event, @"You can't send a nil event");
GDTCOREvent *copiedEvent = [event copy];
copiedEvent.qosTier = GDTCOREventQoSTelemetry;
copiedEvent.clockSnapshot = [GDTCORClock snapshot];
[self.transformerInstance transformEvent:copiedEvent withTransformers:_transformers];
}
- (void)sendDataEvent:(GDTCOREvent *)event {
// TODO: Determine if sending an event before registration is allowed.
GDTCORAssert(event, @"You can't send a nil event");
GDTCORAssert(event.qosTier != GDTCOREventQoSTelemetry, @"Use -sendTelemetryEvent, please.");
GDTCOREvent *copiedEvent = [event copy];
copiedEvent.clockSnapshot = [GDTCORClock snapshot];
[self.transformerInstance transformEvent:copiedEvent withTransformers:_transformers];
}
- (GDTCOREvent *)eventForTransport {
return [[GDTCOREvent alloc] initWithMappingID:_mappingID target:_target];
}
@end
@@ -14,23 +14,23 @@
* limitations under the License.
*/
#import "GDTLibrary/Private/GDTUploadCoordinator.h"
#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h"
#import <GoogleDataTransport/GDTClock.h>
#import <GoogleDataTransport/GDTConsoleLogger.h>
#import <GoogleDataTransport/GDTCORAssert.h>
#import <GoogleDataTransport/GDTCORClock.h>
#import <GoogleDataTransport/GDTCORConsoleLogger.h>
#import "GDTLibrary/Private/GDTAssert.h"
#import "GDTLibrary/Private/GDTReachability.h"
#import "GDTLibrary/Private/GDTRegistrar_Private.h"
#import "GDTLibrary/Private/GDTStorage.h"
#import "GDTCORLibrary/Private/GDTCORReachability.h"
#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h"
#import "GDTCORLibrary/Private/GDTCORStorage.h"
@implementation GDTUploadCoordinator
@implementation GDTCORUploadCoordinator
+ (instancetype)sharedInstance {
static GDTUploadCoordinator *sharedUploader;
static GDTCORUploadCoordinator *sharedUploader;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedUploader = [[GDTUploadCoordinator alloc] init];
sharedUploader = [[GDTCORUploadCoordinator alloc] init];
[sharedUploader startTimer];
});
return sharedUploader;
@@ -40,8 +40,8 @@
self = [super init];
if (self) {
_coordinationQueue =
dispatch_queue_create("com.google.GDTUploadCoordinator", DISPATCH_QUEUE_SERIAL);
_registrar = [GDTRegistrar sharedInstance];
dispatch_queue_create("com.google.GDTCORUploadCoordinator", DISPATCH_QUEUE_SERIAL);
_registrar = [GDTCORRegistrar sharedInstance];
_timerInterval = 30 * NSEC_PER_SEC;
_timerLeeway = 5 * NSEC_PER_SEC;
_targetToInFlightPackages = [[NSMutableDictionary alloc] init];
@@ -49,21 +49,21 @@
return self;
}
- (void)forceUploadForTarget:(GDTTarget)target {
- (void)forceUploadForTarget:(GDTCORTarget)target {
dispatch_async(_coordinationQueue, ^{
GDTUploadConditions conditions = [self uploadConditions];
conditions |= GDTUploadConditionHighPriority;
GDTCORUploadConditions conditions = [self uploadConditions];
conditions |= GDTCORUploadConditionHighPriority;
[self uploadTargets:@[ @(target) ] conditions:conditions];
});
}
#pragma mark - Property overrides
// GDTStorage and GDTUploadCoordinator +sharedInstance methods call each other, so this breaks
// GDTCORStorage and GDTCORUploadCoordinator +sharedInstance methods call each other, so this breaks
// the loop.
- (GDTStorage *)storage {
- (GDTCORStorage *)storage {
if (!_storage) {
_storage = [GDTStorage sharedInstance];
_storage = [GDTCORStorage sharedInstance];
}
return _storage;
}
@@ -81,7 +81,7 @@
self->_timerLeeway);
dispatch_source_set_event_handler(self->_timer, ^{
if (!self->_runningInBackground) {
GDTUploadConditions conditions = [self uploadConditions];
GDTCORUploadConditions conditions = [self uploadConditions];
[self uploadTargets:[self.registrar.targetToUploader allKeys] conditions:conditions];
}
});
@@ -101,9 +101,9 @@
* @param targets An array of targets to trigger.
* @param conditions The set of upload conditions.
*/
- (void)uploadTargets:(NSArray<NSNumber *> *)targets conditions:(GDTUploadConditions)conditions {
- (void)uploadTargets:(NSArray<NSNumber *> *)targets conditions:(GDTCORUploadConditions)conditions {
dispatch_async(_coordinationQueue, ^{
if ((conditions & GDTUploadConditionNoNetwork) == GDTUploadConditionNoNetwork) {
if ((conditions & GDTCORUploadConditionNoNetwork) == GDTCORUploadConditionNoNetwork) {
return;
}
for (NSNumber *target in targets) {
@@ -112,10 +112,10 @@
continue;
}
// Ask the uploader if they can upload and do so, if it can.
id<GDTUploader> uploader = self.registrar.targetToUploader[target];
id<GDTCORUploader> uploader = self.registrar.targetToUploader[target];
if ([uploader readyToUploadWithConditions:conditions]) {
id<GDTPrioritizer> prioritizer = self.registrar.targetToPrioritizer[target];
GDTUploadPackage *package = [prioritizer uploadPackageWithConditions:conditions];
id<GDTCORPrioritizer> prioritizer = self.registrar.targetToPrioritizer[target];
GDTCORUploadPackage *package = [prioritizer uploadPackageWithConditions:conditions];
if (package.events.count) {
self->_targetToInFlightPackages[target] = package;
[uploader uploadPackage:package];
@@ -131,8 +131,8 @@
*
* @return The current upload conditions.
*/
- (GDTUploadConditions)uploadConditions {
SCNetworkReachabilityFlags currentFlags = [GDTReachability currentFlags];
- (GDTCORUploadConditions)uploadConditions {
SCNetworkReachabilityFlags currentFlags = [GDTCORReachability currentFlags];
BOOL reachable =
(currentFlags & kSCNetworkReachabilityFlagsReachable) == kSCNetworkReachabilityFlagsReachable;
BOOL connectionRequired = (currentFlags & kSCNetworkReachabilityFlagsConnectionRequired) ==
@@ -140,14 +140,14 @@
BOOL networkConnected = reachable && !connectionRequired;
if (!networkConnected) {
return GDTUploadConditionNoNetwork;
return GDTCORUploadConditionNoNetwork;
}
BOOL isWWAN = GDTReachabilityFlagsContainWWAN(currentFlags);
BOOL isWWAN = GDTCORReachabilityFlagsContainWWAN(currentFlags);
if (isWWAN) {
return GDTUploadConditionMobileData;
return GDTCORUploadConditionMobileData;
} else {
return GDTUploadConditionWifiData;
return GDTCORUploadConditionWifiData;
}
}
@@ -155,35 +155,42 @@
/** The NSKeyedCoder key for the targetToInFlightPackages property. */
static NSString *const ktargetToInFlightPackagesKey =
@"GDTUploadCoordinatortargetToInFlightPackages";
@"GDTCORUploadCoordinatortargetToInFlightPackages";
+ (BOOL)supportsSecureCoding {
return YES;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
GDTUploadCoordinator *sharedCoordinator = [GDTUploadCoordinator sharedInstance];
sharedCoordinator->_targetToInFlightPackages =
[aDecoder decodeObjectOfClass:[NSMutableDictionary class]
forKey:ktargetToInFlightPackagesKey];
GDTCORUploadCoordinator *sharedCoordinator = [GDTCORUploadCoordinator 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.
[aCoder encodeObject:_targetToInFlightPackages forKey:ktargetToInFlightPackagesKey];
if (_targetToInFlightPackages.count > 0) {
[aCoder encodeObject:_targetToInFlightPackages forKey:ktargetToInFlightPackagesKey];
}
}
#pragma mark - GDTLifecycleProtocol
#pragma mark - GDTCORLifecycleProtocol
- (void)appWillForeground:(GDTApplication *)app {
- (void)appWillForeground:(GDTCORApplication *)app {
// Not entirely thread-safe, but it should be fine.
self->_runningInBackground = NO;
[self startTimer];
}
- (void)appWillBackground:(GDTApplication *)app {
- (void)appWillBackground:(GDTCORApplication *)app {
// Not entirely thread-safe, but it should be fine.
self->_runningInBackground = YES;
@@ -191,49 +198,75 @@ static NSString *const ktargetToInFlightPackagesKey =
[self stopTimer];
// Create an immediate background task to run until the end of the current queue of work.
__block GDTBackgroundIdentifier bgID = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgID];
__block GDTCORBackgroundIdentifier bgID = [app beginBackgroundTaskWithExpirationHandler:^{
if (bgID != GDTCORBackgroundIdentifierInvalid) {
[app endBackgroundTask:bgID];
bgID = GDTCORBackgroundIdentifierInvalid;
}
}];
dispatch_async(_coordinationQueue, ^{
[app endBackgroundTask:bgID];
if (bgID != GDTCORBackgroundIdentifierInvalid) {
[app endBackgroundTask:bgID];
bgID = GDTCORBackgroundIdentifierInvalid;
}
});
}
- (void)appWillTerminate:(GDTApplication *)application {
- (void)appWillTerminate:(GDTCORApplication *)application {
dispatch_sync(_coordinationQueue, ^{
[self stopTimer];
});
}
#pragma mark - GDTUploadPackageProtocol
#pragma mark - GDTCORUploadPackageProtocol
- (void)packageDelivered:(GDTUploadPackage *)package successful:(BOOL)successful {
- (void)packageDelivered:(GDTCORUploadPackage *)package successful:(BOOL)successful {
if (!_coordinationQueue) {
return;
}
dispatch_async(_coordinationQueue, ^{
NSNumber *targetNumber = @(package.target);
[self->_targetToInFlightPackages removeObjectForKey:targetNumber];
id<GDTPrioritizer> prioritizer = self->_registrar.targetToPrioritizer[targetNumber];
if (!prioritizer) {
GDTLogError(GDTMCEPrioritizerError, @"A prioritizer should be registered for this target: %@",
targetNumber);
NSMutableDictionary<NSNumber *, GDTCORUploadPackage *> *targetToInFlightPackages =
self->_targetToInFlightPackages;
GDTCORRegistrar *registrar = self->_registrar;
if (targetToInFlightPackages) {
[targetToInFlightPackages removeObjectForKey:targetNumber];
}
if ([prioritizer respondsToSelector:@selector(packageDelivered:successful:)]) {
[prioritizer packageDelivered:package successful:successful];
if (registrar) {
id<GDTCORPrioritizer> prioritizer = registrar.targetToPrioritizer[targetNumber];
if (!prioritizer) {
GDTCORLogError(GDTCORMCEPrioritizerError,
@"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 {
- (void)packageExpired:(GDTCORUploadPackage *)package {
if (!_coordinationQueue) {
return;
}
dispatch_async(_coordinationQueue, ^{
NSNumber *targetNumber = @(package.target);
[self->_targetToInFlightPackages removeObjectForKey:targetNumber];
id<GDTPrioritizer> prioritizer = self->_registrar.targetToPrioritizer[targetNumber];
id<GDTUploader> uploader = self->_registrar.targetToUploader[targetNumber];
if ([prioritizer respondsToSelector:@selector(packageExpired:)]) {
[prioritizer packageExpired:package];
NSMutableDictionary<NSNumber *, GDTCORUploadPackage *> *targetToInFlightPackages =
self->_targetToInFlightPackages;
GDTCORRegistrar *registrar = self->_registrar;
if (targetToInFlightPackages) {
[targetToInFlightPackages removeObjectForKey:targetNumber];
}
if ([uploader respondsToSelector:@selector(packageExpired:)]) {
[uploader packageExpired:package];
if (registrar) {
id<GDTCORPrioritizer> prioritizer = registrar.targetToPrioritizer[targetNumber];
id<GDTCORUploader> uploader = registrar.targetToUploader[targetNumber];
if ([prioritizer respondsToSelector:@selector(packageExpired:)]) {
[prioritizer packageExpired:package];
}
if ([uploader respondsToSelector:@selector(packageExpired:)]) {
[uploader packageExpired:package];
}
}
});
}
@@ -14,16 +14,17 @@
* limitations under the License.
*/
#import <GoogleDataTransport/GDTUploadPackage.h>
#import <GoogleDataTransport/GDTCORUploadPackage.h>
#import <GoogleDataTransport/GDTClock.h>
#import <GoogleDataTransport/GDTConsoleLogger.h>
#import <GoogleDataTransport/GDTCORClock.h>
#import <GoogleDataTransport/GDTCORConsoleLogger.h>
#import <GoogleDataTransport/GDTCORStoredEvent.h>
#import "GDTLibrary/Private/GDTStorage_Private.h"
#import "GDTLibrary/Private/GDTUploadCoordinator.h"
#import "GDTLibrary/Private/GDTUploadPackage_Private.h"
#import "GDTCORLibrary/Private/GDTCORStorage_Private.h"
#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h"
#import "GDTCORLibrary/Private/GDTCORUploadPackage_Private.h"
@implementation GDTUploadPackage {
@implementation GDTCORUploadPackage {
/** If YES, the package's -completeDelivery method has been called. */
BOOL _isDelivered;
@@ -34,13 +35,13 @@
NSTimer *_expirationTimer;
}
- (instancetype)initWithTarget:(GDTTarget)target {
- (instancetype)initWithTarget:(GDTCORTarget)target {
self = [super init];
if (self) {
_target = target;
_storage = [GDTStorage sharedInstance];
_deliverByTime = [GDTClock clockSnapshotInTheFuture:180000];
_handler = [GDTUploadCoordinator sharedInstance];
_storage = [GDTCORStorage sharedInstance];
_deliverByTime = [GDTCORClock clockSnapshotInTheFuture:180000];
_handler = [GDTCORUploadCoordinator sharedInstance];
_expirationTimer = [NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:@selector(checkIfPackageIsExpired:)
@@ -51,7 +52,7 @@
}
- (instancetype)copy {
GDTUploadPackage *newPackage = [[GDTUploadPackage alloc] initWithTarget:_target];
GDTCORUploadPackage *newPackage = [[GDTCORUploadPackage alloc] initWithTarget:_target];
newPackage->_events = [_events copy];
return newPackage;
}
@@ -68,7 +69,7 @@
[_expirationTimer invalidate];
}
- (void)setStorage:(GDTStorage *)storage {
- (void)setStorage:(GDTCORStorage *)storage {
if (storage != _storage) {
_storage = storage;
}
@@ -76,8 +77,8 @@
- (void)completeDelivery {
if (_isDelivered) {
GDTLogError(GDTMCEDeliverTwice, @"%@",
@"It's an API violation to call -completeDelivery twice.");
GDTCORLogError(GDTCORMCEDeliverTwice, @"%@",
@"It's an API violation to call -completeDelivery twice.");
}
_isDelivered = YES;
if (!_isHandled && _handler &&
@@ -98,7 +99,7 @@
}
- (void)checkIfPackageIsExpired:(NSTimer *)timer {
if ([[GDTClock snapshot] isAfter:_deliverByTime]) {
if ([[GDTCORClock snapshot] isAfter:_deliverByTime]) {
if (_handler && [_handler respondsToSelector:@selector(packageExpired:)]) {
_isHandled = YES;
[_expirationTimer invalidate];
@@ -110,19 +111,19 @@
#pragma mark - NSSecureCoding
/** The keyed archiver key for the events property. */
static NSString *const kEventsKey = @"GDTUploadPackageEventsKey";
static NSString *const kEventsKey = @"GDTCORUploadPackageEventsKey";
/** The keyed archiver key for the _isHandled property. */
static NSString *const kDeliverByTimeKey = @"GDTUploadPackageDeliveryByTimeKey";
static NSString *const kDeliverByTimeKey = @"GDTCORUploadPackageDeliveryByTimeKey";
/** The keyed archiver key for the _isHandled ivar. */
static NSString *const kIsHandledKey = @"GDTUploadPackageIsHandledKey";
static NSString *const kIsHandledKey = @"GDTCORUploadPackageIsHandledKey";
/** The keyed archiver key for the handler property. */
static NSString *const kHandlerKey = @"GDTUploadPackageHandlerKey";
static NSString *const kHandlerKey = @"GDTCORUploadPackageHandlerKey";
/** The keyed archiver key for the target property. */
static NSString *const kTargetKey = @"GDTUploadPackageTargetKey";
static NSString *const kTargetKey = @"GDTCORUploadPackageTargetKey";
+ (BOOL)supportsSecureCoding {
return YES;
@@ -137,14 +138,15 @@ static NSString *const kTargetKey = @"GDTUploadPackageTargetKey";
}
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
GDTTarget target = [aDecoder decodeIntegerForKey:kTargetKey];
GDTCORTarget target = [aDecoder decodeIntegerForKey:kTargetKey];
self = [self initWithTarget:target];
if (self) {
_events = [aDecoder decodeObjectOfClass:[NSSet class] forKey:kEventsKey];
_deliverByTime = [aDecoder decodeObjectOfClass:[GDTClock class] forKey:kDeliverByTimeKey];
NSSet *classes = [NSSet setWithObjects:[NSSet class], [GDTCORStoredEvent class], nil];
_events = [aDecoder decodeObjectOfClasses:classes forKey:kEventsKey];
_deliverByTime = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:kDeliverByTimeKey];
_isHandled = [aDecoder decodeBoolForKey:kIsHandledKey];
// Isn't technically NSSecureCoding, because we don't know the class of this object.
_handler = [aDecoder decodeObjectForKey:kHandlerKey];
// _handler isn't technically NSSecureCoding, because we don't know the class of this object.
// but it gets decoded anyway.
}
return self;
}
@@ -14,13 +14,13 @@
* limitations under the License.
*/
#import <GoogleDataTransport/GDTEvent.h>
#import <GoogleDataTransport/GDTCOREvent.h>
#import <GoogleDataTransport/GDTClock.h>
#import <GoogleDataTransport/GDTCORClock.h>
NS_ASSUME_NONNULL_BEGIN
@interface GDTEvent ()
@interface GDTCOREvent ()
/** The serialized bytes of the event data object. */
@property(nonatomic) NSData *dataObjectTransportBytes;
@@ -21,7 +21,7 @@
NS_ASSUME_NONNULL_BEGIN
/** This class helps determine upload conditions by determining connectivity. */
@interface GDTReachability : NSObject
@interface GDTCORReachability : NSObject
/** The current set flags indicating network conditions */
+ (SCNetworkReachabilityFlags)currentFlags;
@@ -14,9 +14,9 @@
* limitations under the License.
*/
#import "GDTLibrary/Private/GDTReachability.h"
#import "GDTCORLibrary/Private/GDTCORReachability.h"
@interface GDTReachability ()
@interface GDTCORReachability ()
/** Allows manually setting the flags for testing purposes. */
@property(nonatomic, readwrite) SCNetworkReachabilityFlags flags;
@@ -14,9 +14,9 @@
* limitations under the License.
*/
#import <GoogleDataTransport/GDTRegistrar.h>
#import <GoogleDataTransport/GDTCORRegistrar.h>
@interface GDTRegistrar ()
@interface GDTCORRegistrar ()
NS_ASSUME_NONNULL_BEGIN
@@ -24,11 +24,11 @@ NS_ASSUME_NONNULL_BEGIN
@property(nonatomic, readonly) dispatch_queue_t registrarQueue;
/** A map of targets to backend implementations. */
@property(atomic, readonly) NSMutableDictionary<NSNumber *, id<GDTUploader>> *targetToUploader;
@property(atomic, readonly) NSMutableDictionary<NSNumber *, id<GDTCORUploader>> *targetToUploader;
/** A map of targets to prioritizer implementations. */
@property(atomic, readonly)
NSMutableDictionary<NSNumber *, id<GDTPrioritizer>> *targetToPrioritizer;
NSMutableDictionary<NSNumber *, id<GDTCORPrioritizer>> *targetToPrioritizer;
@end
@@ -16,15 +16,15 @@
#import <Foundation/Foundation.h>
#import <GoogleDataTransport/GDTLifecycle.h>
#import <GoogleDataTransport/GDTCORLifecycle.h>
@class GDTEvent;
@class GDTStoredEvent;
@class GDTCOREvent;
@class GDTCORStoredEvent;
NS_ASSUME_NONNULL_BEGIN
/** Manages the storage of events. This class is thread-safe. */
@interface GDTStorage : NSObject <NSSecureCoding, GDTLifecycleProtocol>
@interface GDTCORStorage : NSObject <NSSecureCoding, GDTCORLifecycleProtocol>
/** Creates and/or returns the storage singleton.
*
@@ -33,17 +33,17 @@ NS_ASSUME_NONNULL_BEGIN
+ (instancetype)sharedInstance;
/** Stores event.dataObjectTransportBytes into a shared on-device folder and tracks the event via
* a GDTStoredEvent instance.
* a GDTCORStoredEvent instance.
*
* @param event The event to store.
*/
- (void)storeEvent:(GDTEvent *)event;
- (void)storeEvent:(GDTCOREvent *)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;
- (void)removeEvents:(NSSet<GDTCORStoredEvent *> *)events;
@end
@@ -14,30 +14,30 @@
* limitations under the License.
*/
#import "GDTLibrary/Private/GDTStorage.h"
#import "GDTCORLibrary/Private/GDTCORStorage.h"
@class GDTUploadCoordinator;
@class GDTCORUploadCoordinator;
NS_ASSUME_NONNULL_BEGIN
@interface GDTStorage ()
@interface GDTCORStorage ()
/** 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;
NSMutableDictionary<NSNumber *, NSMutableSet<GDTCORStoredEvent *> *> *targetToEventSet;
/** All the events that have been stored. */
@property(readonly, nonatomic) NSMutableOrderedSet<GDTStoredEvent *> *storedEvents;
@property(readonly, nonatomic) NSMutableOrderedSet<GDTCORStoredEvent *> *storedEvents;
/** The upload coordinator instance used by this storage instance. */
@property(nonatomic) GDTUploadCoordinator *uploadCoordinator;
@property(nonatomic) GDTCORUploadCoordinator *uploadCoordinator;
/** If YES, every call to -storeLog results in background task and serializes the singleton to disk.
*/
@property(nonatomic, readonly) BOOL runningInBackground;
@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.
@@ -16,11 +16,11 @@
#import <Foundation/Foundation.h>
#import <GoogleDataTransport/GDTLifecycle.h>
#import <GoogleDataTransport/GDTCORLifecycle.h>
@class GDTEvent;
@class GDTCOREvent;
@protocol GDTEventTransformer;
@protocol GDTCOREventTransformer;
NS_ASSUME_NONNULL_BEGIN
@@ -30,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN
* 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>
@interface GDTCORTransformer : NSObject <GDTCORLifecycleProtocol>
/** Instantiates or returns the event transformer singleton.
*
@@ -46,8 +46,8 @@ NS_ASSUME_NONNULL_BEGIN
* @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;
- (void)transformEvent:(GDTCOREvent *)event
withTransformers:(nullable NSArray<id<GDTCOREventTransformer>> *)transformers;
@end
@@ -14,19 +14,19 @@
* limitations under the License.
*/
#import "GDTLibrary/Private/GDTTransformer.h"
#import "GDTCORLibrary/Private/GDTCORTransformer.h"
@class GDTStorage;
@class GDTCORStorage;
NS_ASSUME_NONNULL_BEGIN
@interface GDTTransformer ()
@interface GDTCORTransformer ()
/** 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;
@property(nonatomic) GDTCORStorage *storageInstance;
/** If YES, every call to -transformEvent will result in a background task. */
@property(nonatomic, readonly) BOOL runningInBackground;
@@ -14,25 +14,25 @@
* limitations under the License.
*/
#import <GoogleDataTransport/GDTTransport.h>
#import <GoogleDataTransport/GDTCORTransport.h>
@class GDTTransformer;
@class GDTCORTransformer;
NS_ASSUME_NONNULL_BEGIN
@interface GDTTransport ()
@interface GDTCORTransport ()
/** 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;
@property(nonatomic) NSArray<id<GDTCOREventTransformer>> *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;
@property(nonatomic) GDTCORTransformer *transformerInstance;
@end
@@ -16,21 +16,21 @@
#import <Foundation/Foundation.h>
#import <GoogleDataTransport/GDTLifecycle.h>
#import <GoogleDataTransport/GDTRegistrar.h>
#import <GoogleDataTransport/GDTCORLifecycle.h>
#import <GoogleDataTransport/GDTCORRegistrar.h>
#import "GDTLibrary/Private/GDTUploadPackage_Private.h"
#import "GDTCORLibrary/Private/GDTCORUploadPackage_Private.h"
@class GDTClock;
@class GDTStorage;
@class GDTCORClock;
@class GDTCORStorage;
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>
@interface GDTCORUploadCoordinator
: NSObject <NSSecureCoding, GDTCORLifecycleProtocol, GDTCORUploadPackageProtocol>
/** The queue on which all upload coordination will occur. Also used by a dispatch timer. */
/** Creates and/or returrns the singleton.
@@ -51,13 +51,13 @@ NS_ASSUME_NONNULL_BEGIN
/** The map of targets to in-flight packages. */
@property(nonatomic, readonly)
NSMutableDictionary<NSNumber *, GDTUploadPackage *> *targetToInFlightPackages;
NSMutableDictionary<NSNumber *, GDTCORUploadPackage *> *targetToInFlightPackages;
/** The storage object the coordinator will use. Generally used for testing. */
@property(nonatomic) GDTStorage *storage;
@property(nonatomic) GDTCORStorage *storage;
/** The registrar object the coordinator will use. Generally used for testing. */
@property(nonatomic) GDTRegistrar *registrar;
@property(nonatomic) GDTCORRegistrar *registrar;
/** If YES, completion and other operations will result in serializing the singleton to disk. */
@property(nonatomic, readonly) BOOL runningInBackground;
@@ -67,7 +67,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @param target The target that should force an upload.
*/
- (void)forceUploadForTarget:(GDTTarget)target;
- (void)forceUploadForTarget:(GDTCORTarget)target;
/** Starts the upload timer. */
- (void)startTimer;
@@ -14,16 +14,16 @@
* limitations under the License.
*/
#import <GoogleDataTransport/GDTUploadPackage.h>
#import <GoogleDataTransport/GDTCORUploadPackage.h>
@class GDTStorage;
@class GDTCORStorage;
@interface GDTUploadPackage ()
@interface GDTCORUploadPackage ()
/** The storage object this upload package will use to resolve event hashes to files. */
@property(nonatomic) GDTStorage *storage;
@property(nonatomic) GDTCORStorage *storage;
/** A handler that will receive callbacks for certain events. */
@property(nonatomic) id<NSSecureCoding, GDTUploadPackageProtocol> handler;
@property(nonatomic) id<NSSecureCoding, GDTCORUploadPackageProtocol> handler;
@end
@@ -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/GDTCORConsoleLogger.h>
/** A block type that could be run instead of normal assertion logging. No return type, no params.
*/
typedef void (^GDTCORAssertionBlock)(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 GDTCORAssertionBlock _Nullable GDTCORAssertionBlockToRunInstead(void);
#if defined(NS_BLOCK_ASSERTIONS)
#define GDTCORAssert(condition, ...) \
do { \
} while (0);
#define GDTCORFatalAssert(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 GDTCORAssert(condition, ...) \
do { \
if (__builtin_expect(!(condition), 0)) { \
GDTCORAssertionBlock assertionBlock = GDTCORAssertionBlockToRunInstead(); \
if (assertionBlock) { \
assertionBlock(); \
} else { \
__PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \
NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; \
__assert_file__ = __assert_file__ ? __assert_file__ : @"<Unknown File>"; \
GDTCORLogError(GDTCORMCEGeneralError, @"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 GDTCORFatalAssert(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>"; \
GDTCORLogError(GDTCORMCEFatalAssertion, \
@"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)
@@ -19,7 +19,7 @@
NS_ASSUME_NONNULL_BEGIN
/** This class manages the device clock and produces snapshots of the current time. */
@interface GDTClock : NSObject <NSSecureCoding>
@interface GDTCORClock : NSObject <NSSecureCoding>
/** The wallclock time, UTC, in milliseconds. */
@property(nonatomic, readonly) int64_t timeMillis;
@@ -33,13 +33,13 @@ NS_ASSUME_NONNULL_BEGIN
/** The device uptime when this clock was created. */
@property(nonatomic, readonly) int64_t uptime;
/** Creates a GDTClock object using the current time and offsets.
/** Creates a GDTCORClock object using the current time and offsets.
*
* @return A new GDTClock object representing the current time state.
* @return A new GDTCORClock object representing the current time state.
*/
+ (instancetype)snapshot;
/** Creates a GDTClock object representing a time in the future, relative to now.
/** Creates a GDTCORClock 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.
@@ -50,7 +50,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @return YES if the calling clock's time is after the given clock's time.
*/
- (BOOL)isAfter:(GDTClock *)otherClock;
- (BOOL)isAfter:(GDTCORClock *)otherClock;
@end
@@ -23,57 +23,62 @@
* - MCW => MessageCodeWarning
* - MCE => MessageCodeError
*/
typedef NS_ENUM(NSInteger, GDTMessageCode) {
typedef NS_ENUM(NSInteger, GDTCORMessageCode) {
/** For warning messages concerning transportBytes: not being implemented by a data object. */
GDTMCWDataObjectMissingBytesImpl = 1,
GDTCORMCWDataObjectMissingBytesImpl = 1,
/** For warning messages concerning a failed event upload. */
GDTMCWUploadFailed = 2,
GDTCORMCWUploadFailed = 2,
/** For warning messages concerning a forced event upload. */
GDTMCWForcedUpload = 3,
GDTCORMCWForcedUpload = 3,
/** For warning messages concerning a failed reachability call. */
GDTMCWReachabilityFailed = 4,
GDTCORMCWReachabilityFailed = 4,
/** For error messages concerning transform: not being implemented by an event transformer. */
GDTMCETransformerDoesntImplementTransform = 1000,
GDTCORMCETransformerDoesntImplementTransform = 1000,
/** For error messages concerning the creation of a directory failing. */
GDTMCEDirectoryCreationError = 1001,
GDTCORMCEDirectoryCreationError = 1001,
/** For error messages concerning the writing of a event file. */
GDTMCEFileWriteError = 1002,
GDTCORMCEFileWriteError = 1002,
/** For error messages concerning the lack of a prioritizer for a given backend. */
GDTMCEPrioritizerError = 1003,
GDTCORMCEPrioritizerError = 1003,
/** For error messages concerning a package delivery API violation. */
GDTMCEDeliverTwice = 1004,
GDTCORMCEDeliverTwice = 1004,
/** For error messages concerning an error in an implementation of -transportBytes. */
GDTMCETransportBytesError = 1005,
GDTCORMCETransportBytesError = 1005,
/** For general purpose error messages in a dependency. */
GDTMCEGeneralError = 1006
GDTCORMCEGeneralError = 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.
*/
GDTCORMCEFatalAssertion = 1007
};
/** */
FOUNDATION_EXPORT
void GDTLog(GDTMessageCode code, NSString *_Nonnull format, ...);
void GDTCORLog(GDTCORMessageCode 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);
FOUNDATION_EXPORT NSString *_Nonnull GDTCORMessageCodeEnumToString(GDTCORMessageCode code);
// A define to wrap GULLogWarning with slightly more convenient usage.
#define GDTLogWarning(MESSAGE_CODE, MESSAGE_FORMAT, ...) \
GDTLog(MESSAGE_CODE, MESSAGE_FORMAT, __VA_ARGS__);
#define GDTCORLogWarning(MESSAGE_CODE, MESSAGE_FORMAT, ...) \
GDTCORLog(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__);
#define GDTCORLogError(MESSAGE_CODE, MESSAGE_FORMAT, ...) \
GDTCORLog(MESSAGE_CODE, MESSAGE_FORMAT, __VA_ARGS__);
@@ -19,7 +19,7 @@
NS_ASSUME_NONNULL_BEGIN
/** This class represents a future data object, determined at instantiation time. */
@interface GDTDataFuture : NSObject <NSSecureCoding>
@interface GDTCORDataFuture : NSObject <NSSecureCoding>
/** The data, computed on-demand, depending on the initializer. */
@property(nullable, readonly, nonatomic) NSData *data;
@@ -16,36 +16,36 @@
#import <Foundation/Foundation.h>
#import <GoogleDataTransport/GDTEventDataObject.h>
#import <GoogleDataTransport/GDTCOREventDataObject.h>
@class GDTClock;
@class GDTDataFuture;
@class GDTStoredEvent;
@class GDTCORClock;
@class GDTCORDataFuture;
@class GDTCORStoredEvent;
NS_ASSUME_NONNULL_BEGIN
/** The different possible quality of service specifiers. High values indicate high priority. */
typedef NS_ENUM(NSInteger, GDTEventQoS) {
typedef NS_ENUM(NSInteger, GDTCOREventQoS) {
/** The QoS tier wasn't set, and won't ever be sent. */
GDTEventQoSUnknown = 0,
GDTCOREventQoSUnknown = 0,
/** This event is internal telemetry data that should not be sent on its own if possible. */
GDTEventQoSTelemetry = 1,
GDTCOREventQoSTelemetry = 1,
/** This event should be sent, but in a batch only roughly once per day. */
GDTEventQoSDaily = 2,
GDTCOREventQoSDaily = 2,
/** This event should be sent when requested by the uploader. */
GDTEventQosDefault = 3,
GDTCOREventQosDefault = 3,
/** This event should be sent immediately along with any other data that can be batched. */
GDTEventQoSFast = 4,
GDTCOREventQoSFast = 4,
/** This event should only be uploaded on wifi. */
GDTEventQoSWifiOnly = 5,
GDTCOREventQoSWifiOnly = 5,
};
@interface GDTEvent : NSObject <NSSecureCoding>
@interface GDTCOREvent : NSObject <NSSecureCoding>
/** The mapping identifier, to allow backends to map the transport bytes to a proto. */
@property(readonly, nonatomic) NSString *mappingID;
@@ -54,14 +54,14 @@ typedef NS_ENUM(NSInteger, GDTEventQoS) {
@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 GDTCOREventDataObject protocol. */
@property(nullable, nonatomic) id<GDTCOREventDataObject> dataObject;
/** The quality of service tier this event belongs to. */
@property(nonatomic) GDTEventQoS qosTier;
@property(nonatomic) GDTCOREventQoS qosTier;
/** The clock snapshot at the time of the event. */
@property(nonatomic) GDTClock *clockSnapshot;
@property(nonatomic) GDTCORClock *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.
@@ -82,12 +82,12 @@ typedef NS_ENUM(NSInteger, GDTEventQoS) {
- (instancetype)initWithMappingID:(NSString *)mappingID
target:(NSInteger)target NS_DESIGNATED_INITIALIZER;
/** Returns the GDTStoredEvent equivalent of self.
/** Returns the GDTCORStoredEvent equivalent of self.
*
* @param dataFuture The data future representing the transport bytes of the original event.
* @return An equivalent GDTStoredEvent.
* @return An equivalent GDTCORStoredEvent.
*/
- (GDTStoredEvent *)storedEventWithDataFuture:(GDTDataFuture *)dataFuture;
- (GDTCORStoredEvent *)storedEventWithDataFuture:(GDTCORDataFuture *)dataFuture;
@end
@@ -21,7 +21,7 @@ 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>
@protocol GDTCOREventDataObject <NSObject>
@required
@@ -16,12 +16,12 @@
#import <Foundation/Foundation.h>
@class GDTEvent;
@class GDTCOREvent;
NS_ASSUME_NONNULL_BEGIN
/** Defines the API that event transformers must adopt. */
@protocol GDTEventTransformer <NSObject>
@protocol GDTCOREventTransformer <NSObject>
@required
@@ -31,7 +31,7 @@ NS_ASSUME_NONNULL_BEGIN
* @param event The event to transform.
* @return A transformed event, or nil if the transformation dropped the event.
*/
- (GDTEvent *)transform:(GDTEvent *)event;
- (GDTCOREvent *)transform:(GDTCOREvent *)event;
@end
@@ -16,35 +16,36 @@
#import <Foundation/Foundation.h>
#import <GoogleDataTransport/GDTPlatform.h>
#import <GoogleDataTransport/GDTCORPlatform.h>
@class GDTEvent;
@class GDTCOREvent;
NS_ASSUME_NONNULL_BEGIN
/** A protocol defining the lifecycle events objects in the library must respond to immediately. */
@protocol GDTLifecycleProtocol <NSObject>
@protocol GDTCORLifecycleProtocol <NSObject>
@optional
/** Indicates an imminent app termination in the rare occurrence when -applicationWillTerminate: has
* been called.
*
* @param app The GDTApplication instance.
* @param app The GDTCORApplication instance.
*/
- (void)appWillTerminate:(GDTApplication *)app;
- (void)appWillTerminate:(GDTCORApplication *)app;
/** Indicates that the app is moving to background and eventual suspension.
/** Indicates that the app is moving to background and eventual suspension or the current UIScene is
* deactivating.
*
* @param app The GDTApplication instance.
* @param app The GDTCORApplication instance.
*/
- (void)appWillBackground:(GDTApplication *)app;
- (void)appWillBackground:(GDTCORApplication *)app;
/** Indicates that the app is resuming operation.
/** Indicates that the app is resuming operation or a UIScene is activating.
*
* @param app The GDTApplication instance.
* @param app The GDTCORApplication instance.
*/
- (void)appWillForeground:(GDTApplication *)app;
- (void)appWillForeground:(GDTCORApplication *)app;
@end
@@ -52,10 +53,10 @@ NS_ASSUME_NONNULL_BEGIN
*
* 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.
* library (GDTCORStorage and GDTCORUploadCoordinator singletons) will deserialize themselves from
* and to disk before and after every operation, respectively.
*/
@interface GDTLifecycle : NSObject <GDTApplicationDelegate>
@interface GDTCORLifecycle : NSObject <GDTCORApplicationDelegate>
@end
@@ -26,61 +26,61 @@
NS_ASSUME_NONNULL_BEGIN
/** A notification sent out if the app is backgrounding. */
FOUNDATION_EXPORT NSString *const kGDTApplicationDidEnterBackgroundNotification;
FOUNDATION_EXPORT NSString *const kGDTCORApplicationDidEnterBackgroundNotification;
/** A notification sent out if the app is foregrounding. */
FOUNDATION_EXPORT NSString *const kGDTApplicationWillEnterForegroundNotification;
FOUNDATION_EXPORT NSString *const kGDTCORApplicationWillEnterForegroundNotification;
/** A notification sent out if the app is terminating. */
FOUNDATION_EXPORT NSString *const kGDTApplicationWillTerminateNotification;
FOUNDATION_EXPORT NSString *const kGDTCORApplicationWillTerminateNotification;
/** 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);
BOOL GDTCORReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags);
/** A typedef identify background identifiers. */
typedef NSUInteger GDTBackgroundIdentifier;
typedef volatile NSUInteger GDTCORBackgroundIdentifier;
/** A background task's invalid sentinel value. */
FOUNDATION_EXPORT const GDTBackgroundIdentifier GDTBackgroundIdentifierInvalid;
FOUNDATION_EXPORT const GDTCORBackgroundIdentifier GDTCORBackgroundIdentifierInvalid;
#if TARGET_OS_IOS || TARGET_OS_TV
/** A protocol that wraps UIApplicationDelegate or NSObject protocol, depending on the platform. */
@protocol GDTApplicationDelegate <UIApplicationDelegate>
@protocol GDTCORApplicationDelegate <UIApplicationDelegate>
#elif TARGET_OS_OSX
@protocol GDTApplicationDelegate <NSApplicationDelegate>
@protocol GDTCORApplicationDelegate <NSApplicationDelegate>
#else
@protocol GDTApplicationDelegate <NSObject>
@protocol GDTCORApplicationDelegate <NSObject>
#endif // TARGET_OS_IOS || TARGET_OS_TV
@end
/** A cross-platform application class. */
@interface GDTApplication : NSObject <GDTApplicationDelegate>
@interface GDTCORApplication : NSObject <GDTCORApplicationDelegate>
/** Creates and/or returns the shared application instance.
*
* @return The shared application instance.
*/
+ (nullable GDTApplication *)sharedApplication;
+ (nullable GDTCORApplication *)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.
* @return An identifier for the background task, or GDTCORBackgroundIdentifierInvalid if one
* couldn't be created.
*/
- (GDTBackgroundIdentifier)beginBackgroundTaskWithExpirationHandler:
- (GDTCORBackgroundIdentifier)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;
- (void)endBackgroundTask:(GDTCORBackgroundIdentifier)bgID;
@end
@@ -16,39 +16,39 @@
#import <Foundation/Foundation.h>
#import <GoogleDataTransport/GDTLifecycle.h>
#import <GoogleDataTransport/GDTUploadPackage.h>
#import <GoogleDataTransport/GDTCORLifecycle.h>
#import <GoogleDataTransport/GDTCORUploadPackage.h>
@class GDTStoredEvent;
@class GDTCORStoredEvent;
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) {
typedef NS_OPTIONS(NSInteger, GDTCORUploadConditions) {
/** An upload shouldn't be attempted, because there's no network. */
GDTUploadConditionNoNetwork = 1 << 0,
GDTCORUploadConditionNoNetwork = 1 << 0,
/** An upload would likely use mobile data. */
GDTUploadConditionMobileData = 1 << 1,
GDTCORUploadConditionMobileData = 1 << 1,
/** An upload would likely use wifi data. */
GDTUploadConditionWifiData = 1 << 2,
GDTCORUploadConditionWifiData = 1 << 2,
/** An upload uses some sort of network connection, but it's unclear which. */
GDTUploadConditionUnclearConnection = 1 << 3,
GDTCORUploadConditionUnclearConnection = 1 << 3,
/** A high priority event has occurred. */
GDTUploadConditionHighPriority = 1 << 4,
GDTCORUploadConditionHighPriority = 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>
@protocol GDTCORPrioritizer <NSObject, GDTCORLifecycleProtocol, GDTCORUploadPackageProtocol>
@required
@@ -58,7 +58,7 @@ typedef NS_OPTIONS(NSInteger, GDTUploadConditions) {
*
* @param event The event to prioritize.
*/
- (void)prioritizeEvent:(GDTStoredEvent *)event;
- (void)prioritizeEvent:(GDTCORStoredEvent *)event;
/** Returns a set of events to upload given a set of conditions.
*
@@ -66,7 +66,7 @@ typedef NS_OPTIONS(NSInteger, GDTUploadConditions) {
* @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;
- (GDTCORUploadPackage *)uploadPackageWithConditions:(GDTCORUploadConditions)conditions;
@end
@@ -16,14 +16,14 @@
#import <Foundation/Foundation.h>
#import <GoogleDataTransport/GDTPrioritizer.h>
#import <GoogleDataTransport/GDTTargets.h>
#import <GoogleDataTransport/GDTUploader.h>
#import <GoogleDataTransport/GDTCORPrioritizer.h>
#import <GoogleDataTransport/GDTCORTargets.h>
#import <GoogleDataTransport/GDTCORUploader.h>
NS_ASSUME_NONNULL_BEGIN
/** Manages the registration of targets with the transport SDK. */
@interface GDTRegistrar : NSObject <GDTLifecycleProtocol>
@interface GDTCORRegistrar : NSObject <GDTCORLifecycleProtocol>
/** Creates and/or returns the singleton instance.
*
@@ -36,14 +36,14 @@ NS_ASSUME_NONNULL_BEGIN
* @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;
- (void)registerUploader:(id<GDTCORUploader>)backend target:(GDTCORTarget)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;
- (void)registerPrioritizer:(id<GDTCORPrioritizer>)prioritizer target:(GDTCORTarget)target;
@end

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