+
+/// @file FIRInteropParameterNames.h
+///
+/// Predefined event parameter names used by Firebase. This file is a subset of the
+/// FirebaseAnalytics FIRParameterNames.h public header.
+///
+/// The origin of your traffic, such as an Ad network (for example, google) or partner (urban
+/// airship). Identify the advertiser, site, publication, etc. that is sending traffic to your
+/// property. Highly recommended (NSString).
+///
+/// NSDictionary *params = @{
+/// kFIRParameterSource : @"InMobi",
+/// // ...
+/// };
+///
+static NSString *const kFIRIParameterSource NS_SWIFT_NAME(AnalyticsParameterSource) = @"source";
+
+/// The advertising or marketing medium, for example: cpc, banner, email, push. Highly recommended
+/// (NSString).
+///
+/// NSDictionary *params = @{
+/// kFIRParameterMedium : @"email",
+/// // ...
+/// };
+///
+static NSString *const kFIRIParameterMedium NS_SWIFT_NAME(AnalyticsParameterMedium) = @"medium";
+
+/// The individual campaign name, slogan, promo code, etc. Some networks have pre-defined macro to
+/// capture campaign information, otherwise can be populated by developer. Highly Recommended
+/// (NSString).
+///
+/// NSDictionary *params = @{
+/// kFIRParameterCampaign : @"winter_promotion",
+/// // ...
+/// };
+///
+static NSString *const kFIRIParameterCampaign NS_SWIFT_NAME(AnalyticsParameterCampaign) =
+ @"campaign";
+
+/// Message identifier.
+static NSString *const kFIRIParameterMessageIdentifier = @"_nmid";
+
+/// Message name.
+static NSString *const kFIRIParameterMessageName = @"_nmn";
+
+/// Message send time.
+static NSString *const kFIRIParameterMessageTime = @"_nmt";
+
+/// Message device time.
+static NSString *const kFIRIParameterMessageDeviceTime = @"_ndt";
+
+/// Topic message.
+static NSString *const kFIRIParameterTopic = @"_nt";
+
+/// Stores the message_id of the last notification opened by the app.
+static NSString *const kFIRIUserPropertyLastNotification = @"_ln";
diff --git a/Pods/FirebaseAnalyticsInterop/LICENSE b/Pods/FirebaseAnalyticsInterop/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/Pods/FirebaseAnalyticsInterop/LICENSE
@@ -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.
diff --git a/Pods/FirebaseAnalyticsInterop/README.md b/Pods/FirebaseAnalyticsInterop/README.md
new file mode 100644
index 0000000..bf397f0
--- /dev/null
+++ b/Pods/FirebaseAnalyticsInterop/README.md
@@ -0,0 +1,223 @@
+# Firebase iOS Open Source Development [](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/).
diff --git a/Pods/FirebaseCore/Firebase/Core/FIRAnalyticsConfiguration.m b/Pods/FirebaseCore/Firebase/Core/FIRAnalyticsConfiguration.m
new file mode 100644
index 0000000..a57936b
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/FIRAnalyticsConfiguration.m
@@ -0,0 +1,62 @@
+// Copyright 2017 Google
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#import
+
+#import "Private/FIRAnalyticsConfiguration.h"
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-implementations"
+@implementation FIRAnalyticsConfiguration
+#pragma clang diagnostic pop
+
++ (FIRAnalyticsConfiguration *)sharedInstance {
+ static FIRAnalyticsConfiguration *sharedInstance = nil;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ sharedInstance = [[FIRAnalyticsConfiguration alloc] init];
+ });
+ return sharedInstance;
+}
+
+- (void)postNotificationName:(NSString *)name value:(id)value {
+ if (!name.length || !value) {
+ return;
+ }
+ [[NSNotificationCenter defaultCenter] postNotificationName:name
+ object:self
+ userInfo:@{name : value}];
+}
+
+- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled {
+ [self setAnalyticsCollectionEnabled:analyticsCollectionEnabled persistSetting:YES];
+}
+
+- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled
+ persistSetting:(BOOL)shouldPersist {
+ // Persist the measurementEnabledState. Use FIRAnalyticsEnabledState values instead of YES/NO.
+ FIRAnalyticsEnabledState analyticsEnabledState =
+ analyticsCollectionEnabled ? kFIRAnalyticsEnabledStateSetYes : kFIRAnalyticsEnabledStateSetNo;
+ if (shouldPersist) {
+ NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
+ [userDefaults setObject:@(analyticsEnabledState)
+ forKey:kFIRAPersistedConfigMeasurementEnabledStateKey];
+ [userDefaults synchronize];
+ }
+
+ [self postNotificationName:kFIRAnalyticsConfigurationSetEnabledNotification
+ value:@(analyticsCollectionEnabled)];
+}
+
+@end
diff --git a/Pods/FirebaseCore/Firebase/Core/FIRApp.m b/Pods/FirebaseCore/Firebase/Core/FIRApp.m
new file mode 100644
index 0000000..48b76f6
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/FIRApp.m
@@ -0,0 +1,836 @@
+// 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.
+
+#include
+
+#if __has_include()
+#import
+#endif
+
+#if __has_include()
+#import
+#endif
+
+#import "FIRApp.h"
+
+#import "Private/FIRAnalyticsConfiguration.h"
+#import "Private/FIRAppInternal.h"
+#import "Private/FIRBundleUtil.h"
+#import "Private/FIRComponentContainerInternal.h"
+#import "Private/FIRConfigurationInternal.h"
+#import "Private/FIRCoreDiagnosticsConnector.h"
+#import "Private/FIRLibrary.h"
+#import "Private/FIRLogger.h"
+#import "Private/FIROptionsInternal.h"
+
+// The kFIRService strings are only here while transitioning CoreDiagnostics from the Analytics
+// pod to a Core dependency. These symbols are not used and should be deleted after the transition.
+NSString *const kFIRServiceAdMob;
+NSString *const kFIRServiceAuth;
+NSString *const kFIRServiceAuthUI;
+NSString *const kFIRServiceCrash;
+NSString *const kFIRServiceDatabase;
+NSString *const kFIRServiceDynamicLinks;
+NSString *const kFIRServiceFirestore;
+NSString *const kFIRServiceFunctions;
+NSString *const kFIRServiceInstanceID;
+NSString *const kFIRServiceInvites;
+NSString *const kFIRServiceMessaging;
+NSString *const kFIRServiceMeasurement;
+NSString *const kFIRServicePerformance;
+NSString *const kFIRServiceRemoteConfig;
+NSString *const kFIRServiceStorage;
+NSString *const kGGLServiceAnalytics;
+NSString *const kGGLServiceSignIn;
+
+NSString *const kFIRDefaultAppName = @"__FIRAPP_DEFAULT";
+NSString *const kFIRAppReadyToConfigureSDKNotification = @"FIRAppReadyToConfigureSDKNotification";
+NSString *const kFIRAppDeleteNotification = @"FIRAppDeleteNotification";
+NSString *const kFIRAppIsDefaultAppKey = @"FIRAppIsDefaultAppKey";
+NSString *const kFIRAppNameKey = @"FIRAppNameKey";
+NSString *const kFIRGoogleAppIDKey = @"FIRGoogleAppIDKey";
+
+NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat =
+ @"/google/firebase/global_data_collection_enabled:%@";
+NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey =
+ @"FirebaseDataCollectionDefaultEnabled";
+
+NSString *const kFIRAppDiagnosticsNotification = @"FIRAppDiagnosticsNotification";
+
+NSString *const kFIRAppDiagnosticsConfigurationTypeKey = @"ConfigType";
+NSString *const kFIRAppDiagnosticsErrorKey = @"Error";
+NSString *const kFIRAppDiagnosticsFIRAppKey = @"FIRApp";
+NSString *const kFIRAppDiagnosticsSDKNameKey = @"SDKName";
+NSString *const kFIRAppDiagnosticsSDKVersionKey = @"SDKVersion";
+
+// Auth internal notification notification and key.
+NSString *const FIRAuthStateDidChangeInternalNotification =
+ @"FIRAuthStateDidChangeInternalNotification";
+NSString *const FIRAuthStateDidChangeInternalNotificationAppKey =
+ @"FIRAuthStateDidChangeInternalNotificationAppKey";
+NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey =
+ @"FIRAuthStateDidChangeInternalNotificationTokenKey";
+NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey =
+ @"FIRAuthStateDidChangeInternalNotificationUIDKey";
+
+/**
+ * The URL to download plist files.
+ */
+static NSString *const kPlistURL = @"https://console.firebase.google.com/";
+
+/**
+ * An array of all classes that registered as `FIRCoreConfigurable` in order to receive lifecycle
+ * events from Core.
+ */
+static NSMutableArray> *sRegisteredAsConfigurable;
+
+@interface FIRApp ()
+
+#ifdef DEBUG
+@property(nonatomic) BOOL alreadyOutputDataCollectionFlag;
+#endif // DEBUG
+
+@end
+
+@implementation FIRApp
+
+// This is necessary since our custom getter prevents `_options` from being created.
+@synthesize options = _options;
+
+static NSMutableDictionary *sAllApps;
+static FIRApp *sDefaultApp;
+static NSMutableDictionary *sLibraryVersions;
+
++ (void)configure {
+ FIROptions *options = [FIROptions defaultOptions];
+ if (!options) {
+ [NSException raise:kFirebaseCoreErrorDomain
+ format:@"`[FIRApp configure];` (`FirebaseApp.configure()` in Swift) could not find "
+ @"a valid GoogleService-Info.plist in your project. Please download one "
+ @"from %@.",
+ kPlistURL];
+ }
+ [FIRApp configureWithOptions:options];
+#if TARGET_OS_OSX || TARGET_OS_TV
+ FIRLogNotice(kFIRLoggerCore, @"I-COR000028",
+ @"tvOS and macOS SDK support is not part of the official Firebase product. "
+ @"Instead they are community supported. Details at "
+ @"https://github.com/firebase/firebase-ios-sdk/blob/master/README.md.");
+#endif
+}
+
++ (void)configureWithOptions:(FIROptions *)options {
+ if (!options) {
+ [NSException raise:kFirebaseCoreErrorDomain
+ format:@"Options is nil. Please pass a valid options."];
+ }
+ [FIRApp configureWithName:kFIRDefaultAppName options:options];
+}
+
++ (NSCharacterSet *)applicationNameAllowedCharacters {
+ static NSCharacterSet *applicationNameAllowedCharacters;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ NSMutableCharacterSet *allowedNameCharacters = [NSMutableCharacterSet alphanumericCharacterSet];
+ [allowedNameCharacters addCharactersInString:@"-_"];
+ applicationNameAllowedCharacters = [allowedNameCharacters copy];
+ });
+ return applicationNameAllowedCharacters;
+}
+
++ (void)configureWithName:(NSString *)name options:(FIROptions *)options {
+ if (!name || !options) {
+ [NSException raise:kFirebaseCoreErrorDomain format:@"Neither name nor options can be nil."];
+ }
+ if (name.length == 0) {
+ [NSException raise:kFirebaseCoreErrorDomain format:@"Name cannot be empty."];
+ }
+
+ if ([name isEqualToString:kFIRDefaultAppName]) {
+ if (sDefaultApp) {
+ [NSException raise:kFirebaseCoreErrorDomain
+ format:@"Default app has already been configured."];
+ }
+
+ FIRLogDebug(kFIRLoggerCore, @"I-COR000001", @"Configuring the default app.");
+ } else {
+ // Validate the app name and ensure it hasn't been configured already.
+ NSCharacterSet *nameCharacters = [NSCharacterSet characterSetWithCharactersInString:name];
+
+ if (![[self applicationNameAllowedCharacters] isSupersetOfSet:nameCharacters]) {
+ [NSException raise:kFirebaseCoreErrorDomain
+ format:@"App name can only contain alphanumeric, "
+ @"hyphen (-), and underscore (_) characters"];
+ }
+
+ @synchronized(self) {
+ if (sAllApps && sAllApps[name]) {
+ [NSException raise:kFirebaseCoreErrorDomain
+ format:@"App named %@ has already been configured.", name];
+ }
+ }
+
+ FIRLogDebug(kFIRLoggerCore, @"I-COR000002", @"Configuring app named %@", name);
+ }
+
+ @synchronized(self) {
+ FIRApp *app = [[FIRApp alloc] initInstanceWithName:name options:options];
+ if (app.isDefaultApp) {
+ sDefaultApp = app;
+ }
+
+ [FIRApp addAppToAppDictionary:app];
+ [FIRApp sendNotificationsToSDKs:app];
+ }
+}
+
++ (FIRApp *)defaultApp {
+ if (sDefaultApp) {
+ return sDefaultApp;
+ }
+ FIRLogError(kFIRLoggerCore, @"I-COR000003",
+ @"The default Firebase app has not yet been "
+ @"configured. Add `[FIRApp configure];` (`FirebaseApp.configure()` in Swift) to your "
+ @"application initialization. Read more: https://goo.gl/ctyzm8.");
+ return nil;
+}
+
++ (FIRApp *)appNamed:(NSString *)name {
+ @synchronized(self) {
+ if (sAllApps) {
+ FIRApp *app = sAllApps[name];
+ if (app) {
+ return app;
+ }
+ }
+ FIRLogError(kFIRLoggerCore, @"I-COR000004", @"App with name %@ does not exist.", name);
+ return nil;
+ }
+}
+
++ (NSDictionary *)allApps {
+ @synchronized(self) {
+ if (!sAllApps) {
+ FIRLogError(kFIRLoggerCore, @"I-COR000005", @"No app has been configured yet.");
+ }
+ return [sAllApps copy];
+ }
+}
+
+// Public only for tests
++ (void)resetApps {
+ @synchronized(self) {
+ sDefaultApp = nil;
+ [sAllApps removeAllObjects];
+ sAllApps = nil;
+ [sLibraryVersions removeAllObjects];
+ sLibraryVersions = nil;
+ }
+}
+
+- (void)deleteApp:(FIRAppVoidBoolCallback)completion {
+ @synchronized([self class]) {
+ if (sAllApps && sAllApps[self.name]) {
+ FIRLogDebug(kFIRLoggerCore, @"I-COR000006", @"Deleting app named %@", self.name);
+
+ // Remove all cached instances from the container before deleting the app.
+ [self.container removeAllCachedInstances];
+
+ [sAllApps removeObjectForKey:self.name];
+ [self clearDataCollectionSwitchFromUserDefaults];
+ if ([self.name isEqualToString:kFIRDefaultAppName]) {
+ sDefaultApp = nil;
+ }
+ NSDictionary *appInfoDict = @{kFIRAppNameKey : self.name};
+ [[NSNotificationCenter defaultCenter] postNotificationName:kFIRAppDeleteNotification
+ object:[self class]
+ userInfo:appInfoDict];
+ completion(YES);
+ } else {
+ FIRLogError(kFIRLoggerCore, @"I-COR000007", @"App does not exist.");
+ completion(NO);
+ }
+ }
+}
+
++ (void)addAppToAppDictionary:(FIRApp *)app {
+ if (!sAllApps) {
+ sAllApps = [NSMutableDictionary dictionary];
+ }
+ if ([app configureCore]) {
+ sAllApps[app.name] = app;
+ } else {
+ [NSException raise:kFirebaseCoreErrorDomain
+ format:@"Configuration fails. It may be caused by an invalid GOOGLE_APP_ID in "
+ @"GoogleService-Info.plist or set in the customized options."];
+ }
+}
+
+- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options {
+ self = [super init];
+ if (self) {
+ _name = [name copy];
+ _options = [options copy];
+ _options.editingLocked = YES;
+ _isDefaultApp = [name isEqualToString:kFIRDefaultAppName];
+ _container = [[FIRComponentContainer alloc] initWithApp:self];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+- (BOOL)configureCore {
+ [self checkExpectedBundleID];
+ if (![self isAppIDValid]) {
+ return NO;
+ }
+
+ [self logCoreTelemetryIfEnabled];
+
+#if TARGET_OS_IOS
+ // Initialize the Analytics once there is a valid options under default app. Analytics should
+ // always initialize first by itself before the other SDKs.
+ if ([self.name isEqualToString:kFIRDefaultAppName]) {
+ Class firAnalyticsClass = NSClassFromString(@"FIRAnalytics");
+ if (firAnalyticsClass) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wundeclared-selector"
+ SEL startWithConfigurationSelector = @selector(startWithConfiguration:options:);
+#pragma clang diagnostic pop
+ if ([firAnalyticsClass respondsToSelector:startWithConfigurationSelector]) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ [firAnalyticsClass performSelector:startWithConfigurationSelector
+ withObject:[FIRConfiguration sharedInstance].analyticsConfiguration
+ withObject:_options];
+#pragma clang diagnostic pop
+ }
+ }
+ }
+#endif
+
+ [self subscribeForAppDidBecomeActiveNotifications];
+
+ return YES;
+}
+
+- (FIROptions *)options {
+ return [_options copy];
+}
+
+- (void)setDataCollectionDefaultEnabled:(BOOL)dataCollectionDefaultEnabled {
+#ifdef DEBUG
+ FIRLogDebug(kFIRLoggerCore, @"I-COR000034", @"Explicitly %@ data collection flag.",
+ dataCollectionDefaultEnabled ? @"enabled" : @"disabled");
+ self.alreadyOutputDataCollectionFlag = YES;
+#endif // DEBUG
+
+ NSString *key =
+ [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, self.name];
+ [[NSUserDefaults standardUserDefaults] setBool:dataCollectionDefaultEnabled forKey:key];
+
+ // Core also controls the FirebaseAnalytics flag, so check if the Analytics flags are set
+ // within FIROptions and change the Analytics value if necessary. Analytics only works with the
+ // default app, so return if this isn't the default app.
+ if (!self.isDefaultApp) {
+ return;
+ }
+
+ // Check if the Analytics flag is explicitly set. If so, no further actions are necessary.
+ if ([self.options isAnalyticsCollectionExpicitlySet]) {
+ return;
+ }
+
+ // The Analytics flag has not been explicitly set, so update with the value being set.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ [[FIRAnalyticsConfiguration sharedInstance]
+ setAnalyticsCollectionEnabled:dataCollectionDefaultEnabled
+ persistSetting:NO];
+#pragma clang diagnostic pop
+}
+
+- (BOOL)isDataCollectionDefaultEnabled {
+ // Check if it's been manually set before in code, and use that as the higher priority value.
+ NSNumber *defaultsObject = [[self class] readDataCollectionSwitchFromUserDefaultsForApp:self];
+ if (defaultsObject != nil) {
+#ifdef DEBUG
+ if (!self.alreadyOutputDataCollectionFlag) {
+ FIRLogDebug(kFIRLoggerCore, @"I-COR000031", @"Data Collection flag is %@ in user defaults.",
+ [defaultsObject boolValue] ? @"enabled" : @"disabled");
+ self.alreadyOutputDataCollectionFlag = YES;
+ }
+#endif // DEBUG
+ return [defaultsObject boolValue];
+ }
+
+ // Read the Info.plist to see if the flag is set. If it's not set, it should default to `YES`.
+ // As per the implementation of `readDataCollectionSwitchFromPlist`, it's a cached value and has
+ // no performance impact calling multiple times.
+ NSNumber *collectionEnabledPlistValue = [[self class] readDataCollectionSwitchFromPlist];
+ if (collectionEnabledPlistValue != nil) {
+#ifdef DEBUG
+ if (!self.alreadyOutputDataCollectionFlag) {
+ FIRLogDebug(kFIRLoggerCore, @"I-COR000032", @"Data Collection flag is %@ in plist.",
+ [collectionEnabledPlistValue boolValue] ? @"enabled" : @"disabled");
+ self.alreadyOutputDataCollectionFlag = YES;
+ }
+#endif // DEBUG
+ return [collectionEnabledPlistValue boolValue];
+ }
+
+#ifdef DEBUG
+ if (!self.alreadyOutputDataCollectionFlag) {
+ FIRLogDebug(kFIRLoggerCore, @"I-COR000033", @"Data Collection flag is not set.");
+ self.alreadyOutputDataCollectionFlag = YES;
+ }
+#endif // DEBUG
+ return YES;
+}
+
+#pragma mark - private
+
++ (void)sendNotificationsToSDKs:(FIRApp *)app {
+ // TODO: Remove this notification once all SDKs are registered with `FIRCoreConfigurable`.
+ NSNumber *isDefaultApp = [NSNumber numberWithBool:app.isDefaultApp];
+ NSDictionary *appInfoDict = @{
+ kFIRAppNameKey : app.name,
+ kFIRAppIsDefaultAppKey : isDefaultApp,
+ kFIRGoogleAppIDKey : app.options.googleAppID
+ };
+ [[NSNotificationCenter defaultCenter] postNotificationName:kFIRAppReadyToConfigureSDKNotification
+ object:self
+ userInfo:appInfoDict];
+
+ // This is the new way of sending information to SDKs.
+ // TODO: Do we want this on a background thread, maybe?
+ @synchronized(self) {
+ for (Class library in sRegisteredAsConfigurable) {
+ [library configureWithApp:app];
+ }
+ }
+}
+
++ (NSError *)errorForMissingOptions {
+ NSDictionary *errorDict = @{
+ NSLocalizedDescriptionKey :
+ @"Unable to parse GoogleService-Info.plist in order to configure services.",
+ NSLocalizedRecoverySuggestionErrorKey :
+ @"Check formatting and location of GoogleService-Info.plist."
+ };
+ return [NSError errorWithDomain:kFirebaseCoreErrorDomain
+ code:FIRErrorCodeInvalidPlistFile
+ userInfo:errorDict];
+}
+
++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain
+ errorCode:(FIRErrorCode)code
+ service:(NSString *)service
+ reason:(NSString *)reason {
+ NSString *description =
+ [NSString stringWithFormat:@"Configuration failed for service %@.", service];
+ NSDictionary *errorDict =
+ @{NSLocalizedDescriptionKey : description, NSLocalizedFailureReasonErrorKey : reason};
+ return [NSError errorWithDomain:domain code:code userInfo:errorDict];
+}
+
++ (NSError *)errorForInvalidAppID {
+ NSDictionary *errorDict = @{
+ NSLocalizedDescriptionKey : @"Unable to validate Google App ID",
+ NSLocalizedRecoverySuggestionErrorKey :
+ @"Check formatting and location of GoogleService-Info.plist or GoogleAppID set in the "
+ @"customized options."
+ };
+ return [NSError errorWithDomain:kFirebaseCoreErrorDomain
+ code:FIRErrorCodeInvalidAppID
+ userInfo:errorDict];
+}
+
++ (BOOL)isDefaultAppConfigured {
+ return (sDefaultApp != nil);
+}
+
++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version {
+ // Create the set of characters which aren't allowed, only if this feature is used.
+ NSMutableCharacterSet *allowedSet = [NSMutableCharacterSet alphanumericCharacterSet];
+ [allowedSet addCharactersInString:@"-_."];
+ NSCharacterSet *disallowedSet = [allowedSet invertedSet];
+ // Make sure the library name and version strings do not contain unexpected characters, and
+ // add the name/version pair to the dictionary.
+ if ([name rangeOfCharacterFromSet:disallowedSet].location == NSNotFound &&
+ [version rangeOfCharacterFromSet:disallowedSet].location == NSNotFound) {
+ @synchronized(self) {
+ if (!sLibraryVersions) {
+ sLibraryVersions = [[NSMutableDictionary alloc] init];
+ }
+ sLibraryVersions[name] = version;
+ }
+ } else {
+ FIRLogError(kFIRLoggerCore, @"I-COR000027",
+ @"The library name (%@) or version number (%@) contain invalid characters. "
+ @"Only alphanumeric, dash, underscore and period characters are allowed.",
+ name, version);
+ }
+}
+
++ (void)registerInternalLibrary:(nonnull Class)library
+ withName:(nonnull NSString *)name
+ withVersion:(nonnull NSString *)version {
+ // This is called at +load time, keep the work to a minimum.
+
+ // Ensure the class given conforms to the proper protocol.
+ if (![(Class)library conformsToProtocol:@protocol(FIRLibrary)] ||
+ ![(Class)library respondsToSelector:@selector(componentsToRegister)]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Class %@ attempted to register components, but it does not conform to "
+ @"`FIRLibrary or provide a `componentsToRegister:` method.",
+ library];
+ }
+
+ [FIRComponentContainer registerAsComponentRegistrant:library];
+ if ([(Class)library respondsToSelector:@selector(configureWithApp:)]) {
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ sRegisteredAsConfigurable = [[NSMutableArray alloc] init];
+ });
+ @synchronized(self) {
+ [sRegisteredAsConfigurable addObject:library];
+ }
+ }
+ [self registerLibrary:name withVersion:version];
+}
+
++ (NSString *)firebaseUserAgent {
+ @synchronized(self) {
+ NSMutableArray *libraries =
+ [[NSMutableArray alloc] initWithCapacity:sLibraryVersions.count];
+ for (NSString *libraryName in sLibraryVersions) {
+ [libraries addObject:[NSString stringWithFormat:@"%@/%@", libraryName,
+ sLibraryVersions[libraryName]]];
+ }
+ [libraries sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
+ return [libraries componentsJoinedByString:@" "];
+ }
+}
+
+- (void)checkExpectedBundleID {
+ NSArray *bundles = [FIRBundleUtil relevantBundles];
+ NSString *expectedBundleID = [self expectedBundleID];
+ // The checking is only done when the bundle ID is provided in the serviceInfo dictionary for
+ // backward compatibility.
+ if (expectedBundleID != nil && ![FIRBundleUtil hasBundleIdentifierPrefix:expectedBundleID
+ inBundles:bundles]) {
+ FIRLogError(kFIRLoggerCore, @"I-COR000008",
+ @"The project's Bundle ID is inconsistent with "
+ @"either the Bundle ID in '%@.%@', or the Bundle ID in the options if you are "
+ @"using a customized options. To ensure that everything can be configured "
+ @"correctly, you may need to make the Bundle IDs consistent. To continue with this "
+ @"plist file, you may change your app's bundle identifier to '%@'. Or you can "
+ @"download a new configuration file that matches your bundle identifier from %@ "
+ @"and replace the current one.",
+ kServiceInfoFileName, kServiceInfoFileType, expectedBundleID, kPlistURL);
+ }
+}
+
+#pragma mark - private - App ID Validation
+
+/**
+ * Validates the format and fingerprint of the app ID contained in GOOGLE_APP_ID in the plist file.
+ * This is the main method for validating app ID.
+ *
+ * @return YES if the app ID fulfills the expected format and fingerprint, NO otherwise.
+ */
+- (BOOL)isAppIDValid {
+ NSString *appID = _options.googleAppID;
+ BOOL isValid = [FIRApp validateAppID:appID];
+ if (!isValid) {
+ NSString *expectedBundleID = [self expectedBundleID];
+ FIRLogError(kFIRLoggerCore, @"I-COR000009",
+ @"The GOOGLE_APP_ID either in the plist file "
+ @"'%@.%@' or the one set in the customized options is invalid. If you are using "
+ @"the plist file, use the iOS version of bundle identifier to download the file, "
+ @"and do not manually edit the GOOGLE_APP_ID. You may change your app's bundle "
+ @"identifier to '%@'. Or you can download a new configuration file that matches "
+ @"your bundle identifier from %@ and replace the current one.",
+ kServiceInfoFileName, kServiceInfoFileType, expectedBundleID, kPlistURL);
+ };
+ return isValid;
+}
+
++ (BOOL)validateAppID:(NSString *)appID {
+ // Failing validation only occurs when we are sure we are looking at a V2 app ID and it does not
+ // have a valid fingerprint, otherwise we just warn about the potential issue.
+ if (!appID.length) {
+ return NO;
+ }
+
+ NSScanner *stringScanner = [NSScanner scannerWithString:appID];
+ stringScanner.charactersToBeSkipped = nil;
+
+ NSString *appIDVersion;
+ if (![stringScanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet]
+ intoString:&appIDVersion]) {
+ return NO;
+ }
+
+ if (![stringScanner scanString:@":" intoString:NULL]) {
+ // appIDVersion must be separated by ":"
+ return NO;
+ }
+
+ NSArray *knownVersions = @[ @"1" ];
+ if (![knownVersions containsObject:appIDVersion]) {
+ // Permit unknown yet properly formatted app ID versions.
+ FIRLogInfo(kFIRLoggerCore, @"I-COR000010", @"Unknown GOOGLE_APP_ID version: %@", appIDVersion);
+ return YES;
+ }
+
+ if (![self validateAppIDFormat:appID withVersion:appIDVersion]) {
+ return NO;
+ }
+
+ if (![self validateAppIDFingerprint:appID withVersion:appIDVersion]) {
+ return NO;
+ }
+
+ return YES;
+}
+
++ (NSString *)actualBundleID {
+ return [[NSBundle mainBundle] bundleIdentifier];
+}
+
+/**
+ * Validates that the format of the app ID string is what is expected based on the supplied version.
+ * The version must end in ":".
+ *
+ * For v1 app ids the format is expected to be
+ * '::ios:'.
+ *
+ * This method does not verify that the contents of the app id are correct, just that they fulfill
+ * the expected format.
+ *
+ * @param appID Contents of GOOGLE_APP_ID from the plist file.
+ * @param version Indicates what version of the app id format this string should be.
+ * @return YES if provided string fufills the expected format, NO otherwise.
+ */
++ (BOOL)validateAppIDFormat:(NSString *)appID withVersion:(NSString *)version {
+ if (!appID.length || !version.length) {
+ return NO;
+ }
+
+ NSScanner *stringScanner = [NSScanner scannerWithString:appID];
+ stringScanner.charactersToBeSkipped = nil;
+
+ // Skip version part
+ // '**::ios:'
+ if (![stringScanner scanString:version intoString:NULL]) {
+ // The version part is missing or mismatched
+ return NO;
+ }
+
+ // Validate version part (see part between '*' symbols below)
+ // '*:*:ios:'
+ if (![stringScanner scanString:@":" intoString:NULL]) {
+ // appIDVersion must be separated by ":"
+ return NO;
+ }
+
+ // Validate version part (see part between '*' symbols below)
+ // ':**:ios:'.
+ NSInteger projectNumber = NSNotFound;
+ if (![stringScanner scanInteger:&projectNumber]) {
+ // NO project number found.
+ return NO;
+ }
+
+ // Validate version part (see part between '*' symbols below)
+ // ':*:*ios:'.
+ if (![stringScanner scanString:@":" intoString:NULL]) {
+ // The project number must be separated by ":"
+ return NO;
+ }
+
+ // Validate version part (see part between '*' symbols below)
+ // '::*ios*:'.
+ NSString *platform;
+ if (![stringScanner scanUpToString:@":" intoString:&platform]) {
+ return NO;
+ }
+
+ if (![platform isEqualToString:@"ios"]) {
+ // The platform must be @"ios"
+ return NO;
+ }
+
+ // Validate version part (see part between '*' symbols below)
+ // '::ios*:*'.
+ if (![stringScanner scanString:@":" intoString:NULL]) {
+ // The platform must be separated by ":"
+ return NO;
+ }
+
+ // Validate version part (see part between '*' symbols below)
+ // '::ios:**'.
+ unsigned long long fingerprint = NSNotFound;
+ if (![stringScanner scanHexLongLong:&fingerprint]) {
+ // Fingerprint part is missing
+ return NO;
+ }
+
+ if (!stringScanner.isAtEnd) {
+ // There are not allowed characters in the fingerprint part
+ return NO;
+ }
+
+ return YES;
+}
+
+/**
+ * Validates that the fingerprint of the app ID string is what is expected based on the supplied
+ * version.
+ *
+ * Note that the v1 hash algorithm is not permitted on the client and cannot be fully validated.
+ *
+ * @param appID Contents of GOOGLE_APP_ID from the plist file.
+ * @param version Indicates what version of the app id format this string should be.
+ * @return YES if provided string fufills the expected fingerprint and the version is known, NO
+ * otherwise.
+ */
++ (BOOL)validateAppIDFingerprint:(NSString *)appID withVersion:(NSString *)version {
+ // Extract the supplied fingerprint from the supplied app ID.
+ // This assumes the app ID format is the same for all known versions below. If the app ID format
+ // changes in future versions, the tokenizing of the app ID format will need to take into account
+ // the version of the app ID.
+ NSArray *components = [appID componentsSeparatedByString:@":"];
+ if (components.count != 4) {
+ return NO;
+ }
+
+ NSString *suppliedFingerprintString = components[3];
+ if (!suppliedFingerprintString.length) {
+ return NO;
+ }
+
+ uint64_t suppliedFingerprint;
+ NSScanner *scanner = [NSScanner scannerWithString:suppliedFingerprintString];
+ if (![scanner scanHexLongLong:&suppliedFingerprint]) {
+ return NO;
+ }
+
+ if ([version isEqual:@"1"]) {
+ // The v1 hash algorithm is not permitted on the client so the actual hash cannot be validated.
+ return YES;
+ }
+
+ // Unknown version.
+ return NO;
+}
+
+- (NSString *)expectedBundleID {
+ return _options.bundleID;
+}
+
+// end App ID validation
+
+#pragma mark - Reading From Plist & User Defaults
+
+/**
+ * Clears the data collection switch from the standard NSUserDefaults for easier testing and
+ * readability.
+ */
+- (void)clearDataCollectionSwitchFromUserDefaults {
+ NSString *key =
+ [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, self.name];
+ [[NSUserDefaults standardUserDefaults] removeObjectForKey:key];
+}
+
+/**
+ * Reads the data collection switch from the standard NSUserDefaults for easier testing and
+ * readability.
+ */
++ (nullable NSNumber *)readDataCollectionSwitchFromUserDefaultsForApp:(FIRApp *)app {
+ // Read the object in user defaults, and only return if it's an NSNumber.
+ NSString *key =
+ [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, app.name];
+ id collectionEnabledDefaultsObject = [[NSUserDefaults standardUserDefaults] objectForKey:key];
+ if ([collectionEnabledDefaultsObject isKindOfClass:[NSNumber class]]) {
+ return collectionEnabledDefaultsObject;
+ }
+
+ return nil;
+}
+
+/**
+ * Reads the data collection switch from the Info.plist for easier testing and readability. Will
+ * only read once from the plist and return the cached value.
+ */
++ (nullable NSNumber *)readDataCollectionSwitchFromPlist {
+ static NSNumber *collectionEnabledPlistObject;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ // Read the data from the `Info.plist`, only assign it if it's there and an NSNumber.
+ id plistValue = [[NSBundle mainBundle]
+ objectForInfoDictionaryKey:kFIRGlobalAppDataCollectionEnabledPlistKey];
+ if (plistValue && [plistValue isKindOfClass:[NSNumber class]]) {
+ collectionEnabledPlistObject = (NSNumber *)plistValue;
+ }
+ });
+
+ return collectionEnabledPlistObject;
+}
+
+#pragma mark - Sending Logs
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-parameter"
+- (void)sendLogsWithServiceName:(NSString *)serviceName
+ version:(NSString *)version
+ error:(NSError *)error {
+ // Do nothing. Please remove calls to this method.
+}
+#pragma clang diagnostic pop
+
+#pragma mark - App Life Cycle
+
+- (void)subscribeForAppDidBecomeActiveNotifications {
+#if TARGET_OS_IOS || TARGET_OS_TV
+ NSNotificationName notificationName = UIApplicationDidBecomeActiveNotification;
+#endif
+
+#if TARGET_OS_OSX
+ NSNotificationName notificationName = NSApplicationDidBecomeActiveNotification;
+#endif
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(appDidBecomeActive:)
+ name:notificationName
+ object:nil];
+}
+
+- (void)appDidBecomeActive:(NSNotification *)notification {
+ [self logCoreTelemetryIfEnabled];
+}
+
+- (void)logCoreTelemetryIfEnabled {
+ if ([self isDataCollectionDefaultEnabled]) {
+ [FIRCoreDiagnosticsConnector logCoreTelemetryWithOptions:_options];
+ }
+}
+
+@end
diff --git a/Pods/FirebaseCore/Firebase/Core/FIRAppAssociationRegistration.m b/Pods/FirebaseCore/Firebase/Core/FIRAppAssociationRegistration.m
new file mode 100644
index 0000000..2aecdab
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/FIRAppAssociationRegistration.m
@@ -0,0 +1,47 @@
+// Copyright 2017 Google
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#import "Private/FIRAppAssociationRegistration.h"
+
+#import
+
+@implementation FIRAppAssociationRegistration
+
++ (nullable id)registeredObjectWithHost:(id)host
+ key:(NSString *)key
+ creationBlock:(id _Nullable (^)(void))creationBlock {
+ @synchronized(self) {
+ SEL dictKey = @selector(registeredObjectWithHost:key:creationBlock:);
+ NSMutableDictionary *objectsByKey = objc_getAssociatedObject(host, dictKey);
+ if (!objectsByKey) {
+ objectsByKey = [[NSMutableDictionary alloc] init];
+ objc_setAssociatedObject(host, dictKey, objectsByKey, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+ }
+ id obj = objectsByKey[key];
+ NSValue *creationBlockBeingCalled = [NSValue valueWithPointer:dictKey];
+ if (obj) {
+ if ([creationBlockBeingCalled isEqual:obj]) {
+ [NSException raise:@"Reentering registeredObjectWithHost:key:creationBlock: not allowed"
+ format:@"host: %@ key: %@", host, key];
+ }
+ return obj;
+ }
+ objectsByKey[key] = creationBlockBeingCalled;
+ obj = creationBlock();
+ objectsByKey[key] = obj;
+ return obj;
+ }
+}
+
+@end
diff --git a/Pods/FirebaseCore/Firebase/Core/FIRBundleUtil.m b/Pods/FirebaseCore/Firebase/Core/FIRBundleUtil.m
new file mode 100644
index 0000000..65fc309
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/FIRBundleUtil.m
@@ -0,0 +1,75 @@
+// Copyright 2017 Google
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#import "Private/FIRBundleUtil.h"
+
+#import
+
+@implementation FIRBundleUtil
+
++ (NSArray *)relevantBundles {
+ return @[ [NSBundle mainBundle], [NSBundle bundleForClass:[self class]] ];
+}
+
++ (NSString *)optionsDictionaryPathWithResourceName:(NSString *)resourceName
+ andFileType:(NSString *)fileType
+ inBundles:(NSArray *)bundles {
+ // Loop through all bundles to find the config dict.
+ for (NSBundle *bundle in bundles) {
+ NSString *path = [bundle pathForResource:resourceName ofType:fileType];
+ // Use the first one we find.
+ if (path) {
+ return path;
+ }
+ }
+ return nil;
+}
+
++ (NSArray *)relevantURLSchemes {
+ NSMutableArray *result = [[NSMutableArray alloc] init];
+ for (NSBundle *bundle in [[self class] relevantBundles]) {
+ NSArray *urlTypes = [bundle objectForInfoDictionaryKey:@"CFBundleURLTypes"];
+ for (NSDictionary *urlType in urlTypes) {
+ [result addObjectsFromArray:urlType[@"CFBundleURLSchemes"]];
+ }
+ }
+ return result;
+}
+
++ (BOOL)hasBundleIdentifierPrefix:(NSString *)bundleIdentifier inBundles:(NSArray *)bundles {
+ for (NSBundle *bundle in bundles) {
+ // This allows app extensions that have the app's bundle as their prefix to pass this test.
+ NSString *applicationBundleIdentifier =
+ [GULAppEnvironmentUtil isAppExtension]
+ ? [self bundleIdentifierByRemovingLastPartFrom:bundle.bundleIdentifier]
+ : bundle.bundleIdentifier;
+
+ if ([applicationBundleIdentifier isEqualToString:bundleIdentifier]) {
+ return YES;
+ }
+ }
+ return NO;
+}
+
++ (NSString *)bundleIdentifierByRemovingLastPartFrom:(NSString *)bundleIdentifier {
+ NSString *bundleIDComponentsSeparator = @".";
+
+ NSMutableArray *bundleIDComponents =
+ [[bundleIdentifier componentsSeparatedByString:bundleIDComponentsSeparator] mutableCopy];
+ [bundleIDComponents removeLastObject];
+
+ return [bundleIDComponents componentsJoinedByString:bundleIDComponentsSeparator];
+}
+
+@end
diff --git a/Pods/FirebaseCore/Firebase/Core/FIRComponent.m b/Pods/FirebaseCore/Firebase/Core/FIRComponent.m
new file mode 100644
index 0000000..2474d1a
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/FIRComponent.m
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2018 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "Private/FIRComponent.h"
+
+#import "Private/FIRComponentContainer.h"
+#import "Private/FIRDependency.h"
+
+@interface FIRComponent ()
+
+- (instancetype)initWithProtocol:(Protocol *)protocol
+ instantiationTiming:(FIRInstantiationTiming)instantiationTiming
+ dependencies:(NSArray *)dependencies
+ creationBlock:(FIRComponentCreationBlock)creationBlock;
+
+@end
+
+@implementation FIRComponent
+
++ (instancetype)componentWithProtocol:(Protocol *)protocol
+ creationBlock:(FIRComponentCreationBlock)creationBlock {
+ return [[FIRComponent alloc] initWithProtocol:protocol
+ instantiationTiming:FIRInstantiationTimingLazy
+ dependencies:@[]
+ creationBlock:creationBlock];
+}
+
++ (instancetype)componentWithProtocol:(Protocol *)protocol
+ instantiationTiming:(FIRInstantiationTiming)instantiationTiming
+ dependencies:(NSArray *)dependencies
+ creationBlock:(FIRComponentCreationBlock)creationBlock {
+ return [[FIRComponent alloc] initWithProtocol:protocol
+ instantiationTiming:instantiationTiming
+ dependencies:dependencies
+ creationBlock:creationBlock];
+}
+
+- (instancetype)initWithProtocol:(Protocol *)protocol
+ instantiationTiming:(FIRInstantiationTiming)instantiationTiming
+ dependencies:(NSArray *)dependencies
+ creationBlock:(FIRComponentCreationBlock)creationBlock {
+ self = [super init];
+ if (self) {
+ _protocol = protocol;
+ _instantiationTiming = instantiationTiming;
+ _dependencies = [dependencies copy];
+ _creationBlock = creationBlock;
+ }
+ return self;
+}
+
+@end
diff --git a/Pods/FirebaseCore/Firebase/Core/FIRComponentContainer.m b/Pods/FirebaseCore/Firebase/Core/FIRComponentContainer.m
new file mode 100644
index 0000000..1977d0e
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/FIRComponentContainer.m
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2018 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "Private/FIRComponentContainer.h"
+
+#import "Private/FIRAppInternal.h"
+#import "Private/FIRComponent.h"
+#import "Private/FIRLibrary.h"
+#import "Private/FIRLogger.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface FIRComponentContainer ()
+
+/// The dictionary of components that are registered for a particular app. The key is an NSString
+/// of the protocol.
+@property(nonatomic, strong) NSMutableDictionary *components;
+
+/// Cached instances of components that requested to be cached.
+@property(nonatomic, strong) NSMutableDictionary *cachedInstances;
+
+@end
+
+@implementation FIRComponentContainer
+
+// Collection of all classes that register to provide components.
+static NSMutableSet *sFIRComponentRegistrants;
+
+#pragma mark - Public Registration
+
++ (void)registerAsComponentRegistrant:(Class)klass {
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ sFIRComponentRegistrants = [[NSMutableSet alloc] init];
+ });
+
+ [self registerAsComponentRegistrant:klass inSet:sFIRComponentRegistrants];
+}
+
++ (void)registerAsComponentRegistrant:(Class)klass
+ inSet:(NSMutableSet *)allRegistrants {
+ [allRegistrants addObject:klass];
+}
+
+#pragma mark - Internal Initialization
+
+- (instancetype)initWithApp:(FIRApp *)app {
+ return [self initWithApp:app registrants:sFIRComponentRegistrants];
+}
+
+- (instancetype)initWithApp:(FIRApp *)app registrants:(NSMutableSet *)allRegistrants {
+ self = [super init];
+ if (self) {
+ _app = app;
+ _cachedInstances = [NSMutableDictionary dictionary];
+ _components = [NSMutableDictionary dictionary];
+
+ [self populateComponentsFromRegisteredClasses:allRegistrants forApp:app];
+ }
+ return self;
+}
+
+- (void)populateComponentsFromRegisteredClasses:(NSSet *)classes forApp:(FIRApp *)app {
+ // Loop through the verified component registrants and populate the components array.
+ for (Class klass in classes) {
+ // Loop through all the components being registered and store them as appropriate.
+ // Classes which do not provide functionality should use a dummy FIRComponentRegistrant
+ // protocol.
+ for (FIRComponent *component in [klass componentsToRegister]) {
+ // Check if the component has been registered before, and error out if so.
+ NSString *protocolName = NSStringFromProtocol(component.protocol);
+ if (self.components[protocolName]) {
+ FIRLogError(kFIRLoggerCore, @"I-COR000029",
+ @"Attempted to register protocol %@, but it already has an implementation.",
+ protocolName);
+ continue;
+ }
+
+ // Store the creation block for later usage.
+ self.components[protocolName] = component.creationBlock;
+
+ // Instantiate the
+ BOOL shouldInstantiateEager =
+ (component.instantiationTiming == FIRInstantiationTimingAlwaysEager);
+ BOOL shouldInstantiateDefaultEager =
+ (component.instantiationTiming == FIRInstantiationTimingEagerInDefaultApp &&
+ [app isDefaultApp]);
+ if (shouldInstantiateEager || shouldInstantiateDefaultEager) {
+ [self instantiateInstanceForProtocol:component.protocol withBlock:component.creationBlock];
+ }
+ }
+ }
+}
+
+#pragma mark - Instance Creation
+
+/// Instantiate an instance of a class that conforms to the specified protocol.
+/// This will:
+/// - Call the block to create an instance if possible,
+/// - Validate that the instance returned conforms to the protocol it claims to,
+/// - Cache the instance if the block requests it
+- (nullable id)instantiateInstanceForProtocol:(Protocol *)protocol
+ withBlock:(FIRComponentCreationBlock)creationBlock {
+ if (!creationBlock) {
+ return nil;
+ }
+
+ // Create an instance using the creation block.
+ BOOL shouldCache = NO;
+ id instance = creationBlock(self, &shouldCache);
+ if (!instance) {
+ return nil;
+ }
+
+ // An instance was created, validate that it conforms to the protocol it claims to.
+ NSString *protocolName = NSStringFromProtocol(protocol);
+ if (![instance conformsToProtocol:protocol]) {
+ FIRLogError(kFIRLoggerCore, @"I-COR000030",
+ @"An instance conforming to %@ was requested, but the instance provided does not "
+ @"conform to the protocol",
+ protocolName);
+ }
+
+ // The instance is ready to be returned, but check if it should be cached first before returning.
+ if (shouldCache) {
+ self.cachedInstances[protocolName] = instance;
+ }
+
+ return instance;
+}
+
+#pragma mark - Internal Retrieval
+
+- (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];
+ if (cachedInstance) {
+ return cachedInstance;
+ }
+
+ // Use the creation block to instantiate an instance and return it.
+ FIRComponentCreationBlock creationBlock = self.components[protocolName];
+ return [self instantiateInstanceForProtocol:protocol withBlock:creationBlock];
+}
+
+#pragma mark - Lifecycle
+
+- (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) {
+ if ([instance conformsToProtocol:@protocol(FIRComponentLifecycleMaintainer)] &&
+ [instance respondsToSelector:@selector(appWillBeDeleted:)]) {
+ [instance appWillBeDeleted:self.app];
+ }
+ }
+
+ [self.cachedInstances removeAllObjects];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseCore/Firebase/Core/FIRComponentType.m b/Pods/FirebaseCore/Firebase/Core/FIRComponentType.m
new file mode 100644
index 0000000..bdc004f
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/FIRComponentType.m
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2018 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "Private/FIRComponentType.h"
+
+#import "Private/FIRComponentContainerInternal.h"
+
+@implementation FIRComponentType
+
++ (id)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container {
+ // Forward the call to the container.
+ return [container instanceForProtocol:protocol];
+}
+
+@end
diff --git a/Pods/FirebaseCore/Firebase/Core/FIRConfiguration.m b/Pods/FirebaseCore/Firebase/Core/FIRConfiguration.m
new file mode 100644
index 0000000..869f73d
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/FIRConfiguration.m
@@ -0,0 +1,46 @@
+// Copyright 2017 Google
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#import "Private/FIRConfigurationInternal.h"
+
+#import "Private/FIRAnalyticsConfiguration.h"
+
+extern void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel);
+
+@implementation FIRConfiguration
+
++ (instancetype)sharedInstance {
+ static FIRConfiguration *sharedInstance = nil;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ sharedInstance = [[FIRConfiguration alloc] init];
+ });
+ return sharedInstance;
+}
+
+- (instancetype)init {
+ self = [super init];
+ if (self) {
+ _analyticsConfiguration = [FIRAnalyticsConfiguration sharedInstance];
+ }
+ return self;
+}
+
+- (void)setLoggerLevel:(FIRLoggerLevel)loggerLevel {
+ NSAssert(loggerLevel <= FIRLoggerLevelMax && loggerLevel >= FIRLoggerLevelMin,
+ @"Invalid logger level, %ld", (long)loggerLevel);
+ FIRSetLoggerLevel(loggerLevel);
+}
+
+@end
diff --git a/Pods/FirebaseCore/Firebase/Core/FIRCoreDiagnosticsConnector.m b/Pods/FirebaseCore/Firebase/Core/FIRCoreDiagnosticsConnector.m
new file mode 100644
index 0000000..7d504e8
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/FIRCoreDiagnosticsConnector.m
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "Private/FIRCoreDiagnosticsConnector.h"
+
+#import
+
+#import
+
+#import "Private/FIRAppInternal.h"
+#import "Private/FIRDiagnosticsData.h"
+#import "Private/FIROptionsInternal.h"
+
+// Define the interop class symbol declared as an extern in FIRCoreDiagnosticsInterop.
+Class FIRCoreDiagnosticsImplementation;
+
+@implementation FIRCoreDiagnosticsConnector
+
++ (void)initialize {
+ if (!FIRCoreDiagnosticsImplementation) {
+ FIRCoreDiagnosticsImplementation = NSClassFromString(@"FIRCoreDiagnostics");
+ if (FIRCoreDiagnosticsImplementation) {
+ NSAssert([FIRCoreDiagnosticsImplementation
+ conformsToProtocol:@protocol(FIRCoreDiagnosticsInterop)],
+ @"If FIRCoreDiagnostics is implemented, it must conform to the interop protocol.");
+ NSAssert(
+ [FIRCoreDiagnosticsImplementation respondsToSelector:@selector(sendDiagnosticsData:)],
+ @"If FIRCoreDiagnostics is implemented, it must implement +sendDiagnosticsData.");
+ }
+ }
+}
+
++ (void)logCoreTelemetryWithOptions:(FIROptions *)options {
+ if (FIRCoreDiagnosticsImplementation) {
+ FIRDiagnosticsData *diagnosticsData = [[FIRDiagnosticsData alloc] init];
+ [diagnosticsData insertValue:@(YES) forKey:kFIRCDIsDataCollectionDefaultEnabledKey];
+ [diagnosticsData insertValue:[FIRApp firebaseUserAgent] forKey:kFIRCDFirebaseUserAgentKey];
+ [diagnosticsData insertValue:@(FIRConfigTypeCore) forKey:kFIRCDConfigurationTypeKey];
+ [diagnosticsData insertValue:options.googleAppID forKey:kFIRCDGoogleAppIDKey];
+ [diagnosticsData insertValue:options.bundleID forKey:kFIRCDBundleIDKey];
+ [diagnosticsData insertValue:@(options.usingOptionsFromDefaultPlist)
+ forKey:kFIRCDUsingOptionsFromDefaultPlistKey];
+ [diagnosticsData insertValue:options.libraryVersionID forKey:kFIRCDLibraryVersionIDKey];
+ [FIRCoreDiagnosticsImplementation sendDiagnosticsData:diagnosticsData];
+ }
+}
+
+@end
diff --git a/Pods/FirebaseCore/Firebase/Core/FIRDependency.m b/Pods/FirebaseCore/Firebase/Core/FIRDependency.m
new file mode 100644
index 0000000..f979984
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/FIRDependency.m
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2018 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "Private/FIRDependency.h"
+
+@interface FIRDependency ()
+
+- (instancetype)initWithProtocol:(Protocol *)protocol isRequired:(BOOL)required;
+
+@end
+
+@implementation FIRDependency
+
++ (instancetype)dependencyWithProtocol:(Protocol *)protocol {
+ return [[self alloc] initWithProtocol:protocol isRequired:YES];
+}
+
++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required {
+ return [[self alloc] initWithProtocol:protocol isRequired:required];
+}
+
+- (instancetype)initWithProtocol:(Protocol *)protocol isRequired:(BOOL)required {
+ self = [super init];
+ if (self) {
+ _protocol = protocol;
+ _isRequired = required;
+ }
+ return self;
+}
+
+@end
diff --git a/Pods/FirebaseCore/Firebase/Core/FIRDiagnosticsData.m b/Pods/FirebaseCore/Firebase/Core/FIRDiagnosticsData.m
new file mode 100644
index 0000000..0476973
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/FIRDiagnosticsData.m
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "Private/FIRDiagnosticsData.h"
+
+#import
+
+#import "Private/FIRAppInternal.h"
+#import "Private/FIROptionsInternal.h"
+
+@implementation FIRDiagnosticsData {
+ /** Backing ivar for the diagnosticObjects property. */
+ NSMutableDictionary *_diagnosticObjects;
+}
+
+- (instancetype)init {
+ self = [super init];
+ if (self) {
+ _diagnosticObjects = [[NSMutableDictionary alloc] init];
+ }
+ return self;
+}
+
+- (void)insertValue:(nullable id)value forKey:(NSString *)key {
+ if (key) {
+ _diagnosticObjects[key] = value;
+ }
+}
+
+#pragma mark - FIRCoreDiagnosticsData
+
+- (NSDictionary *)diagnosticObjects {
+ if (!_diagnosticObjects[kFIRCDllAppsCountKey]) {
+ _diagnosticObjects[kFIRCDllAppsCountKey] = @([FIRApp allApps].count);
+ }
+ if (!_diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey]) {
+ _diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey] =
+ @([[FIRApp defaultApp] isDataCollectionDefaultEnabled]);
+ }
+ if (!_diagnosticObjects[kFIRCDFirebaseUserAgentKey]) {
+ _diagnosticObjects[kFIRCDFirebaseUserAgentKey] = [FIRApp firebaseUserAgent];
+ }
+ return _diagnosticObjects;
+}
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-parameter"
+- (void)setDiagnosticObjects:(NSDictionary *)diagnosticObjects {
+ NSAssert(NO, @"Please use -insertValue:forKey:");
+}
+#pragma clang diagnostic pop
+
+@end
diff --git a/Pods/FirebaseCore/Firebase/Core/FIRErrors.m b/Pods/FirebaseCore/Firebase/Core/FIRErrors.m
new file mode 100644
index 0000000..72120c5
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/FIRErrors.m
@@ -0,0 +1,21 @@
+// Copyright 2017 Google
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#import "Private/FIRErrors.h"
+
+NSString *const kFirebaseErrorDomain = @"com.firebase";
+NSString *const kFirebaseConfigErrorDomain = @"com.firebase.config";
+NSString *const kFirebaseCoreErrorDomain = @"com.firebase.core";
+NSString *const kFirebasePerfErrorDomain = @"com.firebase.perf";
+NSString *const kFirebaseStorageErrorDomain = @"com.firebase.storage";
diff --git a/Pods/FirebaseCore/Firebase/Core/FIRLogger.m b/Pods/FirebaseCore/Firebase/Core/FIRLogger.m
new file mode 100644
index 0000000..532a96c
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/FIRLogger.m
@@ -0,0 +1,179 @@
+// Copyright 2017 Google
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#import "Private/FIRLogger.h"
+
+#import
+#import
+#import
+
+#import "Private/FIRVersion.h"
+
+FIRLoggerService kFIRLoggerCore = @"[Firebase/Core]";
+
+// All the FIRLoggerService definitions should be migrated to clients. Do not add new ones!
+FIRLoggerService kFIRLoggerABTesting = @"[Firebase/ABTesting]";
+FIRLoggerService kFIRLoggerAdMob = @"[Firebase/AdMob]";
+FIRLoggerService kFIRLoggerAnalytics = @"[Firebase/Analytics]";
+FIRLoggerService kFIRLoggerAuth = @"[Firebase/Auth]";
+FIRLoggerService kFIRLoggerCrash = @"[Firebase/Crash]";
+FIRLoggerService kFIRLoggerMLKit = @"[Firebase/MLKit]";
+FIRLoggerService kFIRLoggerPerf = @"[Firebase/Performance]";
+FIRLoggerService kFIRLoggerRemoteConfig = @"[Firebase/RemoteConfig]";
+
+/// Arguments passed on launch.
+NSString *const kFIRDisableDebugModeApplicationArgument = @"-FIRDebugDisabled";
+NSString *const kFIREnableDebugModeApplicationArgument = @"-FIRDebugEnabled";
+NSString *const kFIRLoggerForceSDTERRApplicationArgument = @"-FIRLoggerForceSTDERR";
+
+/// Key for the debug mode bit in NSUserDefaults.
+NSString *const kFIRPersistedDebugModeKey = @"/google/firebase/debug_mode";
+
+/// NSUserDefaults that should be used to store and read variables. If nil, `standardUserDefaults`
+/// will be used.
+static NSUserDefaults *sFIRLoggerUserDefaults;
+
+static dispatch_once_t sFIRLoggerOnceToken;
+
+// The sFIRAnalyticsDebugMode flag is here to support the -FIRDebugEnabled/-FIRDebugDisabled
+// flags used by Analytics. Users who use those flags expect Analytics to log verbosely,
+// while the rest of Firebase logs at the default level. This flag is introduced to support
+// that behavior.
+static BOOL sFIRAnalyticsDebugMode;
+
+#ifdef DEBUG
+/// The regex pattern for the message code.
+static NSString *const kMessageCodePattern = @"^I-[A-Z]{3}[0-9]{6}$";
+static NSRegularExpression *sMessageCodeRegex;
+#endif
+
+void FIRLoggerInitializeASL() {
+ dispatch_once(&sFIRLoggerOnceToken, ^{
+ // Register Firebase Version with GULLogger.
+ GULLoggerRegisterVersion(FIRVersionString);
+
+ // Override the aslOptions to ASL_OPT_STDERR if the override argument is passed in.
+ NSArray *arguments = [NSProcessInfo processInfo].arguments;
+ BOOL overrideSTDERR = [arguments containsObject:kFIRLoggerForceSDTERRApplicationArgument];
+
+ // Use the standard NSUserDefaults if it hasn't been explicitly set.
+ if (sFIRLoggerUserDefaults == nil) {
+ sFIRLoggerUserDefaults = [NSUserDefaults standardUserDefaults];
+ }
+
+ BOOL forceDebugMode = NO;
+ BOOL debugMode = [sFIRLoggerUserDefaults boolForKey:kFIRPersistedDebugModeKey];
+ if ([arguments containsObject:kFIRDisableDebugModeApplicationArgument]) { // Default mode
+ [sFIRLoggerUserDefaults removeObjectForKey:kFIRPersistedDebugModeKey];
+ } else if ([arguments containsObject:kFIREnableDebugModeApplicationArgument] ||
+ debugMode) { // Debug mode
+ [sFIRLoggerUserDefaults setBool:YES forKey:kFIRPersistedDebugModeKey];
+ forceDebugMode = YES;
+ }
+ GULLoggerInitializeASL();
+ if (overrideSTDERR) {
+ GULLoggerEnableSTDERR();
+ }
+ if (forceDebugMode) {
+ GULLoggerForceDebug();
+ }
+ });
+}
+
+__attribute__((no_sanitize("thread"))) void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode) {
+ sFIRAnalyticsDebugMode = analyticsDebugMode;
+}
+
+void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel) {
+ FIRLoggerInitializeASL();
+ GULSetLoggerLevel((GULLoggerLevel)loggerLevel);
+}
+
+#ifdef DEBUG
+void FIRResetLogger() {
+ extern void GULResetLogger(void);
+ sFIRLoggerOnceToken = 0;
+ [sFIRLoggerUserDefaults removeObjectForKey:kFIRPersistedDebugModeKey];
+ sFIRLoggerUserDefaults = nil;
+ GULResetLogger();
+}
+
+void FIRSetLoggerUserDefaults(NSUserDefaults *defaults) {
+ sFIRLoggerUserDefaults = defaults;
+}
+#endif
+
+/**
+ * Check if the level is high enough to be loggable.
+ *
+ * Analytics can override the log level with an intentional race condition.
+ * Add the attribute to get a clean thread sanitizer run.
+ */
+__attribute__((no_sanitize("thread"))) BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel,
+ BOOL analyticsComponent) {
+ FIRLoggerInitializeASL();
+ if (sFIRAnalyticsDebugMode && analyticsComponent) {
+ return YES;
+ }
+ return GULIsLoggableLevel((GULLoggerLevel)loggerLevel);
+}
+
+void FIRLogBasic(FIRLoggerLevel level,
+ FIRLoggerService service,
+ NSString *messageCode,
+ NSString *message,
+ va_list args_ptr) {
+ FIRLoggerInitializeASL();
+ GULLogBasic((GULLoggerLevel)level, service,
+ sFIRAnalyticsDebugMode && [kFIRLoggerAnalytics isEqualToString:service], messageCode,
+ message, args_ptr);
+}
+
+/**
+ * Generates the logging functions using macros.
+ *
+ * Calling FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configure %@ failed.", @"blah") shows:
+ * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [Firebase/Core][I-COR000001] Configure blah failed.
+ * Calling FIRLogDebug(kFIRLoggerCore, @"I-COR000001", @"Configure succeed.") shows:
+ * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [Firebase/Core][I-COR000001] Configure succeed.
+ */
+#define FIR_LOGGING_FUNCTION(level) \
+ void FIRLog##level(FIRLoggerService service, NSString *messageCode, NSString *message, ...) { \
+ va_list args_ptr; \
+ va_start(args_ptr, message); \
+ FIRLogBasic(FIRLoggerLevel##level, service, messageCode, message, args_ptr); \
+ va_end(args_ptr); \
+ }
+
+FIR_LOGGING_FUNCTION(Error)
+FIR_LOGGING_FUNCTION(Warning)
+FIR_LOGGING_FUNCTION(Notice)
+FIR_LOGGING_FUNCTION(Info)
+FIR_LOGGING_FUNCTION(Debug)
+
+#undef FIR_MAKE_LOGGER
+
+#pragma mark - FIRLoggerWrapper
+
+@implementation FIRLoggerWrapper
+
++ (void)logWithLevel:(FIRLoggerLevel)level
+ withService:(FIRLoggerService)service
+ withCode:(NSString *)messageCode
+ withMessage:(NSString *)message
+ withArgs:(va_list)args {
+ FIRLogBasic(level, service, messageCode, message, args);
+}
+
+@end
diff --git a/Pods/FirebaseCore/Firebase/Core/FIROptions.m b/Pods/FirebaseCore/Firebase/Core/FIROptions.m
new file mode 100644
index 0000000..89a679a
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/FIROptions.m
@@ -0,0 +1,454 @@
+// Copyright 2017 Google
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#import "Private/FIRAppInternal.h"
+#import "Private/FIRBundleUtil.h"
+#import "Private/FIRErrors.h"
+#import "Private/FIRLogger.h"
+#import "Private/FIROptionsInternal.h"
+#import "Private/FIRVersion.h"
+
+// Keys for the strings in the plist file.
+NSString *const kFIRAPIKey = @"API_KEY";
+NSString *const kFIRTrackingID = @"TRACKING_ID";
+NSString *const kFIRGoogleAppID = @"GOOGLE_APP_ID";
+NSString *const kFIRClientID = @"CLIENT_ID";
+NSString *const kFIRGCMSenderID = @"GCM_SENDER_ID";
+NSString *const kFIRAndroidClientID = @"ANDROID_CLIENT_ID";
+NSString *const kFIRDatabaseURL = @"DATABASE_URL";
+NSString *const kFIRStorageBucket = @"STORAGE_BUCKET";
+// The key to locate the expected bundle identifier in the plist file.
+NSString *const kFIRBundleID = @"BUNDLE_ID";
+// The key to locate the project identifier in the plist file.
+NSString *const kFIRProjectID = @"PROJECT_ID";
+
+NSString *const kFIRIsMeasurementEnabled = @"IS_MEASUREMENT_ENABLED";
+NSString *const kFIRIsAnalyticsCollectionEnabled = @"FIREBASE_ANALYTICS_COLLECTION_ENABLED";
+NSString *const kFIRIsAnalyticsCollectionDeactivated = @"FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED";
+
+NSString *const kFIRIsAnalyticsEnabled = @"IS_ANALYTICS_ENABLED";
+NSString *const kFIRIsSignInEnabled = @"IS_SIGNIN_ENABLED";
+
+// Library version ID formatted like:
+// @"5" // Major version (one or more digits)
+// @"04" // Minor version (exactly 2 digits)
+// @"01" // Build number (exactly 2 digits)
+// @"000"; // Fixed "000"
+NSString *kFIRLibraryVersionID;
+
+// Plist file name.
+NSString *const kServiceInfoFileName = @"GoogleService-Info";
+// Plist file type.
+NSString *const kServiceInfoFileType = @"plist";
+
+// Exception raised from attempting to modify a FIROptions after it's been copied to a FIRApp.
+NSString *const kFIRExceptionBadModification =
+ @"Attempted to modify options after it's set on FIRApp. Please modify all properties before "
+ @"initializing FIRApp.";
+
+@interface FIROptions ()
+
+/**
+ * This property maintains the actual configuration key-value pairs.
+ */
+@property(nonatomic, readwrite) NSMutableDictionary *optionsDictionary;
+
+/**
+ * Calls `analyticsOptionsDictionaryWithInfoDictionary:` using [NSBundle mainBundle].infoDictionary.
+ * It combines analytics options from both the infoDictionary and the GoogleService-Info.plist.
+ * Values which are present in the main plist override values from the GoogleService-Info.plist.
+ */
+@property(nonatomic, readonly) NSDictionary *analyticsOptionsDictionary;
+
+/**
+ * Combination of analytics options from both the infoDictionary and the GoogleService-Info.plist.
+ * Values which are present in the infoDictionary override values from the GoogleService-Info.plist.
+ */
+- (NSDictionary *)analyticsOptionsDictionaryWithInfoDictionary:(NSDictionary *)infoDictionary;
+
+/**
+ * Throw exception if editing is locked when attempting to modify an option.
+ */
+- (void)checkEditingLocked;
+
+@end
+
+@implementation FIROptions {
+ /// Backing variable for self.analyticsOptionsDictionary.
+ NSDictionary *_analyticsOptionsDictionary;
+}
+
+static FIROptions *sDefaultOptions = nil;
+static NSDictionary *sDefaultOptionsDictionary = nil;
+
+#pragma mark - Public only for internal class methods
+
++ (FIROptions *)defaultOptions {
+ if (sDefaultOptions != nil) {
+ return sDefaultOptions;
+ }
+
+ NSDictionary *defaultOptionsDictionary = [self defaultOptionsDictionary];
+ if (defaultOptionsDictionary == nil) {
+ return nil;
+ }
+
+ sDefaultOptions = [[FIROptions alloc] initInternalWithOptionsDictionary:defaultOptionsDictionary];
+ return sDefaultOptions;
+}
+
+#pragma mark - Private class methods
+
++ (void)initialize {
+ // Report FirebaseCore version for useragent string
+ [FIRApp registerLibrary:@"fire-ios"
+ withVersion:[NSString stringWithUTF8String:FIRCoreVersionString]];
+
+ NSDictionary *info = [[NSBundle mainBundle] infoDictionary];
+ NSString *xcodeVersion = info[@"DTXcodeBuild"];
+ NSString *sdkVersion = info[@"DTSDKBuild"];
+ if (xcodeVersion) {
+ [FIRApp registerLibrary:@"xcode" withVersion:xcodeVersion];
+ }
+ if (sdkVersion) {
+ [FIRApp registerLibrary:@"apple-sdk" withVersion:sdkVersion];
+ }
+}
+
++ (NSDictionary *)defaultOptionsDictionary {
+ if (sDefaultOptionsDictionary != nil) {
+ return sDefaultOptionsDictionary;
+ }
+ NSString *plistFilePath = [FIROptions plistFilePathWithName:kServiceInfoFileName];
+ if (plistFilePath == nil) {
+ return nil;
+ }
+ sDefaultOptionsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistFilePath];
+ if (sDefaultOptionsDictionary == nil) {
+ FIRLogError(kFIRLoggerCore, @"I-COR000011",
+ @"The configuration file is not a dictionary: "
+ @"'%@.%@'.",
+ kServiceInfoFileName, kServiceInfoFileType);
+ }
+ return sDefaultOptionsDictionary;
+}
+
+// Returns the path of the plist file with a given file name.
++ (NSString *)plistFilePathWithName:(NSString *)fileName {
+ NSArray *bundles = [FIRBundleUtil relevantBundles];
+ NSString *plistFilePath =
+ [FIRBundleUtil optionsDictionaryPathWithResourceName:fileName
+ andFileType:kServiceInfoFileType
+ inBundles:bundles];
+ if (plistFilePath == nil) {
+ FIRLogError(kFIRLoggerCore, @"I-COR000012", @"Could not locate configuration file: '%@.%@'.",
+ fileName, kServiceInfoFileType);
+ }
+ return plistFilePath;
+}
+
++ (void)resetDefaultOptions {
+ sDefaultOptions = nil;
+ sDefaultOptionsDictionary = nil;
+}
+
+#pragma mark - Private instance methods
+
+- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)optionsDictionary {
+ self = [super init];
+ if (self) {
+ _optionsDictionary = [optionsDictionary mutableCopy];
+ _usingOptionsFromDefaultPlist = YES;
+ }
+ return self;
+}
+
+- (id)copyWithZone:(NSZone *)zone {
+ FIROptions *newOptions = [[[self class] allocWithZone:zone] init];
+ if (newOptions) {
+ newOptions.optionsDictionary = self.optionsDictionary;
+ newOptions.deepLinkURLScheme = self.deepLinkURLScheme;
+ newOptions.appGroupID = self.appGroupID;
+ newOptions.editingLocked = self.isEditingLocked;
+ newOptions.usingOptionsFromDefaultPlist = self.usingOptionsFromDefaultPlist;
+ }
+ return newOptions;
+}
+
+#pragma mark - Public instance methods
+
+- (instancetype)initWithContentsOfFile:(NSString *)plistPath {
+ self = [super init];
+ if (self) {
+ if (plistPath == nil) {
+ FIRLogError(kFIRLoggerCore, @"I-COR000013", @"The plist file path is nil.");
+ return nil;
+ }
+ _optionsDictionary = [[NSDictionary dictionaryWithContentsOfFile:plistPath] mutableCopy];
+ if (_optionsDictionary == nil) {
+ FIRLogError(kFIRLoggerCore, @"I-COR000014",
+ @"The configuration file at %@ does not exist or "
+ @"is not a well-formed plist file.",
+ plistPath);
+ return nil;
+ }
+ // TODO: Do we want to validate the dictionary here? It says we do that already in
+ // the public header.
+ }
+ return self;
+}
+
+- (instancetype)initWithGoogleAppID:(NSString *)googleAppID GCMSenderID:(NSString *)GCMSenderID {
+ self = [super init];
+ if (self) {
+ NSMutableDictionary *mutableOptionsDict = [NSMutableDictionary dictionary];
+ [mutableOptionsDict setValue:googleAppID forKey:kFIRGoogleAppID];
+ [mutableOptionsDict setValue:GCMSenderID forKey:kFIRGCMSenderID];
+ [mutableOptionsDict setValue:[[NSBundle mainBundle] bundleIdentifier] forKey:kFIRBundleID];
+ self.optionsDictionary = mutableOptionsDict;
+ }
+ return self;
+}
+
+- (NSString *)APIKey {
+ return self.optionsDictionary[kFIRAPIKey];
+}
+
+- (void)checkEditingLocked {
+ if (self.isEditingLocked) {
+ [NSException raise:kFirebaseCoreErrorDomain format:kFIRExceptionBadModification];
+ }
+}
+
+- (void)setAPIKey:(NSString *)APIKey {
+ [self checkEditingLocked];
+ _optionsDictionary[kFIRAPIKey] = [APIKey copy];
+}
+
+- (NSString *)clientID {
+ return self.optionsDictionary[kFIRClientID];
+}
+
+- (void)setClientID:(NSString *)clientID {
+ [self checkEditingLocked];
+ _optionsDictionary[kFIRClientID] = [clientID copy];
+}
+
+- (NSString *)trackingID {
+ return self.optionsDictionary[kFIRTrackingID];
+}
+
+- (void)setTrackingID:(NSString *)trackingID {
+ [self checkEditingLocked];
+ _optionsDictionary[kFIRTrackingID] = [trackingID copy];
+}
+
+- (NSString *)GCMSenderID {
+ return self.optionsDictionary[kFIRGCMSenderID];
+}
+
+- (void)setGCMSenderID:(NSString *)GCMSenderID {
+ [self checkEditingLocked];
+ _optionsDictionary[kFIRGCMSenderID] = [GCMSenderID copy];
+}
+
+- (NSString *)projectID {
+ return self.optionsDictionary[kFIRProjectID];
+}
+
+- (void)setProjectID:(NSString *)projectID {
+ [self checkEditingLocked];
+ _optionsDictionary[kFIRProjectID] = [projectID copy];
+}
+
+- (NSString *)androidClientID {
+ return self.optionsDictionary[kFIRAndroidClientID];
+}
+
+- (void)setAndroidClientID:(NSString *)androidClientID {
+ [self checkEditingLocked];
+ _optionsDictionary[kFIRAndroidClientID] = [androidClientID copy];
+}
+
+- (NSString *)googleAppID {
+ return self.optionsDictionary[kFIRGoogleAppID];
+}
+
+- (void)setGoogleAppID:(NSString *)googleAppID {
+ [self checkEditingLocked];
+ _optionsDictionary[kFIRGoogleAppID] = [googleAppID copy];
+}
+
+- (NSString *)libraryVersionID {
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ // The unit tests are set up to catch anything that does not properly convert.
+ NSString *version = [NSString stringWithUTF8String:FIRCoreVersionString];
+ NSArray *components = [version componentsSeparatedByString:@"."];
+ NSString *major = [components objectAtIndex:0];
+ NSString *minor = [NSString stringWithFormat:@"%02d", [[components objectAtIndex:1] intValue]];
+ NSString *patch = [NSString stringWithFormat:@"%02d", [[components objectAtIndex:2] intValue]];
+ kFIRLibraryVersionID = [NSString stringWithFormat:@"%@%@%@000", major, minor, patch];
+ });
+ return kFIRLibraryVersionID;
+}
+
+- (void)setLibraryVersionID:(NSString *)libraryVersionID {
+ _optionsDictionary[kFIRLibraryVersionID] = [libraryVersionID copy];
+}
+
+- (NSString *)databaseURL {
+ return self.optionsDictionary[kFIRDatabaseURL];
+}
+
+- (void)setDatabaseURL:(NSString *)databaseURL {
+ [self checkEditingLocked];
+
+ _optionsDictionary[kFIRDatabaseURL] = [databaseURL copy];
+}
+
+- (NSString *)storageBucket {
+ return self.optionsDictionary[kFIRStorageBucket];
+}
+
+- (void)setStorageBucket:(NSString *)storageBucket {
+ [self checkEditingLocked];
+ _optionsDictionary[kFIRStorageBucket] = [storageBucket copy];
+}
+
+- (void)setDeepLinkURLScheme:(NSString *)deepLinkURLScheme {
+ [self checkEditingLocked];
+ _deepLinkURLScheme = [deepLinkURLScheme copy];
+}
+
+- (NSString *)bundleID {
+ return self.optionsDictionary[kFIRBundleID];
+}
+
+- (void)setBundleID:(NSString *)bundleID {
+ [self checkEditingLocked];
+ _optionsDictionary[kFIRBundleID] = [bundleID copy];
+}
+
+- (void)setAppGroupID:(NSString *)appGroupID {
+ [self checkEditingLocked];
+ _appGroupID = [appGroupID copy];
+}
+
+#pragma mark - Internal instance methods
+
+- (NSDictionary *)analyticsOptionsDictionaryWithInfoDictionary:(NSDictionary *)infoDictionary {
+ if (_analyticsOptionsDictionary == nil) {
+ NSMutableDictionary *tempAnalyticsOptions = [[NSMutableDictionary alloc] init];
+ NSArray *measurementKeys = @[
+ kFIRIsMeasurementEnabled, kFIRIsAnalyticsCollectionEnabled,
+ kFIRIsAnalyticsCollectionDeactivated
+ ];
+ for (NSString *key in measurementKeys) {
+ id value = infoDictionary[key] ?: self.optionsDictionary[key] ?: nil;
+ if (!value) {
+ continue;
+ }
+ tempAnalyticsOptions[key] = value;
+ }
+ _analyticsOptionsDictionary = tempAnalyticsOptions;
+ }
+ return _analyticsOptionsDictionary;
+}
+
+- (NSDictionary *)analyticsOptionsDictionary {
+ return [self analyticsOptionsDictionaryWithInfoDictionary:[NSBundle mainBundle].infoDictionary];
+}
+
+/**
+ * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in
+ * GoogleService-Info.plist. This uses the old plist flag IS_MEASUREMENT_ENABLED, which should still
+ * be supported.
+ */
+- (BOOL)isMeasurementEnabled {
+ if (self.isAnalyticsCollectionDeactivated) {
+ return NO;
+ }
+ NSNumber *value = self.analyticsOptionsDictionary[kFIRIsMeasurementEnabled];
+ if (value == nil) {
+ // TODO: This could probably be cleaned up since FIROptions shouldn't know about FIRApp or have
+ // to check if it's the default app. The FIROptions instance can't be modified after
+ // `+configure` is called, so it's not a good place to copy it either in case the flag is
+ // changed at runtime.
+
+ // If no values are set for Analytics, fall back to the global collection switch in FIRApp.
+ // Analytics only supports the default FIRApp, so check that first.
+ if (![FIRApp isDefaultAppConfigured]) {
+ return NO;
+ }
+
+ // Fall back to the default app's collection switch when the key is not in the dictionary.
+ return [FIRApp defaultApp].isDataCollectionDefaultEnabled;
+ }
+ return [value boolValue];
+}
+
+- (BOOL)isAnalyticsCollectionExpicitlySet {
+ // 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) {
+ return YES;
+ }
+
+ // Check if the current Analytics flag is set.
+ id collectionEnabledObject = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionEnabled];
+ if (collectionEnabledObject && [collectionEnabledObject isKindOfClass:[NSNumber class]]) {
+ // It doesn't matter what the value is, it's explicitly set.
+ return YES;
+ }
+
+ // Check if the old measurement flag is set.
+ id measurementEnabledObject = self.analyticsOptionsDictionary[kFIRIsMeasurementEnabled];
+ if (measurementEnabledObject && [measurementEnabledObject isKindOfClass:[NSNumber class]]) {
+ // It doesn't matter what the value is, it's explicitly set.
+ return YES;
+ }
+
+ // No flags are set to explicitly enable or disable FirebaseAnalytics.
+ return NO;
+}
+
+- (BOOL)isAnalyticsCollectionEnabled {
+ if (self.isAnalyticsCollectionDeactivated) {
+ return NO;
+ }
+ NSNumber *value = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionEnabled];
+ if (value == nil) {
+ return self.isMeasurementEnabled; // Fall back to older plist flag.
+ }
+ return [value boolValue];
+}
+
+- (BOOL)isAnalyticsCollectionDeactivated {
+ NSNumber *value = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionDeactivated];
+ if (value == nil) {
+ return NO; // Analytics Collection is not deactivated when the key is not in the dictionary.
+ }
+ return [value boolValue];
+}
+
+- (BOOL)isAnalyticsEnabled {
+ return [self.optionsDictionary[kFIRIsAnalyticsEnabled] boolValue];
+}
+
+- (BOOL)isSignInEnabled {
+ return [self.optionsDictionary[kFIRIsSignInEnabled] boolValue];
+}
+
+@end
diff --git a/Pods/FirebaseCore/Firebase/Core/FIRVersion.m b/Pods/FirebaseCore/Firebase/Core/FIRVersion.m
new file mode 100644
index 0000000..ec0f6ba
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/FIRVersion.m
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+#ifndef Firebase_VERSION
+#error "Firebase_VERSION is not defined: add -DFirebase_VERSION=... to the build invocation"
+#endif
+
+#ifndef FIRCore_VERSION
+#error "FIRCore_VERSION is not defined: add -DFIRCore_VERSION=... to the build invocation"
+#endif
+
+// The following two macros supply the incantation so that the C
+// preprocessor does not try to parse the version as a floating
+// point number. See
+// https://www.guyrutenberg.com/2008/12/20/expanding-macros-into-string-constants-in-c/
+#define STR(x) STR_EXPAND(x)
+#define STR_EXPAND(x) #x
+
+const char *const FIRVersionString = (const char *const)STR(Firebase_VERSION);
+const char *const FIRCoreVersionString = (const char *const)STR(FIRCore_VERSION);
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIRAnalyticsConfiguration.h b/Pods/FirebaseCore/Firebase/Core/Private/FIRAnalyticsConfiguration.h
new file mode 100644
index 0000000..6429ac7
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIRAnalyticsConfiguration.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+/// Values stored in analyticsEnabledState. Never alter these constants since they must match with
+/// values persisted to disk.
+typedef NS_ENUM(int64_t, FIRAnalyticsEnabledState) {
+ // 0 is the default value for keys not found stored in persisted config, so it cannot represent
+ // kFIRAnalyticsEnabledStateSetNo. It must represent kFIRAnalyticsEnabledStateNotSet.
+ kFIRAnalyticsEnabledStateNotSet = 0,
+ kFIRAnalyticsEnabledStateSetYes = 1,
+ kFIRAnalyticsEnabledStateSetNo = 2,
+};
+
+/// The user defaults key for the persisted measurementEnabledState value. FIRAPersistedConfig reads
+/// measurementEnabledState using this same key.
+static NSString *const kFIRAPersistedConfigMeasurementEnabledStateKey =
+ @"/google/measurement/measurement_enabled_state";
+
+static NSString *const kFIRAnalyticsConfigurationSetEnabledNotification =
+ @"FIRAnalyticsConfigurationSetEnabledNotification";
+static NSString *const kFIRAnalyticsConfigurationSetMinimumSessionIntervalNotification =
+ @"FIRAnalyticsConfigurationSetMinimumSessionIntervalNotification";
+static NSString *const kFIRAnalyticsConfigurationSetSessionTimeoutIntervalNotification =
+ @"FIRAnalyticsConfigurationSetSessionTimeoutIntervalNotification";
+
+@interface FIRAnalyticsConfiguration : NSObject
+
+/// Returns the shared instance of FIRAnalyticsConfiguration.
++ (FIRAnalyticsConfiguration *)sharedInstance;
+
+// Sets whether analytics collection is enabled for this app on this device. This setting is
+// persisted across app sessions. By default it is enabled.
+- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled;
+
+/// Sets whether analytics collection is enabled for this app on this device, and a flag to persist
+/// the value or not. The setting should not be persisted if being set by the global data collection
+/// flag.
+- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled
+ persistSetting:(BOOL)shouldPersist;
+
+@end
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIRAppAssociationRegistration.h b/Pods/FirebaseCore/Firebase/Core/Private/FIRAppAssociationRegistration.h
new file mode 100644
index 0000000..3fc69c6
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIRAppAssociationRegistration.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+// TODO: Remove this once Auth moves over to Core's instance registration system.
+/** @class FIRAppAssociationRegistration
+ @brief Manages object associations as a singleton-dependent: At most one object is
+ registered for any given host/key pair, and the object shall be created on-the-fly when
+ asked for.
+ */
+@interface FIRAppAssociationRegistration : NSObject
+
+/** @fn registeredObjectWithHost:key:creationBlock:
+ @brief Retrieves the registered object with a particular host and key.
+ @param host The host object.
+ @param key The key to specify the registered object on the host.
+ @param creationBlock The block to return the object to be registered if not already.
+ The block is executed immediately before this method returns if it is executed at all.
+ It can also be executed multiple times across different method invocations if previous
+ execution of the block returns @c nil.
+ @return The registered object for the host/key pair, or @c nil if no object is registered
+ and @c creationBlock returns @c nil.
+ @remarks The method is thread-safe but non-reentrant in the sense that attempting to call this
+ method again within the @c creationBlock with the same host/key pair raises an exception.
+ The registered object is retained by the host.
+ */
++ (nullable ObjectType)registeredObjectWithHost:(id)host
+ key:(NSString *)key
+ creationBlock:(ObjectType _Nullable (^)(void))creationBlock;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIRAppInternal.h b/Pods/FirebaseCore/Firebase/Core/Private/FIRAppInternal.h
new file mode 100644
index 0000000..ad1a186
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIRAppInternal.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+#import
+
+@class FIRComponentContainer;
+@protocol FIRLibrary;
+
+/**
+ * The internal interface to FIRApp. This is meant for first-party integrators, who need to receive
+ * FIRApp notifications, log info about the success or failure of their configuration, and access
+ * other internal functionality of FIRApp.
+ *
+ * TODO(b/28296561): Restructure this header.
+ */
+NS_ASSUME_NONNULL_BEGIN
+
+typedef NS_ENUM(NSInteger, FIRConfigType) {
+ FIRConfigTypeCore = 1,
+ FIRConfigTypeSDK = 2,
+};
+
+extern NSString *const kFIRDefaultAppName;
+extern NSString *const kFIRAppReadyToConfigureSDKNotification;
+extern NSString *const kFIRAppDeleteNotification;
+extern NSString *const kFIRAppIsDefaultAppKey;
+extern NSString *const kFIRAppNameKey;
+extern NSString *const kFIRGoogleAppIDKey;
+
+/**
+ * The format string for the User Defaults key used for storing the data collection enabled flag.
+ * This includes formatting to append the Firebase App's name.
+ */
+extern NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat;
+
+/**
+ * The plist key used for storing the data collection enabled flag.
+ */
+extern NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey;
+
+/**
+ * A notification fired containing diagnostic information when SDK errors occur.
+ */
+extern NSString *const kFIRAppDiagnosticsNotification;
+
+/** @var FIRAuthStateDidChangeInternalNotification
+ @brief The name of the @c NSNotificationCenter notification which is posted when the auth state
+ changes (e.g. a new token has been produced, a user logs in or out). The object parameter of
+ the notification is a dictionary possibly containing the key:
+ @c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not
+ contain this key it indicates a sign-out event took place.
+ */
+extern NSString *const FIRAuthStateDidChangeInternalNotification;
+
+/** @var FIRAuthStateDidChangeInternalNotificationTokenKey
+ @brief A key present in the dictionary object parameter of the
+ @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this
+ key will contain the new access token.
+ */
+extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey;
+
+/** @var FIRAuthStateDidChangeInternalNotificationAppKey
+ @brief A key present in the dictionary object parameter of the
+ @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this
+ key will contain the FIRApp associated with the auth instance.
+ */
+extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey;
+
+/** @var FIRAuthStateDidChangeInternalNotificationUIDKey
+ @brief A key present in the dictionary object parameter of the
+ @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this
+ key will contain the new user's UID (or nil if there is no longer a user signed in).
+ */
+extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey;
+
+@interface FIRApp ()
+
+/**
+ * A flag indicating if this is the default app (has the default app name).
+ */
+@property(nonatomic, readonly) BOOL isDefaultApp;
+
+/*
+ * The container of interop SDKs for this app.
+ */
+@property(nonatomic) FIRComponentContainer *container;
+
+/**
+ * Creates an error for failing to configure a subspec service. This method is called by each
+ * FIRApp notification listener.
+ */
++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain
+ errorCode:(FIRErrorCode)code
+ service:(NSString *)service
+ reason:(NSString *)reason;
+/**
+ * Checks if the default app is configured without trying to configure it.
+ */
++ (BOOL)isDefaultAppConfigured;
+
+/**
+ * Registers a given third-party library with the given version number to be reported for
+ * analytics.
+ *
+ * @param name Name of the library.
+ * @param version Version of the library.
+ */
++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version;
+
+/**
+ * Registers a given internal library with the given version number to be reported for
+ * analytics.
+ *
+ * @param library Optional parameter for component registration.
+ * @param name Name of the library.
+ * @param version Version of the library.
+ */
++ (void)registerInternalLibrary:(nonnull Class)library
+ withName:(nonnull NSString *)name
+ withVersion:(nonnull NSString *)version;
+
+/**
+ * A concatenated string representing all the third-party libraries and version numbers.
+ */
++ (NSString *)firebaseUserAgent;
+
+/**
+ * Used by each SDK to send logs about SDK configuration status to Clearcut.
+ *
+ * @note This API is a no-op, please remove calls to it.
+ */
+- (void)sendLogsWithServiceName:(NSString *)serviceName
+ version:(NSString *)version
+ error:(NSError *)error;
+
+/**
+ * Can be used by the unit tests in eack SDK to reset FIRApp. This method is thread unsafe.
+ */
++ (void)resetApps;
+
+/**
+ * Can be used by the unit tests in each SDK to set customized options.
+ */
+- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIRBundleUtil.h b/Pods/FirebaseCore/Firebase/Core/Private/FIRBundleUtil.h
new file mode 100644
index 0000000..d9475dd
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIRBundleUtil.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+/**
+ * This class provides utilities for accessing resources in bundles.
+ */
+@interface FIRBundleUtil : NSObject
+
+/**
+ * Finds all relevant bundles, starting with [NSBundle mainBundle].
+ */
++ (NSArray *)relevantBundles;
+
+/**
+ * Reads the options dictionary from one of the provided bundles.
+ *
+ * @param resourceName The resource name, e.g. @"GoogleService-Info".
+ * @param fileType The file type (extension), e.g. @"plist".
+ * @param bundles The bundles to expect, in priority order. See also
+ * +[FIRBundleUtil relevantBundles].
+ */
++ (NSString *)optionsDictionaryPathWithResourceName:(NSString *)resourceName
+ andFileType:(NSString *)fileType
+ inBundles:(NSArray *)bundles;
+
+/**
+ * Finds URL schemes defined in all relevant bundles, starting with those from
+ * [NSBundle mainBundle].
+ */
++ (NSArray *)relevantURLSchemes;
+
+/**
+ * Checks if any of the given bundles have a matching bundle identifier prefix (removing extension
+ * suffixes).
+ */
++ (BOOL)hasBundleIdentifierPrefix:(NSString *)bundleIdentifier inBundles:(NSArray *)bundles;
+
+@end
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIRComponent.h b/Pods/FirebaseCore/Firebase/Core/Private/FIRComponent.h
new file mode 100644
index 0000000..cb51ee7
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIRComponent.h
@@ -0,0 +1,91 @@
+/*
+ * 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
+
+@class FIRApp;
+@class FIRComponentContainer;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// Provides a system to clean up cached instances returned from the component system.
+NS_SWIFT_NAME(ComponentLifecycleMaintainer)
+@protocol FIRComponentLifecycleMaintainer
+/// The associated app will be deleted, clean up any resources as they are about to be deallocated.
+- (void)appWillBeDeleted:(FIRApp *)app;
+@end
+
+typedef _Nullable id (^FIRComponentCreationBlock)(FIRComponentContainer *container,
+ BOOL *isCacheable)
+ NS_SWIFT_NAME(ComponentCreationBlock);
+
+@class FIRDependency;
+
+/// Describes the timing of instantiation. Note: new components should default to lazy unless there
+/// is a strong reason to be eager.
+typedef NS_ENUM(NSInteger, FIRInstantiationTiming) {
+ FIRInstantiationTimingLazy,
+ FIRInstantiationTimingAlwaysEager,
+ FIRInstantiationTimingEagerInDefaultApp
+} NS_SWIFT_NAME(InstantiationTiming);
+
+/// A component that can be used from other Firebase SDKs.
+NS_SWIFT_NAME(Component)
+@interface FIRComponent : NSObject
+
+/// The protocol describing functionality provided from the Component.
+@property(nonatomic, strong, readonly) Protocol *protocol;
+
+/// The timing of instantiation.
+@property(nonatomic, readonly) FIRInstantiationTiming instantiationTiming;
+
+/// An array of dependencies for the component.
+@property(nonatomic, copy, readonly) NSArray *dependencies;
+
+/// A block to instantiate an instance of the component with the appropriate dependencies.
+@property(nonatomic, copy, readonly) FIRComponentCreationBlock creationBlock;
+
+// There's an issue with long NS_SWIFT_NAMES that causes compilation to fail, disable clang-format
+// for the next two methods.
+// clang-format off
+
+/// Creates a component with no dependencies that will be lazily initialized.
++ (instancetype)componentWithProtocol:(Protocol *)protocol
+ creationBlock:(FIRComponentCreationBlock)creationBlock
+NS_SWIFT_NAME(init(_:creationBlock:));
+
+/// Creates a component to be registered with the component container.
+///
+/// @param protocol - The protocol describing functionality provided by the component.
+/// @param instantiationTiming - When the component should be initialized. Use .lazy unless there's
+/// a good reason to be instantiated earlier.
+/// @param dependencies - Any dependencies the `implementingClass` has, optional or required.
+/// @param creationBlock - A block to instantiate the component with a container, and if
+/// @return A component that can be registered with the component container.
++ (instancetype)componentWithProtocol:(Protocol *)protocol
+ instantiationTiming:(FIRInstantiationTiming)instantiationTiming
+ dependencies:(NSArray *)dependencies
+ creationBlock:(FIRComponentCreationBlock)creationBlock
+NS_SWIFT_NAME(init(_:instantiationTiming:dependencies:creationBlock:));
+
+// clang-format on
+
+/// Unavailable.
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainer.h b/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainer.h
new file mode 100644
index 0000000..f3dc356
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainer.h
@@ -0,0 +1,44 @@
+/*
+ * 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
+
+#import "FIRComponentType.h"
+#import "FIRLibrary.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// A type-safe macro to retrieve a component from a container. This should be used to retrieve
+/// components instead of using the container directly.
+#define FIR_COMPONENT(type, container) \
+ [FIRComponentType> instanceForProtocol:@protocol(type) inContainer:container]
+
+@class FIRApp;
+
+/// A container that holds different components that are registered via the
+/// `registerAsComponentRegistrant:` call. These classes should conform to `FIRComponentRegistrant`
+/// in order to properly register components for Core.
+NS_SWIFT_NAME(FirebaseComponentContainer)
+@interface FIRComponentContainer : NSObject
+
+/// A weak reference to the app that an instance of the container belongs to.
+@property(nonatomic, weak, readonly) FIRApp *app;
+
+/// Unavailable. Use the `container` property on `FIRApp`.
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainerInternal.h b/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainerInternal.h
new file mode 100644
index 0000000..e8552fa
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentContainerInternal.h
@@ -0,0 +1,43 @@
+/*
+ * 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
+
+#import "FIRComponent.h"
+#import "FIRComponentContainer.h"
+
+@class FIRApp;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface FIRComponentContainer (Private)
+
+/// Initializes a contain for a given app. This should only be called by the app itself.
+- (instancetype)initWithApp:(FIRApp *)app;
+
+/// Retrieves an instance that conforms to the specified protocol. This will return `nil` if the
+/// protocol wasn't registered, or if the instance couldn't instantiate for the provided app.
+- (nullable id)instanceForProtocol:(Protocol *)protocol NS_SWIFT_NAME(instance(for:));
+
+/// Remove all of the cached instances stored and allow them to clean up after themselves.
+- (void)removeAllCachedInstances;
+
+/// Register a class to provide components for the interoperability system. The class should conform
+/// to `FIRComponentRegistrant` and provide an array of `FIRComponent` objects.
++ (void)registerAsComponentRegistrant:(Class)klass;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentType.h b/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentType.h
new file mode 100644
index 0000000..6f2aca7
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIRComponentType.h
@@ -0,0 +1,34 @@
+/*
+ * 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
+
+@class FIRComponentContainer;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// Do not use directly. A placeholder type in order to provide a macro that will warn users of
+/// mis-matched protocols.
+NS_SWIFT_NAME(ComponentType)
+@interface FIRComponentType<__covariant T> : NSObject
+
+/// Do not use directly. A factory method to retrieve an instance that provides a specific
+/// functionality.
++ (T)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIRConfigurationInternal.h b/Pods/FirebaseCore/Firebase/Core/Private/FIRConfigurationInternal.h
new file mode 100644
index 0000000..ee16886
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIRConfigurationInternal.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "FIRConfiguration.h"
+
+@class FIRAnalyticsConfiguration;
+
+@interface FIRConfiguration ()
+
+/**
+ * The configuration class for Firebase Analytics. This should be removed once the logic for
+ * enabling and disabling Analytics is moved to Analytics.
+ */
+@property(nonatomic, readwrite) FIRAnalyticsConfiguration *analyticsConfiguration;
+
+@end
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIRCoreDiagnosticsConnector.h b/Pods/FirebaseCore/Firebase/Core/Private/FIRCoreDiagnosticsConnector.h
new file mode 100644
index 0000000..76c0c05
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIRCoreDiagnosticsConnector.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+@class FIRDiagnosticsData;
+@class FIROptions;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** Connects FIRCore with the CoreDiagnostics library. */
+@interface FIRCoreDiagnosticsConnector : NSObject
+
+/** Logs FirebaseCore related data.
+ *
+ * @param options The options object containing data to log.
+ */
++ (void)logCoreTelemetryWithOptions:(FIROptions *)options;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIRDependency.h b/Pods/FirebaseCore/Firebase/Core/Private/FIRDependency.h
new file mode 100644
index 0000000..46e9b7e
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIRDependency.h
@@ -0,0 +1,45 @@
+/*
+ * 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
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// A dependency on a specific protocol's functionality.
+NS_SWIFT_NAME(Dependency)
+@interface FIRDependency : NSObject
+
+/// The protocol describing functionality being depended on.
+@property(nonatomic, strong, readonly) Protocol *protocol;
+
+/// A flag to specify if the dependency is required or not.
+@property(nonatomic, readonly) BOOL isRequired;
+
+/// Initializes a dependency that is required. Calls `initWithProtocol:isRequired` with `YES` for
+/// the required parameter.
+/// Creates a required dependency on the specified protocol's functionality.
++ (instancetype)dependencyWithProtocol:(Protocol *)protocol;
+
+/// Creates a dependency on the specified protocol's functionality and specify if it's required for
+/// the class's functionality.
++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required;
+
+/// Use `dependencyWithProtocol:isRequired:` instead.
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIRDiagnosticsData.h b/Pods/FirebaseCore/Firebase/Core/Private/FIRDiagnosticsData.h
new file mode 100644
index 0000000..ac5ef2c
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIRDiagnosticsData.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** Implements the FIRCoreDiagnosticsData protocol to log diagnostics data. */
+@interface FIRDiagnosticsData : NSObject
+
+/** Inserts values into the diagnosticObjects dictionary if the value isn't nil.
+ *
+ * @param value The value to insert if it's not nil.
+ * @param key The key to associate it with.
+ */
+- (void)insertValue:(nullable id)value forKey:(NSString *)key;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIRErrorCode.h b/Pods/FirebaseCore/Firebase/Core/Private/FIRErrorCode.h
new file mode 100644
index 0000000..f77b3d0
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIRErrorCode.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+/** Error codes in Firebase error domain. */
+typedef NS_ENUM(NSInteger, FIRErrorCode) {
+ /**
+ * Unknown error.
+ */
+ FIRErrorCodeUnknown = 0,
+ /**
+ * Loading data from the GoogleService-Info.plist file failed. This is a fatal error and should
+ * not be ignored. Further calls to the API will fail and/or possibly cause crashes.
+ */
+ FIRErrorCodeInvalidPlistFile = -100,
+
+ /**
+ * Validating the Google App ID format failed.
+ */
+ FIRErrorCodeInvalidAppID = -101,
+
+ /**
+ * Error code for failing to configure a specific service.
+ */
+ FIRErrorCodeConfigFailed = -114,
+};
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIRErrors.h b/Pods/FirebaseCore/Firebase/Core/Private/FIRErrors.h
new file mode 100644
index 0000000..19e4732
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIRErrors.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+#include "FIRErrorCode.h"
+
+extern NSString *const kFirebaseErrorDomain;
+extern NSString *const kFirebaseConfigErrorDomain;
+extern NSString *const kFirebaseCoreErrorDomain;
+extern NSString *const kFirebasePerfErrorDomain;
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIRLibrary.h b/Pods/FirebaseCore/Firebase/Core/Private/FIRLibrary.h
new file mode 100644
index 0000000..728c062
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIRLibrary.h
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#ifndef FIRLibrary_h
+#define FIRLibrary_h
+
+#import
+#import "FIRComponent.h"
+
+@class FIRApp;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// Provide an interface to register a library for userAgent logging and availability to others.
+NS_SWIFT_NAME(Library)
+@protocol FIRLibrary
+
+/// Returns one or more FIRComponents that will be registered in
+/// FIRApp and participate in dependency resolution and injection.
++ (NSArray *)componentsToRegister;
+
+@optional
+/// Implement this method if the library needs notifications for lifecycle events. This method is
+/// called when the developer calls `FirebaseApp.configure()`.
++ (void)configureWithApp:(FIRApp *)app;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif /* FIRLibrary_h */
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIRLogger.h b/Pods/FirebaseCore/Firebase/Core/Private/FIRLogger.h
new file mode 100644
index 0000000..548e389
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIRLogger.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * The Firebase services used in Firebase logger.
+ */
+typedef NSString *const FIRLoggerService;
+
+extern FIRLoggerService kFIRLoggerABTesting;
+extern FIRLoggerService kFIRLoggerAdMob;
+extern FIRLoggerService kFIRLoggerAnalytics;
+extern FIRLoggerService kFIRLoggerAuth;
+extern FIRLoggerService kFIRLoggerCrash;
+extern FIRLoggerService kFIRLoggerCore;
+extern FIRLoggerService kFIRLoggerMLKit;
+extern FIRLoggerService kFIRLoggerPerf;
+extern FIRLoggerService kFIRLoggerRemoteConfig;
+
+/**
+ * The key used to store the logger's error count.
+ */
+extern NSString *const kFIRLoggerErrorCountKey;
+
+/**
+ * The key used to store the logger's warning count.
+ */
+extern NSString *const kFIRLoggerWarningCountKey;
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+ * Enables or disables Analytics debug mode.
+ * If set to YES, the logging level for Analytics will be set to FIRLoggerLevelDebug.
+ * Enabling the debug mode has no effect if the app is running from App Store.
+ * (required) analytics debug mode flag.
+ */
+void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode);
+
+/**
+ * Changes the default logging level of FIRLoggerLevelNotice to a user-specified level.
+ * The default level cannot be set above FIRLoggerLevelNotice if the app is running from App Store.
+ * (required) log level (one of the FIRLoggerLevel enum values).
+ */
+void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel);
+
+/**
+ * Checks if the specified logger level is loggable given the current settings.
+ * (required) log level (one of the FIRLoggerLevel enum values).
+ * (required) whether or not this function is called from the Analytics component.
+ */
+BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent);
+
+/**
+ * Logs a message to the Xcode console and the device log. If running from AppStore, will
+ * not log any messages with a level higher than FIRLoggerLevelNotice to avoid log spamming.
+ * (required) log level (one of the FIRLoggerLevel enum values).
+ * (required) service name of type FIRLoggerService.
+ * (required) message code starting with "I-" which means iOS, followed by a capitalized
+ * three-character service identifier and a six digit integer message ID that is unique
+ * within the service.
+ * An example of the message code is @"I-COR000001".
+ * (required) message string which can be a format string.
+ * (optional) variable arguments list obtained from calling va_start, used when message is a format
+ * string.
+ */
+extern void FIRLogBasic(FIRLoggerLevel level,
+ FIRLoggerService service,
+ NSString *messageCode,
+ NSString *message,
+// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable
+// See: http://stackoverflow.com/q/29095469
+#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX
+ va_list args_ptr
+#else
+ va_list _Nullable args_ptr
+#endif
+);
+
+/**
+ * The following functions accept the following parameters in order:
+ * (required) service name of type FIRLoggerService.
+ * (required) message code starting from "I-" which means iOS, followed by a capitalized
+ * three-character service identifier and a six digit integer message ID that is unique
+ * within the service.
+ * An example of the message code is @"I-COR000001".
+ * See go/firebase-log-proposal for details.
+ * (required) message string which can be a format string.
+ * (optional) the list of arguments to substitute into the format string.
+ * Example usage:
+ * FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name);
+ */
+extern void FIRLogError(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
+ NS_FORMAT_FUNCTION(3, 4);
+extern void FIRLogWarning(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
+ NS_FORMAT_FUNCTION(3, 4);
+extern void FIRLogNotice(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
+ NS_FORMAT_FUNCTION(3, 4);
+extern void FIRLogInfo(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
+ NS_FORMAT_FUNCTION(3, 4);
+extern void FIRLogDebug(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
+ NS_FORMAT_FUNCTION(3, 4);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+@interface FIRLoggerWrapper : NSObject
+
+/**
+ * Objective-C wrapper for FIRLogBasic to allow weak linking to FIRLogger
+ * (required) log level (one of the FIRLoggerLevel enum values).
+ * (required) service name of type FIRLoggerService.
+ * (required) message code starting with "I-" which means iOS, followed by a capitalized
+ * three-character service identifier and a six digit integer message ID that is unique
+ * within the service.
+ * An example of the message code is @"I-COR000001".
+ * (required) message string which can be a format string.
+ * (optional) variable arguments list obtained from calling va_start, used when message is a format
+ * string.
+ */
+
++ (void)logWithLevel:(FIRLoggerLevel)level
+ withService:(FIRLoggerService)service
+ withCode:(NSString *)messageCode
+ withMessage:(NSString *)message
+ withArgs:(va_list)args;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIROptionsInternal.h b/Pods/FirebaseCore/Firebase/Core/Private/FIROptionsInternal.h
new file mode 100644
index 0000000..117efda
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIROptionsInternal.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+/**
+ * Keys for the strings in the plist file.
+ */
+extern NSString *const kFIRAPIKey;
+extern NSString *const kFIRTrackingID;
+extern NSString *const kFIRGoogleAppID;
+extern NSString *const kFIRClientID;
+extern NSString *const kFIRGCMSenderID;
+extern NSString *const kFIRAndroidClientID;
+extern NSString *const kFIRDatabaseURL;
+extern NSString *const kFIRStorageBucket;
+extern NSString *const kFIRBundleID;
+extern NSString *const kFIRProjectID;
+
+/**
+ * Keys for the plist file name
+ */
+extern NSString *const kServiceInfoFileName;
+
+extern NSString *const kServiceInfoFileType;
+
+/**
+ * This header file exposes the initialization of FIROptions to internal use.
+ */
+@interface FIROptions ()
+
+/**
+ * resetDefaultOptions and initInternalWithOptionsDictionary: are exposed only for unit tests.
+ */
++ (void)resetDefaultOptions;
+
+/**
+ * Initializes the options with dictionary. The above strings are the keys of the dictionary.
+ * This is the designated initializer.
+ */
+- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)serviceInfoDictionary;
+
+/**
+ * defaultOptions and defaultOptionsDictionary are exposed in order to be used in FIRApp and
+ * other first party services.
+ */
++ (FIROptions *)defaultOptions;
+
++ (NSDictionary *)defaultOptionsDictionary;
+
+/**
+ * Indicates whether or not Analytics collection was explicitly enabled via a plist flag or at
+ * runtime.
+ */
+@property(nonatomic, readonly) BOOL isAnalyticsCollectionExpicitlySet;
+
+/**
+ * Whether or not Analytics Collection was enabled. Analytics Collection is enabled unless
+ * explicitly disabled in GoogleService-Info.plist.
+ */
+@property(nonatomic, readonly) BOOL isAnalyticsCollectionEnabled;
+
+/**
+ * Whether or not Analytics Collection was completely disabled. If YES, then
+ * isAnalyticsCollectionEnabled will be NO.
+ */
+@property(nonatomic, readonly) BOOL isAnalyticsCollectionDeactivated;
+
+/**
+ * The version ID of the client library, e.g. @"1100000".
+ */
+@property(nonatomic, readonly, copy) NSString *libraryVersionID;
+
+/**
+ * The flag indicating whether this object was constructed with the values in the default plist
+ * file.
+ */
+@property(nonatomic) BOOL usingOptionsFromDefaultPlist;
+
+/**
+ * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in
+ * GoogleService-Info.plist.
+ */
+@property(nonatomic, readonly) BOOL isMeasurementEnabled;
+
+/**
+ * Whether or not Analytics was enabled in the developer console.
+ */
+@property(nonatomic, readonly) BOOL isAnalyticsEnabled;
+
+/**
+ * Whether or not SignIn was enabled in the developer console.
+ */
+@property(nonatomic, readonly) BOOL isSignInEnabled;
+
+/**
+ * Whether or not editing is locked. This should occur after FIROptions has been set on a FIRApp.
+ */
+@property(nonatomic, getter=isEditingLocked) BOOL editingLocked;
+
+@end
diff --git a/Pods/FirebaseCore/Firebase/Core/Private/FIRVersion.h b/Pods/FirebaseCore/Firebase/Core/Private/FIRVersion.h
new file mode 100644
index 0000000..226efb1
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Private/FIRVersion.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+/** The version of the Firebase SDK. */
+FOUNDATION_EXPORT const char *const FIRVersionString;
+
+/** The version of the FirebaseCore Component. */
+FOUNDATION_EXPORT const char *const FIRCoreVersionString;
diff --git a/Pods/FirebaseCore/Firebase/Core/Public/FIRApp.h b/Pods/FirebaseCore/Firebase/Core/Public/FIRApp.h
new file mode 100644
index 0000000..e0dd6d6
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Public/FIRApp.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+@class FIROptions;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** A block that takes a BOOL and has no return value. */
+typedef void (^FIRAppVoidBoolCallback)(BOOL success) NS_SWIFT_NAME(FirebaseAppVoidBoolCallback);
+
+/**
+ * The entry point of Firebase SDKs.
+ *
+ * Initialize and configure FIRApp using +[FIRApp configure]
+ * or other customized ways as shown below.
+ *
+ * The logging system has two modes: default mode and debug mode. In default mode, only logs with
+ * log level Notice, Warning and Error will be sent to device. In debug mode, all logs will be sent
+ * to device. The log levels that Firebase uses are consistent with the ASL log levels.
+ *
+ * Enable debug mode by passing the -FIRDebugEnabled argument to the application. You can add this
+ * argument in the application's Xcode scheme. When debug mode is enabled via -FIRDebugEnabled,
+ * further executions of the application will also be in debug mode. In order to return to default
+ * mode, you must explicitly disable the debug mode with the application argument -FIRDebugDisabled.
+ *
+ * It is also possible to change the default logging level in code by calling setLoggerLevel: on
+ * the FIRConfiguration interface.
+ */
+NS_SWIFT_NAME(FirebaseApp)
+@interface FIRApp : NSObject
+
+/**
+ * Configures a default Firebase app. Raises an exception if any configuration step fails. The
+ * default app is named "__FIRAPP_DEFAULT". This method should be called after the app is launched
+ * and before using Firebase services. This method is thread safe and contains synchronous file I/O
+ * (reading GoogleService-Info.plist from disk).
+ */
++ (void)configure;
+
+/**
+ * Configures the default Firebase app with the provided options. The default app is named
+ * "__FIRAPP_DEFAULT". Raises an exception if any configuration step fails. This method is thread
+ * safe.
+ *
+ * @param options The Firebase application options used to configure the service.
+ */
++ (void)configureWithOptions:(FIROptions *)options NS_SWIFT_NAME(configure(options:));
+
+/**
+ * Configures a Firebase app with the given name and options. Raises an exception if any
+ * configuration step fails. This method is thread safe.
+ *
+ * @param name The application's name given by the developer. The name should should only contain
+ Letters, Numbers and Underscore.
+ * @param options The Firebase application options used to configure the services.
+ */
+// clang-format off
++ (void)configureWithName:(NSString *)name
+ options:(FIROptions *)options NS_SWIFT_NAME(configure(name:options:));
+// clang-format on
+
+/**
+ * Returns the default app, or nil if the default app does not exist.
+ */
++ (nullable FIRApp *)defaultApp NS_SWIFT_NAME(app());
+
+/**
+ * Returns a previously created FIRApp instance with the given name, or nil if no such app exists.
+ * This method is thread safe.
+ */
++ (nullable FIRApp *)appNamed:(NSString *)name NS_SWIFT_NAME(app(name:));
+
+/**
+ * Returns the set of all extant FIRApp instances, or nil if there are no FIRApp instances. This
+ * method is thread safe.
+ */
+@property(class, readonly, nullable) NSDictionary *allApps;
+
+/**
+ * Cleans up the current FIRApp, freeing associated data and returning its name to the pool for
+ * future use. This method is thread safe.
+ */
+- (void)deleteApp:(FIRAppVoidBoolCallback)completion;
+
+/**
+ * FIRApp instances should not be initialized directly. Call +[FIRApp configure],
+ * +[FIRApp configureWithOptions:], or +[FIRApp configureWithNames:options:] directly.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/**
+ * Gets the name of this app.
+ */
+@property(nonatomic, copy, readonly) NSString *name;
+
+/**
+ * Gets a copy of the options for this app. These are non-modifiable.
+ */
+@property(nonatomic, copy, readonly) FIROptions *options;
+
+/**
+ * Gets or sets whether automatic data collection is enabled for all products. Defaults to `YES`
+ * unless `FirebaseDataCollectionDefaultEnabled` is set to `NO` in your app's Info.plist. This value
+ * is persisted across runs of the app so that it can be set once when users have consented to
+ * collection.
+ */
+@property(nonatomic, readwrite, getter=isDataCollectionDefaultEnabled)
+ BOOL dataCollectionDefaultEnabled;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseCore/Firebase/Core/Public/FIRConfiguration.h b/Pods/FirebaseCore/Firebase/Core/Public/FIRConfiguration.h
new file mode 100644
index 0000000..8de3b07
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Public/FIRConfiguration.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * This interface provides global level properties that the developer can tweak.
+ */
+NS_SWIFT_NAME(FirebaseConfiguration)
+@interface FIRConfiguration : NSObject
+
+/** Returns the shared configuration object. */
+@property(class, nonatomic, readonly) FIRConfiguration *sharedInstance NS_SWIFT_NAME(shared);
+
+/**
+ * Sets the logging level for internal Firebase logging. Firebase will only log messages
+ * that are logged at or below loggerLevel. The messages are logged both to the Xcode
+ * console and to the device's log. Note that if an app is running from AppStore, it will
+ * never log above FIRLoggerLevelNotice even if loggerLevel is set to a higher (more verbose)
+ * setting.
+ *
+ * @param loggerLevel The maximum logging level. The default level is set to FIRLoggerLevelNotice.
+ */
+- (void)setLoggerLevel:(FIRLoggerLevel)loggerLevel;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseCore/Firebase/Core/Public/FIRLoggerLevel.h b/Pods/FirebaseCore/Firebase/Core/Public/FIRLoggerLevel.h
new file mode 100644
index 0000000..dca3aa0
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Public/FIRLoggerLevel.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+// Note that importing GULLoggerLevel.h will lead to a non-modular header
+// import error.
+
+/**
+ * The log levels used by internal logging.
+ */
+typedef NS_ENUM(NSInteger, FIRLoggerLevel) {
+ /** Error level, matches ASL_LEVEL_ERR. */
+ FIRLoggerLevelError = 3,
+ /** Warning level, matches ASL_LEVEL_WARNING. */
+ FIRLoggerLevelWarning = 4,
+ /** Notice level, matches ASL_LEVEL_NOTICE. */
+ FIRLoggerLevelNotice = 5,
+ /** Info level, matches ASL_LEVEL_INFO. */
+ FIRLoggerLevelInfo = 6,
+ /** Debug level, matches ASL_LEVEL_DEBUG. */
+ FIRLoggerLevelDebug = 7,
+ /** Minimum log level. */
+ FIRLoggerLevelMin = FIRLoggerLevelError,
+ /** Maximum log level. */
+ FIRLoggerLevelMax = FIRLoggerLevelDebug
+} NS_SWIFT_NAME(FirebaseLoggerLevel);
diff --git a/Pods/FirebaseCore/Firebase/Core/Public/FIROptions.h b/Pods/FirebaseCore/Firebase/Core/Public/FIROptions.h
new file mode 100644
index 0000000..67fbe5b
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Public/FIROptions.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * This class provides constant fields of Google APIs.
+ */
+NS_SWIFT_NAME(FirebaseOptions)
+@interface FIROptions : NSObject
+
+/**
+ * Returns the default options. The first time this is called it synchronously reads
+ * GoogleService-Info.plist from disk.
+ */
++ (nullable FIROptions *)defaultOptions NS_SWIFT_NAME(defaultOptions());
+
+/**
+ * An iOS API key used for authenticating requests from your app, e.g.
+ * @"AIzaSyDdVgKwhZl0sTTTLZ7iTmt1r3N2cJLnaDk", used to identify your app to Google servers.
+ */
+@property(nonatomic, copy, nullable) NSString *APIKey NS_SWIFT_NAME(apiKey);
+
+/**
+ * The bundle ID for the application. Defaults to `[[NSBundle mainBundle] bundleID]` when not set
+ * manually or in a plist.
+ */
+@property(nonatomic, copy) NSString *bundleID;
+
+/**
+ * The OAuth2 client ID for iOS application used to authenticate Google users, for example
+ * @"12345.apps.googleusercontent.com", used for signing in with Google.
+ */
+@property(nonatomic, copy, nullable) NSString *clientID;
+
+/**
+ * The tracking ID for Google Analytics, e.g. @"UA-12345678-1", used to configure Google Analytics.
+ */
+@property(nonatomic, copy, nullable) NSString *trackingID;
+
+/**
+ * The Project Number from the Google Developer's console, for example @"012345678901", used to
+ * configure Google Cloud Messaging.
+ */
+@property(nonatomic, copy) NSString *GCMSenderID NS_SWIFT_NAME(gcmSenderID);
+
+/**
+ * The Project ID from the Firebase console, for example @"abc-xyz-123".
+ */
+@property(nonatomic, copy, nullable) NSString *projectID;
+
+/**
+ * The Android client ID used in Google AppInvite when an iOS app has its Android version, for
+ * example @"12345.apps.googleusercontent.com".
+ */
+@property(nonatomic, copy, nullable) NSString *androidClientID;
+
+/**
+ * The Google App ID that is used to uniquely identify an instance of an app.
+ */
+@property(nonatomic, copy) NSString *googleAppID;
+
+/**
+ * The database root URL, e.g. @"http://abc-xyz-123.firebaseio.com".
+ */
+@property(nonatomic, copy, nullable) NSString *databaseURL;
+
+/**
+ * The URL scheme used to set up Durable Deep Link service.
+ */
+@property(nonatomic, copy, nullable) NSString *deepLinkURLScheme;
+
+/**
+ * The Google Cloud Storage bucket name, e.g. @"abc-xyz-123.storage.firebase.com".
+ */
+@property(nonatomic, copy, nullable) NSString *storageBucket;
+
+/**
+ * The App Group identifier to share data between the application and the application extensions.
+ * The App Group must be configured in the application and on the Apple Developer Portal. Default
+ * value `nil`.
+ */
+@property(nonatomic, copy, nullable) NSString *appGroupID;
+
+/**
+ * Initializes a customized instance of FIROptions from the file at the given plist file path. This
+ * will read the file synchronously from disk.
+ * For example,
+ * NSString *filePath =
+ * [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"];
+ * FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath];
+ * Returns nil if the plist file does not exist or is invalid.
+ */
+- (nullable instancetype)initWithContentsOfFile:(NSString *)plistPath;
+
+/**
+ * Initializes a customized instance of FIROptions with required fields. Use the mutable properties
+ * to modify fields for configuring specific services.
+ */
+// clang-format off
+- (instancetype)initWithGoogleAppID:(NSString *)googleAppID
+ GCMSenderID:(NSString *)GCMSenderID
+ NS_SWIFT_NAME(init(googleAppID:gcmSenderID:));
+// clang-format on
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseCore/Firebase/Core/Public/FirebaseCore.h b/Pods/FirebaseCore/Firebase/Core/Public/FirebaseCore.h
new file mode 100644
index 0000000..95119ae
--- /dev/null
+++ b/Pods/FirebaseCore/Firebase/Core/Public/FirebaseCore.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "FIRApp.h"
+#import "FIRConfiguration.h"
+#import "FIRLoggerLevel.h"
+#import "FIROptions.h"
diff --git a/Pods/FirebaseCore/LICENSE b/Pods/FirebaseCore/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/Pods/FirebaseCore/LICENSE
@@ -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.
diff --git a/Pods/FirebaseCore/README.md b/Pods/FirebaseCore/README.md
new file mode 100644
index 0000000..bf397f0
--- /dev/null
+++ b/Pods/FirebaseCore/README.md
@@ -0,0 +1,223 @@
+# Firebase iOS Open Source Development [](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/).
diff --git a/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m b/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m
new file mode 100644
index 0000000..8f87e09
--- /dev/null
+++ b/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m
@@ -0,0 +1,674 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+#include
+
+#import
+#import
+#import
+#import
+
+#import
+#import
+
+#import
+#import
+
+#import
+#import
+#import
+
+#import "FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h"
+
+#import "FIRCDLibrary/FIRCoreDiagnosticsDateFileStorage.h"
+
+/** The logger service string to use when printing to the console. */
+static GULLoggerService kFIRCoreDiagnostics = @"[FirebaseCoreDiagnostics/FIRCoreDiagnostics]";
+
+#ifdef FIREBASE_BUILD_ZIP_FILE
+static BOOL kUsingZipFile = YES;
+#else // FIREBASE_BUILD_ZIP_FILE
+static BOOL kUsingZipFile = NO;
+#endif // FIREBASE_BUILD_ZIP_FILE
+
+#ifdef FIREBASE_BUILD_CARTHAGE
+#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_CARTHAGE
+#elif FIREBASE_BUILD_ZIP_FILE
+#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ZIP_FILE
+#else
+#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_COCOAPODS
+#endif
+
+static NSString *const kFIRServiceMLVisionOnDeviceAutoML = @"MLVisionOnDeviceAutoML";
+static NSString *const kFIRServiceMLVisionOnDeviceFace = @"MLVisionOnDeviceFace";
+static NSString *const kFIRServiceMLVisionOnDeviceBarcode = @"MLVisionOnDeviceBarcode";
+static NSString *const kFIRServiceMLVisionOnDeviceText = @"MLVisionOnDeviceText";
+static NSString *const kFIRServiceMLVisionOnDeviceLabel = @"MLVisionOnDeviceLabel";
+static NSString *const kFIRServiceMLVisionOnDeviceObjectDetection =
+ @"MLVisionOnDeviceObjectDetection";
+static NSString *const kFIRServiceMLModelInterpreter = @"MLModelInterpreter";
+
+static NSString *const kFIRServiceAdMob = @"AdMob";
+static NSString *const kFIRServiceAuth = @"Auth";
+static NSString *const kFIRServiceAuthUI = @"AuthUI";
+static NSString *const kFIRServiceCrash = @"Crash";
+static NSString *const kFIRServiceDatabase = @"Database";
+static NSString *const kFIRServiceDynamicLinks = @"DynamicLinks";
+static NSString *const kFIRServiceFirestore = @"Firestore";
+static NSString *const kFIRServiceFunctions = @"Functions";
+static NSString *const kFIRServiceIAM = @"InAppMessaging";
+static NSString *const kFIRServiceInstanceID = @"InstanceID";
+static NSString *const kFIRServiceInvites = @"Invites";
+static NSString *const kFIRServiceMessaging = @"Messaging";
+static NSString *const kFIRServiceMeasurement = @"Measurement";
+static NSString *const kFIRServicePerformance = @"Performance";
+static NSString *const kFIRServiceRemoteConfig = @"RemoteConfig";
+static NSString *const kFIRServiceStorage = @"Storage";
+static NSString *const kGGLServiceAnalytics = @"Analytics";
+static NSString *const kGGLServiceSignIn = @"SignIn";
+static NSString *const kFIRAppDiagnosticsConfigurationTypeKey =
+ @"FIRAppDiagnosticsConfigurationTypeKey";
+static NSString *const kFIRAppDiagnosticsFIRAppKey = @"FIRAppDiagnosticsFIRAppKey";
+static NSString *const kFIRAppDiagnosticsSDKNameKey = @"FIRAppDiagnosticsSDKNameKey";
+static NSString *const kFIRAppDiagnosticsSDKVersionKey = @"FIRAppDiagnosticsSDKVersionKey";
+
+/**
+ * The file name to the recent heartbeat date.
+ */
+NSString *const kFIRCoreDiagnosticsHeartbeatDateFileName = @"FIREBASE_DIAGNOSTICS_HEARTBEAT_DATE";
+
+/**
+ * @note This should implement the GDTEventDataObject protocol, but can't because of weak-linking.
+ */
+@interface FIRCoreDiagnosticsLog : NSObject
+
+/** The config that will be converted to proto bytes. */
+@property(nonatomic) logs_proto_mobilesdk_ios_ICoreConfiguration config;
+
+@end
+
+@implementation FIRCoreDiagnosticsLog
+
+- (instancetype)initWithConfig:(logs_proto_mobilesdk_ios_ICoreConfiguration)config {
+ self = [super init];
+ if (self) {
+ _config = config;
+ }
+ return self;
+}
+
+// Provided and required by the GDTEventDataObject protocol.
+- (NSData *)transportBytes {
+ pb_ostream_t sizestream = PB_OSTREAM_SIZING;
+
+ // Encode 1 time to determine the size.
+ if (!pb_encode(&sizestream, logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config)) {
+ GDTLogError(GDTMCETransportBytesError, @"Error in nanopb encoding for size: %s",
+ PB_GET_ERROR(&sizestream));
+ }
+
+ // Encode a 2nd time to actually get the bytes from it.
+ size_t bufferSize = sizestream.bytes_written;
+ CFMutableDataRef dataRef = CFDataCreateMutable(CFAllocatorGetDefault(), bufferSize);
+ pb_ostream_t ostream = pb_ostream_from_buffer((void *)CFDataGetBytePtr(dataRef), bufferSize);
+ if (!pb_encode(&ostream, logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config)) {
+ GDTLogError(GDTMCETransportBytesError, @"Error in nanopb encoding for bytes: %s",
+ PB_GET_ERROR(&ostream));
+ }
+ CFDataSetLength(dataRef, ostream.bytes_written);
+
+ return CFBridgingRelease(dataRef);
+}
+
+- (void)dealloc {
+ pb_release(logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config);
+}
+
+@end
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** This class produces a protobuf containing diagnostics and usage data to be logged. */
+@interface FIRCoreDiagnostics : NSObject
+
+/** The queue on which all diagnostics collection will occur. */
+@property(nonatomic, readonly) dispatch_queue_t diagnosticsQueue;
+
+/** The transport object used to send data. */
+@property(nonatomic, readonly) GDTTransport *transport;
+
+/** The storage to store the date of the last sent heartbeat. */
+@property(nonatomic, readonly) FIRCoreDiagnosticsDateFileStorage *heartbeatDateStorage;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+@implementation FIRCoreDiagnostics
+
++ (instancetype)sharedInstance {
+ static FIRCoreDiagnostics *sharedInstance;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ sharedInstance = [[FIRCoreDiagnostics alloc] init];
+ });
+ return sharedInstance;
+}
+
+- (instancetype)init {
+ GDTTransport *transport = [[GDTTransport alloc] initWithMappingID:@"137"
+ transformers:nil
+ target:kGDTTargetCCT];
+
+ FIRCoreDiagnosticsDateFileStorage *dateStorage = [[FIRCoreDiagnosticsDateFileStorage alloc]
+ initWithFileURL:[[self class] filePathURLWithName:kFIRCoreDiagnosticsHeartbeatDateFileName]];
+
+ return [self initWithTransport:transport heartbeatDateStorage:dateStorage];
+}
+
+/** Initializer for unit tests.
+ *
+ * @param transport A `GDTTransport` instance which that be used to send event.
+ * @param heartbeatDateStorage An instanse of date storage to track heartbeat sending.
+ * @return Returns the initialized `FIRCoreDiagnostics` instance.
+ */
+- (instancetype)initWithTransport:(GDTTransport *)transport
+ heartbeatDateStorage:(FIRCoreDiagnosticsDateFileStorage *)heartbeatDateStorage {
+ self = [super init];
+ if (self) {
+ _diagnosticsQueue =
+ dispatch_queue_create("com.google.FIRCoreDiagnostics", DISPATCH_QUEUE_SERIAL);
+ _transport = transport;
+ _heartbeatDateStorage = heartbeatDateStorage;
+ }
+ return self;
+}
+
+#pragma mark - File path helpers
+
+/** Returns the URL path of the file with name fileName under the Application Support folder for
+ * local logging. Creates the Application Support folder if the folder doesn't exist.
+ *
+ * @return the URL path of the file with the name fileName in Application Support.
+ */
++ (NSURL *)filePathURLWithName:(NSString *)fileName {
+ @synchronized(self) {
+ NSArray *paths =
+ NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
+ NSArray *components = @[ paths.lastObject, @"Google/FIRApp" ];
+ NSString *directoryString = [NSString pathWithComponents:components];
+ NSURL *directoryURL = [NSURL fileURLWithPath:directoryString];
+
+ NSError *error;
+ if (![directoryURL checkResourceIsReachableAndReturnError:&error]) {
+ // If fail creating the Application Support directory, return nil.
+ if (![[NSFileManager defaultManager] createDirectoryAtURL:directoryURL
+ withIntermediateDirectories:YES
+ attributes:nil
+ error:&error]) {
+ GULLogWarning(kFIRCoreDiagnostics, YES, @"I-COR100001",
+ @"Unable to create internal state storage: %@", error);
+ return nil;
+ }
+ }
+ return [directoryURL URLByAppendingPathComponent:fileName];
+ }
+}
+
+#pragma mark - Metadata helpers
+
+/** Returns the model of iOS device. Sample platform strings are @"iPhone7,1" for iPhone 6 Plus,
+ * @"iPhone7,2" for iPhone 6, etc. Refer to the Hardware strings at
+ * https://en.wikipedia.org/wiki/List_of_iOS_devices
+ *
+ * @return The device model as an NSString.
+ */
++ (NSString *)deviceModel {
+ static NSString *deviceModel = nil;
+ if (deviceModel == nil) {
+ struct utsname systemInfo;
+ uname(&systemInfo);
+ deviceModel = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
+ }
+ return deviceModel;
+}
+
+#pragma mark - nanopb helper functions
+
+/** Mallocs a pb_bytes_array and copies the given NSString's bytes into the bytes array.
+ *
+ * @note Memory needs to be free manually, through pb_free or pb_release.
+ * @param string The string to encode as pb_bytes.
+ */
+pb_bytes_array_t *FIREncodeString(NSString *string) {
+ NSData *stringBytes = [string dataUsingEncoding:NSUTF8StringEncoding];
+ return FIREncodeData(stringBytes);
+}
+
+/** Mallocs a pb_bytes_array and copies the given NSData bytes into the bytes array.
+ *
+ * @note Memory needs to be free manually, through pb_free or pb_release.
+ * @param data The data to copy into the new bytes array.
+ */
+pb_bytes_array_t *FIREncodeData(NSData *data) {
+ pb_bytes_array_t *pbBytes = malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(data.length));
+ memcpy(pbBytes->bytes, [data bytes], data.length);
+ pbBytes->size = (pb_size_t)data.length;
+ return pbBytes;
+}
+
+/** Maps a service string to the representative nanopb enum.
+ *
+ * @param serviceString The SDK service string to convert.
+ * @return The representative nanopb enum.
+ */
+logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType FIRMapFromServiceStringToTypeEnum(
+ NSString *serviceString) {
+ static NSDictionary *serviceStringToTypeEnum;
+ if (serviceStringToTypeEnum == nil) {
+ serviceStringToTypeEnum = @{
+ kFIRServiceAdMob : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ADMOB),
+ kFIRServiceMessaging : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MESSAGING),
+ kFIRServiceMeasurement :
+ @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MEASUREMENT),
+ kFIRServiceRemoteConfig :
+ @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_REMOTE_CONFIG),
+ kFIRServiceDatabase : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DATABASE),
+ kFIRServiceDynamicLinks :
+ @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DYNAMIC_LINKS),
+ kFIRServiceAuth : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH),
+ kFIRServiceAuthUI : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH_UI),
+ kFIRServiceFirestore : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FIRESTORE),
+ kFIRServiceFunctions : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FUNCTIONS),
+ kFIRServicePerformance :
+ @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_PERFORMANCE),
+ kFIRServiceStorage : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_STORAGE),
+ kFIRServiceMLVisionOnDeviceAutoML :
+ @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_AUTOML),
+ kFIRServiceMLVisionOnDeviceFace :
+ @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_FACE),
+ kFIRServiceMLVisionOnDeviceBarcode :
+ @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_BARCODE),
+ kFIRServiceMLVisionOnDeviceText :
+ @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_TEXT),
+ kFIRServiceMLVisionOnDeviceLabel :
+ @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_LABEL),
+ kFIRServiceMLVisionOnDeviceObjectDetection : @(
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION),
+ kFIRServiceMLModelInterpreter :
+ @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_MODEL_INTERPRETER),
+ kGGLServiceAnalytics : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ANALYTICS),
+ kGGLServiceSignIn : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SIGN_IN),
+ kFIRServiceIAM : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_IN_APP_MESSAGING),
+ };
+ }
+ if (serviceStringToTypeEnum[serviceString] != nil) {
+ return (int32_t)serviceStringToTypeEnum[serviceString].longLongValue;
+ }
+ return logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE;
+}
+
+#pragma mark - Proto population functions
+
+/** Populates the given proto with data related to an SDK logDiagnostics call from the
+ * diagnosticObjects dictionary.
+ *
+ * @param config The proto to populate
+ * @param diagnosticObjects The dictionary of diagnostics objects.
+ */
+void FIRPopulateProtoWithInfoFromUserInfoParams(logs_proto_mobilesdk_ios_ICoreConfiguration *config,
+ NSDictionary *diagnosticObjects) {
+ NSNumber *configurationType = diagnosticObjects[kFIRCDConfigurationTypeKey];
+ if (configurationType != nil) {
+ switch (configurationType.integerValue) {
+ case logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE:
+ config->configuration_type =
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE;
+ config->has_configuration_type = 1;
+ break;
+ case logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK:
+ config->configuration_type =
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK;
+ config->has_configuration_type = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ NSString *sdkName = diagnosticObjects[kFIRCDSdkNameKey];
+ if (sdkName) {
+ config->sdk_name = FIRMapFromServiceStringToTypeEnum(sdkName);
+ config->has_sdk_name = 1;
+ }
+
+ NSString *version = diagnosticObjects[kFIRCDSdkVersionKey];
+ if (version) {
+ config->sdk_version = FIREncodeString(version);
+ }
+}
+
+/** Populates the given proto with data from the calling FIRApp using the given
+ * diagnosticObjects dictionary.
+ *
+ * @param config The proto to populate
+ * @param diagnosticObjects The dictionary of diagnostics objects.
+ */
+void FIRPopulateProtoWithCommonInfoFromApp(logs_proto_mobilesdk_ios_ICoreConfiguration *config,
+ NSDictionary *diagnosticObjects) {
+ config->pod_name = logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE;
+ config->has_pod_name = 1;
+
+ if (!diagnosticObjects[kFIRCDllAppsCountKey]) {
+ GDTLogError(GDTMCEGeneralError, @"%@", @"App count is a required value in the data dict.");
+ }
+ config->app_count = (int32_t)[diagnosticObjects[kFIRCDllAppsCountKey] integerValue];
+ config->has_app_count = 1;
+
+ NSString *googleAppID = diagnosticObjects[kFIRCDGoogleAppIDKey];
+ if (googleAppID.length) {
+ config->app_id = FIREncodeString(googleAppID);
+ }
+
+ NSString *bundleID = diagnosticObjects[kFIRCDBundleIDKey];
+ if (bundleID.length) {
+ config->bundle_id = FIREncodeString(bundleID);
+ }
+
+ NSString *firebaseUserAgent = diagnosticObjects[kFIRCDFirebaseUserAgentKey];
+ if (firebaseUserAgent.length) {
+ config->platform_info = FIREncodeString(firebaseUserAgent);
+ }
+
+ NSNumber *usingOptionsFromDefaultPlist = diagnosticObjects[kFIRCDUsingOptionsFromDefaultPlistKey];
+ if (usingOptionsFromDefaultPlist != nil) {
+ config->use_default_app = [usingOptionsFromDefaultPlist boolValue];
+ config->has_use_default_app = 1;
+ }
+
+ NSString *libraryVersionID = diagnosticObjects[kFIRCDLibraryVersionIDKey];
+ if (libraryVersionID) {
+ config->icore_version = FIREncodeString(libraryVersionID);
+ }
+
+ NSString *deviceModel = [FIRCoreDiagnostics deviceModel];
+ if (deviceModel.length) {
+ config->device_model = FIREncodeString(deviceModel);
+ }
+
+ NSString *osVersion = [GULAppEnvironmentUtil systemVersion];
+ if (osVersion.length) {
+ config->os_version = FIREncodeString(osVersion);
+ }
+
+ config->using_zip_file = kUsingZipFile;
+ config->has_using_zip_file = 1;
+ config->deployment_type = kDeploymentType;
+ config->has_deployment_type = 1;
+ config->deployed_in_app_store = [GULAppEnvironmentUtil isFromAppStore];
+ config->has_deployed_in_app_store = 1;
+}
+
+/** Populates the given proto with installed services data.
+ *
+ * @param config The proto to populate
+ */
+void FIRPopulateProtoWithInstalledServices(logs_proto_mobilesdk_ios_ICoreConfiguration *config) {
+ NSMutableArray *sdkServiceInstalledArray = [NSMutableArray array];
+
+ // AdMob
+ if (NSClassFromString(@"GADBannerView") != nil) {
+ [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAdMob))];
+ }
+ // CloudMessaging
+ if (NSClassFromString(@"FIRMessaging") != nil) {
+ [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMessaging))];
+ }
+ // RemoteConfig
+ if (NSClassFromString(@"FIRRemoteConfig") != nil) {
+ [sdkServiceInstalledArray
+ addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceRemoteConfig))];
+ }
+ // Measurement/Analtyics
+ if (NSClassFromString(@"FIRAnalytics") != nil) {
+ [sdkServiceInstalledArray
+ addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMeasurement))];
+ }
+ // ML Vision On Device AutoML.
+ if (NSClassFromString(@"FIRVisionOnDeviceAutoMLImageLabelerOptions") != nil) {
+ [sdkServiceInstalledArray
+ addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceAutoML))];
+ }
+ // ML Vision On Device Face.
+ if (NSClassFromString(@"FIRVisionFaceDetector") != nil &&
+ NSClassFromString(@"GMVFaceDetector") != nil) {
+ [sdkServiceInstalledArray
+ addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceFace))];
+ }
+ // ML Vision On Device Barcode.
+ if (NSClassFromString(@"FIRVisionBarcodeDetector") != nil &&
+ NSClassFromString(@"GMVBarcodeDetector") != nil) {
+ [sdkServiceInstalledArray
+ addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceBarcode))];
+ }
+ // ML Vision On Device Text.
+ if (NSClassFromString(@"FIRVisionTextDetector") != nil &&
+ NSClassFromString(@"GMVTextDetector") != nil) {
+ [sdkServiceInstalledArray
+ addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceText))];
+ }
+ // ML Vision On Device Image Label.
+ if (NSClassFromString(@"FIRVisionLabelDetector") != nil &&
+ NSClassFromString(@"GMVLabelDetector") != nil) {
+ [sdkServiceInstalledArray
+ addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceLabel))];
+ }
+ // ML Vision On Device Object.
+ if (NSClassFromString(@"FIRVisionObjectDetector") != nil) {
+ [sdkServiceInstalledArray
+ addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceObjectDetection))];
+ }
+ // ML Model Interpreter
+ if (NSClassFromString(@"FIRCustomModelInterpreter") != nil) {
+ [sdkServiceInstalledArray
+ addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLModelInterpreter))];
+ }
+ // Database
+ if (NSClassFromString(@"FIRDatabase") != nil) {
+ [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceDatabase))];
+ }
+ // DynamicDeepLink
+ if (NSClassFromString(@"FIRDynamicLinks") != nil) {
+ [sdkServiceInstalledArray
+ addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceDynamicLinks))];
+ }
+ // Auth
+ if (NSClassFromString(@"FIRAuth") != nil) {
+ [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAuth))];
+ }
+ // AuthUI
+ if (NSClassFromString(@"FUIAuth") != nil) {
+ [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAuthUI))];
+ }
+ // Firestore
+ if (NSClassFromString(@"FIRFirestore") != nil) {
+ [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceFirestore))];
+ }
+ // Functions
+ if (NSClassFromString(@"FIRFunctions") != nil) {
+ [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceFunctions))];
+ }
+ // Performance
+ if (NSClassFromString(@"FIRPerformance") != nil) {
+ [sdkServiceInstalledArray
+ addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServicePerformance))];
+ }
+ // Storage
+ if (NSClassFromString(@"FIRStorage") != nil) {
+ [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceStorage))];
+ }
+ // SignIn via Google pod
+ if (NSClassFromString(@"GIDSignIn") != nil && NSClassFromString(@"GGLContext") != nil) {
+ [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kGGLServiceSignIn))];
+ }
+ // Analytics via Google pod
+ if (NSClassFromString(@"GAI") != nil && NSClassFromString(@"GGLContext") != nil) {
+ [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kGGLServiceAnalytics))];
+ }
+
+ // In-App Messaging
+ if (NSClassFromString(@"FIRInAppMessaging") != nil) {
+ [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceIAM))];
+ }
+
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType *servicesInstalled =
+ malloc(sizeof(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType) *
+ sdkServiceInstalledArray.count);
+ for (NSUInteger i = 0; i < sdkServiceInstalledArray.count; i++) {
+ NSNumber *typeEnum = sdkServiceInstalledArray[i];
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType serviceType =
+ (int32_t)typeEnum.integerValue;
+ servicesInstalled[i] = serviceType;
+ }
+
+ config->sdk_service_installed = servicesInstalled;
+ config->sdk_service_installed_count = (int32_t)sdkServiceInstalledArray.count;
+}
+
+/** Populates the proto with the number of linked frameworks.
+ *
+ * @param config The proto to populate.
+ */
+void FIRPopulateProtoWithNumberOfLinkedFrameworks(
+ logs_proto_mobilesdk_ios_ICoreConfiguration *config) {
+ int numFrameworks = -1; // Subtract the app binary itself.
+ unsigned int numImages;
+ const char **imageNames = objc_copyImageNames(&numImages);
+ for (unsigned int i = 0; i < numImages; i++) {
+ NSString *imageName = [NSString stringWithUTF8String:imageNames[i]];
+ if ([imageName rangeOfString:@"System/Library"].length != 0 // Apple .frameworks
+ || [imageName rangeOfString:@"Developer/Library"].length != 0 // Xcode debug .frameworks
+ || [imageName rangeOfString:@"usr/lib"].length != 0) { // Public .dylibs
+ continue;
+ }
+ numFrameworks++;
+ }
+ free(imageNames);
+ config->dynamic_framework_count = numFrameworks;
+ config->has_dynamic_framework_count = 1;
+}
+
+/** Populates the proto with Info.plist values.
+ *
+ * @param config The proto to populate.
+ */
+void FIRPopulateProtoWithInfoPlistValues(logs_proto_mobilesdk_ios_ICoreConfiguration *config) {
+ NSDictionary *info = [[NSBundle mainBundle] infoDictionary];
+
+ NSString *xcodeVersion = info[@"DTXcodeBuild"] ?: @"";
+ NSString *sdkVersion = info[@"DTSDKBuild"] ?: @"";
+ NSString *combinedVersions = [NSString stringWithFormat:@"%@-%@", xcodeVersion, sdkVersion];
+ config->apple_framework_version = FIREncodeString(combinedVersions);
+
+ NSString *minVersion = info[@"MinimumOSVersion"];
+ if (minVersion) {
+ config->min_supported_ios_version = FIREncodeString(minVersion);
+ }
+
+ // Apps can turn off swizzling in the Info.plist, check if they've explicitly set the value and
+ // report it. It's enabled by default.
+ NSNumber *appDelegateSwizzledNum = info[@"FirebaseAppDelegateProxyEnabled"];
+ BOOL appDelegateSwizzled = YES;
+ if ([appDelegateSwizzledNum isKindOfClass:[NSNumber class]]) {
+ appDelegateSwizzled = [appDelegateSwizzledNum boolValue];
+ }
+ config->swizzling_enabled = appDelegateSwizzled;
+ config->has_swizzling_enabled = 1;
+}
+
+#pragma mark - FIRCoreDiagnosticsInterop
+
++ (void)sendDiagnosticsData:(nonnull id)diagnosticsData {
+ FIRCoreDiagnostics *diagnostics = [FIRCoreDiagnostics sharedInstance];
+ [diagnostics sendDiagnosticsData:diagnosticsData];
+}
+
+- (void)sendDiagnosticsData:(nonnull id)diagnosticsData {
+ dispatch_async(self.diagnosticsQueue, ^{
+ NSDictionary *diagnosticObjects = diagnosticsData.diagnosticObjects;
+ NSNumber *isDataCollectionDefaultEnabled =
+ diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey];
+ if (isDataCollectionDefaultEnabled && ![isDataCollectionDefaultEnabled boolValue]) {
+ return;
+ }
+
+ // Create the proto.
+ logs_proto_mobilesdk_ios_ICoreConfiguration icore_config =
+ logs_proto_mobilesdk_ios_ICoreConfiguration_init_default;
+
+ icore_config.using_gdt = 1;
+ icore_config.has_using_gdt = 1;
+
+ // Populate the proto with information.
+ FIRPopulateProtoWithInfoFromUserInfoParams(&icore_config, diagnosticObjects);
+ FIRPopulateProtoWithCommonInfoFromApp(&icore_config, diagnosticObjects);
+ FIRPopulateProtoWithInstalledServices(&icore_config);
+ FIRPopulateProtoWithNumberOfLinkedFrameworks(&icore_config);
+ FIRPopulateProtoWithInfoPlistValues(&icore_config);
+ [self setHeartbeatFlagIfNeededToConfig:&icore_config];
+
+ // This log object is capable of converting the proto to bytes.
+ FIRCoreDiagnosticsLog *log = [[FIRCoreDiagnosticsLog alloc] initWithConfig:icore_config];
+
+ // Send the log as a telemetry event.
+ GDTEvent *event = [self.transport eventForTransport];
+ event.dataObject = (id)log;
+ [self.transport sendTelemetryEvent:event];
+ });
+}
+
+#pragma mark - Heartbeat
+
+- (void)setHeartbeatFlagIfNeededToConfig:(logs_proto_mobilesdk_ios_ICoreConfiguration *)config {
+ // Check if need to send a heartbeat.
+ NSDate *currentDate = [NSDate date];
+ NSDate *lastCheckin = [self.heartbeatDateStorage date];
+ if (lastCheckin) {
+ // Ensure the previous checkin was on a different date in the past.
+ if ([self isDate:currentDate inSameDayOrBeforeThan:lastCheckin]) {
+ return;
+ }
+ }
+
+ // Update heartbeat sent date.
+ NSError *error;
+ if (![self.heartbeatDateStorage setDate:currentDate error:&error]) {
+ GULLogError(kFIRCoreDiagnostics, NO, @"I-COR100004", @"Unable to persist internal state: %@",
+ error);
+ }
+
+ // Set the flag.
+ config->sdk_name = logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ICORE;
+ config->has_sdk_name = 1;
+}
+
+- (BOOL)isDate:(NSDate *)date1 inSameDayOrBeforeThan:(NSDate *)date2 {
+ return [[NSCalendar currentCalendar] isDate:date1 inSameDayAsDate:date2] ||
+ [date1 compare:date2] == NSOrderedAscending;
+}
+
+@end
diff --git a/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnosticsDateFileStorage.h b/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnosticsDateFileStorage.h
new file mode 100644
index 0000000..93e406a
--- /dev/null
+++ b/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnosticsDateFileStorage.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// Stores a date to a specified file.
+@interface FIRCoreDiagnosticsDateFileStorage : NSObject
+
+- (instancetype)init NS_UNAVAILABLE;
+
+/**
+ * Default initializer.
+ * @param fileURL The URL of the file to store the date. The directory must exist, the file may not
+ * exist, it will be created if needed.
+ */
+- (instancetype)initWithFileURL:(NSURL *)fileURL;
+
+/**
+ * Saves the date to the specified file.
+ * @return YES on success, NO otherwise.
+ */
+- (BOOL)setDate:(nullable NSDate *)date error:(NSError **)outError;
+
+/**
+ * Reads the date to the specified file.
+ * @return Returns date if exists, otherwise `nil`.
+ */
+- (nullable NSDate *)date;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnosticsDateFileStorage.m b/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnosticsDateFileStorage.m
new file mode 100644
index 0000000..f4dca12
--- /dev/null
+++ b/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnosticsDateFileStorage.m
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "FIRCDLibrary/FIRCoreDiagnosticsDateFileStorage.h"
+
+@interface FIRCoreDiagnosticsDateFileStorage ()
+@property(nonatomic, readonly) NSURL *fileURL;
+@end
+
+@implementation FIRCoreDiagnosticsDateFileStorage
+
+- (instancetype)initWithFileURL:(NSURL *)fileURL {
+ if (fileURL == nil) {
+ return nil;
+ }
+
+ self = [super init];
+ if (self) {
+ _fileURL = fileURL;
+ }
+
+ return self;
+}
+
+- (BOOL)setDate:(nullable NSDate *)date error:(NSError **)outError {
+ NSString *stringToSave = @"";
+
+ if (date != nil) {
+ NSTimeInterval timestamp = [date timeIntervalSinceReferenceDate];
+ stringToSave = [NSString stringWithFormat:@"%f", timestamp];
+ }
+
+ return [stringToSave writeToURL:self.fileURL
+ atomically:YES
+ encoding:NSUTF8StringEncoding
+ error:outError];
+}
+
+- (nullable NSDate *)date {
+ NSString *timestampString = [NSString stringWithContentsOfURL:self.fileURL
+ encoding:NSUTF8StringEncoding
+ error:nil];
+ if (timestampString.length == 0) {
+ return nil;
+ }
+
+ NSTimeInterval timestamp = timestampString.doubleValue;
+ return [NSDate dateWithTimeIntervalSinceReferenceDate:timestamp];
+}
+
+@end
diff --git a/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.c b/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.c
new file mode 100644
index 0000000..3c35ffb
--- /dev/null
+++ b/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Automatically generated nanopb constant definitions */
+/* Generated by nanopb-0.3.9.2 */
+
+#include "firebasecore.nanopb.h"
+
+/* @@protoc_insertion_point(includes) */
+#if PB_PROTO_HEADER_VERSION != 30
+#error Regenerate this file with the current version of nanopb generator.
+#endif
+
+
+
+const pb_field_t logs_proto_mobilesdk_ios_ICoreConfiguration_fields[34] = {
+ PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, logs_proto_mobilesdk_ios_ICoreConfiguration, configuration_type, configuration_type, 0),
+ PB_FIELD( 2, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, version_name, configuration_type, 0),
+ PB_FIELD( 3, INT64 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, build_number, version_name, 0),
+ PB_FIELD( 4, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, build_type, build_number, 0),
+ PB_FIELD( 5, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, plist_version, build_type, 0),
+ PB_FIELD( 6, UENUM , REPEATED, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_service_enabled, plist_version, 0),
+ PB_FIELD( 7, UENUM , REPEATED, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_service_installed, sdk_service_enabled, 0),
+ PB_FIELD( 9, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, device_model, sdk_service_installed, 0),
+ PB_FIELD( 10, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, app_id, device_model, 0),
+ PB_FIELD( 11, INT64 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, project_number, app_id, 0),
+ PB_FIELD( 12, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, bundle_id, project_number, 0),
+ PB_FIELD( 13, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, client_id, bundle_id, 0),
+ PB_FIELD( 14, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, install, client_id, 0),
+ PB_FIELD( 16, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, pod_name, install, 0),
+ PB_FIELD( 18, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, icore_version, pod_name, 0),
+ PB_FIELD( 19, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_version, icore_version, 0),
+ PB_FIELD( 20, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_name, sdk_version, 0),
+ PB_FIELD( 21, INT32 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, app_count, sdk_name, 0),
+ PB_FIELD( 22, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, os_version, app_count, 0),
+ PB_FIELD( 23, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, itunes_id, os_version, 0),
+ PB_FIELD( 24, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, min_supported_ios_version, itunes_id, 0),
+ PB_FIELD( 25, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, use_default_app, min_supported_ios_version, 0),
+ PB_FIELD( 26, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, deployed_in_app_store, use_default_app, 0),
+ PB_FIELD( 27, INT32 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, dynamic_framework_count, deployed_in_app_store, 0),
+ PB_FIELD( 28, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, apple_framework_version, dynamic_framework_count, 0),
+ PB_FIELD( 29, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, using_zip_file, apple_framework_version, 0),
+ PB_FIELD( 30, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, deployment_type, using_zip_file, 0),
+ PB_FIELD( 31, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, platform_info, deployment_type, 0),
+ PB_FIELD( 32, INT64 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, app_extensions, platform_info, 0),
+ PB_FIELD( 33, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, swizzling_enabled, app_extensions, 0),
+ PB_FIELD( 34, INT32 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, log_error_count, swizzling_enabled, 0),
+ PB_FIELD( 35, INT32 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, log_warning_count, log_error_count, 0),
+ PB_FIELD( 36, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, using_gdt, log_warning_count, 0),
+ PB_LAST_FIELD
+};
+
+
+
+
+
+
+
+/* @@protoc_insertion_point(eof) */
diff --git a/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h b/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h
new file mode 100644
index 0000000..41059e5
--- /dev/null
+++ b/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Automatically generated nanopb header */
+/* Generated by nanopb-0.3.9.2 */
+
+#ifndef PB_LOGS_PROTO_MOBILESDK_IOS_FIREBASECORE_NANOPB_H_INCLUDED
+#define PB_LOGS_PROTO_MOBILESDK_IOS_FIREBASECORE_NANOPB_H_INCLUDED
+#include
+
+/* @@protoc_insertion_point(includes) */
+#if PB_PROTO_HEADER_VERSION != 30
+#error Regenerate this file with the current version of nanopb generator.
+#endif
+
+
+/* Enum definitions */
+typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType {
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_UNKNOWN_CONFIGURATION_TYPE = 0,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE = 1,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK = 2
+} logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType;
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_UNKNOWN_CONFIGURATION_TYPE
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType)(logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK+1))
+
+typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType {
+ logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_UNKNOWN_BUILD_TYPE = 0,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_INTERNAL = 1,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_EAP = 2,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD = 3
+} logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType;
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_UNKNOWN_BUILD_TYPE
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType)(logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD+1))
+
+typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType {
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE = 0,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ICORE = 1,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ADMOB = 2,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_APP_INVITE = 3,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SIGN_IN = 5,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_GCM = 6,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MAPS = 7,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SCION = 8,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ANALYTICS = 9,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_APP_INDEXING = 10,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_CONFIG = 11,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DURABLE_DEEP_LINKS = 12,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_CRASH = 13,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH = 14,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DATABASE = 15,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_STORAGE = 16,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MESSAGING = 17,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MEASUREMENT = 18,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_REMOTE_CONFIG = 19,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DYNAMIC_LINKS = 20,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_INVITES = 21,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH_UI = 22,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FIRESTORE = 23,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_PERFORMANCE = 24,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_FACE = 26,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_BARCODE = 27,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_TEXT = 28,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_LABEL = 29,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_MODEL_INTERPRETER = 30,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_IN_APP_MESSAGING = 31,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FUNCTIONS = 32,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_NATURAL_LANGUAGE = 33,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_AUTOML = 34,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION = 35
+} logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType;
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType)(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION+1))
+
+typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName {
+ logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_UNKNOWN_POD_NAME = 0,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_GOOGLE = 1,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE = 2
+} logs_proto_mobilesdk_ios_ICoreConfiguration_PodName;
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_UNKNOWN_POD_NAME
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_PodName)(logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE+1))
+
+typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType {
+ logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_UNKNOWN = 0,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_COCOAPODS = 1,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ZIP_FILE = 2,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_CARTHAGE = 3,
+ logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM = 4
+} logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType;
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_UNKNOWN
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType)(logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM+1))
+
+/* Struct definitions */
+typedef struct _logs_proto_mobilesdk_ios_ICoreConfiguration {
+ bool has_configuration_type;
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType configuration_type;
+ pb_bytes_array_t *version_name;
+ bool has_build_number;
+ int64_t build_number;
+ bool has_build_type;
+ logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType build_type;
+ pb_bytes_array_t *plist_version;
+ pb_size_t sdk_service_enabled_count;
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType *sdk_service_enabled;
+ pb_size_t sdk_service_installed_count;
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType *sdk_service_installed;
+ pb_bytes_array_t *device_model;
+ pb_bytes_array_t *app_id;
+ bool has_project_number;
+ int64_t project_number;
+ pb_bytes_array_t *bundle_id;
+ pb_bytes_array_t *client_id;
+ pb_bytes_array_t *install;
+ bool has_pod_name;
+ logs_proto_mobilesdk_ios_ICoreConfiguration_PodName pod_name;
+ pb_bytes_array_t *icore_version;
+ pb_bytes_array_t *sdk_version;
+ bool has_sdk_name;
+ logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType sdk_name;
+ bool has_app_count;
+ int32_t app_count;
+ pb_bytes_array_t *os_version;
+ pb_bytes_array_t *itunes_id;
+ pb_bytes_array_t *min_supported_ios_version;
+ bool has_use_default_app;
+ bool use_default_app;
+ bool has_deployed_in_app_store;
+ bool deployed_in_app_store;
+ bool has_dynamic_framework_count;
+ int32_t dynamic_framework_count;
+ pb_bytes_array_t *apple_framework_version;
+ bool has_using_zip_file;
+ bool using_zip_file;
+ bool has_deployment_type;
+ logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType deployment_type;
+ pb_bytes_array_t *platform_info;
+ bool has_app_extensions;
+ int64_t app_extensions;
+ bool has_swizzling_enabled;
+ bool swizzling_enabled;
+ bool has_log_error_count;
+ int32_t log_error_count;
+ bool has_log_warning_count;
+ int32_t log_warning_count;
+ bool has_using_gdt;
+ bool using_gdt;
+/* @@protoc_insertion_point(struct:logs_proto_mobilesdk_ios_ICoreConfiguration) */
+} logs_proto_mobilesdk_ios_ICoreConfiguration;
+
+/* Default values for struct fields */
+
+/* Initializer values for message structs */
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_init_default {false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_MIN, NULL, 0, NULL, 0, NULL, NULL, NULL, false, 0, NULL, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN, false, 0, NULL, NULL, NULL, false, 0, false, 0, false, 0, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN, NULL, false, 0, false, 0, false, 0, false, 0, false, 0}
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_init_zero {false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_MIN, NULL, 0, NULL, 0, NULL, NULL, NULL, false, 0, NULL, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN, false, 0, NULL, NULL, NULL, false, 0, false, 0, false, 0, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN, NULL, false, 0, false, 0, false, 0, false, 0, false, 0}
+
+/* Field tags (for use in manual encoding/decoding) */
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_pod_name_tag 16
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_configuration_type_tag 1
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_version_name_tag 2
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_icore_version_tag 18
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_version_tag 19
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_build_number_tag 3
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_build_type_tag 4
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_plist_version_tag 5
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_service_enabled_tag 6
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_service_installed_tag 7
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_name_tag 20
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_device_model_tag 9
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_os_version_tag 22
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_app_id_tag 10
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_project_number_tag 11
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_bundle_id_tag 12
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_client_id_tag 13
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_itunes_id_tag 23
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_min_supported_ios_version_tag 24
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_install_tag 14
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_use_default_app_tag 25
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_app_count_tag 21
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_deployed_in_app_store_tag 26
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_dynamic_framework_count_tag 27
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_apple_framework_version_tag 28
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_using_zip_file_tag 29
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_deployment_type_tag 30
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_platform_info_tag 31
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_app_extensions_tag 32
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_swizzling_enabled_tag 33
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_log_error_count_tag 34
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_log_warning_count_tag 35
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_using_gdt_tag 36
+
+/* Struct field encoding specification for nanopb */
+extern const pb_field_t logs_proto_mobilesdk_ios_ICoreConfiguration_fields[34];
+
+/* Maximum encoded size of messages (where known) */
+/* logs_proto_mobilesdk_ios_ICoreConfiguration_size depends on runtime parameters */
+
+/* Message IDs (where set with "msgid" option) */
+#ifdef PB_MSGID
+
+#define FIREBASECORE_MESSAGES \
+
+
+#endif
+
+/* @@protoc_insertion_point(eof) */
+
+#endif
diff --git a/Pods/FirebaseCoreDiagnostics/LICENSE b/Pods/FirebaseCoreDiagnostics/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/Pods/FirebaseCoreDiagnostics/LICENSE
@@ -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.
diff --git a/Pods/FirebaseCoreDiagnostics/README.md b/Pods/FirebaseCoreDiagnostics/README.md
new file mode 100644
index 0000000..bf397f0
--- /dev/null
+++ b/Pods/FirebaseCoreDiagnostics/README.md
@@ -0,0 +1,223 @@
+# Firebase iOS Open Source Development [](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/).
diff --git a/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h b/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h
new file mode 100644
index 0000000..7c74776
--- /dev/null
+++ b/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** If present, is a BOOL wrapped in an NSNumber. */
+static NSString *const kFIRCDIsDataCollectionDefaultEnabledKey =
+ @"FIRCDIsDataCollectionDefaultEnabledKey";
+
+/** If present, is an int32_t wrapped in an NSNumber. */
+static NSString *const kFIRCDConfigurationTypeKey = @"FIRCDConfigurationTypeKey";
+
+/** If present, is an NSString. */
+static NSString *const kFIRCDSdkNameKey = @"FIRCDSdkNameKey";
+
+/** If present, is an NSString. */
+static NSString *const kFIRCDSdkVersionKey = @"FIRCDSdkVersionKey";
+
+/** If present, is an int32_t wrapped in an NSNumber. */
+static NSString *const kFIRCDllAppsCountKey = @"FIRCDllAppsCountKey";
+
+/** If present, is an NSString. */
+static NSString *const kFIRCDGoogleAppIDKey = @"FIRCDGoogleAppIDKey";
+
+/** If present, is an NSString. */
+static NSString *const kFIRCDBundleIDKey = @"FIRCDBundleID";
+
+/** If present, is a BOOL wrapped in an NSNumber. */
+static NSString *const kFIRCDUsingOptionsFromDefaultPlistKey =
+ @"FIRCDUsingOptionsFromDefaultPlistKey";
+
+/** If present, is an NSString. */
+static NSString *const kFIRCDLibraryVersionIDKey = @"FIRCDLibraryVersionIDKey";
+
+/** If present, is an NSString. */
+static NSString *const kFIRCDFirebaseUserAgentKey = @"FIRCDFirebaseUserAgentKey";
+
+/** Defines the interface of a data object needed to log diagnostics data. */
+@protocol FIRCoreDiagnosticsData
+
+@required
+
+/** A dictionary containing data (non-exhaustive) to be logged in diagnostics. */
+@property(nonatomic) NSDictionary *diagnosticObjects;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h b/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h
new file mode 100644
index 0000000..2b0eb71
--- /dev/null
+++ b/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+#import "FIRCoreDiagnosticsData.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** Allows the interoperation of FirebaseCore and FirebaseCoreDiagnostics. */
+@protocol FIRCoreDiagnosticsInterop
+
+/** Sends the given diagnostics data.
+ *
+ * @param diagnosticsData The diagnostics data object to send.
+ */
++ (void)sendDiagnosticsData:(id)diagnosticsData;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseCoreDiagnosticsInterop/LICENSE b/Pods/FirebaseCoreDiagnosticsInterop/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/Pods/FirebaseCoreDiagnosticsInterop/LICENSE
@@ -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.
diff --git a/Pods/FirebaseCoreDiagnosticsInterop/README.md b/Pods/FirebaseCoreDiagnosticsInterop/README.md
new file mode 100644
index 0000000..bf397f0
--- /dev/null
+++ b/Pods/FirebaseCoreDiagnosticsInterop/README.md
@@ -0,0 +1,223 @@
+# Firebase iOS Open Source Development [](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/).
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h
new file mode 100644
index 0000000..6d4b6cb
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h
@@ -0,0 +1,167 @@
+/*
+ * 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
+
+// The format of the debug code will show in the log as: e.g.
+// for code 1000, it will show as I-IID001000.
+typedef NS_ENUM(NSInteger, FIRInstanceIDMessageCode) {
+ // DO NOT USE 2000, 2002.
+ kFIRInstanceIDMessageCodeFIRApp000 = 1000, // I-IID001000
+ kFIRInstanceIDMessageCodeFIRApp001 = 1001,
+ kFIRInstanceIDMessageCodeFIRApp002 = 1002,
+ kFIRInstanceIDMessageCodeInternal001 = 2001,
+ kFIRInstanceIDMessageCodeInternal002 = 2002,
+ // FIRInstanceID.m
+ // DO NOT USE 4000.
+ kFIRInstanceIDMessageCodeInstanceID000 = 3000,
+ kFIRInstanceIDMessageCodeInstanceID001 = 3001,
+ kFIRInstanceIDMessageCodeInstanceID002 = 3002,
+ kFIRInstanceIDMessageCodeInstanceID003 = 3003,
+ kFIRInstanceIDMessageCodeInstanceID004 = 3004,
+ kFIRInstanceIDMessageCodeInstanceID005 = 3005,
+ kFIRInstanceIDMessageCodeInstanceID006 = 3006,
+ kFIRInstanceIDMessageCodeInstanceID007 = 3007,
+ kFIRInstanceIDMessageCodeInstanceID008 = 3008,
+ kFIRInstanceIDMessageCodeInstanceID009 = 3009,
+ kFIRInstanceIDMessageCodeInstanceID010 = 3010,
+ kFIRInstanceIDMessageCodeInstanceID011 = 3011,
+ kFIRInstanceIDMessageCodeInstanceID012 = 3012,
+ kFIRInstanceIDMessageCodeInstanceID013 = 3013,
+ kFIRInstanceIDMessageCodeInstanceID014 = 3014,
+ kFIRInstanceIDMessageCodeInstanceID015 = 3015,
+ kFIRInstanceIDMessageCodeRefetchingTokenForAPNS = 3016,
+ kFIRInstanceIDMessageCodeInstanceID017 = 3017,
+ kFIRInstanceIDMessageCodeInstanceID018 = 3018,
+ // FIRInstanceIDAuthService.m
+ kFIRInstanceIDMessageCodeAuthService000 = 5000,
+ kFIRInstanceIDMessageCodeAuthService001 = 5001,
+ kFIRInstanceIDMessageCodeAuthService002 = 5002,
+ kFIRInstanceIDMessageCodeAuthService003 = 5003,
+ kFIRInstanceIDMessageCodeAuthService004 = 5004,
+ kFIRInstanceIDMessageCodeAuthServiceCheckinInProgress = 5004,
+
+ // FIRInstanceIDBackupExcludedPlist.m
+ kFIRInstanceIDMessageCodeBackupExcludedPlist000 = 6000,
+ kFIRInstanceIDMessageCodeBackupExcludedPlist001 = 6001,
+ kFIRInstanceIDMessageCodeBackupExcludedPlist002 = 6002,
+ kFIRInstanceIDMessageCodeBackupExcludedPlistInvalidPlistEnum = 6003,
+ // FIRInstanceIDCheckinService.m
+ kFIRInstanceIDMessageCodeService000 = 7000,
+ kFIRInstanceIDMessageCodeService001 = 7001,
+ kFIRInstanceIDMessageCodeService002 = 7002,
+ kFIRInstanceIDMessageCodeService003 = 7003,
+ kFIRInstanceIDMessageCodeService004 = 7004,
+ kFIRInstanceIDMessageCodeService005 = 7005,
+ kFIRInstanceIDMessageCodeService006 = 7006,
+ kFIRInstanceIDInvalidNetworkSession = 7007,
+ kFIRInstanceIDInvalidSettingResponse = 7008,
+ // FIRInstanceIDCheckinStore.m
+ // DO NOT USE 8002, 8004 - 8008
+ kFIRInstanceIDMessageCodeCheckinStore000 = 8000,
+ kFIRInstanceIDMessageCodeCheckinStore001 = 8001,
+ kFIRInstanceIDMessageCodeCheckinStore003 = 8003,
+ kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistDeleted = 8009,
+ kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistSaved = 8010,
+ // FIRInstanceIDKeyPair.m
+ // DO NOT USE 9001, 9003
+ kFIRInstanceIDMessageCodeKeyPair000 = 9000,
+ kFIRInstanceIDMessageCodeKeyPair002 = 9002,
+ kFIRInstanceIDMessageCodeKeyPairMigrationError = 9004,
+ kFIRInstanceIDMessageCodeKeyPairMigrationSuccess = 9005,
+ kFIRInstanceIDMessageCodeKeyPairNoLegacyKeyPair = 9006,
+
+ // FIRInstanceIDKeyPairStore.m
+ kFIRInstanceIDMessageCodeKeyPairStore000 = 10000,
+ kFIRInstanceIDMessageCodeKeyPairStore001 = 10001,
+ kFIRInstanceIDMessageCodeKeyPairStore002 = 10002,
+ kFIRInstanceIDMessageCodeKeyPairStore003 = 10003,
+ kFIRInstanceIDMessageCodeKeyPairStore004 = 10004,
+ kFIRInstanceIDMessageCodeKeyPairStore005 = 10005,
+ kFIRInstanceIDMessageCodeKeyPairStore006 = 10006,
+ kFIRInstanceIDMessageCodeKeyPairStore007 = 10007,
+ kFIRInstanceIDMessageCodeKeyPairStore008 = 10008,
+ kFIRInstanceIDMessageCodeKeyPairStoreCouldNotLoadKeyPair = 10009,
+ // FIRInstanceIDKeyPairUtilities.m
+ kFIRInstanceIDMessageCodeKeyPairUtilities000 = 11000,
+ kFIRInstanceIDMessageCodeKeyPairUtilities001 = 11001,
+ kFIRInstanceIDMessageCodeKeyPairUtilitiesFirstConcatenateParamNil = 11002,
+
+ // DO NOT USE 12000 - 12014
+
+ // FIRInstanceIDStore.m
+ // DO NOT USE 13004, 13005, 13007, 13008, 13010, 13011, 13013, 13014
+ kFIRInstanceIDMessageCodeStore000 = 13000,
+ kFIRInstanceIDMessageCodeStore001 = 13001,
+ kFIRInstanceIDMessageCodeStore002 = 13002,
+ kFIRInstanceIDMessageCodeStore003 = 13003,
+ kFIRInstanceIDMessageCodeStore006 = 13006,
+ kFIRInstanceIDMessageCodeStore009 = 13009,
+ kFIRInstanceIDMessageCodeStore012 = 13012,
+ // FIRInstanceIDTokenManager.m
+ // DO NOT USE 14002, 14005
+ kFIRInstanceIDMessageCodeTokenManager000 = 14000,
+ kFIRInstanceIDMessageCodeTokenManager001 = 14001,
+ kFIRInstanceIDMessageCodeTokenManager003 = 14003,
+ kFIRInstanceIDMessageCodeTokenManager004 = 14004,
+ kFIRInstanceIDMessageCodeTokenManagerErrorDeletingFCMTokensOnAppReset = 14006,
+ kFIRInstanceIDMessageCodeTokenManagerDeletedFCMTokensOnAppReset = 14007,
+ kFIRInstanceIDMessageCodeTokenManagerSavedAppVersion = 14008,
+ kFIRInstanceIDMessageCodeTokenManagerErrorInvalidatingAllTokens = 14009,
+ kFIRInstanceIDMessageCodeTokenManagerAPNSChanged = 14010,
+ kFIRInstanceIDMessageCodeTokenManagerAPNSChangedTokenInvalidated = 14011,
+ kFIRInstanceIDMessageCodeTokenManagerInvalidateStaleToken = 14012,
+ // FIRInstanceIDTokenStore.m
+ // DO NOT USE 15002 - 15013
+ kFIRInstanceIDMessageCodeTokenStore000 = 15000,
+ kFIRInstanceIDMessageCodeTokenStore001 = 15001,
+ kFIRInstanceIDMessageCodeTokenStoreExceptionUnarchivingTokenInfo = 15015,
+
+ // DO NOT USE 16000, 18004
+
+ // FIRInstanceIDUtilities.m
+ kFIRInstanceIDMessageCodeUtilitiesMissingBundleIdentifier = 18000,
+ kFIRInstanceIDMessageCodeUtilitiesAppEnvironmentUtilNotAvailable = 18001,
+ kFIRInstanceIDMessageCodeUtilitiesCannotGetHardwareModel = 18002,
+ kFIRInstanceIDMessageCodeUtilitiesCannotGetSystemVersion = 18003,
+ // FIRInstanceIDTokenOperation.m
+ kFIRInstanceIDMessageCodeTokenOperationFailedToSignParams = 19000,
+ // FIRInstanceIDTokenFetchOperation.m
+ // DO NOT USE 20004, 20005
+ kFIRInstanceIDMessageCodeTokenFetchOperationFetchRequest = 20000,
+ kFIRInstanceIDMessageCodeTokenFetchOperationRequestError = 20001,
+ kFIRInstanceIDMessageCodeTokenFetchOperationBadResponse = 20002,
+ kFIRInstanceIDMessageCodeTokenFetchOperationBadTokenStructure = 20003,
+ // FIRInstanceIDTokenDeleteOperation.m
+ kFIRInstanceIDMessageCodeTokenDeleteOperationFetchRequest = 21000,
+ kFIRInstanceIDMessageCodeTokenDeleteOperationRequestError = 21001,
+ kFIRInstanceIDMessageCodeTokenDeleteOperationBadResponse = 21002,
+ // FIRInstanceIDTokenInfo.m
+ kFIRInstanceIDMessageCodeTokenInfoBadAPNSInfo = 22000,
+ kFIRInstanceIDMessageCodeTokenInfoFirebaseAppIDChanged = 22001,
+ kFIRInstanceIDMessageCodeTokenInfoLocaleChanged = 22002,
+ // FIRInstanceIDKeychain.m
+ kFIRInstanceIDKeychainReadItemError = 23000,
+ kFIRInstanceIDKeychainAddItemError = 23001,
+ kFIRInstanceIDKeychainDeleteItemError = 23002,
+ kFIRInstanceIDKeychainCreateKeyPairError = 23003,
+ kFIRInstanceIDKeychainUpdateItemError = 23004,
+
+ // FIRInstanceIDStringEncoding.m
+ kFIRInstanceIDStringEncodingBufferUnderflow = 24000,
+ kFIRInstanceIDStringEncodingBufferOverflow = 24001,
+
+};
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.h
new file mode 100644
index 0000000..32ac7bd
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.h
@@ -0,0 +1,49 @@
+/*
+ * 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 "FIRInstanceID.h"
+
+#import "FIRInstanceIDCheckinService.h"
+
+/**
+ * Internal API used by Firebase SDK teams by calling in reflection or internal teams.
+ */
+// TODO(chliangGoogle) Rename this to Internal.
+@interface FIRInstanceID (Private)
+
+/**
+ * Fetches checkin info for the app. If the app has valid cached checkin preferences
+ * they are returned instead of making a network request.
+ *
+ * @param handler The completion handler to invoke once the request has completed.
+ */
+- (void)fetchCheckinInfoWithHandler:(nullable FIRInstanceIDDeviceCheckinCompletion)handler;
+
+/**
+ * Get the InstanceID for the app. If an ID was created before and cached
+ * successfully we will return that ID. If no cached ID exists we create
+ * a new ID, cache it and return that.
+ *
+ * This is a blocking call and should not really be called on the main thread.
+ *
+ * @param error The error object that represents the error while trying to
+ * retrieve the instance id.
+ *
+ * @return The InstanceID for the app.
+ */
+- (nullable NSString *)appInstanceID:(NSError *_Nullable *_Nullable)error;
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m
new file mode 100644
index 0000000..a078971
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "FIRInstanceID+Private.h"
+
+#import "FIRInstanceIDAuthService.h"
+#import "FIRInstanceIDKeyPairStore.h"
+#import "FIRInstanceIDTokenManager.h"
+
+@interface FIRInstanceID ()
+
+@property(nonatomic, readonly, strong) FIRInstanceIDTokenManager *tokenManager;
+@property(nonatomic, readonly, strong) FIRInstanceIDKeyPairStore *keyPairStore;
+
+@end
+
+@implementation FIRInstanceID (Private)
+
+// This method just wraps our pre-configured auth service to make the request.
+// This method is only needed by first-party users, like Remote Config.
+- (void)fetchCheckinInfoWithHandler:(FIRInstanceIDDeviceCheckinCompletion)handler {
+ [self.tokenManager.authService fetchCheckinInfoWithHandler:handler];
+}
+
+- (NSString *)appInstanceID:(NSError **)error {
+ return [self.keyPairStore appIdentityWithError:error];
+}
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m
new file mode 100644
index 0000000..f52016f
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m
@@ -0,0 +1,1197 @@
+/*
+ * 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 "FIRInstanceID.h"
+
+#import
+#import
+#import
+#import
+#import
+#import
+#import "FIRInstanceID+Private.h"
+#import "FIRInstanceIDAuthService.h"
+#import "FIRInstanceIDCheckinPreferences.h"
+#import "FIRInstanceIDCombinedHandler.h"
+#import "FIRInstanceIDConstants.h"
+#import "FIRInstanceIDDefines.h"
+#import "FIRInstanceIDKeyPairStore.h"
+#import "FIRInstanceIDLogger.h"
+#import "FIRInstanceIDStore.h"
+#import "FIRInstanceIDTokenInfo.h"
+#import "FIRInstanceIDTokenManager.h"
+#import "FIRInstanceIDUtilities.h"
+#import "FIRInstanceIDVersionUtilities.h"
+#import "NSError+FIRInstanceID.h"
+
+// Public constants
+NSString *const kFIRInstanceIDScopeFirebaseMessaging = @"fcm";
+
+#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
+const NSNotificationName kFIRInstanceIDTokenRefreshNotification =
+ @"com.firebase.iid.notif.refresh-token";
+#else
+NSString *const kFIRInstanceIDTokenRefreshNotification = @"com.firebase.iid.notif.refresh-token";
+#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
+
+NSString *const kFIRInstanceIDInvalidNilHandlerError = @"Invalid nil handler.";
+
+// Private constants
+int64_t const kMaxRetryIntervalForDefaultTokenInSeconds = 20 * 60; // 20 minutes
+int64_t const kMinRetryIntervalForDefaultTokenInSeconds = 10; // 10 seconds
+// we retry only a max 5 times.
+// TODO(chliangGoogle): If we still fail we should listen for the network change notification
+// since GCM would have started Reachability. We only start retrying after we see a configuration
+// change.
+NSInteger const kMaxRetryCountForDefaultToken = 5;
+
+#if TARGET_OS_IOS || TARGET_OS_TV
+static NSString *const kEntitlementsAPSEnvironmentKey = @"Entitlements.aps-environment";
+#else
+static NSString *const kEntitlementsAPSEnvironmentKey = @"com.apple.developer.aps-environment";
+#endif
+static NSString *const kEntitlementsKeyForMac = @"Entitlements";
+static NSString *const kAPSEnvironmentDevelopmentValue = @"development";
+/// FIRMessaging selector that returns the current FIRMessaging auto init
+/// enabled flag.
+static NSString *const kFIRInstanceIDFCMSelectorAutoInitEnabled = @"isAutoInitEnabled";
+static NSString *const kFIRInstanceIDFCMSelectorInstance = @"messaging";
+
+static NSString *const kFIRInstanceIDAPNSTokenType = @"APNSTokenType";
+static NSString *const kFIRIIDAppReadyToConfigureSDKNotification =
+ @"FIRAppReadyToConfigureSDKNotification";
+static NSString *const kFIRIIDAppNameKey = @"FIRAppNameKey";
+static NSString *const kFIRIIDErrorDomain = @"com.firebase.instanceid";
+static NSString *const kFIRIIDServiceInstanceID = @"InstanceID";
+
+static NSInteger const kFIRIIDErrorCodeInstanceIDFailed = -121;
+
+typedef void (^FIRInstanceIDKeyPairHandler)(FIRInstanceIDKeyPair *keyPair, NSError *error);
+
+/**
+ * The APNS token type for the app. If the token type is set to `UNKNOWN`
+ * InstanceID will implicitly try to figure out what the actual token type
+ * is from the provisioning profile.
+ * This must match FIRMessagingAPNSTokenType in FIRMessaging.h
+ */
+typedef NS_ENUM(NSInteger, FIRInstanceIDAPNSTokenType) {
+ /// Unknown token type.
+ FIRInstanceIDAPNSTokenTypeUnknown,
+ /// Sandbox token type.
+ FIRInstanceIDAPNSTokenTypeSandbox,
+ /// Production token type.
+ FIRInstanceIDAPNSTokenTypeProd,
+} NS_SWIFT_NAME(InstanceIDAPNSTokenType);
+
+@interface FIRInstanceIDResult ()
+@property(nonatomic, readwrite, copy) NSString *instanceID;
+@property(nonatomic, readwrite, copy) NSString *token;
+@end
+
+@interface FIRInstanceID ()
+
+// FIRApp configuration objects.
+@property(nonatomic, readwrite, copy) NSString *fcmSenderID;
+@property(nonatomic, readwrite, copy) NSString *firebaseAppID;
+
+// Raw APNS token data
+@property(nonatomic, readwrite, strong) NSData *apnsTokenData;
+
+@property(nonatomic, readwrite) FIRInstanceIDAPNSTokenType apnsTokenType;
+// String-based, internal representation of APNS token
+@property(nonatomic, readwrite, copy) NSString *APNSTupleString;
+// Token fetched from the server automatically for the default app.
+@property(nonatomic, readwrite, copy) NSString *defaultFCMToken;
+
+@property(nonatomic, readwrite, strong) FIRInstanceIDTokenManager *tokenManager;
+@property(nonatomic, readwrite, strong) FIRInstanceIDKeyPairStore *keyPairStore;
+
+// backoff and retry for default token
+@property(nonatomic, readwrite, assign) NSInteger retryCountForDefaultToken;
+@property(atomic, strong, nullable)
+ FIRInstanceIDCombinedHandler *defaultTokenFetchHandler;
+
+@end
+
+// InstanceID doesn't provide any functionality to other components,
+// so it provides a private, empty protocol that it conforms to and use it for registration.
+
+@protocol FIRInstanceIDInstanceProvider
+@end
+
+@interface FIRInstanceID ()
+@end
+
+@implementation FIRInstanceIDResult
+- (id)copyWithZone:(NSZone *)zone {
+ FIRInstanceIDResult *result = [[[self class] allocWithZone:zone] init];
+ result.instanceID = self.instanceID;
+ result.token = self.token;
+ return result;
+}
+@end
+
+@implementation FIRInstanceID
+
+// File static to support InstanceID tests that call [FIRInstanceID instanceID] after
+// [FIRInstanceID instanceIDForTests].
+static FIRInstanceID *gInstanceID;
+
++ (instancetype)instanceID {
+ // If the static instance was created, return it. This should only be set in tests and we should
+ // eventually use proper dependency injection for a better test structure.
+ if (gInstanceID != nil) {
+ return gInstanceID;
+ }
+ FIRApp *defaultApp = [FIRApp defaultApp]; // Missing configure will be logged here.
+ FIRInstanceID *instanceID =
+ (FIRInstanceID *)FIR_COMPONENT(FIRInstanceIDInstanceProvider, defaultApp.container);
+ return instanceID;
+}
+
+- (instancetype)initPrivately {
+ self = [super init];
+ if (self != nil) {
+ // Use automatic detection of sandbox, unless otherwise set by developer
+ _apnsTokenType = FIRInstanceIDAPNSTokenTypeUnknown;
+ }
+ return self;
+}
+
++ (FIRInstanceID *)instanceIDForTests {
+ gInstanceID = [[FIRInstanceID alloc] initPrivately];
+ [gInstanceID start];
+ return gInstanceID;
+}
+
+- (void)dealloc {
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+#pragma mark - Tokens
+
+- (NSString *)token {
+ if (!self.fcmSenderID.length) {
+ return nil;
+ }
+
+ NSString *cachedToken = [self cachedTokenIfAvailable];
+
+ if (cachedToken) {
+ return cachedToken;
+ } else {
+ // If we've never had a cached default token, we should fetch one because unrelatedly,
+ // this request will help us determine whether the locally-generated Instance ID keypair is not
+ // unique, and therefore generate a new one.
+ [self defaultTokenWithHandler:nil];
+ return nil;
+ }
+}
+
+- (void)instanceIDWithHandler:(FIRInstanceIDResultHandler)handler {
+ FIRInstanceID_WEAKIFY(self);
+ [self getIDWithHandler:^(NSString *identity, NSError *error) {
+ FIRInstanceID_STRONGIFY(self);
+ // This is in main queue already
+ if (error) {
+ if (handler) {
+ handler(nil, error);
+ }
+ return;
+ }
+ FIRInstanceIDResult *result = [[FIRInstanceIDResult alloc] init];
+ result.instanceID = identity;
+ NSString *cachedToken = [self cachedTokenIfAvailable];
+ if (cachedToken) {
+ if (handler) {
+ result.token = cachedToken;
+ handler(result, nil);
+ }
+ // If no handler, simply return since client has generated iid and token.
+ return;
+ }
+ [self defaultTokenWithHandler:^(NSString *_Nullable token, NSError *_Nullable error) {
+ if (handler) {
+ if (error) {
+ handler(nil, error);
+ return;
+ }
+ result.token = token;
+ handler(result, nil);
+ }
+ }];
+ }];
+}
+
+- (NSString *)cachedTokenIfAvailable {
+ FIRInstanceIDTokenInfo *cachedTokenInfo =
+ [self.tokenManager cachedTokenInfoWithAuthorizedEntity:self.fcmSenderID
+ scope:kFIRInstanceIDDefaultTokenScope];
+ return cachedTokenInfo.token;
+}
+
+- (void)setDefaultFCMToken:(NSString *)defaultFCMToken {
+ if (_defaultFCMToken && defaultFCMToken && [defaultFCMToken isEqualToString:_defaultFCMToken]) {
+ return;
+ }
+
+ _defaultFCMToken = defaultFCMToken;
+
+ // Sending this notification out will ensure that FIRMessaging has the updated
+ // default FCM token.
+ NSNotification *internalDefaultTokenNotification =
+ [NSNotification notificationWithName:kFIRInstanceIDDefaultGCMTokenNotification
+ object:_defaultFCMToken];
+ [[NSNotificationQueue defaultQueue] enqueueNotification:internalDefaultTokenNotification
+ postingStyle:NSPostASAP];
+}
+
+- (void)tokenWithAuthorizedEntity:(NSString *)authorizedEntity
+ scope:(NSString *)scope
+ options:(NSDictionary *)options
+ handler:(FIRInstanceIDTokenHandler)handler {
+ if (!handler) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID000,
+ kFIRInstanceIDInvalidNilHandlerError);
+ return;
+ }
+
+ NSMutableDictionary *tokenOptions = [NSMutableDictionary dictionary];
+ if (options.count) {
+ [tokenOptions addEntriesFromDictionary:options];
+ }
+
+ NSString *APNSKey = kFIRInstanceIDTokenOptionsAPNSKey;
+ NSString *serverTypeKey = kFIRInstanceIDTokenOptionsAPNSIsSandboxKey;
+
+ if (tokenOptions[APNSKey] != nil && tokenOptions[serverTypeKey] == nil) {
+ // APNS key was given, but server type is missing. Supply the server type with automatic
+ // checking. This can happen when the token is requested from FCM, which does not include a
+ // server type during its request.
+ tokenOptions[serverTypeKey] = @([self isSandboxApp]);
+ }
+
+ // comparing enums to ints directly throws a warning
+ FIRInstanceIDErrorCode noError = INT_MAX;
+ FIRInstanceIDErrorCode errorCode = noError;
+ if (FIRInstanceIDIsValidGCMScope(scope) && !tokenOptions[APNSKey]) {
+ errorCode = kFIRInstanceIDErrorCodeMissingAPNSToken;
+ } else if (FIRInstanceIDIsValidGCMScope(scope) &&
+ ![tokenOptions[APNSKey] isKindOfClass:[NSData class]]) {
+ errorCode = kFIRInstanceIDErrorCodeInvalidRequest;
+ } else if (![authorizedEntity length]) {
+ errorCode = kFIRInstanceIDErrorCodeInvalidAuthorizedEntity;
+ } else if (![scope length]) {
+ errorCode = kFIRInstanceIDErrorCodeInvalidScope;
+ } else if (!self.keyPairStore) {
+ errorCode = kFIRInstanceIDErrorCodeInvalidStart;
+ }
+
+ FIRInstanceIDTokenHandler newHandler = ^(NSString *token, NSError *error) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ handler(token, error);
+ });
+ };
+
+ if (errorCode != noError) {
+ newHandler(nil, [NSError errorWithFIRInstanceIDErrorCode:errorCode]);
+ return;
+ }
+
+ // TODO(chliangGoogle): Add some validation logic that the APNs token data and sandbox value are
+ // supplied in the valid format (NSData and BOOL, respectively).
+
+ // Add internal options
+ if (self.firebaseAppID) {
+ tokenOptions[kFIRInstanceIDTokenOptionsFirebaseAppIDKey] = self.firebaseAppID;
+ }
+
+ FIRInstanceID_WEAKIFY(self);
+ FIRInstanceIDAuthService *authService = self.tokenManager.authService;
+ [authService
+ fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, NSError *error) {
+ FIRInstanceID_STRONGIFY(self);
+ if (error) {
+ newHandler(nil, error);
+ return;
+ }
+
+ // Only use the token in the cache if the APNSInfo matches what the request's options has.
+ // It's possible for the request to be with a newer APNs device token, which should be
+ // honored.
+ FIRInstanceIDTokenInfo *cachedTokenInfo =
+ [self.tokenManager cachedTokenInfoWithAuthorizedEntity:authorizedEntity scope:scope];
+ if (cachedTokenInfo) {
+ // Ensure that the cached token matches APNs data before returning it.
+ FIRInstanceIDAPNSInfo *optionsAPNSInfo =
+ [[FIRInstanceIDAPNSInfo alloc] initWithTokenOptionsDictionary:tokenOptions];
+ // If either the APNs info is missing in both, or if they are an exact match, then we can
+ // use this cached token.
+ if ((!cachedTokenInfo.APNSInfo && !optionsAPNSInfo) ||
+ [cachedTokenInfo.APNSInfo isEqualToAPNSInfo:optionsAPNSInfo]) {
+ newHandler(cachedTokenInfo.token, nil);
+ return;
+ }
+ }
+
+ FIRInstanceID_WEAKIFY(self);
+ [self asyncLoadKeyPairWithHandler:^(FIRInstanceIDKeyPair *keyPair, NSError *error) {
+ FIRInstanceID_STRONGIFY(self);
+
+ if (error) {
+ NSError *newError =
+ [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair];
+ newHandler(nil, newError);
+
+ } else {
+ [self.tokenManager fetchNewTokenWithAuthorizedEntity:[authorizedEntity copy]
+ scope:[scope copy]
+ keyPair:keyPair
+ options:tokenOptions
+ handler:newHandler];
+ }
+ }];
+ }];
+}
+
+- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity
+ scope:(NSString *)scope
+ handler:(FIRInstanceIDDeleteTokenHandler)handler {
+ if (!handler) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID001,
+ kFIRInstanceIDInvalidNilHandlerError);
+ }
+
+ // comparing enums to ints directly throws a warning
+ FIRInstanceIDErrorCode noError = INT_MAX;
+ FIRInstanceIDErrorCode errorCode = noError;
+
+ if (![authorizedEntity length]) {
+ errorCode = kFIRInstanceIDErrorCodeInvalidAuthorizedEntity;
+ } else if (![scope length]) {
+ errorCode = kFIRInstanceIDErrorCodeInvalidScope;
+ } else if (!self.keyPairStore) {
+ errorCode = kFIRInstanceIDErrorCodeInvalidStart;
+ }
+
+ FIRInstanceIDDeleteTokenHandler newHandler = ^(NSError *error) {
+ // If a default token is deleted successfully, reset the defaultFCMToken too.
+ if (!error && [authorizedEntity isEqualToString:self.fcmSenderID] &&
+ [scope isEqualToString:kFIRInstanceIDDefaultTokenScope]) {
+ self.defaultFCMToken = nil;
+ }
+ dispatch_async(dispatch_get_main_queue(), ^{
+ handler(error);
+ });
+ };
+
+ if (errorCode != noError) {
+ newHandler([NSError errorWithFIRInstanceIDErrorCode:errorCode]);
+ return;
+ }
+
+ FIRInstanceID_WEAKIFY(self);
+ FIRInstanceIDAuthService *authService = self.tokenManager.authService;
+ [authService
+ fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, NSError *error) {
+ FIRInstanceID_STRONGIFY(self);
+ if (error) {
+ newHandler(error);
+ return;
+ }
+
+ FIRInstanceID_WEAKIFY(self);
+ [self asyncLoadKeyPairWithHandler:^(FIRInstanceIDKeyPair *keyPair, NSError *error) {
+ FIRInstanceID_STRONGIFY(self);
+ if (error) {
+ NSError *newError =
+ [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair];
+ newHandler(newError);
+
+ } else {
+ [self.tokenManager deleteTokenWithAuthorizedEntity:authorizedEntity
+ scope:scope
+ keyPair:keyPair
+ handler:newHandler];
+ }
+ }];
+ }];
+}
+
+- (void)asyncLoadKeyPairWithHandler:(FIRInstanceIDKeyPairHandler)handler {
+ FIRInstanceID_WEAKIFY(self);
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ FIRInstanceID_STRONGIFY(self);
+
+ NSError *error = nil;
+ FIRInstanceIDKeyPair *keyPair = [self.keyPairStore loadKeyPairWithError:&error];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (error) {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID002,
+ @"Failed to retreieve keyPair %@", error);
+ if (handler) {
+ handler(nil, error);
+ }
+ } else if (!keyPair && !error) {
+ if (handler) {
+ handler(nil,
+ [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]);
+ }
+ } else {
+ if (handler) {
+ handler(keyPair, nil);
+ }
+ }
+ });
+ });
+}
+
+#pragma mark - Identity
+
+- (void)getIDWithHandler:(FIRInstanceIDHandler)handler {
+ if (!handler) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID003,
+ kFIRInstanceIDInvalidNilHandlerError);
+ return;
+ }
+
+ void (^callHandlerOnMainThread)(NSString *, NSError *) = ^(NSString *identity, NSError *error) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ handler(identity, error);
+ });
+ };
+
+ if (!self.keyPairStore) {
+ NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidStart];
+ callHandlerOnMainThread(nil, error);
+ return;
+ }
+
+ FIRInstanceID_WEAKIFY(self);
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ FIRInstanceID_STRONGIFY(self);
+ NSError *error;
+ NSString *appIdentity = [self.keyPairStore appIdentityWithError:&error];
+ // When getID is explicitly called, trigger getToken to make sure token always exists.
+ // This is to avoid ID conflict (ID is not checked for conflict until we generate a token)
+ if (appIdentity) {
+ [self token];
+ }
+ callHandlerOnMainThread(appIdentity, error);
+ });
+}
+
+- (void)deleteIDWithHandler:(FIRInstanceIDDeleteHandler)handler {
+ if (!handler) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID004,
+ kFIRInstanceIDInvalidNilHandlerError);
+ return;
+ }
+
+ void (^callHandlerOnMainThread)(NSError *) = ^(NSError *error) {
+ if ([NSThread isMainThread]) {
+ handler(error);
+ return;
+ }
+ dispatch_async(dispatch_get_main_queue(), ^{
+ handler(error);
+ });
+ };
+
+ if (!self.keyPairStore) {
+ FIRInstanceIDErrorCode error = kFIRInstanceIDErrorCodeInvalidStart;
+ callHandlerOnMainThread([NSError errorWithFIRInstanceIDErrorCode:error]);
+ return;
+ }
+
+ FIRInstanceID_WEAKIFY(self);
+ void (^deleteTokensHandler)(NSError *) = ^void(NSError *error) {
+ FIRInstanceID_STRONGIFY(self);
+ if (error) {
+ callHandlerOnMainThread(error);
+ return;
+ }
+ [self deleteIdentityWithHandler:^(NSError *error) {
+ callHandlerOnMainThread(error);
+ }];
+ };
+
+ [self asyncLoadKeyPairWithHandler:^(FIRInstanceIDKeyPair *keyPair, NSError *error) {
+ FIRInstanceID_STRONGIFY(self);
+ if (error) {
+ NSError *newError =
+ [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair];
+ callHandlerOnMainThread(newError);
+ } else {
+ [self.tokenManager deleteAllTokensWithKeyPair:keyPair handler:deleteTokensHandler];
+ }
+ }];
+}
+
+- (void)notifyIdentityReset {
+ [self deleteIdentityWithHandler:nil];
+}
+
+// Delete all the local cache checkin, IID and token.
+- (void)deleteIdentityWithHandler:(FIRInstanceIDDeleteHandler)handler {
+ // Delete tokens.
+ [self.tokenManager deleteAllTokensLocallyWithHandler:^(NSError *deleteTokenError) {
+ // Reset FCM token.
+ self.defaultFCMToken = nil;
+ if (deleteTokenError) {
+ if (handler) {
+ handler(deleteTokenError);
+ }
+ return;
+ }
+
+ // Delete Instance ID.
+ [self.keyPairStore
+ deleteSavedKeyPairWithSubtype:kFIRInstanceIDKeyPairSubType
+ handler:^(NSError *error) {
+ NSError *deletePlistError;
+ [self.keyPairStore
+ removeKeyPairCreationTimePlistWithError:&deletePlistError];
+ if (error || deletePlistError) {
+ if (handler) {
+ // Prefer to use the delete Instance ID error.
+ error = [NSError
+ errorWithFIRInstanceIDErrorCode:
+ kFIRInstanceIDErrorCodeUnknown
+ userInfo:@{
+ NSUnderlyingErrorKey : error
+ ? error
+ : deletePlistError
+ }];
+ handler(error);
+ }
+ return;
+ }
+ // Delete checkin.
+ [self.tokenManager.authService
+ resetCheckinWithHandler:^(NSError *error) {
+ if (error) {
+ if (handler) {
+ handler(error);
+ }
+ return;
+ }
+ // Only request new token if FCM auto initialization is
+ // enabled.
+ if ([self isFCMAutoInitEnabled]) {
+ // Deletion succeeds! Requesting new checkin, IID and token.
+ // TODO(chliangGoogle) see if dispatch_after is necessary
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
+ (int64_t)(0.5 * NSEC_PER_SEC)),
+ dispatch_get_main_queue(), ^{
+ [self defaultTokenWithHandler:nil];
+ });
+ }
+ if (handler) {
+ handler(nil);
+ }
+ }];
+ }];
+ }];
+}
+
+#pragma mark - Checkin
+
+- (BOOL)tryToLoadValidCheckinInfo {
+ FIRInstanceIDCheckinPreferences *checkinPreferences =
+ [self.tokenManager.authService checkinPreferences];
+ return [checkinPreferences hasValidCheckinInfo];
+}
+
+- (NSString *)deviceAuthID {
+ return [self.tokenManager.authService checkinPreferences].deviceID;
+}
+
+- (NSString *)secretToken {
+ return [self.tokenManager.authService checkinPreferences].secretToken;
+}
+
+- (NSString *)versionInfo {
+ return [self.tokenManager.authService checkinPreferences].versionInfo;
+}
+
+#pragma mark - Config
+
++ (void)load {
+ [FIRApp registerInternalLibrary:(Class)self
+ withName:@"fire-iid"
+ withVersion:FIRInstanceIDCurrentLibraryVersion()];
+}
+
++ (nonnull NSArray *)componentsToRegister {
+ FIRComponentCreationBlock creationBlock =
+ ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) {
+ // Ensure it's cached so it returns the same instance every time instanceID is called.
+ *isCacheable = YES;
+ FIRInstanceID *instanceID = [[FIRInstanceID alloc] initPrivately];
+ [instanceID start];
+ return instanceID;
+ };
+ FIRComponent *instanceIDProvider =
+ [FIRComponent componentWithProtocol:@protocol(FIRInstanceIDInstanceProvider)
+ instantiationTiming:FIRInstantiationTimingLazy
+ dependencies:@[]
+ creationBlock:creationBlock];
+ return @[ instanceIDProvider ];
+}
+
++ (void)configureWithApp:(FIRApp *)app {
+ if (!app.isDefaultApp) {
+ // Only configure for the default FIRApp.
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeFIRApp002,
+ @"Firebase Instance ID only works with the default app.");
+ return;
+ }
+ [[FIRInstanceID instanceID] configureInstanceIDWithOptions:app.options app:app];
+}
+
+- (void)configureInstanceIDWithOptions:(FIROptions *)options app:(FIRApp *)firApp {
+ NSString *GCMSenderID = options.GCMSenderID;
+ if (!GCMSenderID.length) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeFIRApp000,
+ @"Firebase not set up correctly, nil or empty senderID.");
+ [FIRInstanceID exitWithReason:@"GCM_SENDER_ID must not be nil or empty." forFirebaseApp:firApp];
+ return;
+ }
+
+ self.fcmSenderID = GCMSenderID;
+ self.firebaseAppID = firApp.options.googleAppID;
+
+ // FCM generates a FCM token during app start for sending push notification to device.
+ // This is not needed for app extension.
+ if (![GULAppEnvironmentUtil isAppExtension]) {
+ [self didCompleteConfigure];
+ }
+}
+
++ (NSError *)configureErrorWithReason:(nonnull NSString *)reason {
+ NSString *description =
+ [NSString stringWithFormat:@"Configuration failed for service %@.", kFIRIIDServiceInstanceID];
+ if (!reason.length) {
+ reason = @"Unknown reason";
+ }
+
+ NSDictionary *userInfo =
+ @{NSLocalizedDescriptionKey : description, NSLocalizedFailureReasonErrorKey : reason};
+
+ return [NSError errorWithDomain:kFIRIIDErrorDomain
+ code:kFIRIIDErrorCodeInstanceIDFailed
+ userInfo:userInfo];
+}
+
++ (void)exitWithReason:(nonnull NSString *)reason forFirebaseApp:(FIRApp *)firebaseApp {
+ [NSException raise:kFIRIIDErrorDomain
+ format:@"Could not configure Firebase InstanceID. %@", reason];
+}
+
+// This is used to start any operations when we receive FirebaseSDK setup notification
+// from FIRCore.
+- (void)didCompleteConfigure {
+ NSString *cachedToken = [self cachedTokenIfAvailable];
+ // When there is a cached token, do the token refresh.
+ if (cachedToken) {
+ // Clean up expired tokens by checking the token refresh policy.
+ if ([self.tokenManager checkForTokenRefreshPolicy]) {
+ // Default token is expired, fetch default token from server.
+ [self defaultTokenWithHandler:nil];
+ }
+ // Notify FCM with the default token.
+ self.defaultFCMToken = [self token];
+ } else if ([self isFCMAutoInitEnabled]) {
+ // When there is no cached token, must check auto init is enabled.
+ // If it's disabled, don't initiate token generation/refresh.
+ // If no cache token and auto init is enabled, fetch a token from server.
+ [self defaultTokenWithHandler:nil];
+ // Notify FCM with the default token.
+ self.defaultFCMToken = [self token];
+ }
+ // ONLY checkin when auto data collection is turned on.
+ if ([self isFCMAutoInitEnabled]) {
+ [self.tokenManager.authService scheduleCheckin:YES];
+ }
+}
+
+- (BOOL)isFCMAutoInitEnabled {
+ Class messagingClass = NSClassFromString(kFIRInstanceIDFCMSDKClassString);
+ // Firebase Messaging is not installed, auto init should be disabled since it's for FCM.
+ if (!messagingClass) {
+ return NO;
+ }
+
+ // Messaging doesn't have the singleton method, auto init should be enabled since FCM exists.
+ SEL instanceSelector = NSSelectorFromString(kFIRInstanceIDFCMSelectorInstance);
+ if (![messagingClass respondsToSelector:instanceSelector]) {
+ return YES;
+ }
+
+ // Get FIRMessaging shared instance.
+ IMP messagingInstanceIMP = [messagingClass methodForSelector:instanceSelector];
+ id (*getMessagingInstance)(id, SEL) = (void *)messagingInstanceIMP;
+ id messagingInstance = getMessagingInstance(messagingClass, instanceSelector);
+
+ // Messaging doesn't have the property, auto init should be enabled since FCM exists.
+ SEL autoInitSelector = NSSelectorFromString(kFIRInstanceIDFCMSelectorAutoInitEnabled);
+ if (![messagingInstance respondsToSelector:autoInitSelector]) {
+ return YES;
+ }
+
+ // Get autoInitEnabled method.
+ IMP isAutoInitEnabledIMP = [messagingInstance methodForSelector:autoInitSelector];
+ BOOL (*isAutoInitEnabled)(id, SEL) = (BOOL(*)(id, SEL))isAutoInitEnabledIMP;
+
+ // Check FCM's isAutoInitEnabled property.
+ return isAutoInitEnabled(messagingInstance, autoInitSelector);
+}
+
+// Actually makes InstanceID instantiate both the IID and Token-related subsystems.
+- (void)start {
+ if (![FIRInstanceIDStore hasSubDirectory:kFIRInstanceIDSubDirectoryName]) {
+ [FIRInstanceIDStore createSubDirectory:kFIRInstanceIDSubDirectoryName];
+ }
+
+ [self setupTokenManager];
+ [self setupKeyPairManager];
+ [self setupNotificationListeners];
+}
+
+// Creates the token manager, which is used for fetching, caching, and retrieving tokens.
+- (void)setupTokenManager {
+ self.tokenManager = [[FIRInstanceIDTokenManager alloc] init];
+}
+
+// Creates a key pair manager, which stores the public/private keys needed to generate an
+// application instance ID.
+- (void)setupKeyPairManager {
+ self.keyPairStore = [[FIRInstanceIDKeyPairStore alloc] init];
+ if ([self.keyPairStore invalidateKeyPairsIfNeeded]) {
+ // Reset tokens right away when keypair is deleted, otherwise async call can make first query
+ // of token happens before reset old tokens during app start.
+ // TODO(chliangGoogle): Delete all tokens on server too, using
+ // deleteAllTokensWithKeyPair:handler:. This requires actually retrieving the invalid keypair
+ // from Keychain, which is something that the key pair store does not currently do.
+ [self.tokenManager deleteAllTokensLocallyWithHandler:nil];
+ }
+}
+
+- (void)setupNotificationListeners {
+ // To prevent double notifications remove observer from all events during setup.
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+ [center removeObserver:self];
+ [center addObserver:self
+ selector:@selector(notifyIdentityReset)
+ name:kFIRInstanceIDIdentityInvalidatedNotification
+ object:nil];
+ [center addObserver:self
+ selector:@selector(notifyAPNSTokenIsSet:)
+ name:kFIRInstanceIDAPNSTokenNotification
+ object:nil];
+}
+
+#pragma mark - Private Helpers
+/// Maximum retry count to fetch the default token.
++ (int64_t)maxRetryCountForDefaultToken {
+ return kMaxRetryCountForDefaultToken;
+}
+
+/// Minimum interval in seconds between retries to fetch the default token.
++ (int64_t)minIntervalForDefaultTokenRetry {
+ return kMinRetryIntervalForDefaultTokenInSeconds;
+}
+
+/// Maximum retry interval between retries to fetch default token.
++ (int64_t)maxRetryIntervalForDefaultTokenInSeconds {
+ return kMaxRetryIntervalForDefaultTokenInSeconds;
+}
+
+- (NSInteger)retryIntervalToFetchDefaultToken {
+ if (self.retryCountForDefaultToken >= [[self class] maxRetryCountForDefaultToken]) {
+ return (NSInteger)[[self class] maxRetryIntervalForDefaultTokenInSeconds];
+ }
+ // exponential backoff with a fixed initial retry time
+ // 11s, 22s, 44s, 88s ...
+ int64_t minInterval = [[self class] minIntervalForDefaultTokenRetry];
+ return (NSInteger)MIN(
+ (1 << self.retryCountForDefaultToken) + minInterval * self.retryCountForDefaultToken,
+ kMaxRetryIntervalForDefaultTokenInSeconds);
+}
+
+- (void)defaultTokenWithHandler:(nullable FIRInstanceIDTokenHandler)aHandler {
+ [self defaultTokenWithRetry:NO handler:aHandler];
+}
+
+/**
+ * @param retry Indicates if the method is called to perform a retry after a failed attempt.
+ * If `YES`, then actual token request will be performed even if `self.defaultTokenFetchHandler !=
+ * nil`
+ */
+- (void)defaultTokenWithRetry:(BOOL)retry handler:(nullable FIRInstanceIDTokenHandler)aHandler {
+ BOOL shouldPerformRequest = retry || self.defaultTokenFetchHandler == nil;
+
+ if (!self.defaultTokenFetchHandler) {
+ self.defaultTokenFetchHandler = [[FIRInstanceIDCombinedHandler alloc] init];
+ }
+
+ if (aHandler) {
+ [self.defaultTokenFetchHandler addHandler:aHandler];
+ }
+
+ if (!shouldPerformRequest) {
+ return;
+ }
+
+ NSDictionary *instanceIDOptions = @{};
+ BOOL hasFirebaseMessaging = NSClassFromString(kFIRInstanceIDFCMSDKClassString) != nil;
+ if (hasFirebaseMessaging && self.apnsTokenData) {
+ BOOL isSandboxApp = (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeSandbox);
+ if (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeUnknown) {
+ isSandboxApp = [self isSandboxApp];
+ }
+ instanceIDOptions = @{
+ kFIRInstanceIDTokenOptionsAPNSKey : self.apnsTokenData,
+ kFIRInstanceIDTokenOptionsAPNSIsSandboxKey : @(isSandboxApp),
+ };
+ }
+
+ FIRInstanceID_WEAKIFY(self);
+ FIRInstanceIDTokenHandler newHandler = ^void(NSString *token, NSError *error) {
+ FIRInstanceID_STRONGIFY(self);
+
+ if (error) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID009,
+ @"Failed to fetch default token %@", error);
+
+ // This notification can be sent multiple times since we can't guarantee success at any point
+ // of time.
+ NSNotification *tokenFetchFailNotification =
+ [NSNotification notificationWithName:kFIRInstanceIDDefaultGCMTokenFailNotification
+ object:[error copy]];
+ [[NSNotificationQueue defaultQueue] enqueueNotification:tokenFetchFailNotification
+ postingStyle:NSPostASAP];
+
+ self.retryCountForDefaultToken = (NSInteger)MIN(self.retryCountForDefaultToken + 1,
+ [[self class] maxRetryCountForDefaultToken]);
+
+ // Do not retry beyond the maximum limit.
+ if (self.retryCountForDefaultToken < [[self class] maxRetryCountForDefaultToken]) {
+ NSInteger retryInterval = [self retryIntervalToFetchDefaultToken];
+ [self retryGetDefaultTokenAfter:retryInterval];
+ } else {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID007,
+ @"Failed to retrieve the default FCM token after %ld retries",
+ (long)self.retryCountForDefaultToken);
+ [self performDefaultTokenHandlerWithToken:nil error:error];
+ }
+ } else {
+ // If somebody updated IID with APNS token while our initial request did not have it
+ // set we need to update it on the server.
+ NSData *deviceTokenInRequest = instanceIDOptions[kFIRInstanceIDTokenOptionsAPNSKey];
+ BOOL isSandboxInRequest =
+ [instanceIDOptions[kFIRInstanceIDTokenOptionsAPNSIsSandboxKey] boolValue];
+ // Note that APNSTupleStringInRequest will be nil if deviceTokenInRequest is nil
+ NSString *APNSTupleStringInRequest = FIRInstanceIDAPNSTupleStringForTokenAndServerType(
+ deviceTokenInRequest, isSandboxInRequest);
+ // If the APNs value either remained nil, or was the same non-nil value, the APNs value
+ // did not change.
+ BOOL APNSRemainedSameDuringFetch =
+ (self.APNSTupleString == nil && APNSTupleStringInRequest == nil) ||
+ ([self.APNSTupleString isEqualToString:APNSTupleStringInRequest]);
+ if (!APNSRemainedSameDuringFetch && hasFirebaseMessaging) {
+ // APNs value did change mid-fetch, so the token should be re-fetched with the current APNs
+ // value.
+ [self retryGetDefaultTokenAfter:0];
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeRefetchingTokenForAPNS,
+ @"Received APNS token while fetching default token. "
+ @"Refetching default token.");
+ // Do not notify and handle completion handler since this is a retry.
+ // Simply return.
+ return;
+ } else {
+ FIRInstanceIDLoggerInfo(kFIRInstanceIDMessageCodeInstanceID010,
+ @"Successfully fetched default token.");
+ }
+ // Post the required notifications if somebody is waiting.
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID008, @"Got default token %@",
+ token);
+ NSString *previousFCMToken = self.defaultFCMToken;
+ self.defaultFCMToken = token;
+
+ // Only notify of token refresh if we have a new valid token that's different than before
+ if (self.defaultFCMToken.length && ![self.defaultFCMToken isEqualToString:previousFCMToken]) {
+ NSNotification *tokenRefreshNotification =
+ [NSNotification notificationWithName:kFIRInstanceIDTokenRefreshNotification
+ object:[self.defaultFCMToken copy]];
+ [[NSNotificationQueue defaultQueue] enqueueNotification:tokenRefreshNotification
+ postingStyle:NSPostASAP];
+ }
+
+ [self performDefaultTokenHandlerWithToken:token error:nil];
+ }
+ };
+
+ [self tokenWithAuthorizedEntity:self.fcmSenderID
+ scope:kFIRInstanceIDDefaultTokenScope
+ options:instanceIDOptions
+ handler:newHandler];
+}
+
+/**
+ *
+ */
+- (void)performDefaultTokenHandlerWithToken:(NSString *)token error:(NSError *)error {
+ if (!self.defaultTokenFetchHandler) {
+ return;
+ }
+
+ [self.defaultTokenFetchHandler combinedHandler](token, error);
+ self.defaultTokenFetchHandler = nil;
+}
+
+- (void)retryGetDefaultTokenAfter:(NSTimeInterval)retryInterval {
+ FIRInstanceID_WEAKIFY(self);
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(retryInterval * NSEC_PER_SEC)),
+ dispatch_get_main_queue(), ^{
+ FIRInstanceID_STRONGIFY(self);
+ // Pass nil: no new handlers to be added, currently existing handlers
+ // will be called
+ [self defaultTokenWithRetry:YES handler:nil];
+ });
+}
+
+#pragma mark - APNS Token
+// This should only be triggered from FCM.
+- (void)notifyAPNSTokenIsSet:(NSNotification *)notification {
+ NSData *token = notification.object;
+ if (!token || ![token isKindOfClass:[NSData class]]) {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInternal002, @"Invalid APNS token type %@",
+ NSStringFromClass([notification.object class]));
+ return;
+ }
+ NSInteger type = [notification.userInfo[kFIRInstanceIDAPNSTokenType] integerValue];
+
+ // The APNS token is being added, or has changed (rare)
+ if ([self.apnsTokenData isEqualToData:token]) {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID011,
+ @"Trying to reset APNS token to the same value. Will return");
+ return;
+ }
+ // Use this token type for when we have to automatically fetch tokens in the future
+ self.apnsTokenType = type;
+ BOOL isSandboxApp = (type == FIRInstanceIDAPNSTokenTypeSandbox);
+ if (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeUnknown) {
+ isSandboxApp = [self isSandboxApp];
+ }
+ self.apnsTokenData = [token copy];
+ self.APNSTupleString = FIRInstanceIDAPNSTupleStringForTokenAndServerType(token, isSandboxApp);
+
+ // Pro-actively invalidate the default token, if the APNs change makes it
+ // invalid. Previously, we invalidated just before fetching the token.
+ NSArray *invalidatedTokens =
+ [self.tokenManager updateTokensToAPNSDeviceToken:self.apnsTokenData isSandbox:isSandboxApp];
+
+ // Re-fetch any invalidated tokens automatically, this time with the current APNs token, so that
+ // they are up-to-date.
+ if (invalidatedTokens.count > 0) {
+ FIRInstanceID_WEAKIFY(self);
+ [self asyncLoadKeyPairWithHandler:^(FIRInstanceIDKeyPair *keyPair, NSError *error) {
+ FIRInstanceID_STRONGIFY(self);
+ if (self == nil) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID017,
+ @"Instance ID shut down during token reset. Aborting");
+ return;
+ }
+ if (self.apnsTokenData == nil) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID018,
+ @"apnsTokenData was set to nil during token reset. Aborting");
+ return;
+ }
+
+ NSMutableDictionary *tokenOptions = [@{
+ kFIRInstanceIDTokenOptionsAPNSKey : self.apnsTokenData,
+ kFIRInstanceIDTokenOptionsAPNSIsSandboxKey : @(isSandboxApp)
+ } mutableCopy];
+ if (self.firebaseAppID) {
+ tokenOptions[kFIRInstanceIDTokenOptionsFirebaseAppIDKey] = self.firebaseAppID;
+ }
+
+ for (FIRInstanceIDTokenInfo *tokenInfo in invalidatedTokens) {
+ if ([tokenInfo.token isEqualToString:self.defaultFCMToken]) {
+ // We will perform a special fetch for the default FCM token, so that the delegate methods
+ // are called. For all others, we will do an internal re-fetch.
+ [self defaultTokenWithHandler:nil];
+ } else {
+ [self.tokenManager fetchNewTokenWithAuthorizedEntity:tokenInfo.authorizedEntity
+ scope:tokenInfo.scope
+ keyPair:keyPair
+ options:tokenOptions
+ handler:^(NSString *_Nullable token,
+ NSError *_Nullable error){
+
+ }];
+ }
+ }
+ }];
+ }
+}
+
+- (BOOL)isSandboxApp {
+ static BOOL isSandboxApp = YES;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ isSandboxApp = ![self isProductionApp];
+ });
+ return isSandboxApp;
+}
+
+- (BOOL)isProductionApp {
+ const BOOL defaultAppTypeProd = YES;
+
+ NSError *error = nil;
+ if ([GULAppEnvironmentUtil isSimulator]) {
+ [self logAPNSConfigurationError:@"Running InstanceID on a simulator doesn't have APNS. "
+ @"Use prod profile by default."];
+ return defaultAppTypeProd;
+ }
+
+ if ([GULAppEnvironmentUtil isFromAppStore]) {
+ // Apps distributed via AppStore or TestFlight use the Production APNS certificates.
+ return defaultAppTypeProd;
+ }
+#if TARGET_OS_IOS || TARGET_OS_TV
+ NSString *path = [[[NSBundle mainBundle] bundlePath]
+ stringByAppendingPathComponent:@"embedded.mobileprovision"];
+#elif TARGET_OS_OSX
+ NSString *path = [[[[NSBundle mainBundle] resourcePath] stringByDeletingLastPathComponent]
+ stringByAppendingPathComponent:@"embedded.provisionprofile"];
+#endif
+
+ if ([GULAppEnvironmentUtil isAppStoreReceiptSandbox] && !path.length) {
+ // Distributed via TestFlight
+ return defaultAppTypeProd;
+ }
+
+ NSMutableData *profileData = [NSMutableData dataWithContentsOfFile:path options:0 error:&error];
+
+ if (!profileData.length || error) {
+ NSString *errorString =
+ [NSString stringWithFormat:@"Error while reading embedded mobileprovision %@", error];
+ [self logAPNSConfigurationError:errorString];
+ return defaultAppTypeProd;
+ }
+
+ // The "embedded.mobileprovision" sometimes contains characters with value 0, which signals the
+ // end of a c-string and halts the ASCII parser, or with value > 127, which violates strict 7-bit
+ // ASCII. Replace any 0s or invalid characters in the input.
+ uint8_t *profileBytes = (uint8_t *)profileData.bytes;
+ for (int i = 0; i < profileData.length; i++) {
+ uint8_t currentByte = profileBytes[i];
+ if (!currentByte || currentByte > 127) {
+ profileBytes[i] = '.';
+ }
+ }
+
+ NSString *embeddedProfile = [[NSString alloc] initWithBytesNoCopy:profileBytes
+ length:profileData.length
+ encoding:NSASCIIStringEncoding
+ freeWhenDone:NO];
+
+ if (error || !embeddedProfile.length) {
+ NSString *errorString =
+ [NSString stringWithFormat:@"Error while reading embedded mobileprovision %@", error];
+ [self logAPNSConfigurationError:errorString];
+ return defaultAppTypeProd;
+ }
+
+ NSScanner *scanner = [NSScanner scannerWithString:embeddedProfile];
+ NSString *plistContents;
+ if ([scanner scanUpToString:@"" intoString:&plistContents]) {
+ plistContents = [plistContents stringByAppendingString:@""];
+ }
+ }
+
+ if (!plistContents.length) {
+ return defaultAppTypeProd;
+ }
+
+ NSData *data = [plistContents dataUsingEncoding:NSUTF8StringEncoding];
+ if (!data.length) {
+ [self logAPNSConfigurationError:@"Couldn't read plist fetched from embedded mobileprovision"];
+ return defaultAppTypeProd;
+ }
+
+ NSError *plistMapError;
+ id plistData = [NSPropertyListSerialization propertyListWithData:data
+ options:NSPropertyListImmutable
+ format:nil
+ error:&plistMapError];
+ if (plistMapError || ![plistData isKindOfClass:[NSDictionary class]]) {
+ NSString *errorString =
+ [NSString stringWithFormat:@"Error while converting assumed plist to dict %@",
+ plistMapError.localizedDescription];
+ [self logAPNSConfigurationError:errorString];
+ return defaultAppTypeProd;
+ }
+ NSDictionary *plistMap = (NSDictionary *)plistData;
+
+ if ([plistMap valueForKeyPath:@"ProvisionedDevices"]) {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID012,
+ @"Provisioning profile has specifically provisioned devices, "
+ @"most likely a Dev profile.");
+ }
+
+#if TARGET_OS_IOS || TARGET_OS_TV
+ NSString *apsEnvironment = [plistMap valueForKeyPath:kEntitlementsAPSEnvironmentKey];
+#elif TARGET_OS_OSX
+ NSDictionary *entitlements = [plistMap valueForKey:kEntitlementsKeyForMac];
+ NSString *apsEnvironment = [entitlements valueForKey:kEntitlementsAPSEnvironmentKey];
+#endif
+
+ NSString *debugString __unused =
+ [NSString stringWithFormat:@"APNS Environment in profile: %@", apsEnvironment];
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID013, @"%@", debugString);
+
+ // No aps-environment in the profile.
+ if (!apsEnvironment.length) {
+ [self logAPNSConfigurationError:@"No aps-environment set. If testing on a device APNS is not "
+ @"correctly configured. Please recheck your provisioning "
+ @"profiles. If testing on a simulator this is fine since APNS "
+ @"doesn't work on the simulator."];
+ return defaultAppTypeProd;
+ }
+
+ if ([apsEnvironment isEqualToString:kAPSEnvironmentDevelopmentValue]) {
+ return NO;
+ }
+
+ return defaultAppTypeProd;
+}
+
+/// Log error messages only when Messaging exists in the pod.
+- (void)logAPNSConfigurationError:(NSString *)errorString {
+ BOOL hasFirebaseMessaging = NSClassFromString(kFIRInstanceIDFCMSDKClassString) != nil;
+ if (hasFirebaseMessaging) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID014, @"%@", errorString);
+ } else {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID015, @"%@", errorString);
+ }
+}
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h
new file mode 100644
index 0000000..92b2469
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * Represents an APNS device token and whether its environment is for sandbox.
+ * It can read from and write to an NSDictionary for simple serialization.
+ */
+@interface FIRInstanceIDAPNSInfo : NSObject
+
+/// The APNs device token, provided by the OS to the application delegate
+@property(nonatomic, readonly, strong) NSData *deviceToken;
+/// Represents whether or not this is deviceToken is for the sandbox
+/// environment, or production.
+@property(nonatomic, readonly, getter=isSandbox) BOOL sandbox;
+
+/**
+ * Initializes the receiver with an APNs device token, and boolean
+ * representing whether that token is for the sandbox environment.
+ *
+ * @param deviceToken The APNs device token typically provided by the
+ * operating system.
+ * @param isSandbox YES if the APNs device token is for the sandbox
+ * environment, or NO if it is for production.
+ * @return An instance of FIRInstanceIDAPNSInfo.
+ */
+- (instancetype)initWithDeviceToken:(NSData *)deviceToken isSandbox:(BOOL)isSandbox;
+
+/**
+ * Initializes the receiver from a token options dictionary containing data
+ * within the `kFIRInstanceIDTokenOptionsAPNSKey` and
+ * `kFIRInstanceIDTokenOptionsAPNSIsSandboxKey` keys. The token should be an
+ * NSData blob, and the sandbox value should be an NSNumber
+ * representing a boolean value.
+ *
+ * @param dictionary A dictionary containing values under the keys
+ * `kFIRInstanceIDTokenOptionsAPNSKey` and
+ * `kFIRInstanceIDTokenOptionsAPNSIsSandboxKey`.
+ * @return An instance of FIRInstanceIDAPNSInfo, or nil if the
+ * dictionary data was invalid or missing.
+ */
+- (nullable instancetype)initWithTokenOptionsDictionary:(NSDictionary *)dictionary;
+
+- (BOOL)isEqualToAPNSInfo:(FIRInstanceIDAPNSInfo *)otherInfo;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m
new file mode 100644
index 0000000..d1f9d08
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m
@@ -0,0 +1,79 @@
+/*
+ * 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 "FIRInstanceIDAPNSInfo.h"
+
+#import "FIRInstanceIDConstants.h"
+
+/// The key used to find the APNs device token in an archive.
+NSString *const kFIRInstanceIDAPNSInfoTokenKey = @"device_token";
+/// The key used to find the sandbox value in an archive.
+NSString *const kFIRInstanceIDAPNSInfoSandboxKey = @"sandbox";
+
+@implementation FIRInstanceIDAPNSInfo
+
+- (instancetype)initWithDeviceToken:(NSData *)deviceToken isSandbox:(BOOL)isSandbox {
+ self = [super init];
+ if (self) {
+ _deviceToken = [deviceToken copy];
+ _sandbox = isSandbox;
+ }
+ return self;
+}
+
+- (instancetype)initWithTokenOptionsDictionary:(NSDictionary *)dictionary {
+ id deviceToken = dictionary[kFIRInstanceIDTokenOptionsAPNSKey];
+ if (![deviceToken isKindOfClass:[NSData class]]) {
+ return nil;
+ }
+
+ id isSandbox = dictionary[kFIRInstanceIDTokenOptionsAPNSIsSandboxKey];
+ if (![isSandbox isKindOfClass:[NSNumber class]]) {
+ return nil;
+ }
+ self = [super init];
+ if (self) {
+ _deviceToken = (NSData *)deviceToken;
+ _sandbox = ((NSNumber *)isSandbox).boolValue;
+ }
+ return self;
+}
+
+#pragma mark - NSCoding
+
+- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
+ id deviceToken = [aDecoder decodeObjectForKey:kFIRInstanceIDAPNSInfoTokenKey];
+ if (![deviceToken isKindOfClass:[NSData class]]) {
+ return nil;
+ }
+ BOOL isSandbox = [aDecoder decodeBoolForKey:kFIRInstanceIDAPNSInfoSandboxKey];
+ return [self initWithDeviceToken:(NSData *)deviceToken isSandbox:isSandbox];
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+ [aCoder encodeObject:self.deviceToken forKey:kFIRInstanceIDAPNSInfoTokenKey];
+ [aCoder encodeBool:self.sandbox forKey:kFIRInstanceIDAPNSInfoSandboxKey];
+}
+
+- (BOOL)isEqualToAPNSInfo:(FIRInstanceIDAPNSInfo *)otherInfo {
+ if ([super isEqual:otherInfo]) {
+ return YES;
+ }
+ return ([self.deviceToken isEqualToData:otherInfo.deviceToken] &&
+ self.isSandbox == otherInfo.isSandbox);
+}
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h
new file mode 100644
index 0000000..347ddda
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h
@@ -0,0 +1,98 @@
+/*
+ * 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
+
+extern NSString *__nonnull const kFIRInstanceIDKeychainWildcardIdentifier;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * Wrapper around storing FCM auth data in iOS keychain.
+ */
+@interface FIRInstanceIDAuthKeychain : NSObject
+
+/**
+ * Designated Initializer. Init a generic `SecClassGenericPassword` keychain with `identifier`
+ * as the `kSecAttrGeneric`.
+ *
+ * @param identifier The generic attribute to be used by the keychain.
+ *
+ * @return A Keychain object with `kSecAttrGeneric` attribute set to identifier.
+ */
+- (instancetype)initWithIdentifier:(NSString *)identifier;
+
+/**
+ * Get keychain items matching the given service and account. The service and/or account
+ * can be a wildcard (`kFIRInstanceIDKeychainWildcardIdentifier`), which case the query
+ * will include all items matching any services and/or accounts.
+ *
+ * @param service The kSecAttrService used to save the password. Can be wildcard.
+ * @param account The kSecAttrAccount used to save the password. Can be wildcard.
+ *
+ * @return An array of |NSData|s matching the provided inputs.
+ */
+- (NSArray *)itemsMatchingService:(NSString *)service account:(NSString *)account;
+
+/**
+ * Get keychain item for a given service and account.
+ *
+ * @param service The kSecAttrService used to save the password.
+ * @param account The kSecAttrAccount used to save the password.
+ *
+ * @return A cached keychain item for a given account and service, or nil if it was not
+ * found or could not be retrieved.
+ */
+- (NSData *)dataForService:(NSString *)service account:(NSString *)account;
+
+/**
+ * Remove the cached items from the keychain matching the service, account and access group.
+ * In case the items do not exist, YES is returned but with a valid error object with code
+ * `errSecItemNotFound`.
+ *
+ * @param service The kSecAttrService used to save the password.
+ * @param account The kSecAttrAccount used to save the password.
+ * @param handler The callback handler which is invoked when the remove operation is complete, with
+ * an error if there is any.
+ */
+- (void)removeItemsMatchingService:(NSString *)service
+ account:(NSString *)account
+ handler:(nullable void (^)(NSError *error))handler;
+
+/**
+ * Set the data for a given service and account with a specific accessibility. If
+ * accessibility is NULL we use `kSecAttrAccessibleAlwaysThisDeviceOnly` which
+ * prevents backup and restore to iCloud, and works for app extension that can
+ * execute right after a device is restarted (and not unlocked).
+ *
+ * @param data The data to save.
+ * @param service The `kSecAttrService` used to save the password.
+ * @param accessibility The `kSecAttrAccessibility` used to save the password. If NULL
+ * set this to `kSecAttrAccessibleAlwaysThisDeviceOnly`.
+ * @param account The `kSecAttrAccount` used to save the password.
+ * @param handler The callback handler which is invoked when the add operation is complete,
+ * with an error if there is any.
+ *
+ */
+- (void)setData:(NSData *)data
+ forService:(NSString *)service
+ accessibility:(nullable CFTypeRef)accessibility
+ account:(NSString *)account
+ handler:(nullable void (^)(NSError *))handler;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m
new file mode 100644
index 0000000..348a915
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m
@@ -0,0 +1,223 @@
+/*
+ * 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 "FIRInstanceIDAuthKeyChain.h"
+#import "FIRInstanceIDKeychain.h"
+#import "FIRInstanceIDLogger.h"
+
+/**
+ * The error type representing why we couldn't read data from the keychain.
+ */
+typedef NS_ENUM(int, FIRInstanceIDKeychainErrorType) {
+ kFIRInstanceIDKeychainErrorBadArguments = -1301,
+};
+
+NSString *const kFIRInstanceIDKeychainWildcardIdentifier = @"*";
+
+@interface FIRInstanceIDAuthKeychain ()
+
+@property(nonatomic, copy) NSString *generic;
+// cachedKeychainData is keyed by service and account, the value is an array of NSData.
+// It is used to cache the tokens per service, per account, as well as checkin data per service,
+// per account inside the keychain.
+@property(nonatomic)
+ NSMutableDictionary *> *>
+ *cachedKeychainData;
+
+@end
+
+@implementation FIRInstanceIDAuthKeychain
+
+- (instancetype)initWithIdentifier:(NSString *)identifier {
+ self = [super init];
+ if (self) {
+ _generic = [identifier copy];
+ _cachedKeychainData = [[NSMutableDictionary alloc] init];
+ }
+ return self;
+}
+
++ (NSMutableDictionary *)keychainQueryForService:(NSString *)service
+ account:(NSString *)account
+ generic:(NSString *)generic {
+ NSDictionary *query = @{(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword};
+
+ NSMutableDictionary *finalQuery = [NSMutableDictionary dictionaryWithDictionary:query];
+ if ([generic length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:generic]) {
+ finalQuery[(__bridge NSString *)kSecAttrGeneric] = generic;
+ }
+ if ([account length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:account]) {
+ finalQuery[(__bridge NSString *)kSecAttrAccount] = account;
+ }
+ if ([service length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:service]) {
+ finalQuery[(__bridge NSString *)kSecAttrService] = service;
+ }
+ return finalQuery;
+}
+
+- (NSMutableDictionary *)keychainQueryForService:(NSString *)service account:(NSString *)account {
+ return [[self class] keychainQueryForService:service account:account generic:self.generic];
+}
+
+- (NSArray *)itemsMatchingService:(NSString *)service account:(NSString *)account {
+ // If query wildcard service, it asks for all the results, which always query from keychain.
+ if (![service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] &&
+ ![account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] &&
+ _cachedKeychainData[service][account]) {
+ // As long as service, account array exist, even it's empty, it means we've queried it before,
+ // returns the cache value.
+ return _cachedKeychainData[service][account];
+ }
+
+ NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account];
+ NSMutableArray *results;
+ keychainQuery[(__bridge id)kSecReturnData] = (__bridge id)kCFBooleanTrue;
+#if TARGET_OS_IOS || TARGET_OS_TV
+ keychainQuery[(__bridge id)kSecReturnAttributes] = (__bridge id)kCFBooleanTrue;
+ keychainQuery[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitAll;
+ // FIRInstanceIDKeychain should only take a query and return a result, will handle the query here.
+ NSArray *passwordInfos =
+ CFBridgingRelease([[FIRInstanceIDKeychain sharedInstance] itemWithQuery:keychainQuery]);
+#elif TARGET_OS_OSX
+ keychainQuery[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne;
+ NSData *passwordInfos =
+ CFBridgingRelease([[FIRInstanceIDKeychain sharedInstance] itemWithQuery:keychainQuery]);
+#endif
+
+ if (!passwordInfos) {
+ // Nothing was found, simply return from this sync block.
+ // Make sure to label the cache entry empty, signaling that we've queried this entry.
+ if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] ||
+ [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) {
+ // Do not update cache if it's wildcard query.
+ return @[];
+ } else if (_cachedKeychainData[service]) {
+ [_cachedKeychainData[service] setObject:@[] forKey:account];
+ } else {
+ [_cachedKeychainData setObject:[@{account : @[]} mutableCopy] forKey:service];
+ }
+ return @[];
+ }
+ results = [[NSMutableArray alloc] init];
+#if TARGET_OS_IOS || TARGET_OS_TV
+ NSInteger numPasswords = passwordInfos.count;
+ for (NSUInteger i = 0; i < numPasswords; i++) {
+ NSDictionary *passwordInfo = [passwordInfos objectAtIndex:i];
+ if (passwordInfo[(__bridge id)kSecValueData]) {
+ [results addObject:passwordInfo[(__bridge id)kSecValueData]];
+ }
+ }
+#elif TARGET_OS_OSX
+ [results addObject:passwordInfos];
+#endif
+ // We query the keychain because it didn't exist in cache, now query is done, update the result in
+ // the cache.
+ if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] ||
+ [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) {
+ // Do not update cache if it's wildcard query.
+ return [results copy];
+ } else if (_cachedKeychainData[service]) {
+ [_cachedKeychainData[service] setObject:[results copy] forKey:account];
+ } else {
+ NSMutableDictionary *entry = [@{account : [results copy]} mutableCopy];
+ [_cachedKeychainData setObject:entry forKey:service];
+ }
+ return [results copy];
+}
+
+- (NSData *)dataForService:(NSString *)service account:(NSString *)account {
+ NSArray *items = [self itemsMatchingService:service account:account];
+ // If items is nil or empty, nil will be returned.
+ return items.firstObject;
+}
+
+- (void)removeItemsMatchingService:(NSString *)service
+ account:(NSString *)account
+ handler:(void (^)(NSError *error))handler {
+ if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) {
+ // Delete all keychain items.
+ _cachedKeychainData = [[NSMutableDictionary alloc] init];
+ } else if ([account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) {
+ // Delete all entries under service,
+ if (_cachedKeychainData[service]) {
+ _cachedKeychainData[service] = [[NSMutableDictionary alloc] init];
+ }
+ } else if (_cachedKeychainData[service]) {
+ // We should keep the service/account entry instead of nil so we know
+ // it's "empty entry" instead of "not query from keychain yet".
+ [_cachedKeychainData[service] setObject:@[] forKey:account];
+ } else {
+ [_cachedKeychainData setObject:[@{account : @[]} mutableCopy] forKey:service];
+ }
+ NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account];
+ [[FIRInstanceIDKeychain sharedInstance] removeItemWithQuery:keychainQuery handler:handler];
+}
+
+- (void)setData:(NSData *)data
+ forService:(NSString *)service
+ accessibility:(CFTypeRef)accessibility
+ account:(NSString *)account
+ handler:(void (^)(NSError *))handler {
+ if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] ||
+ [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) {
+ if (handler) {
+ handler([NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain
+ code:kFIRInstanceIDKeychainErrorBadArguments
+ userInfo:nil]);
+ }
+ return;
+ }
+ [self removeItemsMatchingService:service
+ account:account
+ handler:^(NSError *error) {
+ if (error) {
+ if (handler) {
+ handler(error);
+ }
+ return;
+ }
+ if (data.length > 0) {
+ NSMutableDictionary *keychainQuery =
+ [self keychainQueryForService:service account:account];
+ keychainQuery[(__bridge id)kSecValueData] = data;
+
+ if (accessibility != NULL) {
+ keychainQuery[(__bridge id)kSecAttrAccessible] =
+ (__bridge id)accessibility;
+ } else {
+ // Defaults to No backup
+ keychainQuery[(__bridge id)kSecAttrAccessible] =
+ (__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly;
+ }
+ [[FIRInstanceIDKeychain sharedInstance]
+ addItemWithQuery:keychainQuery
+ handler:handler];
+ }
+ }];
+ // Set the cache value. This must happen after removeItemsMatchingService:account:handler was
+ // called, so the cache value was reset before setting a new value.
+ if (_cachedKeychainData[service]) {
+ if (_cachedKeychainData[service][account]) {
+ _cachedKeychainData[service][account] = @[ data ];
+ } else {
+ [_cachedKeychainData[service] setObject:@[ data ] forKey:account];
+ }
+ } else {
+ [_cachedKeychainData setObject:[@{account : @[ data ]} mutableCopy] forKey:service];
+ }
+}
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h
new file mode 100644
index 0000000..1fb715e
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h
@@ -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
+#import "FIRInstanceIDCheckinService.h"
+
+@class FIRInstanceIDCheckinPreferences;
+@class FIRInstanceIDStore;
+
+/**
+ * FIRInstanceIDAuthService is responsible for retrieving, caching, and supplying checkin info
+ * for the rest of Instance ID. A checkin can be scheduled, meaning that it will keep retrying the
+ * checkin request until it is successful. A checkin can also be requested directly, with a
+ * completion handler.
+ */
+@interface FIRInstanceIDAuthService : NSObject
+
+/**
+ * Used only for testing. In addition to taking a store (for locally caching the checkin info), it
+ * also takes a checkinService.
+ */
+- (instancetype)initWithCheckinService:(FIRInstanceIDCheckinService *)checkinService
+ store:(FIRInstanceIDStore *)store;
+
+/**
+ * Initializes the auth service given a store (which provides the local caching of checkin info).
+ * This initializer will create its own instance of FIRInstanceIDCheckinService.
+ */
+- (instancetype)initWithStore:(FIRInstanceIDStore *)store;
+
+#pragma mark - Checkin Service
+
+/**
+ * Checks if the current deviceID and secret are valid or not.
+ *
+ * @return YES if the checkin credentials are valid else NO.
+ */
+- (BOOL)hasValidCheckinInfo;
+
+/**
+ * Fetch checkin info from the server. This would usually refresh the existing
+ * checkin credentials for the current app.
+ *
+ * @param handler The completion handler to invoke once the checkin info has been
+ * refreshed.
+ */
+- (void)fetchCheckinInfoWithHandler:(FIRInstanceIDDeviceCheckinCompletion)handler;
+
+/**
+ * Schedule checkin. Will hit the network only if the currently loaded checkin
+ * preferences are stale.
+ *
+ * @param immediately YES if we want it to be scheduled immediately else NO.
+ */
+- (void)scheduleCheckin:(BOOL)immediately;
+
+/**
+ * Returns the checkin preferences currently loaded in memory. The Checkin preferences
+ * can be either valid or invalid.
+ *
+ * @return The checkin preferences loaded in memory.
+ */
+- (FIRInstanceIDCheckinPreferences *)checkinPreferences;
+
+/**
+ * Cancels any ongoing checkin fetch, if any.
+ */
+- (void)stopCheckinRequest;
+
+/**
+ * Resets the checkin information.
+ *
+ * @param handler The callback handler which is invoked when checkin reset is complete,
+ * with an error if there is any.
+ */
+- (void)resetCheckinWithHandler:(void (^)(NSError *error))handler;
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m
new file mode 100644
index 0000000..8c33c44
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m
@@ -0,0 +1,302 @@
+/*
+ * 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 "FIRInstanceIDAuthService.h"
+
+#import "FIRInstanceIDCheckinPreferences+Internal.h"
+#import "FIRInstanceIDCheckinPreferences.h"
+#import "FIRInstanceIDCheckinPreferences_Private.h"
+#import "FIRInstanceIDConstants.h"
+#import "FIRInstanceIDDefines.h"
+#import "FIRInstanceIDLogger.h"
+#import "FIRInstanceIDStore.h"
+#import "NSError+FIRInstanceID.h"
+
+// Max time interval between checkin retry in seconds.
+static const int64_t kMaxCheckinRetryIntervalInSeconds = 1 << 5;
+
+@interface FIRInstanceIDAuthService ()
+
+// Used to retrieve and cache the checkin info to disk and Keychain.
+@property(nonatomic, readwrite, strong) FIRInstanceIDStore *store;
+// Used to perform single checkin fetches.
+@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinService *checkinService;
+// The current checkin info. It will be compared to what is retrieved to determine whether it is
+// different than what is in the cache.
+@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinPreferences *checkinPreferences;
+
+// This array will track multiple handlers waiting for checkin to be performed. When a checkin
+// request completes, all the handlers will be notified.
+// Changes to the checkinHandlers array should happen in a thread-safe manner.
+@property(nonatomic, readonly, strong)
+ NSMutableArray *checkinHandlers;
+
+// This is set to true if there is a checkin request in-flight.
+@property(atomic, readwrite, assign) BOOL isCheckinInProgress;
+// This timer is used a perform checkin retries. It is cancellable.
+@property(atomic, readwrite, strong) NSTimer *scheduledCheckinTimer;
+// The number of times checkin has been retried during a scheduled checkin.
+@property(atomic, readwrite, assign) int checkinRetryCount;
+
+@end
+
+@implementation FIRInstanceIDAuthService
+
+- (instancetype)initWithCheckinService:(FIRInstanceIDCheckinService *)checkinService
+ store:(FIRInstanceIDStore *)store {
+ self = [super init];
+ if (self) {
+ _store = store;
+ _checkinPreferences = [_store cachedCheckinPreferences];
+ _checkinService = checkinService;
+ _checkinHandlers = [NSMutableArray array];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [_scheduledCheckinTimer invalidate];
+}
+
+- (instancetype)initWithStore:(FIRInstanceIDStore *)store {
+ FIRInstanceIDCheckinService *checkinService = [[FIRInstanceIDCheckinService alloc] init];
+ return [self initWithCheckinService:checkinService store:store];
+}
+
+#pragma mark - Schedule Checkin
+
+- (void)scheduleCheckin:(BOOL)immediately {
+ // Checkin is still valid, so a remote checkin is not required.
+ if ([self.checkinPreferences hasValidCheckinInfo]) {
+ return;
+ }
+
+ // Checkin is already scheduled, so this (non-immediate) request can be ignored.
+ if (!immediately && [self.scheduledCheckinTimer isValid]) {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService000,
+ @"Checkin sync already scheduled. Will not schedule.");
+ return;
+ }
+
+ if (immediately) {
+ [self performScheduledCheckin];
+ } else {
+ int64_t checkinRetryDuration = [self calculateNextCheckinRetryIntervalInSeconds];
+ [self startCheckinTimerWithDuration:(NSTimeInterval)checkinRetryDuration];
+ }
+}
+
+- (void)startCheckinTimerWithDuration:(NSTimeInterval)timerDuration {
+ self.scheduledCheckinTimer =
+ [NSTimer scheduledTimerWithTimeInterval:timerDuration
+ target:self
+ selector:@selector(onScheduledCheckinTimerFired:)
+ userInfo:nil
+ repeats:NO];
+ // Add some tolerance to the timer, to allow iOS to be more flexible with this timer
+ self.scheduledCheckinTimer.tolerance = 0.5;
+}
+
+- (void)clearScheduledCheckinTimer {
+ [self.scheduledCheckinTimer invalidate];
+ self.scheduledCheckinTimer = nil;
+}
+
+- (void)onScheduledCheckinTimerFired:(NSTimer *)timer {
+ [self performScheduledCheckin];
+}
+
+- (void)performScheduledCheckin {
+ // No checkin scheduled as of now.
+ [self clearScheduledCheckinTimer];
+
+ // Checkin is still valid, so a remote checkin is not required.
+ if ([self.checkinPreferences hasValidCheckinInfo]) {
+ return;
+ }
+
+ FIRInstanceID_WEAKIFY(self);
+ [self
+ fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, NSError *error) {
+ FIRInstanceID_STRONGIFY(self);
+ self.checkinRetryCount++;
+
+ if (error) {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService001, @"Checkin error %@.",
+ error);
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ // Schedule another checkin
+ [self scheduleCheckin:NO];
+ });
+
+ } else {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService002, @"Checkin success.");
+ }
+ }];
+}
+
+- (int64_t)calculateNextCheckinRetryIntervalInSeconds {
+ // persistent failures can lead to overflow prevent that.
+ if (self.checkinRetryCount >= 10) {
+ return kMaxCheckinRetryIntervalInSeconds;
+ }
+ return MIN(1 << self.checkinRetryCount, kMaxCheckinRetryIntervalInSeconds);
+}
+
+#pragma mark - Checkin Service
+
+- (BOOL)hasValidCheckinInfo {
+ return [self.checkinPreferences hasValidCheckinInfo];
+}
+
+- (void)fetchCheckinInfoWithHandler:(nonnull FIRInstanceIDDeviceCheckinCompletion)handler {
+ // Perform any changes to self.checkinHandlers and _isCheckinInProgress in a thread-safe way.
+ @synchronized(self) {
+ [self.checkinHandlers addObject:handler];
+
+ if (_isCheckinInProgress) {
+ // Nothing more to do until our checkin request is done
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthServiceCheckinInProgress,
+ @"Checkin is in progress\n");
+ return;
+ }
+ }
+
+ // Checkin is still valid, so a remote checkin is not required.
+ if ([self.checkinPreferences hasValidCheckinInfo]) {
+ [self notifyCheckinHandlersWithCheckin:self.checkinPreferences error:nil];
+ return;
+ }
+
+ @synchronized(self) {
+ _isCheckinInProgress = YES;
+ }
+ [self.checkinService
+ checkinWithExistingCheckin:self.checkinPreferences
+ completion:^(FIRInstanceIDCheckinPreferences *checkinPreferences,
+ NSError *error) {
+ @synchronized(self) {
+ self->_isCheckinInProgress = NO;
+ }
+ if (error) {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService003,
+ @"Failed to checkin device %@", error);
+ [self notifyCheckinHandlersWithCheckin:nil error:error];
+ return;
+ }
+
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService004,
+ @"Successfully got checkin credentials");
+ BOOL hasSameCachedPreferences =
+ [self cachedCheckinMatchesCheckin:checkinPreferences];
+ checkinPreferences.hasPreCachedAuthCredentials = hasSameCachedPreferences;
+
+ // Update to the most recent checkin preferences
+ self.checkinPreferences = checkinPreferences;
+
+ // Save the checkin info to disk
+ // Keychain might not be accessible, so confirm that checkin preferences can
+ // be saved
+ [self.store
+ saveCheckinPreferences:checkinPreferences
+ handler:^(NSError *checkinSaveError) {
+ if (checkinSaveError && !hasSameCachedPreferences) {
+ // The checkin info was new, but it couldn't be
+ // written to the Keychain. Delete any stuff that was
+ // cached in memory. This doesn't delete any
+ // previously persisted preferences.
+ FIRInstanceIDLoggerError(
+ kFIRInstanceIDMessageCodeService004,
+ @"Unable to save checkin info, resetting "
+ @"checkin preferences "
+ "in memory.");
+ [checkinPreferences reset];
+ [self
+ notifyCheckinHandlersWithCheckin:nil
+ error:
+ checkinSaveError];
+ } else {
+ // The checkin is either new, or it was the same (and
+ // it couldn't be saved). Either way, report that the
+ // checkin preferences were received successfully.
+ [self notifyCheckinHandlersWithCheckin:
+ checkinPreferences
+ error:nil];
+ if (!hasSameCachedPreferences) {
+ // Checkin is new.
+ // Notify any listeners that might be waiting for
+ // checkin to be fetched, such as Firebase
+ // Messaging (for its MCS connection).
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [[NSNotificationCenter defaultCenter]
+ postNotificationName:
+ kFIRInstanceIDCheckinFetchedNotification
+ object:nil];
+ });
+ }
+ }
+ }];
+ }];
+}
+
+- (FIRInstanceIDCheckinPreferences *)checkinPreferences {
+ return _checkinPreferences;
+}
+
+- (void)stopCheckinRequest {
+ [self.checkinService stopFetching];
+}
+
+- (void)resetCheckinWithHandler:(void (^)(NSError *error))handler {
+ [self.store removeCheckinPreferencesWithHandler:^(NSError *error) {
+ if (!error) {
+ self.checkinPreferences = nil;
+ }
+ if (handler) {
+ handler(error);
+ }
+ }];
+}
+
+#pragma mark - Private
+
+/**
+ * Goes through the current list of checkin handlers and fires them with the same checkin and/or
+ * error info. The checkin handlers will get cleared after.
+ */
+- (void)notifyCheckinHandlersWithCheckin:(nullable FIRInstanceIDCheckinPreferences *)checkin
+ error:(nullable NSError *)error {
+ @synchronized(self) {
+ for (FIRInstanceIDDeviceCheckinCompletion handler in self.checkinHandlers) {
+ handler(checkin, error);
+ }
+ [self.checkinHandlers removeAllObjects];
+ }
+}
+
+/**
+ * Given a |checkin|, it will compare it to the current checkinPreferences to see if the
+ * deviceID and secretToken are the same.
+ */
+- (BOOL)cachedCheckinMatchesCheckin:(FIRInstanceIDCheckinPreferences *)checkin {
+ if (self.checkinPreferences && checkin) {
+ return ([self.checkinPreferences.deviceID isEqualToString:checkin.deviceID] &&
+ [self.checkinPreferences.secretToken isEqualToString:checkin.secretToken]);
+ }
+ return NO;
+}
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h
new file mode 100644
index 0000000..bccaced
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h
@@ -0,0 +1,81 @@
+/*
+ * 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
+
+@interface FIRInstanceIDBackupExcludedPlist : NSObject
+
+/**
+ * Caches the plist contents in memory so we don't hit the disk each time we want
+ * to query something in the plist. This is loaded lazily i.e. if you write to the
+ * plist the contents you want to write will be stored here if the write was
+ * successful. The other case where it is loaded is if you read the plist contents
+ * by calling `contentAsDictionary`.
+ *
+ * In case you write to the plist and then try to read the file using
+ * `contentAsDictionary` we would just return the cachedPlistContents since it would
+ * represent the disk contents.
+ */
+@property(nonatomic, readonly, strong) NSDictionary *cachedPlistContents;
+
+/**
+ * Init a backup excluded plist file.
+ *
+ * @param fileName The filename for the plist file.
+ * @param subDirectory The subdirectory in Application Support to save the plist.
+ *
+ * @return Helper which allows to read write data to a backup excluded plist.
+ */
+- (instancetype)initWithFileName:(NSString *)fileName subDirectory:(NSString *)subDirectory;
+
+/**
+ * Write dictionary data to the backup excluded plist file. If the file does not exist
+ * it would be created before writing to it.
+ *
+ * @param dict The data to be written to the plist.
+ * @param error The error object if any while writing the data.
+ *
+ * @return YES if the write was successful else NO.
+ */
+- (BOOL)writeDictionary:(NSDictionary *)dict error:(NSError **)error;
+
+/**
+ * Delete the backup excluded plist created with the above filename.
+ *
+ * @param error The error object if any while deleting the file.
+ *
+ * @return YES If the delete was successful else NO.
+ */
+- (BOOL)deleteFile:(NSError **)error;
+
+/**
+ * The contents of the plist file. We also store the contents of the file in-memory.
+ * If the in-memory contents are valid we return the in-memory contents else we read
+ * the file from disk.
+ *
+ * @return A dictionary object that contains the contents of the plist file if the file
+ * exists else nil.
+ */
+- (NSDictionary *)contentAsDictionary;
+
+/**
+ * Check if the plist exists on the disk or not.
+ *
+ * @return YES if the file exists on the disk else NO.
+ */
+- (BOOL)doesFileExist;
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m
new file mode 100644
index 0000000..ca930e6
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m
@@ -0,0 +1,202 @@
+/*
+ * 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 "FIRInstanceIDBackupExcludedPlist.h"
+
+#import "FIRInstanceIDLogger.h"
+
+typedef enum : NSUInteger {
+ FIRInstanceIDPlistDirectoryUnknown,
+ FIRInstanceIDPlistDirectoryDocuments,
+ FIRInstanceIDPlistDirectoryApplicationSupport,
+} FIRInstanceIDPlistDirectory;
+
+@interface FIRInstanceIDBackupExcludedPlist ()
+
+@property(nonatomic, readwrite, copy) NSString *fileName;
+@property(nonatomic, readwrite, copy) NSString *subDirectoryName;
+@property(nonatomic, readwrite, assign) BOOL fileInStandardDirectory;
+
+@property(nonatomic, readwrite, strong) NSDictionary *cachedPlistContents;
+
+@end
+
+@implementation FIRInstanceIDBackupExcludedPlist
+
+- (instancetype)initWithFileName:(NSString *)fileName subDirectory:(NSString *)subDirectory {
+ self = [super init];
+ if (self) {
+ _fileName = [fileName copy];
+ _subDirectoryName = [subDirectory copy];
+#if TARGET_OS_IOS
+ _fileInStandardDirectory = [self moveToApplicationSupportSubDirectory:subDirectory];
+#else
+ // For tvOS and macOS, we never store the content in document folder, so
+ // the migration is unnecessary.
+ _fileInStandardDirectory = YES;
+#endif
+ }
+ return self;
+}
+
+- (BOOL)writeDictionary:(NSDictionary *)dict error:(NSError **)error {
+ NSString *path = [self plistPathInDirectory:[self plistDirectory]];
+ if (![dict writeToFile:path atomically:YES]) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist000,
+ @"Failed to write to %@.plist", self.fileName);
+ return NO;
+ }
+
+ // Successfully wrote contents -- change the in-memory contents
+ self.cachedPlistContents = [dict copy];
+
+ NSURL *URL = [NSURL fileURLWithPath:path];
+ if (error) {
+ *error = nil;
+ }
+
+ NSDictionary *preferences = [URL resourceValuesForKeys:@[ NSURLIsExcludedFromBackupKey ]
+ error:error];
+ if ([preferences[NSURLIsExcludedFromBackupKey] boolValue]) {
+ return YES;
+ }
+
+ BOOL success = [URL setResourceValue:@(YES) forKey:NSURLIsExcludedFromBackupKey error:error];
+ if (!success) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist001,
+ @"Error excluding %@ from backup, %@", [URL lastPathComponent],
+ error ? *error : @"");
+ }
+ return success;
+}
+
+- (BOOL)deleteFile:(NSError **)error {
+ BOOL success = YES;
+ NSString *path = [self plistPathInDirectory:[self plistDirectory]];
+ if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
+ success = [[NSFileManager defaultManager] removeItemAtPath:path error:error];
+ }
+ // remove the in-memory contents
+ self.cachedPlistContents = nil;
+ return success;
+}
+
+- (NSDictionary *)contentAsDictionary {
+ if (!self.cachedPlistContents) {
+ NSString *path = [self plistPathInDirectory:[self plistDirectory]];
+ if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
+ self.cachedPlistContents = [[NSDictionary alloc] initWithContentsOfFile:path];
+ }
+ }
+ return self.cachedPlistContents;
+}
+
+- (BOOL)moveToApplicationSupportSubDirectory:(NSString *)subDirectoryName {
+ NSArray *directoryPaths =
+ NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES);
+ // This only going to happen inside iOS so it is an applicationSupportDirectory.
+ NSString *applicationSupportDirPath = directoryPaths.lastObject;
+ NSArray *components = @[ applicationSupportDirPath, subDirectoryName ];
+ NSString *subDirectoryPath = [NSString pathWithComponents:components];
+ BOOL hasSubDirectory;
+ if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath
+ isDirectory:&hasSubDirectory]) {
+ // Cannot move to non-existent directory
+ return NO;
+ }
+
+ if ([self doesFileExistInDirectory:FIRInstanceIDPlistDirectoryDocuments]) {
+ NSString *oldPlistPath = [self plistPathInDirectory:FIRInstanceIDPlistDirectoryDocuments];
+ NSString *newPlistPath =
+ [self plistPathInDirectory:FIRInstanceIDPlistDirectoryApplicationSupport];
+ if ([self doesFileExistInDirectory:FIRInstanceIDPlistDirectoryApplicationSupport]) {
+ // File exists in both Documents and ApplicationSupport
+ return NO;
+ }
+ NSError *moveError;
+ if (![[NSFileManager defaultManager] moveItemAtPath:oldPlistPath
+ toPath:newPlistPath
+ error:&moveError]) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist002,
+ @"Failed to move file %@ from %@ to %@. Error: %@", self.fileName,
+ oldPlistPath, newPlistPath, moveError);
+ return NO;
+ }
+ }
+ // We moved the file if it existed, otherwise we didn't need to do anything
+ return YES;
+}
+
+- (BOOL)doesFileExist {
+ return [self doesFileExistInDirectory:[self plistDirectory]];
+}
+
+#pragma mark - Private
+
+- (FIRInstanceIDPlistDirectory)plistDirectory {
+ if (_fileInStandardDirectory) {
+ return FIRInstanceIDPlistDirectoryApplicationSupport;
+ } else {
+ return FIRInstanceIDPlistDirectoryDocuments;
+ };
+}
+
+- (NSString *)plistPathInDirectory:(FIRInstanceIDPlistDirectory)directory {
+ return [self pathWithName:self.fileName inDirectory:directory];
+}
+
+- (NSString *)pathWithName:(NSString *)plistName
+ inDirectory:(FIRInstanceIDPlistDirectory)directory {
+ NSArray *directoryPaths;
+ NSArray *components = @[];
+ NSString *plistNameWithExtension = [NSString stringWithFormat:@"%@.plist", plistName];
+ switch (directory) {
+ case FIRInstanceIDPlistDirectoryDocuments:
+ directoryPaths =
+ NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+ components = @[ directoryPaths.lastObject, plistNameWithExtension ];
+ break;
+
+ case FIRInstanceIDPlistDirectoryApplicationSupport:
+ directoryPaths =
+ NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES);
+ components = @[ directoryPaths.lastObject, _subDirectoryName, plistNameWithExtension ];
+ break;
+
+ default:
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlistInvalidPlistEnum,
+ @"Invalid plist directory type: %lu", (unsigned long)directory);
+ NSAssert(NO, @"Invalid plist directory type: %lu", (unsigned long)directory);
+ break;
+ }
+
+ return [NSString pathWithComponents:components];
+}
+
+- (BOOL)doesFileExistInDirectory:(FIRInstanceIDPlistDirectory)directory {
+ NSString *path = [self plistPathInDirectory:directory];
+ return [[NSFileManager defaultManager] fileExistsAtPath:path];
+}
+
+- (NSSearchPathDirectory)supportedDirectory {
+#if TARGET_OS_TV
+ return NSCachesDirectory;
+#else
+ return NSApplicationSupportDirectory;
+#endif
+}
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h
new file mode 100644
index 0000000..a62fad1
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "FIRInstanceIDCheckinPreferences.h"
+
+@interface FIRInstanceIDCheckinPreferences (Internal)
+
+/**
+ * Parse the checkin auth credentials saved in the Keychain to initialize checkin
+ * preferences.
+ *
+ * @param keychainContent The checkin auth credentials saved in the Keychain.
+ *
+ * @return A valid checkin preferences object if the checkin auth credentials in the
+ * keychain can be parsed successfully else nil.
+ */
++ (FIRInstanceIDCheckinPreferences *)preferencesFromKeychainContents:(NSString *)keychainContent;
+
+/**
+ * Default initializer for InstanceID checkin preferences.
+ *
+ * @param deviceID The deviceID for the app.
+ * @param secretToken The secret token the app uses to authenticate with the server.
+ *
+ * @return A checkin preferences object with given deviceID and secretToken.
+ */
+- (instancetype)initWithDeviceID:(NSString *)deviceID secretToken:(NSString *)secretToken;
+
+/**
+ * Update checkin preferences from the preferences dict persisted as a plist. The dict contains
+ * all the checkin preferences retrieved from the server except the deviceID and secret which
+ * are stored in the Keychain.
+ *
+ * @param checkinPlistContent The checkin preferences saved in a plist on the disk.
+ */
+- (void)updateWithCheckinPlistContents:(NSDictionary *)checkinPlistContent;
+
+/**
+ * Reset the current checkin preferences object.
+ */
+- (void)reset;
+
+/**
+ * The string that contains the checkin auth credentials i.e. deviceID and secret. This
+ * needs to be stored in the Keychain.
+ *
+ * @return The checkin auth credential string containing the deviceID and secret.
+ */
+- (NSString *)checkinKeychainContent;
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m
new file mode 100644
index 0000000..88cc40a
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m
@@ -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 "FIRInstanceIDCheckinPreferences+Internal.h"
+
+#import "FIRInstanceIDCheckinService.h"
+#import "FIRInstanceIDUtilities.h"
+
+static NSString *const kCheckinKeychainContentSeparatorString = @"|";
+
+@interface FIRInstanceIDCheckinPreferences ()
+
+@property(nonatomic, readwrite, copy) NSString *deviceID;
+@property(nonatomic, readwrite, copy) NSString *secretToken;
+@property(nonatomic, readwrite, copy) NSString *digest;
+@property(nonatomic, readwrite, copy) NSString *versionInfo;
+@property(nonatomic, readwrite, copy) NSString *deviceDataVersion;
+
+@property(nonatomic, readwrite, strong) NSMutableDictionary *gServicesData;
+@property(nonatomic, readwrite, assign) int64_t lastCheckinTimestampMillis;
+
+@end
+
+@implementation FIRInstanceIDCheckinPreferences (Internal)
+
++ (FIRInstanceIDCheckinPreferences *)preferencesFromKeychainContents:(NSString *)keychainContent {
+ NSString *deviceID = [self checkinDeviceIDFromKeychainContent:keychainContent];
+ NSString *secret = [self checkinSecretFromKeychainContent:keychainContent];
+ if ([deviceID length] && [secret length]) {
+ return [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:deviceID secretToken:secret];
+ } else {
+ return nil;
+ }
+}
+
+- (instancetype)initWithDeviceID:(NSString *)deviceID secretToken:(NSString *)secretToken {
+ self = [super init];
+ if (self) {
+ self.deviceID = [deviceID copy];
+ self.secretToken = [secretToken copy];
+ }
+ return self;
+}
+
+- (void)reset {
+ self.deviceID = nil;
+ self.secretToken = nil;
+ self.digest = nil;
+ self.versionInfo = nil;
+ self.gServicesData = nil;
+ self.deviceDataVersion = nil;
+ self.lastCheckinTimestampMillis = 0;
+}
+
+- (void)updateWithCheckinPlistContents:(NSDictionary *)checkinPlistContent {
+ for (NSString *key in checkinPlistContent) {
+ if ([kFIRInstanceIDDigestStringKey isEqualToString:key]) {
+ self.digest = [checkinPlistContent[key] copy];
+ } else if ([kFIRInstanceIDVersionInfoStringKey isEqualToString:key]) {
+ self.versionInfo = [checkinPlistContent[key] copy];
+ } else if ([kFIRInstanceIDLastCheckinTimeKey isEqualToString:key]) {
+ self.lastCheckinTimestampMillis = [checkinPlistContent[key] longLongValue];
+ } else if ([kFIRInstanceIDGServicesDictionaryKey isEqualToString:key]) {
+ self.gServicesData = [checkinPlistContent[key] mutableCopy];
+ } else if ([kFIRInstanceIDDeviceDataVersionKey isEqualToString:key]) {
+ self.deviceDataVersion = [checkinPlistContent[key] copy];
+ }
+ // Otherwise we have some keys we don't care about
+ }
+}
+
+- (NSString *)checkinKeychainContent {
+ if ([self.deviceID length] && [self.secretToken length]) {
+ return [NSString stringWithFormat:@"%@%@%@", self.deviceID,
+ kCheckinKeychainContentSeparatorString, self.secretToken];
+ } else {
+ return nil;
+ }
+}
+
++ (NSString *)checkinDeviceIDFromKeychainContent:(NSString *)keychainContent {
+ return [self checkinKeychainContent:keychainContent forIndex:0];
+}
+
++ (NSString *)checkinSecretFromKeychainContent:(NSString *)keychainContent {
+ return [self checkinKeychainContent:keychainContent forIndex:1];
+}
+
++ (NSString *)checkinKeychainContent:(NSString *)keychainContent forIndex:(int)index {
+ NSArray *keychainComponents =
+ [keychainContent componentsSeparatedByString:kCheckinKeychainContentSeparatorString];
+ if (index >= 0 && index < 2 && [keychainComponents count] == 2) {
+ return keychainComponents[index];
+ } else {
+ return nil;
+ }
+}
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.h
new file mode 100644
index 0000000..be3ec57
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.h
@@ -0,0 +1,62 @@
+/*
+ * 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
+
+/**
+ * The preferences InstanceID loads from checkin server. The deviceID and secret that checkin
+ * provides is used to authenticate all future requests to the server. Besides the deviceID
+ * and secret the other information that checkin provides is stored in a plist on the device.
+ * The deviceID and secret are persisted in the device keychain.
+ */
+@interface FIRInstanceIDCheckinPreferences : NSObject
+
+/**
+ * DeviceID and secretToken are the checkin auth credentials and are stored in the Keychain.
+ */
+@property(nonatomic, readonly, copy) NSString *deviceID;
+@property(nonatomic, readonly, copy) NSString *secretToken;
+
+/**
+ * All the other checkin preferences other than deviceID and secret are stored in a plist.
+ */
+@property(nonatomic, readonly, copy) NSString *deviceDataVersion;
+@property(nonatomic, readonly, copy) NSString *digest;
+@property(nonatomic, readonly, copy) NSString *versionInfo;
+@property(nonatomic, readonly, assign) int64_t lastCheckinTimestampMillis;
+
+/**
+ * The content retrieved from checkin server that should be persisted in a plist. This
+ * doesn't contain the deviceID and secret which are stored in the Keychain since they
+ * should be more private.
+ *
+ * @return The checkin preferences that should be persisted in a plist.
+ */
+- (NSDictionary *)checkinPlistContents;
+
+/**
+ * Return whether checkin info exists, valid or not.
+ */
+- (BOOL)hasCheckinInfo;
+
+/**
+ * Verify if checkin preferences are valid or not.
+ *
+ * @return YES if valid checkin preferences else NO.
+ */
+- (BOOL)hasValidCheckinInfo;
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m
new file mode 100644
index 0000000..2f3c55e
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m
@@ -0,0 +1,95 @@
+/*
+ * 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 "FIRInstanceIDCheckinPreferences.h"
+
+#import
+#import "FIRInstanceIDCheckinService.h"
+#import "FIRInstanceIDUtilities.h"
+
+const NSTimeInterval kFIRInstanceIDDefaultCheckinInterval = 7 * 24 * 60 * 60; // 7 days.
+
+@interface FIRInstanceIDCheckinPreferences ()
+
+@property(nonatomic, readwrite, copy) NSString *deviceID;
+@property(nonatomic, readwrite, copy) NSString *secretToken;
+@property(nonatomic, readwrite, copy) NSString *digest;
+@property(nonatomic, readwrite, copy) NSString *versionInfo;
+@property(nonatomic, readwrite, copy) NSString *deviceDataVersion;
+
+@property(nonatomic, readwrite, strong) NSMutableDictionary *gServicesData;
+@property(nonatomic, readwrite, assign) int64_t lastCheckinTimestampMillis;
+
+// This flag indicates that we have already saved the above deviceID and secret
+// to our keychain and hence we don't need to save again. This is helpful since
+// on checkin refresh we can avoid writing to the Keychain which can sometimes
+// be very buggy. For info check this https://forums.developer.apple.com/thread/4743
+@property(nonatomic, readwrite, assign) BOOL hasPreCachedAuthCredentials;
+
+@end
+
+@implementation FIRInstanceIDCheckinPreferences
+
+- (NSDictionary *)checkinPlistContents {
+ NSMutableDictionary *checkinPlistContents = [NSMutableDictionary dictionary];
+ checkinPlistContents[kFIRInstanceIDDigestStringKey] = self.digest ?: @"";
+ checkinPlistContents[kFIRInstanceIDVersionInfoStringKey] = self.versionInfo ?: @"";
+ checkinPlistContents[kFIRInstanceIDDeviceDataVersionKey] = self.deviceDataVersion ?: @"";
+ checkinPlistContents[kFIRInstanceIDLastCheckinTimeKey] = @(self.lastCheckinTimestampMillis);
+ checkinPlistContents[kFIRInstanceIDGServicesDictionaryKey] =
+ [self.gServicesData count] ? self.gServicesData : @{};
+ return checkinPlistContents;
+}
+
+- (BOOL)hasCheckinInfo {
+ return (self.deviceID.length && self.secretToken.length);
+}
+
+- (BOOL)hasValidCheckinInfo {
+ int64_t currentTimestampInMillis = FIRInstanceIDCurrentTimestampInMilliseconds();
+ int64_t timeSinceLastCheckinInMillis = currentTimestampInMillis - self.lastCheckinTimestampMillis;
+
+ BOOL hasCheckinInfo = [self hasCheckinInfo];
+ NSString *lastLocale =
+ [[GULUserDefaults standardUserDefaults] stringForKey:kFIRInstanceIDUserDefaultsKeyLocale];
+ // If it's app's first time open and checkin is already fetched and no locale information is
+ // stored, then checkin info is valid. We should not checkin again because locale is considered
+ // "changed".
+ if (hasCheckinInfo && !lastLocale) {
+ NSString *currentLocale = FIRInstanceIDCurrentLocale();
+ [[GULUserDefaults standardUserDefaults] setObject:currentLocale
+ forKey:kFIRInstanceIDUserDefaultsKeyLocale];
+ return YES;
+ }
+
+ // If locale has changed, checkin info is no longer valid.
+ // Also update locale information if changed. (Only do it here not in token refresh)
+ if (FIRInstanceIDHasLocaleChanged()) {
+ NSString *currentLocale = FIRInstanceIDCurrentLocale();
+ [[GULUserDefaults standardUserDefaults] setObject:currentLocale
+ forKey:kFIRInstanceIDUserDefaultsKeyLocale];
+ return NO;
+ }
+
+ return (hasCheckinInfo &&
+ (timeSinceLastCheckinInMillis / 1000.0 < kFIRInstanceIDDefaultCheckinInterval));
+}
+
+- (void)setHasPreCachedAuthCredentials:(BOOL)hasPreCachedAuthCredentials {
+ _hasPreCachedAuthCredentials = hasPreCachedAuthCredentials;
+}
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h
new file mode 100644
index 0000000..23b55e1
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h
@@ -0,0 +1,27 @@
+/*
+ * 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 "FIRInstanceIDCheckinPreferences.h"
+
+/** Checkin refresh interval. **/
+FOUNDATION_EXPORT const NSTimeInterval kFIRInstanceIDDefaultCheckinInterval;
+
+@interface FIRInstanceIDCheckinPreferences ()
+
+- (BOOL)hasPreCachedAuthCredentials;
+- (void)setHasPreCachedAuthCredentials:(BOOL)hasPreCachedAuthCredentials;
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h
new file mode 100644
index 0000000..cc97e47
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h
@@ -0,0 +1,81 @@
+/*
+ * 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
+
+#import "FIRInstanceIDUtilities.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+// keys in Checkin preferences
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDDeviceAuthIdKey;
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDSecretTokenKey;
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDDigestStringKey;
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDLastCheckinTimeKey;
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDVersionInfoStringKey;
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDGServicesDictionaryKey;
+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
+ * `FIRInstanceIDCache` and periodically refreshed to prevent them from being stale.
+ * Each client needs to register with checkin before registering with InstanceID.
+ */
+@interface FIRInstanceIDCheckinService : NSObject
+
+/**
+ * Execute a device checkin request to obtain an deviceID, secret token,
+ * gService data.
+ *
+ * @param existingCheckin An existing checkin preference object, if available.
+ * @param completion Completion hander called on success or failure of device checkin.
+ */
+- (void)checkinWithExistingCheckin:(nullable FIRInstanceIDCheckinPreferences *)existingCheckin
+ completion:(FIRInstanceIDDeviceCheckinCompletion)completion;
+
+/**
+ * This would stop any request that the service made to the checkin backend and also
+ * release any callback handlers that it holds.
+ */
+- (void)stopFetching;
+
+/**
+ * Set test block for mock testing network requests.
+ *
+ * @param block The block to invoke as a mock response from the network.
+ */
++ (void)setCheckinTestBlock:(nullable FIRInstanceIDURLRequestTestBlock)block;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m
new file mode 100644
index 0000000..6d2b5ff
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m
@@ -0,0 +1,244 @@
+/*
+ * 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 "FIRInstanceIDCheckinService.h"
+
+#import "FIRInstanceIDCheckinPreferences+Internal.h"
+#import "FIRInstanceIDCheckinPreferences_Private.h"
+#import "FIRInstanceIDDefines.h"
+#import "FIRInstanceIDLogger.h"
+#import "FIRInstanceIDStore.h"
+#import "FIRInstanceIDUtilities.h"
+#import "NSError+FIRInstanceID.h"
+
+static NSString *const kDeviceCheckinURL = @"https://device-provisioning.googleapis.com/checkin";
+
+// keys in Checkin preferences
+NSString *const kFIRInstanceIDDeviceAuthIdKey = @"GMSInstanceIDDeviceAuthIdKey";
+NSString *const kFIRInstanceIDSecretTokenKey = @"GMSInstanceIDSecretTokenKey";
+NSString *const kFIRInstanceIDDigestStringKey = @"GMSInstanceIDDigestKey";
+NSString *const kFIRInstanceIDLastCheckinTimeKey = @"GMSInstanceIDLastCheckinTimestampKey";
+NSString *const kFIRInstanceIDVersionInfoStringKey = @"GMSInstanceIDVersionInfo";
+NSString *const kFIRInstanceIDGServicesDictionaryKey = @"GMSInstanceIDGServicesData";
+NSString *const kFIRInstanceIDDeviceDataVersionKey = @"GMSInstanceIDDeviceDataVersion";
+
+static NSUInteger const kCheckinType = 2; // DeviceType IOS in l/w/a/_checkin.proto
+static NSUInteger const kCheckinVersion = 2;
+static NSUInteger const kFragment = 0;
+
+static FIRInstanceIDURLRequestTestBlock testBlock;
+
+@interface FIRInstanceIDCheckinService ()
+
+@property(nonatomic, readwrite, strong) NSURLSession *session;
+
+@end
+
+@implementation FIRInstanceIDCheckinService
+;
+
+- (instancetype)init {
+ self = [super init];
+ if (self) {
+ // Create an URLSession once, even though checkin should happen about once a day
+ NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
+ config.timeoutIntervalForResource = 60.0f; // 1 minute
+ config.allowsCellularAccess = YES;
+ _session = [NSURLSession sessionWithConfiguration:config];
+ _session.sessionDescription = @"com.google.iid-checkin";
+ }
+ return self;
+}
+
+- (void)dealloc {
+ testBlock = nil;
+ [self.session invalidateAndCancel];
+}
+
+- (void)checkinWithExistingCheckin:(FIRInstanceIDCheckinPreferences *)existingCheckin
+ completion:(FIRInstanceIDDeviceCheckinCompletion)completion {
+ if (self.session == nil) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDInvalidNetworkSession,
+ @"Inconsistent state: NSURLSession has been invalidated");
+ NSError *error =
+ [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn];
+ if (completion) {
+ completion(nil, error);
+ }
+ return;
+ }
+
+ NSURL *url = [NSURL URLWithString:kDeviceCheckinURL];
+ NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
+ [request setValue:@"application/json" forHTTPHeaderField:@"content-type"];
+ NSDictionary *checkinParameters = [self checkinParametersWithExistingCheckin:existingCheckin];
+ NSData *checkinData = [NSJSONSerialization dataWithJSONObject:checkinParameters
+ options:0
+ error:nil];
+ request.HTTPMethod = @"POST";
+ request.HTTPBody = checkinData;
+
+ void (^handler)(NSData *, NSURLResponse *, NSError *) =
+ ^(NSData *data, NSURLResponse *response, NSError *error) {
+ if (error) {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService000,
+ @"Device checkin HTTP fetch error. Error Code: %ld",
+ (long)error.code);
+ if (completion) {
+ completion(nil, error);
+ }
+ return;
+ }
+
+ NSError *serializationError;
+ NSDictionary *dataResponse = [NSJSONSerialization JSONObjectWithData:data
+ options:0
+ error:&serializationError];
+ if (serializationError) {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService001,
+ @"Error serializing json object. Error Code: %ld",
+ _FIRInstanceID_L(serializationError.code));
+ if (completion) {
+ completion(nil, serializationError);
+ }
+ return;
+ }
+
+ NSString *deviceAuthID = [dataResponse[@"android_id"] stringValue];
+ NSString *secretToken = [dataResponse[@"security_token"] stringValue];
+ if ([deviceAuthID length] == 0) {
+ NSError *error =
+ [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidRequest];
+ if (completion) {
+ completion(nil, error);
+ }
+ return;
+ }
+
+ int64_t lastCheckinTimestampMillis = [dataResponse[@"time_msec"] longLongValue];
+ int64_t currentTimestampMillis = FIRInstanceIDCurrentTimestampInMilliseconds();
+ // Somehow the server clock gets out of sync with the device clock.
+ // Reset the last checkin timestamp in case this happens.
+ if (lastCheckinTimestampMillis > currentTimestampMillis) {
+ FIRInstanceIDLoggerDebug(
+ kFIRInstanceIDMessageCodeService002, @"Invalid last checkin timestamp %@ in future.",
+ [NSDate dateWithTimeIntervalSince1970:lastCheckinTimestampMillis / 1000.0]);
+ lastCheckinTimestampMillis = currentTimestampMillis;
+ }
+
+ NSString *deviceDataVersionInfo = dataResponse[@"device_data_version_info"] ?: @"";
+ NSString *digest = dataResponse[@"digest"] ?: @"";
+
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService003,
+ @"Checkin successful with authId: %@, "
+ @"digest: %@, "
+ @"lastCheckinTimestamp: %lld",
+ deviceAuthID, digest, lastCheckinTimestampMillis);
+
+ NSString *versionInfo = dataResponse[@"version_info"] ?: @"";
+ NSMutableDictionary *gservicesData = [NSMutableDictionary dictionary];
+
+ // Read gServices data.
+ NSArray *flatSettings = dataResponse[@"setting"];
+ for (NSDictionary *dict in flatSettings) {
+ if (dict[@"name"] && dict[@"value"]) {
+ gservicesData[dict[@"name"]] = dict[@"value"];
+ } else {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDInvalidSettingResponse,
+ @"Invalid setting in checkin response: (%@: %@)",
+ dict[@"name"], dict[@"value"]);
+ }
+ }
+
+ FIRInstanceIDCheckinPreferences *checkinPreferences =
+ [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:deviceAuthID
+ secretToken:secretToken];
+ NSDictionary *preferences = @{
+ kFIRInstanceIDDigestStringKey : digest,
+ kFIRInstanceIDVersionInfoStringKey : versionInfo,
+ kFIRInstanceIDLastCheckinTimeKey : @(lastCheckinTimestampMillis),
+ kFIRInstanceIDGServicesDictionaryKey : gservicesData,
+ kFIRInstanceIDDeviceDataVersionKey : deviceDataVersionInfo,
+ };
+ [checkinPreferences updateWithCheckinPlistContents:preferences];
+ if (completion) {
+ completion(checkinPreferences, nil);
+ }
+ };
+ // Test block
+ if (testBlock) {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService005,
+ @"Test block set, will not hit the server");
+ testBlock(request, handler);
+ return;
+ }
+
+ NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request completionHandler:handler];
+ [task resume];
+}
+
+- (void)stopFetching {
+ [self.session invalidateAndCancel];
+ // The session cannot be reused after invalidation. Dispose it to prevent accident reusing.
+ self.session = nil;
+}
+
+#pragma mark - Private
+
+- (NSDictionary *)checkinParametersWithExistingCheckin:
+ (nullable FIRInstanceIDCheckinPreferences *)checkinPreferences {
+ NSString *deviceModel = FIRInstanceIDDeviceModel();
+ NSString *systemVersion = FIRInstanceIDOperatingSystemVersion();
+ NSString *osVersion = [NSString stringWithFormat:@"IOS_%@", systemVersion];
+
+ // Get locale from GCM if GCM exists else use system API.
+ NSString *locale = FIRInstanceIDCurrentLocale();
+
+ NSInteger userNumber = 0; // Multi Profile may change this.
+ NSInteger userSerialNumber = 0; // Multi Profile may change this
+
+ uint32_t loggingID = arc4random();
+ NSString *timeZone = [NSTimeZone localTimeZone].name;
+ int64_t lastCheckingTimestampMillis = checkinPreferences.lastCheckinTimestampMillis;
+
+ NSDictionary *checkinParameters = @{
+ @"checkin" : @{
+ @"iosbuild" : @{@"model" : deviceModel, @"os_version" : osVersion},
+ @"type" : @(kCheckinType),
+ @"user_number" : @(userNumber),
+ @"last_checkin_msec" : @(lastCheckingTimestampMillis),
+ },
+ @"fragment" : @(kFragment),
+ @"logging_id" : @(loggingID),
+ @"locale" : locale,
+ @"version" : @(kCheckinVersion),
+ @"digest" : checkinPreferences.digest ?: @"",
+ @"time_zone" : timeZone,
+ @"user_serial_number" : @(userSerialNumber),
+ @"id" : @([checkinPreferences.deviceID longLongValue]),
+ @"security_token" : @([checkinPreferences.secretToken longLongValue]),
+ };
+
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService006, @"Checkin parameters: %@",
+ checkinParameters);
+ return checkinParameters;
+}
+
++ (void)setCheckinTestBlock:(FIRInstanceIDURLRequestTestBlock)block {
+ testBlock = [block copy];
+}
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h
new file mode 100644
index 0000000..5e1b119
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h
@@ -0,0 +1,108 @@
+/*
+ * 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
+
+@class FIRInstanceIDAuthKeychain;
+@class FIRInstanceIDBackupExcludedPlist;
+@class FIRInstanceIDCheckinPreferences;
+
+// These values exposed for testing
+extern NSString *const kFIRInstanceIDCheckinKeychainService;
+extern NSString *const kFIRInstanceIDLegacyCheckinKeychainAccount;
+extern NSString *const kFIRInstanceIDLegacyCheckinKeychainService;
+
+/**
+ * Checkin preferences backing store.
+ */
+@interface FIRInstanceIDCheckinStore : NSObject
+
+/**
+ * Designated Initializer. Initialize a checkin store with the given backup excluded
+ * plist filename.
+ *
+ * @param checkinFilename The backup excluded plist filename to persist checkin
+ * preferences.
+ *
+ * @param subDirectoryName Sub-directory in standard directory where we write
+ * InstanceID plist.
+ *
+ * @return Store to persist checkin preferences.
+ */
+- (instancetype)initWithCheckinPlistFileName:(NSString *)checkinFilename
+ subDirectoryName:(NSString *)subDirectoryName;
+
+/**
+ * Initialize a checkin store with the given backup excluded plist and keychain.
+ *
+ * @param plist The backup excluded plist to persist checkin preferences.
+ * @param keychain The keychain used to persist checkin auth preferences.
+ *
+ * @return Store to persist checkin preferences.
+ */
+- (instancetype)initWithCheckinPlist:(FIRInstanceIDBackupExcludedPlist *)plist
+ keychain:(FIRInstanceIDAuthKeychain *)keychain;
+
+/**
+ * Checks whether the backup excluded checkin preferences are present on the disk or not.
+ *
+ * @return YES if the backup excluded checkin plist exists on the disks else NO.
+ */
+- (BOOL)hasCheckinPlist;
+
+#pragma mark - Save
+
+/**
+ * Save the checkin preferences to backing store.
+ *
+ * @param preferences Checkin preferences to save.
+ * @param handler The callback handler which is invoked when the operation is complete,
+ * with an error if there is any.
+ */
+- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences
+ handler:(void (^)(NSError *error))handler;
+
+#pragma mark - Delete
+
+/**
+ * Remove the cached checkin preferences.
+ *
+ * @param handler The callback handler which is invoked when the operation is complete,
+ * with an error if there is any.
+ */
+- (void)removeCheckinPreferencesWithHandler:(void (^)(NSError *error))handler;
+
+#pragma mark - Get
+
+/**
+ * Get the cached device secret. If we cannot access it for some reason we
+ * return the appropriate error object.
+ *
+ * @return The cached checkin preferences if present else nil.
+ */
+- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences;
+
+/**
+ * Migrate the checkin item from old service/account to the new one.
+ * The new account is dynamic as it uses bundle ID.
+ * This is to ensure checkin is not shared across apps, but still the same
+ * if app has used GCM before.
+ * This call should only happen once.
+ *
+ */
+- (void)migrateCheckinItemIfNeeded;
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m
new file mode 100644
index 0000000..99715a5
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m
@@ -0,0 +1,238 @@
+/*
+ * 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 "FIRInstanceIDCheckinStore.h"
+
+#import "FIRInstanceIDAuthKeyChain.h"
+#import "FIRInstanceIDBackupExcludedPlist.h"
+#import "FIRInstanceIDCheckinPreferences+Internal.h"
+#import "FIRInstanceIDCheckinPreferences_Private.h"
+#import "FIRInstanceIDCheckinService.h"
+#import "FIRInstanceIDLogger.h"
+#import "FIRInstanceIDUtilities.h"
+#import "FIRInstanceIDVersionUtilities.h"
+#import "NSError+FIRInstanceID.h"
+
+static NSString *const kFIRInstanceIDCheckinKeychainGeneric = @"com.google.iid";
+
+NSString *const kFIRInstanceIDCheckinKeychainService = @"com.google.iid.checkin";
+NSString *const kFIRInstanceIDLegacyCheckinKeychainAccount = @"com.google.iid.checkin-account";
+NSString *const kFIRInstanceIDLegacyCheckinKeychainService = @"com.google.iid.checkin-service";
+
+// Checkin plist used to have the deviceID and secret stored in them and that's why they
+// had 6 items in it. Since the deviceID and secret have been moved to the keychain
+// there would only be 4 items.
+static const NSInteger kOldCheckinPlistCount = 6;
+
+@interface FIRInstanceIDCheckinStore ()
+
+@property(nonatomic, readwrite, strong) FIRInstanceIDBackupExcludedPlist *plist;
+@property(nonatomic, readwrite, strong) FIRInstanceIDAuthKeychain *keychain;
+// Checkin will store items under
+// Keychain account: ,
+// Keychain service: |kFIRInstanceIDCheckinKeychainService|
+@property(nonatomic, readonly) NSString *bundleIdentifierForKeychainAccount;
+
+@end
+
+@implementation FIRInstanceIDCheckinStore
+
+- (instancetype)initWithCheckinPlistFileName:(NSString *)checkinFilename
+ subDirectoryName:(NSString *)subDirectoryName {
+ FIRInstanceIDBackupExcludedPlist *plist =
+ [[FIRInstanceIDBackupExcludedPlist alloc] initWithFileName:checkinFilename
+ subDirectory:subDirectoryName];
+
+ FIRInstanceIDAuthKeychain *keychain =
+ [[FIRInstanceIDAuthKeychain alloc] initWithIdentifier:kFIRInstanceIDCheckinKeychainGeneric];
+ return [self initWithCheckinPlist:plist keychain:keychain];
+}
+
+- (instancetype)initWithCheckinPlist:(FIRInstanceIDBackupExcludedPlist *)plist
+ keychain:(FIRInstanceIDAuthKeychain *)keychain {
+ self = [super init];
+ if (self) {
+ _plist = plist;
+ _keychain = keychain;
+ }
+ return self;
+}
+
+- (BOOL)hasCheckinPlist {
+ return [self.plist doesFileExist];
+}
+
+- (NSString *)bundleIdentifierForKeychainAccount {
+ static NSString *bundleIdentifier;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ bundleIdentifier = FIRInstanceIDAppIdentifier();
+ });
+ return bundleIdentifier;
+}
+
+- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences
+ handler:(void (^)(NSError *error))handler {
+ NSDictionary *checkinPlistContents = [preferences checkinPlistContents];
+ NSString *checkinKeychainContent = [preferences checkinKeychainContent];
+
+ if (![checkinKeychainContent length]) {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore000,
+ @"Failed to get checkin keychain content from memory.");
+ if (handler) {
+ handler([NSError
+ errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn]);
+ }
+ return;
+ }
+ if (![checkinPlistContents count]) {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore001,
+ @"Failed to get checkin plist contents from memory.");
+ if (handler) {
+ handler([NSError
+ errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn]);
+ }
+ return;
+ }
+
+ // Save all other checkin preferences in a plist
+ NSError *error;
+ if (![self.plist writeDictionary:checkinPlistContents error:&error]) {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore003,
+ @"Failed to save checkin plist contents."
+ @"Will delete auth credentials");
+ [self.keychain removeItemsMatchingService:kFIRInstanceIDCheckinKeychainService
+ account:self.bundleIdentifierForKeychainAccount
+ handler:nil];
+ if (handler) {
+ handler(error);
+ }
+ return;
+ }
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistSaved,
+ @"Checkin plist file is saved");
+
+ // Save the deviceID and secret in the Keychain
+ if (!preferences.hasPreCachedAuthCredentials) {
+ NSData *data = [checkinKeychainContent dataUsingEncoding:NSUTF8StringEncoding];
+ [self.keychain setData:data
+ forService:kFIRInstanceIDCheckinKeychainService
+ accessibility:nil
+ account:self.bundleIdentifierForKeychainAccount
+ handler:^(NSError *error) {
+ if (error) {
+ if (handler) {
+ handler(error);
+ }
+ return;
+ }
+ if (handler) {
+ handler(nil);
+ }
+ }];
+ } else {
+ handler(nil);
+ }
+}
+
+- (void)removeCheckinPreferencesWithHandler:(void (^)(NSError *error))handler {
+ // Delete the checkin preferences plist first to avoid delay.
+ NSError *deletePlistError;
+ if (![self.plist deleteFile:&deletePlistError]) {
+ handler(deletePlistError);
+ return;
+ }
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistDeleted,
+ @"Deleted checkin plist file.");
+ // Remove deviceID and secret from Keychain
+ [self.keychain
+ removeItemsMatchingService:kFIRInstanceIDCheckinKeychainService
+ account:self.bundleIdentifierForKeychainAccount
+ handler:^(NSError *error) {
+ // Try to remove from old location as well because migration
+ // is no longer needed. Consider this is either a fresh install
+ // or an identity wipe.
+ [self.keychain
+ removeItemsMatchingService:kFIRInstanceIDLegacyCheckinKeychainService
+ account:kFIRInstanceIDLegacyCheckinKeychainAccount
+ handler:nil];
+ handler(error);
+ }];
+}
+
+- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences {
+ // Query the keychain for deviceID and secret
+ NSData *item = [self.keychain dataForService:kFIRInstanceIDCheckinKeychainService
+ account:self.bundleIdentifierForKeychainAccount];
+
+ // Check info found in keychain
+ NSString *checkinKeychainContent = [[NSString alloc] initWithData:item
+ encoding:NSUTF8StringEncoding];
+ FIRInstanceIDCheckinPreferences *checkinPreferences =
+ [FIRInstanceIDCheckinPreferences preferencesFromKeychainContents:checkinKeychainContent];
+
+ NSDictionary *checkinPlistContents = [self.plist contentAsDictionary];
+
+ NSString *plistDeviceAuthID = checkinPlistContents[kFIRInstanceIDDeviceAuthIdKey];
+ NSString *plistSecretToken = checkinPlistContents[kFIRInstanceIDSecretTokenKey];
+
+ // If deviceID and secret not found in the keychain verify that we don't have them in the
+ // checkin preferences plist.
+ if (![checkinPreferences.deviceID length] && ![checkinPreferences.secretToken length]) {
+ if ([plistDeviceAuthID length] && [plistSecretToken length]) {
+ // Couldn't find checkin credentials in keychain but found them in the plist.
+ checkinPreferences =
+ [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:plistDeviceAuthID
+ secretToken:plistSecretToken];
+ } else {
+ // Couldn't find checkin credentials in keychain nor plist
+ return nil;
+ }
+ } else if (kOldCheckinPlistCount == checkinPlistContents.count) {
+ // same check as above but just to be extra sure that we cover all upgrade cases properly.
+ // TODO(chliangGoogle): Remove this case, after verifying it's not needed
+ if ([plistDeviceAuthID length] && [plistSecretToken length]) {
+ checkinPreferences =
+ [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:plistDeviceAuthID
+ secretToken:plistSecretToken];
+ }
+ }
+
+ [checkinPreferences updateWithCheckinPlistContents:checkinPlistContents];
+ return checkinPreferences;
+}
+
+- (void)migrateCheckinItemIfNeeded {
+ // Check for checkin in the old location, using the legacy keys
+ // Query the keychain for deviceID and secret
+ NSData *dataInOldLocation =
+ [self.keychain dataForService:kFIRInstanceIDLegacyCheckinKeychainService
+ account:kFIRInstanceIDLegacyCheckinKeychainAccount];
+ if (dataInOldLocation) {
+ // Save to new location
+ [self.keychain setData:dataInOldLocation
+ forService:kFIRInstanceIDCheckinKeychainService
+ accessibility:NULL
+ account:self.bundleIdentifierForKeychainAccount
+ handler:nil];
+ // Remove from old location
+ [self.keychain removeItemsMatchingService:kFIRInstanceIDLegacyCheckinKeychainService
+ account:kFIRInstanceIDLegacyCheckinKeychainAccount
+ handler:nil];
+ }
+}
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h
new file mode 100644
index 0000000..dcb5429
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * A generic class to combine several handler blocks into a single block in a thread-safe manner
+ */
+@interface FIRInstanceIDCombinedHandler : NSObject
+
+- (void)addHandler:(void (^)(ResultType _Nullable result, NSError* _Nullable error))handler;
+- (void (^)(ResultType _Nullable result, NSError* _Nullable error))combinedHandler;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m
new file mode 100644
index 0000000..bc6be6c
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "FIRInstanceIDCombinedHandler.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef void (^FIRInstanseIDHandler)(id _Nullable result, NSError *_Nullable error);
+
+@interface FIRInstanceIDCombinedHandler ()
+@property(atomic, readonly, strong) NSMutableArray *handlers;
+@end
+
+NS_ASSUME_NONNULL_END
+
+@implementation FIRInstanceIDCombinedHandler
+
+- (instancetype)init {
+ self = [super init];
+ if (self) {
+ _handlers = [NSMutableArray array];
+ }
+ return self;
+}
+
+- (void)addHandler:(FIRInstanseIDHandler)handler {
+ if (!handler) {
+ return;
+ }
+
+ @synchronized(self) {
+ [self.handlers addObject:handler];
+ }
+}
+
+- (FIRInstanseIDHandler)combinedHandler {
+ FIRInstanseIDHandler combinedHandler = nil;
+
+ @synchronized(self) {
+ NSArray *handlers = [self.handlers copy];
+ combinedHandler = ^(id result, NSError *error) {
+ for (FIRInstanseIDHandler handler in handlers) {
+ handler(result, error);
+ }
+ };
+ }
+
+ return combinedHandler;
+}
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h
new file mode 100644
index 0000000..cd2e131
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+#pragma mark - Commands
+
+/**
+ * Value included in a structured response or GCM message from IID, indicating
+ * an identity reset.
+ */
+FOUNDATION_EXPORT NSString *const kFIRInstanceID_CMD_RST;
+
+#pragma mark - Notifications
+
+/// Notification used to deliver GCM messages for InstanceID.
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDCheckinFetchedNotification;
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDAPNSTokenNotification;
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultGCMTokenNotification;
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultGCMTokenFailNotification;
+
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDIdentityInvalidatedNotification;
+
+#pragma mark - Miscellaneous
+
+/// The scope used to save the IID "*" scope token. This is used for saving the
+/// IID auth token that we receive from the server. This feature was never
+/// implemented on the server side.
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDAllScopeIdentifier;
+/// The scope used to save the IID "*" scope token.
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultTokenScope;
+
+/// Subdirectory in search path directory to store InstanceID preferences.
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDSubDirectoryName;
+
+/// The key for APNS token in options dictionary.
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsAPNSKey;
+
+/// The key for APNS token environment type in options dictionary.
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsAPNSIsSandboxKey;
+
+/// The key for GMP AppID sent in registration requests.
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsFirebaseAppIDKey;
+
+/// The key to enable auto-register by swizzling AppDelegate's methods.
+FOUNDATION_EXPORT NSString *const kFIRInstanceIDAppDelegateProxyEnabledInfoPlistKey;
+
+/// Error code for missing entitlements in Keychain. iOS Keychain error
+/// https://forums.developer.apple.com/thread/4743
+FOUNDATION_EXPORT const int kFIRInstanceIDSecMissingEntitlementErrorCode;
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m
new file mode 100644
index 0000000..81f4620
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m
@@ -0,0 +1,46 @@
+/*
+ * 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 "FIRInstanceIDConstants.h"
+
+// Commands
+NSString *const kFIRInstanceID_CMD_RST = @"RST";
+
+// NOTIFICATIONS
+NSString *const kFIRInstanceIDCheckinFetchedNotification = @"com.google.gcm.notif-checkin-fetched";
+NSString *const kFIRInstanceIDAPNSTokenNotification = @"com.firebase.iid.notif.apns-token";
+NSString *const kFIRInstanceIDDefaultGCMTokenNotification = @"com.firebase.iid.notif.fcm-token";
+NSString *const kFIRInstanceIDDefaultGCMTokenFailNotification =
+ @"com.firebase.iid.notif.fcm-token-fail";
+
+NSString *const kFIRInstanceIDIdentityInvalidatedNotification = @"com.google.iid.identity-invalid";
+
+// Miscellaneous
+NSString *const kFIRInstanceIDAllScopeIdentifier = @"iid-all";
+NSString *const kFIRInstanceIDDefaultTokenScope = @"*";
+NSString *const kFIRInstanceIDSubDirectoryName = @"Google/FirebaseInstanceID";
+
+// Registration Options
+NSString *const kFIRInstanceIDTokenOptionsAPNSKey = @"apns_token";
+NSString *const kFIRInstanceIDTokenOptionsAPNSIsSandboxKey = @"apns_sandbox";
+NSString *const kFIRInstanceIDTokenOptionsFirebaseAppIDKey = @"gmp_app_id";
+
+NSString *const kFIRInstanceIDAppDelegateProxyEnabledInfoPlistKey =
+ @"FirebaseAppDelegateProxyEnabled";
+
+// iOS Keychain error https://forums.developer.apple.com/thread/4743
+// An undocumented error code hence need to be redeclared.
+const int kFIRInstanceIDSecMissingEntitlementErrorCode = -34018;
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h
new file mode 100644
index 0000000..ccc25b3
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FIRInstanceIDLib_FIRInstanceIDDefines_h
+#define FIRInstanceIDLib_FIRInstanceIDDefines_h
+
+#define _FIRInstanceID_VERBOSE_LOGGING 1
+
+// Verbose Logging
+#if (_FIRInstanceID_VERBOSE_LOGGING)
+#define FIRInstanceID_DEV_VERBOSE_LOG(...) NSLog(__VA_ARGS__)
+#else
+#define FIRInstanceID_DEV_VERBOSE_LOG(...) \
+ do { \
+ } while (0)
+#endif // VERBOSE_LOGGING
+
+// WEAKIFY & STRONGIFY
+// Helper macro.
+#define _FIRInstanceID_WEAKNAME(VAR) VAR##_weak_
+
+#define FIRInstanceID_WEAKIFY(VAR) __weak __typeof__(VAR) _FIRInstanceID_WEAKNAME(VAR) = (VAR);
+
+#define FIRInstanceID_STRONGIFY(VAR) \
+ _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wshadow\"") \
+ __strong __typeof__(VAR) VAR = _FIRInstanceID_WEAKNAME(VAR); \
+ _Pragma("clang diagnostic pop")
+
+// Type Conversions (used for NSInteger etc)
+#ifndef _FIRInstanceID_L
+#define _FIRInstanceID_L(v) (long)(v)
+#endif
+
+#endif
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.h
new file mode 100644
index 0000000..a1aa5e1
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.h
@@ -0,0 +1,78 @@
+/*
+ * 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
+
+@interface FIRInstanceIDKeyPair : NSObject
+
+- (instancetype)init __attribute__((
+ unavailable("Use -initWithPrivateKey:publicKey:publicKeyData:privateKeyData: instead.")));
+;
+
+/**
+ * Initialize a new 2048 bit RSA keypair. This also stores the keypair in the Keychain
+ * Preferences.
+ *
+ * @param publicKey The publicKey stored in Keychain.
+ * @param privateKey The privateKey stored in Keychain.
+ * @param publicKeyData The publicKey in NSData format.
+ * @param privateKeyData The privateKey in NSData format.
+ *
+ * @return A new KeyPair instance with the generated public and private key.
+ */
+- (instancetype)initWithPrivateKey:(SecKeyRef)privateKey
+ publicKey:(SecKeyRef)publicKey
+ publicKeyData:(NSData *)publicKeyData
+ privateKeyData:(NSData *)privateKeyData NS_DESIGNATED_INITIALIZER;
+
+/**
+ * The public key in the RSA 20148 bit generated KeyPair.
+ *
+ * @return The 2048 bit RSA KeyPair's public key.
+ */
+@property(nonatomic, readonly, strong) NSData *publicKeyData;
+
+/**
+ * The private key in the RSA 20148 bit generated KeyPair.
+ *
+ * @return The 2048 bit RSA KeyPair's private key.
+ */
+@property(nonatomic, readonly, strong) NSData *privateKeyData;
+
+#pragma mark - Info
+
+/**
+ * Checks if the private and public keyPair are valid or not.
+ *
+ * @return YES if keypair is valid else NO.
+ */
+- (BOOL)isValid;
+
+/**
+ * The public key in the RSA 2048 bit generated KeyPair.
+ *
+ * @return The 2048 bit RSA KeyPair's public key.
+ */
+- (SecKeyRef)publicKey;
+
+/**
+ * The private key in the RSA 2048 bit generated KeyPair.
+ *
+ * @return The 2048 bit RSA KeyPair's private key.
+ */
+- (SecKeyRef)privateKey;
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.m
new file mode 100644
index 0000000..52b27c2
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPair.m
@@ -0,0 +1,73 @@
+/*
+ * 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 "FIRInstanceIDKeyPair.h"
+
+#import
+
+#import "FIRInstanceIDKeyPairUtilities.h"
+#import "FIRInstanceIDKeychain.h"
+#import "FIRInstanceIDLogger.h"
+#import "NSError+FIRInstanceID.h"
+
+@interface FIRInstanceIDKeyPair () {
+ SecKeyRef _privateKey;
+ SecKeyRef _publicKey;
+}
+
+@property(nonatomic, readwrite, strong) NSData *publicKeyData;
+@property(nonatomic, readwrite, strong) NSData *privateKeyData;
+@end
+
+@implementation FIRInstanceIDKeyPair
+- (instancetype)initWithPrivateKey:(SecKeyRef)privateKey
+ publicKey:(SecKeyRef)publicKey
+ publicKeyData:(NSData *)publicKeyData
+ privateKeyData:(NSData *)privateKeyData {
+ self = [super init];
+ if (self) {
+ _privateKey = privateKey;
+ _publicKey = publicKey;
+ _publicKeyData = publicKeyData;
+ _privateKeyData = privateKeyData;
+ }
+ return self;
+}
+
+- (void)dealloc {
+ if (_privateKey) {
+ CFRelease(_privateKey);
+ }
+ if (_publicKey) {
+ CFRelease(_publicKey);
+ }
+}
+
+#pragma mark - Info
+
+- (BOOL)isValid {
+ return _privateKey != NULL && _publicKey != NULL;
+}
+
+- (SecKeyRef)publicKey {
+ return _publicKey;
+}
+
+- (SecKeyRef)privateKey {
+ return _privateKey;
+}
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.h
new file mode 100644
index 0000000..02c2896
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.h
@@ -0,0 +1,85 @@
+/*
+ * 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
+
+@class FIRInstanceIDKeyPair;
+
+extern NSString *const kFIRInstanceIDKeyPairSubType;
+
+@class FIRInstanceIDKeyPairStore;
+
+@interface FIRInstanceIDKeyPairStore : NSObject
+
+/**
+ * Invalidates the cached keypairs in the Keychain, if needed. The keypair metadata plist is
+ * checked for existence. If the plist file does not exist, it is a signal of a new installation,
+ * and therefore the key pairs are not valid.
+ *
+ * Returns YES if keypair has been invalidated.
+ */
+- (BOOL)invalidateKeyPairsIfNeeded;
+
+/**
+ * Delete the cached RSA keypair from Keychain with the given subtype.
+ *
+ * @param subtype The subtype used to cache the RSA keypair in Keychain.
+ * @param handler The callback handler which is invoked when the keypair deletion is
+ * complete, with an error if there is any.
+ */
+- (void)deleteSavedKeyPairWithSubtype:(NSString *)subtype handler:(void (^)(NSError *))handler;
+
+/**
+ * Delete the plist that caches KeyPair generation timestamps.
+ *
+ * @param error The error if any while deleting the plist else nil.
+ *
+ * @return YES if the delete was successful else NO.
+ */
+- (BOOL)removeKeyPairCreationTimePlistWithError:(NSError **)error;
+
+/**
+ * Loads a cached KeyPair if it exists in the Keychain else generate a new
+ * one. If a keyPair already exists in memory this will just return that. This should
+ * not be called from the main thread since it could potentially lead to creating a new
+ * RSA-2048 bit keyPair which is an expensive operation.
+ *
+ * @param error The error, if any, while accessing the Keychain.
+ *
+ * @return A valid 2048 bit RSA key pair.
+ */
+- (FIRInstanceIDKeyPair *)loadKeyPairWithError:(NSError **)error;
+
+/**
+ * Check if the Keychain has any cached keypairs or not.
+ *
+ * @return YES if the Keychain has cached RSA KeyPairs else NO.
+ */
+- (BOOL)hasCachedKeyPairs;
+
+/**
+ * Return an identifier for the app instance. The result is a short identifier that can
+ * be used as a key when storing information about the app. This method will return the same
+ * ID as long as the application identity remains active. If the identity has been revoked or
+ * expired the method will generate and return a new identifier.
+ *
+ * @param error The error if any while loading the RSA KeyPair.
+ *
+ * @return The identifier, as url safe string.
+ */
+- (NSString *)appIdentityWithError:(NSError *__autoreleasing *)error;
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.m
new file mode 100644
index 0000000..48a0d7c
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairStore.m
@@ -0,0 +1,525 @@
+/*
+ * 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 "FIRInstanceIDKeyPairStore.h"
+
+#import "FIRInstanceIDBackupExcludedPlist.h"
+#import "FIRInstanceIDConstants.h"
+#import "FIRInstanceIDKeyPair.h"
+#import "FIRInstanceIDKeyPairUtilities.h"
+#import "FIRInstanceIDKeychain.h"
+#import "FIRInstanceIDLogger.h"
+#import "FIRInstanceIDUtilities.h"
+#import "NSError+FIRInstanceID.h"
+
+// NOTE: These values should be in sync with what InstanceID saves in as.
+static NSString *const kFIRInstanceIDKeyPairStoreFileName = @"com.google.iid-keypair";
+
+static NSString *const kFIRInstanceIDStoreKeyGenerationTime = @"cre";
+
+static NSString *const kFIRInstanceIDStoreKeyPrefix = @"com.google.iid-";
+static NSString *const kFIRInstanceIDStoreKeyPublic = @"|P|";
+static NSString *const kFIRInstanceIDStoreKeyPrivate = @"|K|";
+static NSString *const kFIRInstanceIDStoreKeySubtype = @"|S|";
+
+static NSString *const kFIRInstanceIDKeyPairPublicTagPrefix = @"com.google.iid.keypair.public-";
+static NSString *const kFIRInstanceIDKeyPairPrivateTagPrefix = @"com.google.iid.keypair.private-";
+
+static const int kMaxMissingEntitlementErrorCount = 3;
+
+NSString *const kFIRInstanceIDKeyPairSubType = @"";
+
+// Query the key with NSData format
+NSData *FIRInstanceIDKeyDataWithTag(NSString *tag) {
+ if (![tag length]) {
+ return NULL;
+ }
+ NSDictionary *queryKey = FIRInstanceIDKeyPairQuery(tag, YES, YES);
+ CFTypeRef result = [[FIRInstanceIDKeychain sharedInstance] itemWithQuery:queryKey];
+ if (!result) {
+ return NULL;
+ }
+ return (__bridge NSData *)result;
+}
+
+// Query the key given a tag
+SecKeyRef FIRInstanceIDCachedKeyRefWithTag(NSString *tag) {
+ if (!tag.length) {
+ return NULL;
+ }
+ NSDictionary *queryKey = FIRInstanceIDKeyPairQuery(tag, YES, NO);
+ CFTypeRef result = [[FIRInstanceIDKeychain sharedInstance] itemWithQuery:queryKey];
+ return (SecKeyRef)result;
+}
+
+// Check if keypair has been migrated from the legacy to the new version
+BOOL FIRInstanceIDHasMigratedKeyPair(NSString *legacyPublicKeyTag, NSString *newPublicKeyTag) {
+ NSData *oldPublicKeyData = FIRInstanceIDKeyDataWithTag(legacyPublicKeyTag);
+ NSData *newPublicKeyData = FIRInstanceIDKeyDataWithTag(newPublicKeyTag);
+ return [oldPublicKeyData isEqualToData:newPublicKeyData];
+}
+
+// The legacy value is hardcoded to be the same key. This is a potential problem in shared keychain
+// environments.
+NSString *FIRInstanceIDLegacyPublicTagWithSubtype(NSString *subtype) {
+ NSString *prefix = kFIRInstanceIDStoreKeyPrefix;
+ return [NSString stringWithFormat:@"%@%@%@", prefix, subtype, kFIRInstanceIDStoreKeyPublic];
+}
+
+// The legacy value is hardcoded to be the same key. This is a potential problem in shared keychain
+// environments.
+NSString *FIRInstanceIDLegacyPrivateTagWithSubtype(NSString *subtype) {
+ NSString *prefix = kFIRInstanceIDStoreKeyPrefix;
+ return [NSString stringWithFormat:@"%@%@%@", prefix, subtype, kFIRInstanceIDStoreKeyPrivate];
+}
+
+NSString *FIRInstanceIDPublicTagWithSubtype(NSString *subtype) {
+ static NSString *publicTag;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ NSString *mainAppBundleID = FIRInstanceIDAppIdentifier();
+ publicTag =
+ [NSString stringWithFormat:@"%@%@", kFIRInstanceIDKeyPairPublicTagPrefix, mainAppBundleID];
+ });
+ return publicTag;
+}
+
+NSString *FIRInstanceIDPrivateTagWithSubtype(NSString *subtype) {
+ static NSString *privateTag;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ NSString *mainAppBundleID = FIRInstanceIDAppIdentifier();
+ privateTag =
+ [NSString stringWithFormat:@"%@%@", kFIRInstanceIDKeyPairPrivateTagPrefix, mainAppBundleID];
+ });
+ return privateTag;
+}
+
+NSString *FIRInstanceIDCreationTimeKeyWithSubtype(NSString *subtype) {
+ return [NSString stringWithFormat:@"%@%@%@", subtype, kFIRInstanceIDStoreKeySubtype,
+ kFIRInstanceIDStoreKeyGenerationTime];
+}
+
+@interface FIRInstanceIDKeyPairStore ()
+
+@property(nonatomic, readwrite, strong) FIRInstanceIDBackupExcludedPlist *plist;
+@property(atomic, readwrite, strong) FIRInstanceIDKeyPair *keyPair;
+@property(nonatomic, readwrite, assign) NSInteger keychainEntitlementsErrorCount;
+
+@end
+
+@implementation FIRInstanceIDKeyPairStore
+
+- (instancetype)init {
+ self = [super init];
+ if (self) {
+ NSString *fileName = [[self class] keyStoreFileName];
+ _plist =
+ [[FIRInstanceIDBackupExcludedPlist alloc] initWithFileName:fileName
+ subDirectory:kFIRInstanceIDSubDirectoryName];
+ }
+ return self;
+}
+
+- (BOOL)invalidateKeyPairsIfNeeded {
+ // Currently keypairs are always invalidated if self.plist is missing. This normally indicates
+ // a fresh install (or an uninstall/reinstall). In those situations the key pairs should be
+ // deleted.
+ // NOTE: Although this class refers to multiple key pairs, with different subtypes, in practice
+ // only a single subtype is currently supported. (b/64906549)
+ if (![self.plist doesFileExist]) {
+ // A fresh install, clear all the key pairs in the key chain. Do not perform migration as all
+ // key pairs are gone.
+ [self deleteSavedKeyPairWithSubtype:kFIRInstanceIDKeyPairSubType handler:nil];
+ return YES;
+ }
+ // Not a fresh install, perform migration at early state.
+ [self migrateKeyPairCacheIfNeededWithHandler:nil];
+ return NO;
+}
+
+- (BOOL)hasCachedKeyPairs {
+ NSError *error;
+ if ([self cachedKeyPairWithSubtype:kFIRInstanceIDKeyPairSubType error:&error] == nil) {
+ if (error) {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPairStore000,
+ @"Failed to get the cached keyPair %@", error);
+ }
+ error = nil;
+ [self removeKeyPairCreationTimePlistWithError:&error];
+ if (error) {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPairStore001,
+ @"Failed to remove keyPair creationTime plist %@", error);
+ }
+ return NO;
+ }
+ return YES;
+}
+
+- (NSString *)appIdentityWithError:(NSError *__autoreleasing *)error {
+ // Load the keyPair from Keychain (or generate a key pair, if this is the first run of the app).
+ FIRInstanceIDKeyPair *keyPair = [self loadKeyPairWithError:error];
+ if (!keyPair) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStoreCouldNotLoadKeyPair,
+ @"Keypair could not be loaded from Keychain. Error: %@", (*error));
+ return nil;
+ }
+
+ if (error) {
+ *error = nil;
+ }
+ NSString *appIdentity = FIRInstanceIDAppIdentity(keyPair);
+ if (!appIdentity.length) {
+ if (error) {
+ *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown];
+ }
+ }
+ return appIdentity;
+}
+
+- (FIRInstanceIDKeyPair *)loadKeyPairWithError:(NSError **)error {
+ // In case we call this from different threads we don't want to generate or fetch the
+ // keyPair multiple times. Once we have a keyPair in the cache it would mostly be used
+ // from there.
+ @synchronized(self) {
+ if ([self.keyPair isValid]) {
+ return self.keyPair;
+ }
+
+ if (self.keychainEntitlementsErrorCount >= kMaxMissingEntitlementErrorCount) {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPairStore002,
+ @"Keychain not accessible, Entitlements missing error (-34018). "
+ @"Will not check token in cache.");
+ return nil;
+ }
+
+ if (!self.keyPair) {
+ self.keyPair = [self validCachedKeyPairWithSubtype:kFIRInstanceIDKeyPairSubType error:error];
+ }
+
+ if ((*error).code == kFIRInstanceIDSecMissingEntitlementErrorCode) {
+ self.keychainEntitlementsErrorCount++;
+ }
+
+ if (!self.keyPair) {
+ self.keyPair = [self generateAndSaveKeyWithSubtype:kFIRInstanceIDKeyPairSubType
+ creationTime:FIRInstanceIDCurrentTimestampInSeconds()
+ error:error];
+ }
+ }
+ return self.keyPair;
+}
+
+// TODO(chliangGoogle: Remove subtype support, as it's not being used.
+- (FIRInstanceIDKeyPair *)generateAndSaveKeyWithSubtype:(NSString *)subtype
+ creationTime:(int64_t)creationTime
+ error:(NSError **)error {
+ NSString *publicKeyTag = FIRInstanceIDPublicTagWithSubtype(subtype);
+ NSString *privateKeyTag = FIRInstanceIDPrivateTagWithSubtype(subtype);
+ FIRInstanceIDKeyPair *keyPair =
+ [[FIRInstanceIDKeychain sharedInstance] generateKeyPairWithPrivateTag:privateKeyTag
+ publicTag:publicKeyTag];
+
+ if (![keyPair isValid]) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore003,
+ @"Unable to generate keypair.");
+ return nil;
+ }
+
+ NSString *creationTimeKey = FIRInstanceIDCreationTimeKeyWithSubtype(subtype);
+ NSDictionary *keyPairData = @{creationTimeKey : @(creationTime)};
+
+ if (error) {
+ *error = nil;
+ }
+ NSMutableDictionary *allKeyPairs = [[self.plist contentAsDictionary] mutableCopy];
+ if (allKeyPairs.count) {
+ [allKeyPairs addEntriesFromDictionary:keyPairData];
+ } else {
+ allKeyPairs = [keyPairData mutableCopy];
+ }
+ if (![self.plist writeDictionary:allKeyPairs error:error]) {
+ [FIRInstanceIDKeyPairStore deleteKeyPairWithPrivateTag:privateKeyTag
+ publicTag:publicKeyTag
+ handler:nil];
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore004,
+ @"Failed to save keypair data to plist %@", error ? *error : @"");
+ return nil;
+ }
+
+ return keyPair;
+}
+
+- (FIRInstanceIDKeyPair *)validCachedKeyPairWithSubtype:(NSString *)subtype
+ error:(NSError **)error {
+ // On a new install (or if the ID was deleted), the plist will be missing, which should trigger
+ // a reset of the key pairs in Keychain (if they exist).
+ NSDictionary *allKeyPairs = [self.plist contentAsDictionary];
+ NSString *creationTimeKey = FIRInstanceIDCreationTimeKeyWithSubtype(subtype);
+
+ if (allKeyPairs[creationTimeKey] > 0) {
+ return [self cachedKeyPairWithSubtype:subtype error:error];
+ } else {
+ // There is no need to reset keypair again here as FIRInstanceID init call is always
+ // going to be ahead of this call, which already trigger keypair reset if it's new install
+ FIRInstanceIDErrorCode code = kFIRInstanceIDErrorCodeInvalidKeyPairCreationTime;
+ if (error) {
+ *error = [NSError errorWithFIRInstanceIDErrorCode:code];
+ }
+ return nil;
+ }
+}
+
+- (FIRInstanceIDKeyPair *)cachedKeyPairWithSubtype:(NSString *)subtype
+ error:(NSError *__autoreleasing *)error {
+ // base64 encoded keys
+ NSString *publicKeyTag = FIRInstanceIDPublicTagWithSubtype(subtype);
+ NSString *privateKeyTag = FIRInstanceIDPrivateTagWithSubtype(subtype);
+ return [FIRInstanceIDKeyPairStore keyPairForPrivateKeyTag:privateKeyTag
+ publicKeyTag:publicKeyTag
+ error:error];
+}
+
++ (FIRInstanceIDKeyPair *)keyPairForPrivateKeyTag:(NSString *)privateKeyTag
+ publicKeyTag:(NSString *)publicKeyTag
+ error:(NSError *__autoreleasing *)error {
+ if (![privateKeyTag length] || ![publicKeyTag length]) {
+ if (error) {
+ *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPairTags];
+ }
+ return nil;
+ }
+
+ SecKeyRef privateKeyRef = FIRInstanceIDCachedKeyRefWithTag(privateKeyTag);
+ SecKeyRef publicKeyRef = FIRInstanceIDCachedKeyRefWithTag(publicKeyTag);
+
+ if (!privateKeyRef || !publicKeyRef) {
+ if (error) {
+ *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeMissingKeyPair];
+ }
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPair000,
+ @"No keypair info is found with tag %@", privateKeyTag);
+ return nil;
+ }
+
+ NSData *publicKeyData = FIRInstanceIDKeyDataWithTag(publicKeyTag);
+ NSData *privateKeyData = FIRInstanceIDKeyDataWithTag(privateKeyTag);
+
+ FIRInstanceIDKeyPair *keyPair = [[FIRInstanceIDKeyPair alloc] initWithPrivateKey:privateKeyRef
+ publicKey:publicKeyRef
+ publicKeyData:publicKeyData
+ privateKeyData:privateKeyData];
+ return keyPair;
+}
+
+// Migrates from keypair saved under legacy keys (hardcoded value) to dynamic keys (stable, but
+// unique for the app's bundle id
+- (void)migrateKeyPairCacheIfNeededWithHandler:(void (^)(NSError *error))handler {
+ // Attempt to load keypair using legacy keys
+ NSString *legacyPublicKeyTag =
+ FIRInstanceIDLegacyPublicTagWithSubtype(kFIRInstanceIDKeyPairSubType);
+ NSString *legacyPrivateKeyTag =
+ FIRInstanceIDLegacyPrivateTagWithSubtype(kFIRInstanceIDKeyPairSubType);
+ NSError *error;
+ FIRInstanceIDKeyPair *keyPair =
+ [FIRInstanceIDKeyPairStore keyPairForPrivateKeyTag:legacyPrivateKeyTag
+ publicKeyTag:legacyPublicKeyTag
+ error:&error];
+ if (![keyPair isValid]) {
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPairNoLegacyKeyPair,
+ @"There's no legacy keypair so no need to do migration.");
+ if (handler) {
+ handler(nil);
+ }
+ return;
+ }
+
+ // Check whether migration already done.
+ NSString *publicKeyTag = FIRInstanceIDPublicTagWithSubtype(kFIRInstanceIDKeyPairSubType);
+ if (FIRInstanceIDHasMigratedKeyPair(legacyPublicKeyTag, publicKeyTag)) {
+ if (handler) {
+ handler(nil);
+ }
+ return;
+ }
+
+ // Also cache locally since we are sure to use the migrated key pair.
+ self.keyPair = keyPair;
+
+ // Either new key pair doesn't exist or it's different than legacy key pair, start the migration.
+ __block NSError *updateKeyRefError;
+
+ NSString *privateKeyTag = FIRInstanceIDPrivateTagWithSubtype(kFIRInstanceIDKeyPairSubType);
+ [self updateKeyRef:keyPair.publicKey
+ withTag:publicKeyTag
+ handler:^(NSError *error) {
+ if (error) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairMigrationError,
+ @"Unable to migrate key pair from legacy ones.");
+ updateKeyRefError = error;
+ }
+ }];
+
+ [self updateKeyRef:keyPair.privateKey
+ withTag:privateKeyTag
+ handler:^(NSError *error) {
+ if (error) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairMigrationError,
+ @"Unable to migrate key pair from legacy ones.");
+ updateKeyRefError = error;
+ }
+
+ if (handler) {
+ handler(updateKeyRefError);
+ }
+ }];
+}
+
+// Used for migrating from legacy tags to updated tags. The legacy keychain is not deleted for
+// backward compatibility.
+// TODO(chliangGoogle) Delete the legacy keychain when GCM is fully deprecated.
+- (void)updateKeyRef:(SecKeyRef)keyRef
+ withTag:(NSString *)tag
+ handler:(void (^)(NSError *error))handler {
+ NSData *updatedTagData = [tag dataUsingEncoding:NSUTF8StringEncoding];
+
+ __block NSError *keychainError;
+
+ // Always delete the old keychain before adding a new one to avoid conflicts.
+ NSDictionary *deleteQuery = @{
+ (__bridge id)kSecAttrApplicationTag : updatedTagData,
+ (__bridge id)kSecClass : (__bridge id)kSecClassKey,
+ (__bridge id)kSecAttrKeyType : (__bridge id)kSecAttrKeyTypeRSA,
+ (__bridge id)kSecReturnRef : @(YES),
+ };
+ [[FIRInstanceIDKeychain sharedInstance] removeItemWithQuery:deleteQuery
+ handler:^(NSError *error) {
+ if (error) {
+ keychainError = error;
+ }
+ }];
+
+ NSDictionary *addQuery = @{
+ (__bridge id)kSecAttrApplicationTag : updatedTagData,
+ (__bridge id)kSecClass : (__bridge id)kSecClassKey,
+ (__bridge id)kSecValueRef : (__bridge id)keyRef,
+ (__bridge id)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly,
+ };
+ [[FIRInstanceIDKeychain sharedInstance] addItemWithQuery:addQuery
+ handler:^(NSError *addError) {
+ if (addError) {
+ keychainError = addError;
+ }
+
+ if (handler) {
+ handler(keychainError);
+ }
+ }];
+}
+
+- (void)deleteSavedKeyPairWithSubtype:(NSString *)subtype
+ handler:(void (^)(NSError *error))handler {
+ NSDictionary *allKeyPairs = [self.plist contentAsDictionary];
+
+ NSString *publicKeyTag = FIRInstanceIDPublicTagWithSubtype(subtype);
+ NSString *privateKeyTag = FIRInstanceIDPrivateTagWithSubtype(subtype);
+ NSString *creationTimeKey = FIRInstanceIDCreationTimeKeyWithSubtype(subtype);
+
+ // remove the creation time
+ if (allKeyPairs[creationTimeKey] > 0) {
+ NSMutableDictionary *newKeyPairs = [NSMutableDictionary dictionaryWithDictionary:allKeyPairs];
+ [newKeyPairs removeObjectForKey:creationTimeKey];
+
+ NSError *plistError;
+ if (![self.plist writeDictionary:newKeyPairs error:&plistError]) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore006,
+ @"Unable to remove keypair creation time from plist %@", plistError);
+ }
+ }
+
+ self.keyPair = nil;
+
+ [FIRInstanceIDKeyPairStore
+ deleteKeyPairWithPrivateTag:privateKeyTag
+ publicTag:publicKeyTag
+ handler:^(NSError *error) {
+ // Delete legacy key pairs from GCM/FCM If they exist. All key pairs
+ // should be deleted when app is newly installed.
+ NSString *legacyPublicKeyTag =
+ FIRInstanceIDLegacyPublicTagWithSubtype(subtype);
+ NSString *legacyPrivateKeyTag =
+ FIRInstanceIDLegacyPrivateTagWithSubtype(subtype);
+ [FIRInstanceIDKeyPairStore
+ deleteKeyPairWithPrivateTag:legacyPrivateKeyTag
+ publicTag:legacyPublicKeyTag
+ handler:nil];
+ if (error) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore007,
+ @"Unable to remove RSA keypair, error: %@",
+ error);
+ if (handler) {
+ handler(error);
+ }
+ } else {
+ if (handler) {
+ handler(nil);
+ }
+ }
+ }];
+}
+
++ (void)deleteKeyPairWithPrivateTag:(NSString *)privateTag
+ publicTag:(NSString *)publicTag
+ handler:(void (^)(NSError *))handler {
+ NSDictionary *queryPublicKey = FIRInstanceIDKeyPairQuery(publicTag, NO, NO);
+ NSDictionary *queryPrivateKey = FIRInstanceIDKeyPairQuery(privateTag, NO, NO);
+
+ __block NSError *keychainError;
+
+ // Always remove public key first because it is the key we generate IID.
+ [[FIRInstanceIDKeychain sharedInstance] removeItemWithQuery:queryPublicKey
+ handler:^(NSError *error) {
+ if (error) {
+ keychainError = error;
+ }
+ }];
+
+ [[FIRInstanceIDKeychain sharedInstance] removeItemWithQuery:queryPrivateKey
+ handler:^(NSError *error) {
+ if (error) {
+ keychainError = error;
+ }
+
+ if (handler) {
+ handler(keychainError);
+ }
+ }];
+}
+
+- (BOOL)removeKeyPairCreationTimePlistWithError:(NSError *__autoreleasing *)error {
+ if (![self.plist deleteFile:error]) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore008,
+ @"Unable to delete keypair creation times plist");
+ return NO;
+ }
+ return YES;
+}
+
++ (NSString *)keyStoreFileName {
+ return kFIRInstanceIDKeyPairStoreFileName;
+}
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.h
new file mode 100644
index 0000000..b8baa6a
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import
+
+@class FIRInstanceIDKeyPair;
+
+/**
+ * A web-safe base64 encoded string with no padding.
+ *
+ * @param data The data to encode.
+ *
+ * @return A web-safe base 64 encoded string with no padding.
+ */
+FOUNDATION_EXPORT NSString *FIRInstanceIDWebSafeBase64(NSData *data);
+
+FOUNDATION_EXPORT NSData *FIRInstanceIDSHA1(NSData *data);
+
+FOUNDATION_EXPORT NSDictionary *FIRInstanceIDKeyPairQuery(NSString *tag,
+ BOOL addReturnAttr,
+ BOOL returnData);
+
+FOUNDATION_EXPORT NSString *FIRInstanceIDAppIdentity(FIRInstanceIDKeyPair *keyPair);
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.m
new file mode 100644
index 0000000..021d94b
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeyPairUtilities.m
@@ -0,0 +1,83 @@
+/*
+ * 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 "FIRInstanceIDKeyPairUtilities.h"
+
+#import
+
+#import "FIRInstanceIDKeyPair.h"
+#import "FIRInstanceIDLogger.h"
+#import "FIRInstanceIDStringEncoding.h"
+
+NSString *FIRInstanceIDWebSafeBase64(NSData *data) {
+ // Websafe encoding with no padding.
+ FIRInstanceIDStringEncoding *encoding =
+ [FIRInstanceIDStringEncoding rfc4648Base64WebsafeStringEncoding];
+ [encoding setDoPad:NO];
+ return [encoding encode:data];
+}
+
+NSData *FIRInstanceIDSHA1(NSData *data) {
+ unsigned int outputLength = CC_SHA1_DIGEST_LENGTH;
+ unsigned char output[outputLength];
+ unsigned int length = (unsigned int)[data length];
+
+ CC_SHA1(data.bytes, length, output);
+ return [NSMutableData dataWithBytes:output length:outputLength];
+}
+
+NSDictionary *FIRInstanceIDKeyPairQuery(NSString *tag, BOOL addReturnAttr, BOOL returnData) {
+ NSMutableDictionary *queryKey = [NSMutableDictionary dictionary];
+ NSData *tagData = [tag dataUsingEncoding:NSUTF8StringEncoding];
+
+ queryKey[(__bridge id)kSecClass] = (__bridge id)kSecClassKey;
+ queryKey[(__bridge id)kSecAttrApplicationTag] = tagData;
+ queryKey[(__bridge id)kSecAttrKeyType] = (__bridge id)kSecAttrKeyTypeRSA;
+ if (addReturnAttr) {
+ if (returnData) {
+ queryKey[(__bridge id)kSecReturnData] = @(YES);
+ } else {
+ queryKey[(__bridge id)kSecReturnRef] = @(YES);
+ }
+ }
+ return queryKey;
+}
+
+NSString *FIRInstanceIDAppIdentity(FIRInstanceIDKeyPair *keyPair) {
+ // An Instance-ID is a 64 bit (8 byte) integer with a fixed 4-bit header of 0111 (=^ 0x7).
+ // The variable 60 bits are obtained by truncating the SHA1 of the app-instance's public key.
+ SecKeyRef publicKeyRef = [keyPair publicKey];
+ if (!publicKeyRef) {
+ FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPair002,
+ @"Unable to create a valid asymmetric crypto key");
+ return nil;
+ }
+ NSData *publicKeyData = keyPair.publicKeyData;
+ NSData *publicKeySHA1 = FIRInstanceIDSHA1(publicKeyData);
+
+ const uint8_t *bytes = publicKeySHA1.bytes;
+ NSMutableData *identityData = [NSMutableData dataWithData:publicKeySHA1];
+
+ uint8_t b0 = bytes[0];
+ // Take the first byte and make the initial four 7 by initially making the initial 4 bits 0
+ // and then adding 0x70 to it.
+ b0 = 0x70 + (0xF & b0);
+ // failsafe should give you back b0 itself
+ b0 = (b0 & 0xFF);
+ [identityData replaceBytesInRange:NSMakeRange(0, 1) withBytes:&b0];
+ NSData *data = [identityData subdataWithRange:NSMakeRange(0, 8 * sizeof(Byte))];
+ return FIRInstanceIDWebSafeBase64(data);
+}
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h
new file mode 100644
index 0000000..0bd2a49
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h
@@ -0,0 +1,76 @@
+/*
+ * 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
+
+/* The Keychain error domain */
+extern NSString *const kFIRInstanceIDKeychainErrorDomain;
+
+@class FIRInstanceIDKeyPair;
+
+/*
+ * Wrapping the keychain operations in a serialize queue. This is to avoid keychain operation
+ * blocking main queue.
+ */
+@interface FIRInstanceIDKeychain : NSObject
+
+/**
+ * FIRInstanceIDKeychain.
+ *
+ * @return A shared instance of FIRInstanceIDKeychain.
+ */
++ (instancetype)sharedInstance;
+
+/**
+ * Get keychain items matching the given a query.
+ *
+ * @param keychainQuery The keychain query.
+ *
+ * @return An CFTypeRef result matching the provided inputs.
+ */
+- (CFTypeRef)itemWithQuery:(NSDictionary *)keychainQuery;
+
+/**
+ * Remove the cached items from the keychain matching the query.
+ *
+ * @param keychainQuery The keychain query.
+ * @param handler The callback handler which is invoked when the remove operation is
+ * complete, with an error if there is any.
+ */
+- (void)removeItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *error))handler;
+
+/**
+ * Add the item with a given query.
+ *
+ * @param keychainQuery The keychain query.
+ * @param handler The callback handler which is invoked when the add operation is
+ * complete, with an error if there is any.
+ */
+- (void)addItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *))handler;
+
+#pragma mark - Keypair
+/**
+ * Generate a public/private key pair given their tags.
+ *
+ * @param privateTag The private tag associated with the private key.
+ * @param publicTag The public tag associated with the public key.
+ *
+ * @return A new FIRInstanceIDKeyPair object.
+ */
+- (FIRInstanceIDKeyPair *)generateKeyPairWithPrivateTag:(NSString *)privateTag
+ publicTag:(NSString *)publicTag;
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m
new file mode 100644
index 0000000..81c7372
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m
@@ -0,0 +1,174 @@
+/*
+ * 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 "FIRInstanceIDKeychain.h"
+
+#import "FIRInstanceIDKeyPair.h"
+#import "FIRInstanceIDKeyPairUtilities.h"
+#import "FIRInstanceIDLogger.h"
+
+NSString *const kFIRInstanceIDKeychainErrorDomain = @"com.google.iid";
+
+static const NSUInteger kRSA2048KeyPairSize = 2048;
+
+@interface FIRInstanceIDKeychain () {
+ dispatch_queue_t _keychainOperationQueue;
+}
+
+@end
+
+@implementation FIRInstanceIDKeychain
+
++ (instancetype)sharedInstance {
+ static FIRInstanceIDKeychain *sharedInstance;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ sharedInstance = [[FIRInstanceIDKeychain alloc] init];
+ });
+ return sharedInstance;
+}
+
+- (instancetype)init {
+ self = [super init];
+ if (self) {
+ _keychainOperationQueue =
+ dispatch_queue_create("com.google.FirebaseInstanceID.Keychain", DISPATCH_QUEUE_SERIAL);
+ }
+ return self;
+}
+
+- (CFTypeRef)itemWithQuery:(NSDictionary *)keychainQuery {
+ __block SecKeyRef keyRef = NULL;
+ dispatch_sync(_keychainOperationQueue, ^{
+ OSStatus status =
+ SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyRef);
+
+ if (status != noErr) {
+ if (keyRef) {
+ CFRelease(keyRef);
+ }
+ FIRInstanceIDLoggerDebug(kFIRInstanceIDKeychainReadItemError,
+ @"Info is not found in Keychain. OSStatus: %d. Keychain query: %@",
+ (int)status, keychainQuery);
+ }
+ });
+ return keyRef;
+}
+
+- (void)removeItemWithQuery:(NSDictionary *)keychainQuery
+ handler:(void (^)(NSError *error))handler {
+ dispatch_async(_keychainOperationQueue, ^{
+ OSStatus status = SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
+ if (status != noErr) {
+ FIRInstanceIDLoggerDebug(
+ kFIRInstanceIDKeychainDeleteItemError,
+ @"Couldn't delete item from Keychain OSStatus: %d with the keychain query %@",
+ (int)status, keychainQuery);
+ }
+
+ if (handler) {
+ NSError *error;
+ // When item is not found, it should NOT be considered as an error. The operation should
+ // continue.
+ if (status != noErr && status != errSecItemNotFound) {
+ error = [NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain
+ code:status
+ userInfo:nil];
+ }
+ dispatch_async(dispatch_get_main_queue(), ^{
+ handler(error);
+ });
+ }
+ });
+}
+
+- (void)addItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *))handler {
+ dispatch_async(_keychainOperationQueue, ^{
+ OSStatus status = SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);
+
+ if (handler) {
+ NSError *error;
+ if (status != noErr) {
+ FIRInstanceIDLoggerWarning(kFIRInstanceIDKeychainAddItemError,
+ @"Couldn't add item to Keychain OSStatus: %d", (int)status);
+ error = [NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain
+ code:status
+ userInfo:nil];
+ }
+ dispatch_async(dispatch_get_main_queue(), ^{
+ handler(error);
+ });
+ }
+ });
+}
+
+- (FIRInstanceIDKeyPair *)generateKeyPairWithPrivateTag:(NSString *)privateTag
+ publicTag:(NSString *)publicTag {
+ // TODO(chliangGoogle) this is called by appInstanceID, which is an internal API used by other
+ // Firebase teams, will see if we can make it async.
+ NSData *publicTagData = [publicTag dataUsingEncoding:NSUTF8StringEncoding];
+ NSData *privateTagData = [privateTag dataUsingEncoding:NSUTF8StringEncoding];
+
+ NSDictionary *privateKeyAttr = @{
+ (__bridge id)kSecAttrIsPermanent : @YES,
+ (__bridge id)kSecAttrApplicationTag : privateTagData,
+ (__bridge id)kSecAttrLabel : @"Firebase InstanceID Key Pair Private Key",
+ (__bridge id)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly,
+ };
+
+ NSDictionary *publicKeyAttr = @{
+ (__bridge id)kSecAttrIsPermanent : @YES,
+ (__bridge id)kSecAttrApplicationTag : publicTagData,
+ (__bridge id)kSecAttrLabel : @"Firebase InstanceID Key Pair Public Key",
+ (__bridge id)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly,
+ };
+
+ NSDictionary *keyPairAttributes = @{
+ (__bridge id)kSecAttrKeyType : (__bridge id)kSecAttrKeyTypeRSA,
+ (__bridge id)kSecAttrLabel : @"Firebase InstanceID Key Pair",
+ (__bridge id)kSecAttrKeySizeInBits : @(kRSA2048KeyPairSize),
+ (__bridge id)kSecPrivateKeyAttrs : privateKeyAttr,
+ (__bridge id)kSecPublicKeyAttrs : publicKeyAttr,
+ };
+
+ __block SecKeyRef privateKey = NULL;
+ __block SecKeyRef publicKey = NULL;
+ dispatch_sync(_keychainOperationQueue, ^{
+ // SecKeyGeneratePair does not allow you to set kSetAttrAccessible on the keys. We need the keys
+ // to be accessible even when the device is locked (i.e. app is woken up during a push
+ // notification, or some background refresh).
+ OSStatus status =
+ SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttributes, &publicKey, &privateKey);
+ if (status != noErr || publicKey == NULL || privateKey == NULL) {
+ FIRInstanceIDLoggerWarning(kFIRInstanceIDKeychainCreateKeyPairError,
+ @"Couldn't create keypair from Keychain OSStatus: %d",
+ (int)status);
+ }
+ });
+ // Extract the actual public and private key data from the Keychain
+ NSDictionary *publicKeyDataQuery = FIRInstanceIDKeyPairQuery(publicTag, YES, YES);
+ NSDictionary *privateKeyDataQuery = FIRInstanceIDKeyPairQuery(privateTag, YES, YES);
+
+ NSData *publicKeyData = (__bridge NSData *)[self itemWithQuery:publicKeyDataQuery];
+ NSData *privateKeyData = (__bridge NSData *)[self itemWithQuery:privateKeyDataQuery];
+
+ return [[FIRInstanceIDKeyPair alloc] initWithPrivateKey:privateKey
+ publicKey:publicKey
+ publicKeyData:publicKeyData
+ privateKeyData:privateKeyData];
+}
+
+@end
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h
new file mode 100644
index 0000000..ab93976
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2019 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "FIRIMessageCode.h"
+
+// The convenience macros are only defined if they haven't already been defined.
+#ifndef FIRInstanceIDLoggerInfo
+
+// Convenience macros that log to the shared GTMLogger instance. These macros
+// are how users should typically log to FIRInstanceIDLogger.
+#define FIRInstanceIDLoggerDebug(code, ...) \
+ [FIRInstanceIDSharedLogger() logFuncDebug:__func__ messageCode:code msg:__VA_ARGS__]
+#define FIRInstanceIDLoggerInfo(code, ...) \
+ [FIRInstanceIDSharedLogger() logFuncInfo:__func__ messageCode:code msg:__VA_ARGS__]
+#define FIRInstanceIDLoggerNotice(code, ...) \
+ [FIRInstanceIDSharedLogger() logFuncNotice:__func__ messageCode:code msg:__VA_ARGS__]
+#define FIRInstanceIDLoggerWarning(code, ...) \
+ [FIRInstanceIDSharedLogger() logFuncWarning:__func__ messageCode:code msg:__VA_ARGS__]
+#define FIRInstanceIDLoggerError(code, ...) \
+ [FIRInstanceIDSharedLogger() logFuncError:__func__ messageCode:code msg:__VA_ARGS__]
+
+#endif // !defined(FIRInstanceIDLoggerInfo)
+
+@interface FIRInstanceIDLogger : NSObject
+
+- (void)logFuncDebug:(const char *)func
+ messageCode:(FIRInstanceIDMessageCode)messageCode
+ msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4);
+
+- (void)logFuncInfo:(const char *)func
+ messageCode:(FIRInstanceIDMessageCode)messageCode
+ msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4);
+
+- (void)logFuncNotice:(const char *)func
+ messageCode:(FIRInstanceIDMessageCode)messageCode
+ msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4);
+
+- (void)logFuncWarning:(const char *)func
+ messageCode:(FIRInstanceIDMessageCode)messageCode
+ msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4);
+
+- (void)logFuncError:(const char *)func
+ messageCode:(FIRInstanceIDMessageCode)messageCode
+ msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4);
+
+@end
+
+/**
+ * Instantiates and/or returns a shared GTMLogger used exclusively
+ * for InstanceID log messages.
+ * @return the shared GTMLogger instance
+ */
+FIRInstanceIDLogger *FIRInstanceIDSharedLogger(void);
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m
new file mode 100644
index 0000000..2600d3b
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m
@@ -0,0 +1,92 @@
+/*
+ * 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 "FIRInstanceIDLogger.h"
+
+#import
+
+// Re-definition of FIRLogger service, as it is not included in :FIRAppHeaders target
+NSString *const kFIRInstanceIDLoggerService = @"[Firebase/InstanceID]";
+
+@implementation FIRInstanceIDLogger
+
+#pragma mark - Log Helpers
+
++ (NSString *)formatMessageCode:(FIRInstanceIDMessageCode)messageCode {
+ return [NSString stringWithFormat:@"I-IID%06ld", (long)messageCode];
+}
+
+- (void)logFuncDebug:(const char *)func
+ messageCode:(FIRInstanceIDMessageCode)messageCode
+ msg:(NSString *)fmt, ... {
+ va_list args;
+ va_start(args, fmt);
+ FIRLogBasic(FIRLoggerLevelDebug, kFIRInstanceIDLoggerService,
+ [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args);
+ va_end(args);
+}
+
+- (void)logFuncInfo:(const char *)func
+ messageCode:(FIRInstanceIDMessageCode)messageCode
+ msg:(NSString *)fmt, ... {
+ va_list args;
+ va_start(args, fmt);
+ FIRLogBasic(FIRLoggerLevelInfo, kFIRInstanceIDLoggerService,
+ [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args);
+ va_end(args);
+}
+
+- (void)logFuncNotice:(const char *)func
+ messageCode:(FIRInstanceIDMessageCode)messageCode
+ msg:(NSString *)fmt, ... {
+ va_list args;
+ va_start(args, fmt);
+ FIRLogBasic(FIRLoggerLevelNotice, kFIRInstanceIDLoggerService,
+ [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args);
+ va_end(args);
+}
+
+- (void)logFuncWarning:(const char *)func
+ messageCode:(FIRInstanceIDMessageCode)messageCode
+ msg:(NSString *)fmt, ... {
+ va_list args;
+ va_start(args, fmt);
+ FIRLogBasic(FIRLoggerLevelWarning, kFIRInstanceIDLoggerService,
+ [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args);
+ va_end(args);
+}
+
+- (void)logFuncError:(const char *)func
+ messageCode:(FIRInstanceIDMessageCode)messageCode
+ msg:(NSString *)fmt, ... {
+ va_list args;
+ va_start(args, fmt);
+ FIRLogBasic(FIRLoggerLevelError, kFIRInstanceIDLoggerService,
+ [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args);
+ va_end(args);
+}
+
+@end
+
+FIRInstanceIDLogger *FIRInstanceIDSharedLogger() {
+ static dispatch_once_t onceToken;
+ static FIRInstanceIDLogger *logger;
+ dispatch_once(&onceToken, ^{
+ logger = [[FIRInstanceIDLogger alloc] init];
+ });
+
+ return logger;
+}
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h
new file mode 100644
index 0000000..d1f2634
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h
@@ -0,0 +1,183 @@
+/*
+ * 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
+
+NS_ASSUME_NONNULL_BEGIN
+
+@class FIRInstanceIDBackupExcludedPlist;
+@class FIRInstanceIDCheckinPreferences;
+@class FIRInstanceIDCheckinStore;
+@class FIRInstanceIDTokenInfo;
+@class FIRInstanceIDTokenStore;
+
+@class FIRInstanceIDStore;
+@protocol FIRInstanceIDStoreDelegate
+
+/**
+ * This is called when the store has decided to invalide its tokens associated with the
+ * previous checkin credentials. After deleting the tokens locally, it calls this method
+ * to notify the delegate of the change. If possible, the delegate should use this time
+ * to request the invalidation of the tokens on the server as well.
+ */
+- (void)store:(FIRInstanceIDStore *)store
+ didDeleteFCMScopedTokensForCheckin:(FIRInstanceIDCheckinPreferences *)checkin;
+
+@end
+
+/**
+ * Used to persist the InstanceID tokens. This is also used to cache the Checkin
+ * credentials. The store also checks for stale entries in the store and
+ * let's us know if things in the store are stale or not. It does not however
+ * acts on stale entries in anyway.
+ */
+@interface FIRInstanceIDStore : NSObject
+
+/**
+ * The delegate set in the initializer which is notified of changes in the store.
+ */
+@property(nonatomic, readonly, weak) NSObject *delegate;
+
+- (instancetype)init __attribute__((unavailable("Use initWithDelegate: instead.")));
+
+/**
+ * Initialize a default store to persist InstanceID tokens and options.
+ *
+ * @param delegate The delegate with which to be notified of changes in the store.
+ * @return Store to persist InstanceID tokens.
+ */
+- (instancetype)initWithDelegate:(NSObject *)delegate;
+
+/**
+ * Initialize a store with the token store used to persist tokens, and a checkin store.
+ * Used for testing.
+ *
+ * @param checkinStore Persistent store that persists checkin preferences.
+ * @param tokenStore Persistent store that persists tokens.
+ *
+ * @return Store to persist InstanceID tokens and options.
+ */
+- (instancetype)initWithCheckinStore:(FIRInstanceIDCheckinStore *)checkinStore
+ tokenStore:(FIRInstanceIDTokenStore *)tokenStore
+ delegate:(NSObject *)delegate
+ NS_DESIGNATED_INITIALIZER;
+
+#pragma mark - Save
+/**
+ * Save the instanceID token info to the store.
+ *
+ * @param tokenInfo The token info to store.
+ * @param handler The callback handler which is invoked when the operation is complete,
+ * with an error if there is any.
+ */
+- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo handler:(void (^)(NSError *))handler;
+
+#pragma mark - Get
+
+/**
+ * Get the cached token info.
+ *
+ * @param authorizedEntity The authorized entity for which we want the token.
+ * @param scope The scope for which we want the token.
+ *
+ * @return The cached token info if any for the given authorizedEntity and scope else
+ * returns nil.
+ */
+- (nullable FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity
+ scope:(NSString *)scope;
+/**
+ * Return all cached token infos from the Keychain.
+ *
+ * @return The cached token infos, if any, that are stored in the Keychain.
+ */
+- (NSArray *)cachedTokenInfos;
+
+#pragma mark - Delete
+
+/**
+ * Remove the cached token for a given authorizedEntity and scope. If the token was never
+ * cached or deleted from the cache before this is a no-op.
+ *
+ * @param authorizedEntity The authorizedEntity for the cached token.
+ * @param scope The scope for the cached token
+ */
+- (void)removeCachedTokenWithAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope;
+
+/**
+ * Removes all cached tokens from the persistent store. In case deleting the cached tokens
+ * fails we try to delete the backup excluded plist that stores the tokens.
+ *
+ * @param handler The callback handler which is invoked when the operation is complete,
+ * with an error if there is any.
+ *
+ */
+- (void)removeAllCachedTokensWithHandler:(nullable void (^)(NSError *error))handler;
+
+#pragma mark - Persisting Checkin Preferences
+
+/**
+ * Save the checkin preferences
+ *
+ * @param preferences Checkin preferences to save.
+ * @param handler The callback handler which is invoked when the operation is complete,
+ * with an error if there is any.
+ */
+- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences
+ handler:(nullable void (^)(NSError *error))handler;
+
+/**
+ * Return the cached checkin preferences.
+ *
+ * @return Checkin preferences.
+ */
+- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences;
+
+/**
+ * Remove the cached checkin preferences from the store.
+ *
+ * @param handler The callback handler which is invoked when the operation is complete,
+ * with an error if there is any.
+ */
+- (void)removeCheckinPreferencesWithHandler:(nullable void (^)(NSError *error))handler;
+
+#pragma mark - Standard Directory sub-directory
+
+/**
+ * Check if supported directory has InstanceID subdirectory
+ *
+ * @return YES if the Application Support directory has InstanceID subdirectory else NO.
+ */
++ (BOOL)hasSubDirectory:(NSString *)subDirectoryName;
+
+/**
+ * Create InstanceID subdirectory in Application support directory.
+ *
+ * @return YES if the subdirectory was created successfully else NO.
+ */
++ (BOOL)createSubDirectory:(NSString *)subDirectoryName;
+
+/**
+ * Removes Application Support subdirectory for InstanceID.
+ *
+ * @param error The error object if any while trying to delete the sub-directory.
+ *
+ * @return YES if the deletion was successful else NO.
+ */
++ (BOOL)removeSubDirectory:(NSString *)subDirectoryName error:(NSError **)error;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m
new file mode 100644
index 0000000..1c7a0d0
--- /dev/null
+++ b/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m
@@ -0,0 +1,242 @@
+/*
+ * 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 "FIRInstanceIDStore.h"
+
+#import "FIRInstanceIDCheckinPreferences.h"
+#import "FIRInstanceIDCheckinStore.h"
+#import "FIRInstanceIDConstants.h"
+#import "FIRInstanceIDLogger.h"
+#import "FIRInstanceIDTokenStore.h"
+#import "FIRInstanceIDVersionUtilities.h"
+
+// NOTE: These values should be in sync with what InstanceID saves in as.
+static NSString *const kCheckinFileName = @"g-checkin";
+
+// APNS token (use the old key value i.e. with prefix GMS)
+static NSString *const kFIRInstanceIDLibraryVersion = @"GMSInstanceID-version";
+
+@interface FIRInstanceIDStore ()
+
+@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinStore *checkinStore;
+@property(nonatomic, readwrite, strong) FIRInstanceIDTokenStore *tokenStore;
+
+@end
+
+@implementation FIRInstanceIDStore
+
+- (instancetype)initWithDelegate:(NSObject *)delegate {
+ FIRInstanceIDCheckinStore *checkinStore = [[FIRInstanceIDCheckinStore alloc]
+ initWithCheckinPlistFileName:kCheckinFileName
+ subDirectoryName:kFIRInstanceIDSubDirectoryName];
+
+ FIRInstanceIDTokenStore *tokenStore = [FIRInstanceIDTokenStore defaultStore];
+
+ return [self initWithCheckinStore:checkinStore tokenStore:tokenStore delegate:delegate];
+}
+
+- (instancetype)initWithCheckinStore:(FIRInstanceIDCheckinStore *)checkinStore
+ tokenStore:(FIRInstanceIDTokenStore *)tokenStore
+ delegate:(NSObject