Push from command line

This commit is contained in:
Deniz Duezgoeren
2019-08-12 11:20:21 +02:00
parent 3a919dcb23
commit f1345eac14
512 changed files with 103288 additions and 1930 deletions
@@ -0,0 +1,188 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h"
#if TARGET_OS_IOS || TARGET_OS_TV
#import <UIKit/UIKit.h>
#elif TARGET_OS_OSX
#import <AppKit/AppKit.h>
#endif // TARGET_OS_IOS || TARGET_OS_TV
#import <GoogleDataTransport/GDTConsoleLogger.h>
#import <nanopb/pb.h>
#import <nanopb/pb_decode.h>
#import <nanopb/pb_encode.h>
#import "GDTCCTLibrary/Private/GDTCCTPrioritizer.h"
#pragma mark - General purpose encoders
pb_bytes_array_t *GDTCCTEncodeString(NSString *string) {
NSData *stringBytes = [string dataUsingEncoding:NSUTF8StringEncoding];
return GDTCCTEncodeData(stringBytes);
}
pb_bytes_array_t *GDTCCTEncodeData(NSData *data) {
pb_bytes_array_t *pbBytes = malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(data.length));
memcpy(pbBytes->bytes, [data bytes], data.length);
pbBytes->size = (pb_size_t)data.length;
return pbBytes;
}
#pragma mark - CCT object constructors
NSData *_Nullable GDTCCTEncodeBatchedLogRequest(gdt_cct_BatchedLogRequest *batchedLogRequest) {
pb_ostream_t sizestream = PB_OSTREAM_SIZING;
// Encode 1 time to determine the size.
if (!pb_encode(&sizestream, gdt_cct_BatchedLogRequest_fields, batchedLogRequest)) {
GDTLogError(GDTMCEGeneralError, @"Error in nanopb encoding for size: %s",
PB_GET_ERROR(&sizestream));
}
// Encode a 2nd time to actually get the bytes from it.
size_t bufferSize = sizestream.bytes_written;
CFMutableDataRef dataRef = CFDataCreateMutable(CFAllocatorGetDefault(), bufferSize);
pb_ostream_t ostream = pb_ostream_from_buffer((void *)CFDataGetBytePtr(dataRef), bufferSize);
if (!pb_encode(&ostream, gdt_cct_BatchedLogRequest_fields, batchedLogRequest)) {
GDTLogError(GDTMCEGeneralError, @"Error in nanopb encoding for bytes: %s",
PB_GET_ERROR(&ostream));
}
CFDataSetLength(dataRef, ostream.bytes_written);
return CFBridgingRelease(dataRef);
}
gdt_cct_BatchedLogRequest GDTCCTConstructBatchedLogRequest(
NSDictionary<NSString *, NSSet<GDTStoredEvent *> *> *logMappingIDToLogSet) {
gdt_cct_BatchedLogRequest batchedLogRequest = gdt_cct_BatchedLogRequest_init_default;
NSUInteger numberOfLogRequests = logMappingIDToLogSet.count;
gdt_cct_LogRequest *logRequests = malloc(sizeof(gdt_cct_LogRequest) * numberOfLogRequests);
__block int i = 0;
[logMappingIDToLogSet enumerateKeysAndObjectsUsingBlock:^(
NSString *_Nonnull logMappingID,
NSSet<GDTStoredEvent *> *_Nonnull logSet, BOOL *_Nonnull stop) {
int32_t logSource = [logMappingID intValue];
gdt_cct_LogRequest logRequest = GDTCCTConstructLogRequest(logSource, logSet);
logRequests[i] = logRequest;
i++;
}];
batchedLogRequest.log_request = logRequests;
batchedLogRequest.log_request_count = (pb_size_t)numberOfLogRequests;
return batchedLogRequest;
}
gdt_cct_LogRequest GDTCCTConstructLogRequest(int32_t logSource,
NSSet<GDTStoredEvent *> *_Nonnull logSet) {
if (logSet.count == 0) {
GDTLogError(GDTMCEGeneralError, @"%@", @"An empty event set can't be serialized to proto.");
gdt_cct_LogRequest logRequest = gdt_cct_LogRequest_init_default;
return logRequest;
}
gdt_cct_LogRequest logRequest = gdt_cct_LogRequest_init_default;
logRequest.log_source = logSource;
logRequest.has_log_source = 1;
logRequest.client_info = GDTCCTConstructClientInfo();
logRequest.has_client_info = 1;
logRequest.log_event = malloc(sizeof(gdt_cct_LogEvent) * logSet.count);
int i = 0;
for (GDTStoredEvent *log in logSet) {
gdt_cct_LogEvent logEvent = GDTCCTConstructLogEvent(log);
logRequest.log_event[i] = logEvent;
i++;
}
logRequest.log_event_count = (pb_size_t)logSet.count;
return logRequest;
}
gdt_cct_LogEvent GDTCCTConstructLogEvent(GDTStoredEvent *event) {
gdt_cct_LogEvent logEvent = gdt_cct_LogEvent_init_default;
logEvent.event_time_ms = event.clockSnapshot.timeMillis;
logEvent.has_event_time_ms = 1;
logEvent.event_uptime_ms = event.clockSnapshot.uptime;
logEvent.has_event_uptime_ms = 1;
logEvent.timezone_offset_seconds = event.clockSnapshot.timezoneOffsetSeconds;
logEvent.has_timezone_offset_seconds = 1;
// TODO: Read network_connection_info from the custom params dict.
NSError *error;
NSData *extensionBytes = [NSData dataWithContentsOfURL:event.dataFuture.fileURL
options:0
error:&error];
if (error) {
GDTLogError(GDTMCEGeneralError, @"There was an error reading extension bytes from disk: %@",
error);
return logEvent;
}
logEvent.source_extension = GDTCCTEncodeData(extensionBytes); // read bytes from the file.
return logEvent;
}
gdt_cct_ClientInfo GDTCCTConstructClientInfo() {
gdt_cct_ClientInfo clientInfo = gdt_cct_ClientInfo_init_default;
clientInfo.client_type = gdt_cct_ClientInfo_ClientType_IOS_FIREBASE;
clientInfo.has_client_type = 1;
#if TARGET_OS_IOS || TARGET_OS_TV
clientInfo.ios_client_info = GDTCCTConstructiOSClientInfo();
clientInfo.has_ios_client_info = 1;
#elif TARGET_OS_OSX
// TODO(mikehaney24): Expand the proto to include macOS client info.
#endif
return clientInfo;
}
gdt_cct_IosClientInfo GDTCCTConstructiOSClientInfo() {
gdt_cct_IosClientInfo iOSClientInfo = gdt_cct_IosClientInfo_init_default;
#if TARGET_OS_IOS || TARGET_OS_TV
UIDevice *device = [UIDevice currentDevice];
NSBundle *bundle = [NSBundle mainBundle];
NSLocale *locale = [NSLocale currentLocale];
iOSClientInfo.os_full_version = GDTCCTEncodeString(device.systemVersion);
NSArray *versionComponents = [device.systemVersion componentsSeparatedByString:@"."];
iOSClientInfo.os_major_version = GDTCCTEncodeString(versionComponents[0]);
NSString *version = [bundle objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
if (version) {
iOSClientInfo.application_build = GDTCCTEncodeString(version);
}
iOSClientInfo.country = GDTCCTEncodeString([locale objectForKey:NSLocaleCountryCode]);
iOSClientInfo.model = GDTCCTEncodeString(device.model);
NSString *languageCode = bundle.preferredLocalizations.firstObject;
iOSClientInfo.language_code =
languageCode ? GDTCCTEncodeString(languageCode) : GDTCCTEncodeString(@"en");
iOSClientInfo.application_bundle_id = GDTCCTEncodeString(bundle.bundleIdentifier);
#endif
return iOSClientInfo;
}
#pragma mark - CCT Object decoders
gdt_cct_LogResponse GDTCCTDecodeLogResponse(NSData *data, NSError **error) {
gdt_cct_LogResponse response = gdt_cct_LogResponse_init_default;
pb_istream_t istream = pb_istream_from_buffer([data bytes], [data length]);
if (!pb_decode(&istream, gdt_cct_LogResponse_fields, &response)) {
NSString *nanopb_error = [NSString stringWithFormat:@"%s", PB_GET_ERROR(&istream)];
NSDictionary *userInfo = @{@"nanopb error:" : nanopb_error};
if (error != NULL) {
*error = [NSError errorWithDomain:NSURLErrorDomain code:-1 userInfo:userInfo];
}
response = (gdt_cct_LogResponse)gdt_cct_LogResponse_init_default;
}
return response;
}
@@ -0,0 +1,188 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "GDTCCTLibrary/Private/GDTCCTPrioritizer.h"
#import <GoogleDataTransport/GDTEvent.h>
#import <GoogleDataTransport/GDTRegistrar.h>
#import <GoogleDataTransport/GDTStoredEvent.h>
#import <GoogleDataTransport/GDTTargets.h>
const static int64_t kMillisPerDay = 8.64e+7;
@implementation GDTCCTPrioritizer
+ (void)load {
GDTCCTPrioritizer *prioritizer = [GDTCCTPrioritizer sharedInstance];
[[GDTRegistrar sharedInstance] registerPrioritizer:prioritizer target:kGDTTargetCCT];
}
+ (instancetype)sharedInstance {
static GDTCCTPrioritizer *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[GDTCCTPrioritizer alloc] init];
});
return sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
_queue = dispatch_queue_create("com.google.GDTCCTPrioritizer", DISPATCH_QUEUE_SERIAL);
_events = [[NSMutableSet alloc] init];
}
return self;
}
#pragma mark - GDTPrioritizer Protocol
- (void)prioritizeEvent:(GDTStoredEvent *)event {
dispatch_async(_queue, ^{
[self.events addObject:event];
});
}
- (GDTUploadPackage *)uploadPackageWithConditions:(GDTUploadConditions)conditions {
GDTUploadPackage *package = [[GDTUploadPackage alloc] initWithTarget:kGDTTargetCCT];
dispatch_sync(_queue, ^{
NSSet<GDTStoredEvent *> *logEventsThatWillBeSent;
// A high priority event effectively flushes all events to be sent.
if ((conditions & GDTUploadConditionHighPriority) == GDTUploadConditionHighPriority) {
package.events = self.events;
return;
}
// If on wifi, upload logs that are ok to send on wifi.
if ((conditions & GDTUploadConditionWifiData) == GDTUploadConditionWifiData) {
logEventsThatWillBeSent = [self logEventsOkToSendOnWifi];
} else {
logEventsThatWillBeSent = [self logEventsOkToSendOnMobileData];
}
// If it's been > 24h since the last daily upload, upload logs with the daily QoS.
if (self.timeOfLastDailyUpload) {
int64_t millisSinceLastUpload =
[GDTClock snapshot].timeMillis - self.timeOfLastDailyUpload.timeMillis;
if (millisSinceLastUpload > kMillisPerDay) {
logEventsThatWillBeSent =
[logEventsThatWillBeSent setByAddingObjectsFromSet:[self logEventsOkToSendDaily]];
}
} else {
self.timeOfLastDailyUpload = [GDTClock snapshot];
logEventsThatWillBeSent =
[logEventsThatWillBeSent setByAddingObjectsFromSet:[self logEventsOkToSendDaily]];
}
package.events = logEventsThatWillBeSent;
});
return package;
}
#pragma mark - Private helper methods
/** The different possible quality of service specifiers. High values indicate high priority. */
typedef NS_ENUM(NSInteger, GDTCCTQoSTier) {
/** The QoS tier wasn't set, and won't ever be sent. */
GDTCCTQoSDefault = 0,
/** This event is internal telemetry data that should not be sent on its own if possible. */
GDTCCTQoSTelemetry = 1,
/** This event should be sent, but in a batch only roughly once per day. */
GDTCCTQoSDaily = 2,
/** This event should only be uploaded on wifi. */
GDTCCTQoSWifiOnly = 5,
};
/** Converts a GDTEventQoS to a GDTCCTQoS tier.
*
* @param qosTier The GDTEventQoS value.
* @return A static NSNumber that represents the CCT QoS tier.
*/
FOUNDATION_STATIC_INLINE
NSNumber *GDTCCTQosTierFromGDTEventQosTier(GDTEventQoS qosTier) {
switch (qosTier) {
case GDTEventQoSWifiOnly:
return @(GDTCCTQoSWifiOnly);
break;
case GDTEventQoSTelemetry:
// falls through.
case GDTEventQoSDaily:
return @(GDTCCTQoSDaily);
break;
default:
return @(GDTCCTQoSDefault);
break;
}
}
/** Returns a set of logs that are ok to upload whilst on mobile data.
*
* @note This should be called from a thread safe method.
* @return A set of logs that are ok to upload whilst on mobile data.
*/
- (NSSet<GDTStoredEvent *> *)logEventsOkToSendOnMobileData {
return
[self.events objectsPassingTest:^BOOL(GDTStoredEvent *_Nonnull event, BOOL *_Nonnull stop) {
return [GDTCCTQosTierFromGDTEventQosTier(event.qosTier) isEqual:@(GDTCCTQoSDefault)];
}];
}
/** Returns a set of logs that are ok to upload whilst on wifi.
*
* @note This should be called from a thread safe method.
* @return A set of logs that are ok to upload whilst on wifi.
*/
- (NSSet<GDTStoredEvent *> *)logEventsOkToSendOnWifi {
return
[self.events objectsPassingTest:^BOOL(GDTStoredEvent *_Nonnull event, BOOL *_Nonnull stop) {
NSNumber *qosTier = GDTCCTQosTierFromGDTEventQosTier(event.qosTier);
return [qosTier isEqual:@(GDTCCTQoSDefault)] || [qosTier isEqual:@(GDTCCTQoSWifiOnly)] ||
[qosTier isEqual:@(GDTCCTQoSDaily)];
}];
}
/** Returns a set of logs that only should have a single upload attempt per day.
*
* @note This should be called from a thread safe method.
* @return A set of logs that are ok to upload only once per day.
*/
- (NSSet<GDTStoredEvent *> *)logEventsOkToSendDaily {
return
[self.events objectsPassingTest:^BOOL(GDTStoredEvent *_Nonnull event, BOOL *_Nonnull stop) {
return [GDTCCTQosTierFromGDTEventQosTier(event.qosTier) isEqual:@(GDTCCTQoSDaily)];
}];
}
#pragma mark - GDTUploadPackageProtocol
- (void)packageDelivered:(GDTUploadPackage *)package successful:(BOOL)successful {
dispatch_async(_queue, ^{
NSSet<GDTStoredEvent *> *events = [package.events copy];
for (GDTStoredEvent *event in events) {
[self.events removeObject:event];
}
});
}
- (void)packageExpired:(GDTUploadPackage *)package {
[self packageDelivered:package successful:YES];
}
@end
@@ -0,0 +1,206 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "GDTCCTLibrary/Private/GDTCCTUploader.h"
#import <GoogleDataTransport/GDTConsoleLogger.h>
#import <GoogleDataTransport/GDTPlatform.h>
#import <GoogleDataTransport/GDTRegistrar.h>
#import <nanopb/pb.h>
#import <nanopb/pb_decode.h>
#import <nanopb/pb_encode.h>
#import "GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h"
#import "GDTCCTLibrary/Private/GDTCCTPrioritizer.h"
#import "GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h"
@interface GDTCCTUploader ()
// Redeclared as readwrite.
@property(nullable, nonatomic, readwrite) NSURLSessionUploadTask *currentTask;
/** If running in the background, the current background ID. */
@property(nonatomic) GDTBackgroundIdentifier backgroundID;
@end
@implementation GDTCCTUploader
+ (void)load {
GDTCCTUploader *uploader = [GDTCCTUploader sharedInstance];
[[GDTRegistrar sharedInstance] registerUploader:uploader target:kGDTTargetCCT];
}
+ (instancetype)sharedInstance {
static GDTCCTUploader *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[GDTCCTUploader alloc] init];
});
return sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
_uploaderQueue = dispatch_queue_create("com.google.GDTCCTUploader", DISPATCH_QUEUE_SERIAL);
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_uploaderSession = [NSURLSession sessionWithConfiguration:config];
_backgroundID = GDTBackgroundIdentifierInvalid;
}
return self;
}
- (NSURL *)defaultServerURL {
static NSURL *defaultServerURL;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// These strings should be interleaved to construct the real URL. This is just to (hopefully)
// fool github URL scanning bots.
const char *p1 = "hts/frbslgiggolai.o/0clgbth";
const char *p2 = "tp:/ieaeogn.ogepscmvc/o/ac";
const char defaultURL[54] = {
p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], p1[4], p2[4], p1[5],
p2[5], p1[6], p2[6], p1[7], p2[7], p1[8], p2[8], p1[9], p2[9], p1[10], p2[10],
p1[11], p2[11], p1[12], p2[12], p1[13], p2[13], p1[14], p2[14], p1[15], p2[15], p1[16],
p2[16], p1[17], p2[17], p1[18], p2[18], p1[19], p2[19], p1[20], p2[20], p1[21], p2[21],
p1[22], p2[22], p1[23], p2[23], p1[24], p2[24], p1[25], p2[25], p1[26], '\0'};
defaultServerURL = [NSURL URLWithString:[NSString stringWithUTF8String:defaultURL]];
});
return defaultServerURL;
}
- (void)uploadPackage:(GDTUploadPackage *)package {
dispatch_async(_uploaderQueue, ^{
if (self->_currentTask || self->_currentUploadPackage) {
GDTLogWarning(GDTMCWUploadFailed, @"%@",
@"An upload shouldn't be initiated with another in progress.");
return;
}
NSURL *serverURL = self.serverURL ? self.serverURL : [self defaultServerURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:serverURL];
request.HTTPMethod = @"POST";
id completionHandler =
^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {
if (error) {
GDTLogWarning(GDTMCWUploadFailed, @"There was an error uploading events: %@", error);
}
NSError *decodingError;
gdt_cct_LogResponse logResponse = GDTCCTDecodeLogResponse(data, &decodingError);
if (!decodingError && logResponse.has_next_request_wait_millis) {
self->_nextUploadTime =
[GDTClock clockSnapshotInTheFuture:logResponse.next_request_wait_millis];
} else {
// 15 minutes from now.
self->_nextUploadTime = [GDTClock clockSnapshotInTheFuture:15 * 60 * 1000];
}
pb_release(gdt_cct_LogResponse_fields, &logResponse);
[package completeDelivery];
if (self->_backgroundID != GDTBackgroundIdentifierInvalid) {
[[GDTApplication sharedApplication] endBackgroundTask:self->_backgroundID];
self->_backgroundID = GDTBackgroundIdentifierInvalid;
}
self.currentTask = nil;
self.currentUploadPackage = nil;
};
self->_currentUploadPackage = package;
NSData *requestProtoData = [self constructRequestProtoFromPackage:(GDTUploadPackage *)package];
self.currentTask = [self.uploaderSession uploadTaskWithRequest:request
fromData:requestProtoData
completionHandler:completionHandler];
[self.currentTask resume];
});
}
- (BOOL)readyToUploadWithConditions:(GDTUploadConditions)conditions {
__block BOOL result = NO;
dispatch_sync(_uploaderQueue, ^{
if (self->_currentUploadPackage) {
result = NO;
return;
}
if (self->_currentTask) {
result = NO;
return;
}
if ((conditions & GDTUploadConditionHighPriority) == GDTUploadConditionHighPriority) {
result = YES;
return;
} else if (self->_nextUploadTime) {
result = [[GDTClock snapshot] isAfter:self->_nextUploadTime];
return;
}
result = YES;
});
return result;
}
#pragma mark - Private helper methods
/** Constructs data given an upload package.
*
* @param package The upload package used to construct the request proto bytes.
* @return Proto bytes representing a gdt_cct_LogRequest object.
*/
- (nonnull NSData *)constructRequestProtoFromPackage:(GDTUploadPackage *)package {
// Segment the log events by log type.
NSMutableDictionary<NSString *, NSMutableSet<GDTStoredEvent *> *> *logMappingIDToLogSet =
[[NSMutableDictionary alloc] init];
[package.events
enumerateObjectsUsingBlock:^(GDTStoredEvent *_Nonnull event, BOOL *_Nonnull stop) {
NSMutableSet *logSet = logMappingIDToLogSet[event.mappingID];
logSet = logSet ? logSet : [[NSMutableSet alloc] init];
[logSet addObject:event];
logMappingIDToLogSet[event.mappingID] = logSet;
}];
gdt_cct_BatchedLogRequest batchedLogRequest =
GDTCCTConstructBatchedLogRequest(logMappingIDToLogSet);
NSData *data = GDTCCTEncodeBatchedLogRequest(&batchedLogRequest);
pb_release(gdt_cct_BatchedLogRequest_fields, &batchedLogRequest);
return data ? data : [[NSData alloc] init];
}
#pragma mark - GDTUploadPackageProtocol
- (void)packageExpired:(GDTUploadPackage *)package {
dispatch_async(_uploaderQueue, ^{
[self.currentTask cancel];
self.currentTask = nil;
self.currentUploadPackage = nil;
});
}
#pragma mark - GDTLifecycleProtocol
- (void)appWillBackground:(GDTApplication *)app {
_backgroundID = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:self->_backgroundID];
}];
}
- (void)appWillTerminate:(GDTApplication *)application {
dispatch_sync(_uploaderQueue, ^{
[self.currentTask cancel];
[self.currentUploadPackage completeDelivery];
});
}
@end
@@ -0,0 +1,112 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <GoogleDataTransport/GDTStoredEvent.h>
#import "GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h"
NS_ASSUME_NONNULL_BEGIN
#pragma mark - General purpose encoders
/** Converts an NSString* to a pb_bytes_array_t*.
*
* @note malloc is called in this method. Ensure that pb_release is called on this or the parent.
*
* @param string The string to convert.
* @return A newly allocated array of bytes representing the UTF8 encoding of the string.
*/
pb_bytes_array_t *GDTCCTEncodeString(NSString *string);
/** Converts an NSData to a pb_bytes_array_t*.
*
* @note malloc is called in this method. Ensure that pb_release is called on this or the parent.
*
* @param data The data to convert.
* @return A newly allocated array of bytes with [data bytes] copied into it.
*/
pb_bytes_array_t *GDTCCTEncodeData(NSData *data);
#pragma mark - CCT object constructors
/** Encodes a batched log request.
*
* @note Ensure that pb_release is called on the batchedLogRequest param.
*
* @param batchedLogRequest A pointer to the log batch to encode to bytes.
* @return An NSData object representing the bytes of the log request batch.
*/
FOUNDATION_EXPORT
NSData *GDTCCTEncodeBatchedLogRequest(gdt_cct_BatchedLogRequest *batchedLogRequest);
/** Constructs a gdt_cct_BatchedLogRequest given sets of events segemented by mapping ID.
*
* @note malloc is called in this method. Ensure that pb_release is called on this or the parent.
*
* @param logMappingIDToLogSet A map of mapping IDs to sets of events to convert into a batch.
* @return A newly created gdt_cct_BatchedLogRequest.
*/
FOUNDATION_EXPORT
gdt_cct_BatchedLogRequest GDTCCTConstructBatchedLogRequest(
NSDictionary<NSString *, NSSet<GDTStoredEvent *> *> *logMappingIDToLogSet);
/** Constructs a log request given a log source and a set of events.
*
* @note malloc is called in this method. Ensure that pb_release is called on this or the parent.
* @param logSource The CCT log source to put into the log request.
* @param logSet The set of events to send in this log request.
*/
FOUNDATION_EXPORT
gdt_cct_LogRequest GDTCCTConstructLogRequest(int32_t logSource, NSSet<GDTStoredEvent *> *logSet);
/** Constructs a gdt_cct_LogEvent given a GDTStoredEvent*.
*
* @param event The GDTStoredEvent to convert.
* @return The new gdt_cct_LogEvent object.
*/
FOUNDATION_EXPORT
gdt_cct_LogEvent GDTCCTConstructLogEvent(GDTStoredEvent *event);
/** Constructs a gdt_cct_ClientInfo representing the client device.
*
* @return The new gdt_cct_ClientInfo object.
*/
FOUNDATION_EXPORT
gdt_cct_ClientInfo GDTCCTConstructClientInfo(void);
/** Constructs a gdt_cct_IosClientInfo representing the client device.
*
* @return The new gdt_cct_IosClientInfo object.
*/
FOUNDATION_EXPORT
gdt_cct_IosClientInfo GDTCCTConstructiOSClientInfo(void);
#pragma mark - CCT object decoders
/** Decodes a gdt_cct_LogResponse given proto bytes.
*
* @note malloc is called in this method. Ensure that pb_release is called on the return value.
*
* @param data The proto bytes of the gdt_cct_LogResponse.
* @param error An error that will be populated if something went wrong during decoding.
* @return A newly allocated gdt_cct_LogResponse from the data, if the bytes decoded properly.
*/
FOUNDATION_EXPORT
gdt_cct_LogResponse GDTCCTDecodeLogResponse(NSData *data, NSError **error);
NS_ASSUME_NONNULL_END
@@ -0,0 +1,44 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <GoogleDataTransport/GDTClock.h>
#import <GoogleDataTransport/GDTPrioritizer.h>
NS_ASSUME_NONNULL_BEGIN
/** Manages the prioritization of events from GoogleDataTransport. */
@interface GDTCCTPrioritizer : NSObject <GDTPrioritizer>
/** The queue on which this prioritizer operates. */
@property(nonatomic) dispatch_queue_t queue;
/** All log events that have been processed by this prioritizer. */
@property(nonatomic) NSMutableSet<GDTStoredEvent *> *events;
/** The most recent attempted upload of daily uploaded logs. */
@property(nonatomic) GDTClock *timeOfLastDailyUpload;
/** Creates and/or returns the singleton instance of this class.
*
* @return The singleton instance of this class.
*/
+ (instancetype)sharedInstance;
NS_ASSUME_NONNULL_END
@end
@@ -0,0 +1,52 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <GoogleDataTransport/GDTUploader.h>
NS_ASSUME_NONNULL_BEGIN
/** Class capable of uploading events to the CCT backend. */
@interface GDTCCTUploader : NSObject <GDTUploader>
/** The queue on which all CCT uploading will occur. */
@property(nonatomic, readonly) dispatch_queue_t uploaderQueue;
/** The server URL to upload to. Look at .m for the default value. */
@property(nonatomic) NSURL *serverURL;
/** The URL session that will attempt upload. */
@property(nonatomic, readonly) NSURLSession *uploaderSession;
/** The current upload task. */
@property(nullable, nonatomic, readonly) NSURLSessionUploadTask *currentTask;
/** Current upload package. */
@property(nullable, nonatomic) GDTUploadPackage *currentUploadPackage;
/** The next upload time. */
@property(nullable, nonatomic) GDTClock *nextUploadTime;
/** Creates and/or returns the singleton instance of this class.
*
* @return The singleton instance of this class.
*/
+ (instancetype)sharedInstance;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,128 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.3.9.2 */
#include "cct.nanopb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
const gdt_cct_NetworkConnectionInfo_NetworkType gdt_cct_NetworkConnectionInfo_network_type_default = gdt_cct_NetworkConnectionInfo_NetworkType_NONE;
const gdt_cct_NetworkConnectionInfo_MobileSubtype gdt_cct_NetworkConnectionInfo_mobile_subtype_default = gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE;
const gdt_cct_QosTierConfiguration_QosTier gdt_cct_LogRequest_qos_tier_default = gdt_cct_QosTierConfiguration_QosTier_DEFAULT;
const int32_t gdt_cct_QosTierConfiguration_log_source_default = 0;
const pb_field_t gdt_cct_LogEvent_fields[7] = {
PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, gdt_cct_LogEvent, event_time_ms, event_time_ms, 0),
PB_FIELD( 6, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_LogEvent, source_extension, event_time_ms, 0),
PB_FIELD( 11, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, event_code, source_extension, 0),
PB_FIELD( 15, SINT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, timezone_offset_seconds, event_code, 0),
PB_FIELD( 17, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, event_uptime_ms, timezone_offset_seconds, 0),
PB_FIELD( 23, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, network_connection_info, event_uptime_ms, &gdt_cct_NetworkConnectionInfo_fields),
PB_LAST_FIELD
};
const pb_field_t gdt_cct_NetworkConnectionInfo_fields[3] = {
PB_FIELD( 1, ENUM , OPTIONAL, STATIC , FIRST, gdt_cct_NetworkConnectionInfo, network_type, network_type, &gdt_cct_NetworkConnectionInfo_network_type_default),
PB_FIELD( 2, UENUM , OPTIONAL, STATIC , OTHER, gdt_cct_NetworkConnectionInfo, mobile_subtype, network_type, &gdt_cct_NetworkConnectionInfo_mobile_subtype_default),
PB_LAST_FIELD
};
const pb_field_t gdt_cct_IosClientInfo_fields[8] = {
PB_FIELD( 3, BYTES , OPTIONAL, POINTER , FIRST, gdt_cct_IosClientInfo, os_major_version, os_major_version, 0),
PB_FIELD( 4, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, os_full_version, os_major_version, 0),
PB_FIELD( 5, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, application_build, os_full_version, 0),
PB_FIELD( 6, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, country, application_build, 0),
PB_FIELD( 7, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, model, country, 0),
PB_FIELD( 8, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, language_code, model, 0),
PB_FIELD( 11, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, application_bundle_id, language_code, 0),
PB_LAST_FIELD
};
const pb_field_t gdt_cct_ClientInfo_fields[3] = {
PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, gdt_cct_ClientInfo, client_type, client_type, 0),
PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_ClientInfo, ios_client_info, client_type, &gdt_cct_IosClientInfo_fields),
PB_LAST_FIELD
};
const pb_field_t gdt_cct_BatchedLogRequest_fields[2] = {
PB_FIELD( 1, MESSAGE , REPEATED, POINTER , FIRST, gdt_cct_BatchedLogRequest, log_request, log_request, &gdt_cct_LogRequest_fields),
PB_LAST_FIELD
};
const pb_field_t gdt_cct_LogRequest_fields[7] = {
PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, gdt_cct_LogRequest, client_info, client_info, &gdt_cct_ClientInfo_fields),
PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, log_source, client_info, 0),
PB_FIELD( 3, MESSAGE , REPEATED, POINTER , OTHER, gdt_cct_LogRequest, log_event, log_source, &gdt_cct_LogEvent_fields),
PB_FIELD( 4, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, request_time_ms, log_event, 0),
PB_FIELD( 8, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, request_uptime_ms, request_time_ms, 0),
PB_FIELD( 9, UENUM , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, qos_tier, request_uptime_ms, &gdt_cct_LogRequest_qos_tier_default),
PB_LAST_FIELD
};
const pb_field_t gdt_cct_QosTierConfiguration_fields[3] = {
PB_FIELD( 2, UENUM , OPTIONAL, STATIC , FIRST, gdt_cct_QosTierConfiguration, qos_tier, qos_tier, 0),
PB_FIELD( 3, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_QosTierConfiguration, log_source, qos_tier, &gdt_cct_QosTierConfiguration_log_source_default),
PB_LAST_FIELD
};
const pb_field_t gdt_cct_QosTiersOverride_fields[3] = {
PB_FIELD( 1, MESSAGE , REPEATED, POINTER , FIRST, gdt_cct_QosTiersOverride, qos_tier_configuration, qos_tier_configuration, &gdt_cct_QosTierConfiguration_fields),
PB_FIELD( 2, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_QosTiersOverride, qos_tier_fingerprint, qos_tier_configuration, 0),
PB_LAST_FIELD
};
const pb_field_t gdt_cct_LogResponse_fields[3] = {
PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, gdt_cct_LogResponse, next_request_wait_millis, next_request_wait_millis, 0),
PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_LogResponse, qos_tier, next_request_wait_millis, &gdt_cct_QosTiersOverride_fields),
PB_LAST_FIELD
};
/* Check that field information fits in pb_field_t */
#if !defined(PB_FIELD_32BIT)
/* If you get an error here, it means that you need to define PB_FIELD_32BIT
* compile-time option. You can do that in pb.h or on compiler command line.
*
* The reason you need to do this is that some of your messages contain tag
* numbers or field sizes that are larger than what can fit in 8 or 16 bit
* field descriptors.
*/
PB_STATIC_ASSERT((pb_membersize(gdt_cct_LogEvent, network_connection_info) < 65536 && pb_membersize(gdt_cct_ClientInfo, ios_client_info) < 65536 && pb_membersize(gdt_cct_LogRequest, client_info) < 65536 && pb_membersize(gdt_cct_LogResponse, qos_tier) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_gdt_cct_LogEvent_gdt_cct_NetworkConnectionInfo_gdt_cct_IosClientInfo_gdt_cct_ClientInfo_gdt_cct_BatchedLogRequest_gdt_cct_LogRequest_gdt_cct_QosTierConfiguration_gdt_cct_QosTiersOverride_gdt_cct_LogResponse)
#endif
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
/* If you get an error here, it means that you need to define PB_FIELD_16BIT
* compile-time option. You can do that in pb.h or on compiler command line.
*
* The reason you need to do this is that some of your messages contain tag
* numbers or field sizes that are larger than what can fit in the default
* 8 bit descriptors.
*/
PB_STATIC_ASSERT((pb_membersize(gdt_cct_LogEvent, network_connection_info) < 256 && pb_membersize(gdt_cct_ClientInfo, ios_client_info) < 256 && pb_membersize(gdt_cct_LogRequest, client_info) < 256 && pb_membersize(gdt_cct_LogResponse, qos_tier) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_gdt_cct_LogEvent_gdt_cct_NetworkConnectionInfo_gdt_cct_IosClientInfo_gdt_cct_ClientInfo_gdt_cct_BatchedLogRequest_gdt_cct_LogRequest_gdt_cct_QosTierConfiguration_gdt_cct_QosTiersOverride_gdt_cct_LogResponse)
#endif
/* @@protoc_insertion_point(eof) */
@@ -0,0 +1,281 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Automatically generated nanopb header */
/* Generated by nanopb-0.3.9.2 */
#ifndef PB_GDT_CCT_CCT_NANOPB_H_INCLUDED
#define PB_GDT_CCT_CCT_NANOPB_H_INCLUDED
#include <nanopb/pb.h>
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
/* Enum definitions */
typedef enum _gdt_cct_NetworkConnectionInfo_NetworkType {
gdt_cct_NetworkConnectionInfo_NetworkType_NONE = -1,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE = 0,
gdt_cct_NetworkConnectionInfo_NetworkType_WIFI = 1,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_MMS = 2,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_SUPL = 3,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_DUN = 4,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_HIPRI = 5,
gdt_cct_NetworkConnectionInfo_NetworkType_WIMAX = 6,
gdt_cct_NetworkConnectionInfo_NetworkType_BLUETOOTH = 7,
gdt_cct_NetworkConnectionInfo_NetworkType_DUMMY = 8,
gdt_cct_NetworkConnectionInfo_NetworkType_ETHERNET = 9,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_FOTA = 10,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_IMS = 11,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_CBS = 12,
gdt_cct_NetworkConnectionInfo_NetworkType_WIFI_P2P = 13,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_IA = 14,
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_EMERGENCY = 15,
gdt_cct_NetworkConnectionInfo_NetworkType_PROXY = 16,
gdt_cct_NetworkConnectionInfo_NetworkType_VPN = 17
} gdt_cct_NetworkConnectionInfo_NetworkType;
#define _gdt_cct_NetworkConnectionInfo_NetworkType_MIN gdt_cct_NetworkConnectionInfo_NetworkType_NONE
#define _gdt_cct_NetworkConnectionInfo_NetworkType_MAX gdt_cct_NetworkConnectionInfo_NetworkType_VPN
#define _gdt_cct_NetworkConnectionInfo_NetworkType_ARRAYSIZE ((gdt_cct_NetworkConnectionInfo_NetworkType)(gdt_cct_NetworkConnectionInfo_NetworkType_VPN+1))
typedef enum _gdt_cct_NetworkConnectionInfo_MobileSubtype {
gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE = 0,
gdt_cct_NetworkConnectionInfo_MobileSubtype_GPRS = 1,
gdt_cct_NetworkConnectionInfo_MobileSubtype_EDGE = 2,
gdt_cct_NetworkConnectionInfo_MobileSubtype_UMTS = 3,
gdt_cct_NetworkConnectionInfo_MobileSubtype_CDMA = 4,
gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_0 = 5,
gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_A = 6,
gdt_cct_NetworkConnectionInfo_MobileSubtype_RTT = 7,
gdt_cct_NetworkConnectionInfo_MobileSubtype_HSDPA = 8,
gdt_cct_NetworkConnectionInfo_MobileSubtype_HSUPA = 9,
gdt_cct_NetworkConnectionInfo_MobileSubtype_HSPA = 10,
gdt_cct_NetworkConnectionInfo_MobileSubtype_IDEN = 11,
gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_B = 12,
gdt_cct_NetworkConnectionInfo_MobileSubtype_LTE = 13,
gdt_cct_NetworkConnectionInfo_MobileSubtype_EHRPD = 14,
gdt_cct_NetworkConnectionInfo_MobileSubtype_HSPAP = 15,
gdt_cct_NetworkConnectionInfo_MobileSubtype_GSM = 16,
gdt_cct_NetworkConnectionInfo_MobileSubtype_TD_SCDMA = 17,
gdt_cct_NetworkConnectionInfo_MobileSubtype_IWLAN = 18,
gdt_cct_NetworkConnectionInfo_MobileSubtype_LTE_CA = 19,
gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED = 100
} gdt_cct_NetworkConnectionInfo_MobileSubtype;
#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_MIN gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE
#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_MAX gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED
#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_ARRAYSIZE ((gdt_cct_NetworkConnectionInfo_MobileSubtype)(gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED+1))
typedef enum _gdt_cct_ClientInfo_ClientType {
gdt_cct_ClientInfo_ClientType_CLIENT_UNKNOWN = 0,
gdt_cct_ClientInfo_ClientType_IOS_FIREBASE = 15
} gdt_cct_ClientInfo_ClientType;
#define _gdt_cct_ClientInfo_ClientType_MIN gdt_cct_ClientInfo_ClientType_CLIENT_UNKNOWN
#define _gdt_cct_ClientInfo_ClientType_MAX gdt_cct_ClientInfo_ClientType_IOS_FIREBASE
#define _gdt_cct_ClientInfo_ClientType_ARRAYSIZE ((gdt_cct_ClientInfo_ClientType)(gdt_cct_ClientInfo_ClientType_IOS_FIREBASE+1))
typedef enum _gdt_cct_QosTierConfiguration_QosTier {
gdt_cct_QosTierConfiguration_QosTier_DEFAULT = 0,
gdt_cct_QosTierConfiguration_QosTier_UNMETERED_ONLY = 1,
gdt_cct_QosTierConfiguration_QosTier_UNMETERED_OR_DAILY = 2,
gdt_cct_QosTierConfiguration_QosTier_FAST_IF_RADIO_AWAKE = 3,
gdt_cct_QosTierConfiguration_QosTier_NEVER = 4
} gdt_cct_QosTierConfiguration_QosTier;
#define _gdt_cct_QosTierConfiguration_QosTier_MIN gdt_cct_QosTierConfiguration_QosTier_DEFAULT
#define _gdt_cct_QosTierConfiguration_QosTier_MAX gdt_cct_QosTierConfiguration_QosTier_NEVER
#define _gdt_cct_QosTierConfiguration_QosTier_ARRAYSIZE ((gdt_cct_QosTierConfiguration_QosTier)(gdt_cct_QosTierConfiguration_QosTier_NEVER+1))
/* Struct definitions */
typedef struct _gdt_cct_BatchedLogRequest {
pb_size_t log_request_count;
struct _gdt_cct_LogRequest *log_request;
/* @@protoc_insertion_point(struct:gdt_cct_BatchedLogRequest) */
} gdt_cct_BatchedLogRequest;
typedef struct _gdt_cct_IosClientInfo {
pb_bytes_array_t *os_major_version;
pb_bytes_array_t *os_full_version;
pb_bytes_array_t *application_build;
pb_bytes_array_t *country;
pb_bytes_array_t *model;
pb_bytes_array_t *language_code;
pb_bytes_array_t *application_bundle_id;
/* @@protoc_insertion_point(struct:gdt_cct_IosClientInfo) */
} gdt_cct_IosClientInfo;
typedef struct _gdt_cct_ClientInfo {
bool has_client_type;
gdt_cct_ClientInfo_ClientType client_type;
bool has_ios_client_info;
gdt_cct_IosClientInfo ios_client_info;
/* @@protoc_insertion_point(struct:gdt_cct_ClientInfo) */
} gdt_cct_ClientInfo;
typedef struct _gdt_cct_NetworkConnectionInfo {
bool has_network_type;
gdt_cct_NetworkConnectionInfo_NetworkType network_type;
bool has_mobile_subtype;
gdt_cct_NetworkConnectionInfo_MobileSubtype mobile_subtype;
/* @@protoc_insertion_point(struct:gdt_cct_NetworkConnectionInfo) */
} gdt_cct_NetworkConnectionInfo;
typedef struct _gdt_cct_QosTierConfiguration {
bool has_qos_tier;
gdt_cct_QosTierConfiguration_QosTier qos_tier;
bool has_log_source;
int32_t log_source;
/* @@protoc_insertion_point(struct:gdt_cct_QosTierConfiguration) */
} gdt_cct_QosTierConfiguration;
typedef struct _gdt_cct_QosTiersOverride {
pb_size_t qos_tier_configuration_count;
struct _gdt_cct_QosTierConfiguration *qos_tier_configuration;
bool has_qos_tier_fingerprint;
int64_t qos_tier_fingerprint;
/* @@protoc_insertion_point(struct:gdt_cct_QosTiersOverride) */
} gdt_cct_QosTiersOverride;
typedef struct _gdt_cct_LogEvent {
bool has_event_time_ms;
int64_t event_time_ms;
pb_bytes_array_t *source_extension;
bool has_event_code;
int32_t event_code;
bool has_timezone_offset_seconds;
int64_t timezone_offset_seconds;
bool has_event_uptime_ms;
int64_t event_uptime_ms;
bool has_network_connection_info;
gdt_cct_NetworkConnectionInfo network_connection_info;
/* @@protoc_insertion_point(struct:gdt_cct_LogEvent) */
} gdt_cct_LogEvent;
typedef struct _gdt_cct_LogRequest {
bool has_client_info;
gdt_cct_ClientInfo client_info;
bool has_log_source;
int32_t log_source;
pb_size_t log_event_count;
struct _gdt_cct_LogEvent *log_event;
bool has_request_time_ms;
int64_t request_time_ms;
bool has_request_uptime_ms;
int64_t request_uptime_ms;
bool has_qos_tier;
gdt_cct_QosTierConfiguration_QosTier qos_tier;
/* @@protoc_insertion_point(struct:gdt_cct_LogRequest) */
} gdt_cct_LogRequest;
typedef struct _gdt_cct_LogResponse {
bool has_next_request_wait_millis;
int64_t next_request_wait_millis;
bool has_qos_tier;
gdt_cct_QosTiersOverride qos_tier;
/* @@protoc_insertion_point(struct:gdt_cct_LogResponse) */
} gdt_cct_LogResponse;
/* Default values for struct fields */
extern const gdt_cct_NetworkConnectionInfo_NetworkType gdt_cct_NetworkConnectionInfo_network_type_default;
extern const gdt_cct_NetworkConnectionInfo_MobileSubtype gdt_cct_NetworkConnectionInfo_mobile_subtype_default;
extern const gdt_cct_QosTierConfiguration_QosTier gdt_cct_LogRequest_qos_tier_default;
extern const int32_t gdt_cct_QosTierConfiguration_log_source_default;
/* Initializer values for message structs */
#define gdt_cct_LogEvent_init_default {false, 0, NULL, false, 0, false, 0, false, 0, false, gdt_cct_NetworkConnectionInfo_init_default}
#define gdt_cct_NetworkConnectionInfo_init_default {false, gdt_cct_NetworkConnectionInfo_NetworkType_NONE, false, gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE}
#define gdt_cct_IosClientInfo_init_default {NULL, NULL, NULL, NULL, NULL, NULL, NULL}
#define gdt_cct_ClientInfo_init_default {false, _gdt_cct_ClientInfo_ClientType_MIN, false, gdt_cct_IosClientInfo_init_default}
#define gdt_cct_BatchedLogRequest_init_default {0, NULL}
#define gdt_cct_LogRequest_init_default {false, gdt_cct_ClientInfo_init_default, false, 0, 0, NULL, false, 0, false, 0, false, gdt_cct_QosTierConfiguration_QosTier_DEFAULT}
#define gdt_cct_QosTierConfiguration_init_default {false, _gdt_cct_QosTierConfiguration_QosTier_MIN, false, 0}
#define gdt_cct_QosTiersOverride_init_default {0, NULL, false, 0}
#define gdt_cct_LogResponse_init_default {false, 0, false, gdt_cct_QosTiersOverride_init_default}
#define gdt_cct_LogEvent_init_zero {false, 0, NULL, false, 0, false, 0, false, 0, false, gdt_cct_NetworkConnectionInfo_init_zero}
#define gdt_cct_NetworkConnectionInfo_init_zero {false, _gdt_cct_NetworkConnectionInfo_NetworkType_MIN, false, _gdt_cct_NetworkConnectionInfo_MobileSubtype_MIN}
#define gdt_cct_IosClientInfo_init_zero {NULL, NULL, NULL, NULL, NULL, NULL, NULL}
#define gdt_cct_ClientInfo_init_zero {false, _gdt_cct_ClientInfo_ClientType_MIN, false, gdt_cct_IosClientInfo_init_zero}
#define gdt_cct_BatchedLogRequest_init_zero {0, NULL}
#define gdt_cct_LogRequest_init_zero {false, gdt_cct_ClientInfo_init_zero, false, 0, 0, NULL, false, 0, false, 0, false, _gdt_cct_QosTierConfiguration_QosTier_MIN}
#define gdt_cct_QosTierConfiguration_init_zero {false, _gdt_cct_QosTierConfiguration_QosTier_MIN, false, 0}
#define gdt_cct_QosTiersOverride_init_zero {0, NULL, false, 0}
#define gdt_cct_LogResponse_init_zero {false, 0, false, gdt_cct_QosTiersOverride_init_zero}
/* Field tags (for use in manual encoding/decoding) */
#define gdt_cct_BatchedLogRequest_log_request_tag 1
#define gdt_cct_IosClientInfo_os_major_version_tag 3
#define gdt_cct_IosClientInfo_os_full_version_tag 4
#define gdt_cct_IosClientInfo_application_build_tag 5
#define gdt_cct_IosClientInfo_country_tag 6
#define gdt_cct_IosClientInfo_model_tag 7
#define gdt_cct_IosClientInfo_language_code_tag 8
#define gdt_cct_IosClientInfo_application_bundle_id_tag 11
#define gdt_cct_ClientInfo_client_type_tag 1
#define gdt_cct_ClientInfo_ios_client_info_tag 4
#define gdt_cct_NetworkConnectionInfo_network_type_tag 1
#define gdt_cct_NetworkConnectionInfo_mobile_subtype_tag 2
#define gdt_cct_QosTierConfiguration_qos_tier_tag 2
#define gdt_cct_QosTierConfiguration_log_source_tag 3
#define gdt_cct_QosTiersOverride_qos_tier_configuration_tag 1
#define gdt_cct_QosTiersOverride_qos_tier_fingerprint_tag 2
#define gdt_cct_LogEvent_event_time_ms_tag 1
#define gdt_cct_LogEvent_event_code_tag 11
#define gdt_cct_LogEvent_event_uptime_ms_tag 17
#define gdt_cct_LogEvent_source_extension_tag 6
#define gdt_cct_LogEvent_timezone_offset_seconds_tag 15
#define gdt_cct_LogEvent_network_connection_info_tag 23
#define gdt_cct_LogRequest_request_time_ms_tag 4
#define gdt_cct_LogRequest_request_uptime_ms_tag 8
#define gdt_cct_LogRequest_client_info_tag 1
#define gdt_cct_LogRequest_log_source_tag 2
#define gdt_cct_LogRequest_log_event_tag 3
#define gdt_cct_LogRequest_qos_tier_tag 9
#define gdt_cct_LogResponse_next_request_wait_millis_tag 1
#define gdt_cct_LogResponse_qos_tier_tag 3
/* Struct field encoding specification for nanopb */
extern const pb_field_t gdt_cct_LogEvent_fields[7];
extern const pb_field_t gdt_cct_NetworkConnectionInfo_fields[3];
extern const pb_field_t gdt_cct_IosClientInfo_fields[8];
extern const pb_field_t gdt_cct_ClientInfo_fields[3];
extern const pb_field_t gdt_cct_BatchedLogRequest_fields[2];
extern const pb_field_t gdt_cct_LogRequest_fields[7];
extern const pb_field_t gdt_cct_QosTierConfiguration_fields[3];
extern const pb_field_t gdt_cct_QosTiersOverride_fields[3];
extern const pb_field_t gdt_cct_LogResponse_fields[3];
/* Maximum encoded size of messages (where known) */
/* gdt_cct_LogEvent_size depends on runtime parameters */
#define gdt_cct_NetworkConnectionInfo_size 13
/* gdt_cct_IosClientInfo_size depends on runtime parameters */
/* gdt_cct_ClientInfo_size depends on runtime parameters */
/* gdt_cct_BatchedLogRequest_size depends on runtime parameters */
/* gdt_cct_LogRequest_size depends on runtime parameters */
#define gdt_cct_QosTierConfiguration_size 13
/* gdt_cct_QosTiersOverride_size depends on runtime parameters */
/* gdt_cct_LogResponse_size depends on runtime parameters */
/* Message IDs (where set with "msgid" option) */
#ifdef PB_MSGID
#define CCT_MESSAGES \
#endif
/* @@protoc_insertion_point(eof) */
#endif
+202
View File
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+223
View File
@@ -0,0 +1,223 @@
# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk)
This repository contains a subset of the Firebase iOS SDK source. It currently
includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore,
FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging,
FirebaseInAppMessagingDisplay, FirebaseMessaging and FirebaseStorage.
The repository also includes GoogleUtilities source. The
[GoogleUtilities](GoogleUtilities/README.md) pod is
a set of utilities used by Firebase and other Google products.
Firebase is an app development platform with tools to help you build, grow and
monetize your app. More information about Firebase can be found at
[https://firebase.google.com](https://firebase.google.com).
## Installation
See the three subsections for details about three different installation methods.
1. [Standard pod install](README.md#standard-pod-install)
1. [Installing from the GitHub repo](README.md#installing-from-github)
1. [Experimental Carthage](README.md#carthage-ios-only)
### Standard pod install
Go to
[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup).
### Installing from GitHub
For releases starting with 5.0.0, the source for each release is also deployed
to CocoaPods master and available via standard
[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod).
These instructions can be used to access the Firebase repo at other branches,
tags, or commits.
#### Background
See
[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod)
for instructions and options about overriding pod source locations.
#### Accessing Firebase Source Snapshots
All of the official releases are tagged in this repo and available via CocoaPods. To access a local
source snapshot or unreleased branch, use Podfile directives like the following:
To access FirebaseFirestore via a branch:
```
pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master'
pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master'
```
To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do:
```
pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk'
pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk'
```
### Carthage (iOS only)
Instructions for the experimental Carthage distribution are at
[Carthage](Carthage.md).
### Rome
Instructions for installing binary frameworks via
[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md).
## Development
To develop Firebase software in this repository, ensure that you have at least
the following software:
* Xcode 10.1 (or later)
* CocoaPods 1.7.2 (or later)
For the pod that you want to develop:
`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open`
Firestore and Functions have self contained Xcode projects. See
[Firestore/README.md](Firestore/README.md) and
[Functions/README.md](Functions/README.md).
### Adding a New Firebase Pod
See [AddNewPod.md](AddNewPod.md).
### Code Formatting
To ensure that the code is formatted consistently, run the script
[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh)
before creating a PR.
Travis will verify that any code changes are done in a style compliant way. Install
`clang-format` and `swiftformat`.
These commands will get the right versions:
```
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/773cb75d360b58f32048f5964038d09825a507c8/Formula/clang-format.rb
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/3dfea1004e0736754bbf49673cca8aaed8a94089/Formula/swiftformat.rb
```
Note: if you already have a newer version of these installed you may need to
`brew switch` to this version.
### Running Unit Tests
Select a scheme and press Command-u to build a component and run its unit tests.
#### Viewing Code Coverage
First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`.
After running the `AllUnitTests_iOS` scheme in Xcode, execute
`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output`
at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results.
### Running Sample Apps
In order to run the sample apps and integration tests, you'll need valid
`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist
files without real values, but can be replaced with real plist files. To get your own
`GoogleService-Info.plist` files:
1. Go to the [Firebase Console](https://console.firebase.google.com/)
2. Create a new Firebase project, if you don't already have one
3. For each sample app you want to test, create a new Firebase app with the sample app's bundle
identifier (e.g. `com.google.Database-Example`)
4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file
(e.g. in [Example/Database/App/](Example/Database/App/));
Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require
special Apple capabilities, and you will have to change the sample app to use a unique bundle
identifier that you can control in your own Apple Developer account.
## Specific Component Instructions
See the sections below for any special instructions for those components.
### Firebase Auth
If you're doing specific Firebase Auth development, see
[the Auth Sample README](Example/Auth/README.md) for instructions about
building and running the FirebaseAuth pod along with various samples and tests.
### Firebase Database
To run the Database Integration tests, make your database authentication rules
[public](https://firebase.google.com/docs/database/security/quickstart).
### Firebase Storage
To run the Storage Integration tests, follow the instructions in
[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m).
#### Push Notifications
Push notifications can only be delivered to specially provisioned App IDs in the developer portal.
In order to actually test receiving push notifications, you will need to:
1. Change the bundle identifier of the sample app to something you own in your Apple Developer
account, and enable that App ID for push notifications.
2. You'll also need to
[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs)
at **Project Settings > Cloud Messaging > [Your Firebase App]**.
3. Ensure your iOS device is added to your Apple Developer portal as a test device.
#### iOS Simulator
The iOS Simulator cannot register for remote notifications, and will not receive push notifications.
In order to receive push notifications, you'll have to follow the steps above and run the app on a
physical device.
## Community Supported Efforts
We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are
very grateful! We'd like to empower as many developers as we can to be able to use Firebase and
participate in the Firebase community.
### macOS and tvOS
Thanks to contributions from the community, FirebaseAuth, FirebaseCore, FirebaseDatabase, FirebaseMessaging,
FirebaseFirestore, FirebaseFunctions and FirebaseStorage now compile, run unit tests, and work on
macOS and tvOS.
For tvOS, checkout the [Sample](Example/tvOSSample).
Keep in mind that macOS and tvOS are not officially supported by Firebase, and this repository is
actively developed primarily for iOS. While we can catch basic unit test issues with Travis, there
may be some changes where the SDK no longer works as expected on macOS or tvOS. If you encounter
this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues).
Note that the Firebase pod is not available for macOS and tvOS.
To install, add a subset of the following to the Podfile:
```
pod 'FirebaseAuth'
pod 'FirebaseCore'
pod 'FirebaseDatabase'
pod 'FirebaseFirestore'
pod 'FirebaseFunctions'
pod 'FirebaseMessaging'
pod 'FirebaseStorage'
```
## Roadmap
See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source
plans and directions.
## Contributing
See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase
iOS SDK.
## License
The contents of this repository is licensed under the
[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
Your use of Firebase is governed by the
[Terms of Service for Firebase Services](https://firebase.google.com/terms/).