From a1b328198f45579d193ced4fdadf38187c9cf7a4 Mon Sep 17 00:00:00 2001 From: chkuang-g <31869252+chkuang-g@users.noreply.github.com> Date: Wed, 2 Sep 2020 16:36:47 -0700 Subject: [PATCH 01/57] Update firebase-cpp-sdk-issue.md --- .github/ISSUE_TEMPLATE/firebase-cpp-sdk-issue.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/firebase-cpp-sdk-issue.md b/.github/ISSUE_TEMPLATE/firebase-cpp-sdk-issue.md index 44897e00..2507996b 100644 --- a/.github/ISSUE_TEMPLATE/firebase-cpp-sdk-issue.md +++ b/.github/ISSUE_TEMPLATE/firebase-cpp-sdk-issue.md @@ -7,6 +7,8 @@ assignees: '' --- +## For Firebase C++ SDK issues, please report to [Firebase C++ open-source](https://github.com/firebase/firebase-cpp-sdk/issues) + ### Please fill in the following fields: Firebase C++ SDK version: Firebase plugins in use (Auth, Database, etc.): @@ -18,6 +20,4 @@ Platform you are targeting (iOS, Android, and/or desktop): (Please list the full steps to reproduce the issue. Include device logs, and stack traces if available.) ### Please answer the following, if applicable: -Have you been able to reproduce this issue with just the Firebase C++ quickstarts (this GitHub project)? - What's the issue repro rate? (eg 100%, 1/5 etc) From 7a3ccac30a22bc88941f9802cd45b1e46cc131f6 Mon Sep 17 00:00:00 2001 From: chkuang-g <31869252+chkuang-g@users.noreply.github.com> Date: Tue, 8 Sep 2020 16:32:28 -0700 Subject: [PATCH 02/57] Update and rename firebase-cpp-sdk-issue.md to issue.md --- .../ISSUE_TEMPLATE/firebase-cpp-sdk-issue.md | 23 ------------ .github/ISSUE_TEMPLATE/issue.md | 35 +++++++++++++++++++ 2 files changed, 35 insertions(+), 23 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/firebase-cpp-sdk-issue.md create mode 100644 .github/ISSUE_TEMPLATE/issue.md diff --git a/.github/ISSUE_TEMPLATE/firebase-cpp-sdk-issue.md b/.github/ISSUE_TEMPLATE/firebase-cpp-sdk-issue.md deleted file mode 100644 index 2507996b..00000000 --- a/.github/ISSUE_TEMPLATE/firebase-cpp-sdk-issue.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -name: Firebase C++ SDK issue -about: Please use this template to report issues with the Firebase C++ SDK. -title: '' -labels: new -assignees: '' - ---- - -## For Firebase C++ SDK issues, please report to [Firebase C++ open-source](https://github.com/firebase/firebase-cpp-sdk/issues) - -### Please fill in the following fields: -Firebase C++ SDK version: -Firebase plugins in use (Auth, Database, etc.): -Additional SDKs you are using (Facebook, AdMob, etc.): -Platform you are using the SDK on (Mac, Windows, or Linux): -Platform you are targeting (iOS, Android, and/or desktop): - -### Please describe the issue here: -(Please list the full steps to reproduce the issue. Include device logs, and stack traces if available.) - -### Please answer the following, if applicable: -What's the issue repro rate? (eg 100%, 1/5 etc) diff --git a/.github/ISSUE_TEMPLATE/issue.md b/.github/ISSUE_TEMPLATE/issue.md new file mode 100644 index 00000000..40cdd78e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue.md @@ -0,0 +1,35 @@ +--- +name: Firebase C++ Sample issue +about: Report issues with the Firebase C++ Sample. +labels: new +--- + + +### [READ] For Firebase C++ SDK issues, please report to [Firebase C++ open-source](https://github.com/firebase/firebase-cpp-sdk/issues) + +Once you've read this section and determined that your issue is appropriate for this repository, please delete this section. + +### [REQUIRED] Please fill in the following fields: + + * Which Firebase Sample? (Auth, Database, etc.): _____ + * Firebase C++ SDK version: _____ + * Additional SDKs you are using (Facebook, AdMob, etc.): _____ + * Platform you are using the SDK on (Mac, Windows, or Linux): _____ + * Platform you are targeting (iOS, Android, and/or desktop): _____ + +### [REQUIRED] Please describe the issue here: + +(Please list the full steps to reproduce the issue. Include device logs, and stack traces if available.) + +#### Steps to reproduce: + +What's the issue repro rate? (eg 100%, 1/5 etc) + +What happened? How can we make the problem occur? +This could be a description, log/console output, etc. + +If you have a downloadable sample project that reproduces the bug you're reporting, you will +likely receive a faster response on your issue. From 1f94c2c5c37cd1ca4464b9ed6a4dbf49361bd559 Mon Sep 17 00:00:00 2001 From: chkuang-g <31869252+chkuang-g@users.noreply.github.com> Date: Tue, 8 Sep 2020 17:02:24 -0700 Subject: [PATCH 03/57] Update issue.md --- .github/ISSUE_TEMPLATE/issue.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/issue.md b/.github/ISSUE_TEMPLATE/issue.md index 40cdd78e..10edc34a 100644 --- a/.github/ISSUE_TEMPLATE/issue.md +++ b/.github/ISSUE_TEMPLATE/issue.md @@ -8,7 +8,7 @@ validate_template=true template_path=.github/ISSUE_TEMPLATE/issue.md --> -### [READ] For Firebase C++ SDK issues, please report to [Firebase C++ open-source](https://github.com/firebase/firebase-cpp-sdk/issues) +### [READ] For Firebase C++ SDK issues, please report to [Firebase C++ open-source](https://github.com/firebase/firebase-cpp-sdk/issues/new/choose) Once you've read this section and determined that your issue is appropriate for this repository, please delete this section. From ba7d41a6a97812d1a82bf6f0e248370b63a38d34 Mon Sep 17 00:00:00 2001 From: chkuang-g <31869252+chkuang-g@users.noreply.github.com> Date: Tue, 8 Sep 2020 17:51:09 -0700 Subject: [PATCH 04/57] Update issue.md --- .github/ISSUE_TEMPLATE/issue.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/issue.md b/.github/ISSUE_TEMPLATE/issue.md index 10edc34a..94c20889 100644 --- a/.github/ISSUE_TEMPLATE/issue.md +++ b/.github/ISSUE_TEMPLATE/issue.md @@ -14,11 +14,11 @@ Once you've read this section and determined that your issue is appropriate for ### [REQUIRED] Please fill in the following fields: - * Which Firebase Sample? (Auth, Database, etc.): _____ + * Which Firebase Sample: _____ (Auth, Database, etc.) * Firebase C++ SDK version: _____ - * Additional SDKs you are using (Facebook, AdMob, etc.): _____ - * Platform you are using the SDK on (Mac, Windows, or Linux): _____ - * Platform you are targeting (iOS, Android, and/or desktop): _____ + * Additional SDKs you are using: _____ (Facebook, AdMob, etc.) + * Platform you are using the SDK on: _____ (Mac, Windows, or Linux) + * Platform you are targeting: _____ (iOS, Android, and/or desktop) ### [REQUIRED] Please describe the issue here: From f4d8254d8efdd3be1fc007a5dc476fce6a5bef7b Mon Sep 17 00:00:00 2001 From: Vimanyu Date: Wed, 25 Nov 2020 14:05:36 -0800 Subject: [PATCH 05/57] adding noop workflow to main. Only if you have a workflow in main, can you trigger it manually via the Github UI. Pushing a dummy workflow so that we can develop in other feature branches and test things by manually activating the workflows. --- .github/workflows/desktop.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/workflows/desktop.yml diff --git a/.github/workflows/desktop.yml b/.github/workflows/desktop.yml new file mode 100644 index 00000000..b606cea0 --- /dev/null +++ b/.github/workflows/desktop.yml @@ -0,0 +1,14 @@ +name: Desktop builds + +on: + workflow_dispatch: + inputs: + apis: + description: 'CSV of apis whose quickstart examples we should build' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: noop + run: true From 33605f4e2aaed7bfb08fde97b3b8d1934aa17c50 Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Tue, 23 Feb 2021 15:23:06 -0500 Subject: [PATCH 06/57] Updated dependencies to 7.0.0 --- admob/testapp/Podfile | 2 +- analytics/testapp/Podfile | 2 +- .../testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- auth/testapp/Podfile | 2 +- auth/testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- database/testapp/Podfile | 4 ++-- .../testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- dynamic_links/testapp/Podfile | 2 +- .../testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- firestore/testapp/Podfile | 6 +++--- firestore/testapp/src/common_main.cc | 16 +++++++++------- .../testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- functions/testapp/Podfile | 4 ++-- .../testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- messaging/testapp/Podfile | 2 +- .../testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- readme.md | 7 +++++++ remote_config/testapp/Podfile | 2 +- .../testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- storage/testapp/Podfile | 4 ++-- .../testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- 21 files changed, 49 insertions(+), 40 deletions(-) diff --git a/admob/testapp/Podfile b/admob/testapp/Podfile index 269cc6be..9759f528 100644 --- a/admob/testapp/Podfile +++ b/admob/testapp/Podfile @@ -2,5 +2,5 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' # AdMob test application. target 'testapp' do - pod 'Firebase/AdMob', '6.24.0' + pod 'Firebase/AdMob', '7.0.0' end diff --git a/analytics/testapp/Podfile b/analytics/testapp/Podfile index 63db963c..f7888311 100644 --- a/analytics/testapp/Podfile +++ b/analytics/testapp/Podfile @@ -2,5 +2,5 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' # Analytics test application. target 'testapp' do - pod 'Firebase/Analytics', '6.24.0' + pod 'Firebase/Analytics', '7.0.0' end diff --git a/analytics/testapp/testapp.xcodeproj/project.pbxproj b/analytics/testapp/testapp.xcodeproj/project.pbxproj index baf45c4c..6c325725 100644 --- a/analytics/testapp/testapp.xcodeproj/project.pbxproj +++ b/analytics/testapp/testapp.xcodeproj/project.pbxproj @@ -208,7 +208,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -245,7 +245,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/auth/testapp/Podfile b/auth/testapp/Podfile index a71424d3..d2ddd900 100644 --- a/auth/testapp/Podfile +++ b/auth/testapp/Podfile @@ -2,5 +2,5 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' # Auth test application. target 'testapp' do - pod 'Firebase/Auth', '6.24.0' + pod 'Firebase/Auth', '7.0.0' end diff --git a/auth/testapp/testapp.xcodeproj/project.pbxproj b/auth/testapp/testapp.xcodeproj/project.pbxproj index baf45c4c..6c325725 100644 --- a/auth/testapp/testapp.xcodeproj/project.pbxproj +++ b/auth/testapp/testapp.xcodeproj/project.pbxproj @@ -208,7 +208,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -245,7 +245,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/database/testapp/Podfile b/database/testapp/Podfile index 3509b28c..966f7b10 100644 --- a/database/testapp/Podfile +++ b/database/testapp/Podfile @@ -2,6 +2,6 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' # Firebase Realtime Database test application. target 'testapp' do - pod 'Firebase/Database', '6.24.0' - pod 'Firebase/Auth', '6.24.0' + pod 'Firebase/Database', '7.0.0' + pod 'Firebase/Auth', '7.0.0' end diff --git a/database/testapp/testapp.xcodeproj/project.pbxproj b/database/testapp/testapp.xcodeproj/project.pbxproj index baf45c4c..6c325725 100644 --- a/database/testapp/testapp.xcodeproj/project.pbxproj +++ b/database/testapp/testapp.xcodeproj/project.pbxproj @@ -208,7 +208,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -245,7 +245,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/dynamic_links/testapp/Podfile b/dynamic_links/testapp/Podfile index be1c85ab..8af0d756 100644 --- a/dynamic_links/testapp/Podfile +++ b/dynamic_links/testapp/Podfile @@ -2,5 +2,5 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' # Dynamic Links test application. target 'testapp' do - pod 'Firebase/DynamicLinks', '6.24.0' + pod 'Firebase/DynamicLinks', '7.0.0' end diff --git a/dynamic_links/testapp/testapp.xcodeproj/project.pbxproj b/dynamic_links/testapp/testapp.xcodeproj/project.pbxproj index baf45c4c..6c325725 100644 --- a/dynamic_links/testapp/testapp.xcodeproj/project.pbxproj +++ b/dynamic_links/testapp/testapp.xcodeproj/project.pbxproj @@ -208,7 +208,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -245,7 +245,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/firestore/testapp/Podfile b/firestore/testapp/Podfile index eb725652..b4fb49d8 100644 --- a/firestore/testapp/Podfile +++ b/firestore/testapp/Podfile @@ -2,7 +2,7 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' # Firebase Firestore test application. target 'testapp' do - pod 'Firebase/Analytics', '6.24.0' - pod 'Firebase/Firestore', '6.24.0' - pod 'Firebase/Auth', '6.24.0' + pod 'Firebase/Analytics', '7.0.0' + pod 'Firebase/Firestore', '7.0.0' + pod 'Firebase/Auth', '7.0.0' end diff --git a/firestore/testapp/src/common_main.cc b/firestore/testapp/src/common_main.cc index 3fd6757e..3f2d05ad 100644 --- a/firestore/testapp/src/common_main.cc +++ b/firestore/testapp/src/common_main.cc @@ -65,11 +65,12 @@ class TestEventListener : public Countable, public: explicit TestEventListener(std::string name) : name_(std::move(name)) {} - void OnEvent(const T& value, - const firebase::firestore::Error error) override { + void OnEvent(const T& value, const firebase::firestore::Error error_code, + const std::string& error_message) override { event_count_++; - if (error != firebase::firestore::kOk) { - LogMessage("ERROR: EventListener %s got %d.", name_.c_str(), error); + if (error_code != firebase::firestore::kErrorOk) { + LogMessage("ERROR: EventListener %s got %d (%s).", name_.c_str(), + error_code, error_message.c_str()); } } @@ -79,8 +80,9 @@ class TestEventListener : public Countable, firebase::firestore::ListenerRegistration AttachTo(U* ref) { #if !defined(STLPORT) return ref->AddSnapshotListener( - [this](const T& result, firebase::firestore::Error error) { - OnEvent(result, error); + [this](const T& result, firebase::firestore::Error error_code, + const std::string& error_message) { + OnEvent(result, error_code, error_message); }); #else return ref->AddSnapshotListener(this); @@ -294,7 +296,7 @@ extern "C" int common_main(int argc, const char* argv[]) { collection.Document("three"), firebase::firestore::MapFieldValue{ {"int", firebase::firestore::FieldValue::Integer(321)}}); - return firebase::firestore::kOk; + return firebase::firestore::kErrorOk; }), "firestore.RunTransaction"); LogMessage("Tested transaction."); diff --git a/firestore/testapp/testapp.xcodeproj/project.pbxproj b/firestore/testapp/testapp.xcodeproj/project.pbxproj index cabe181e..81ed36ca 100644 --- a/firestore/testapp/testapp.xcodeproj/project.pbxproj +++ b/firestore/testapp/testapp.xcodeproj/project.pbxproj @@ -284,7 +284,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -321,7 +321,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/functions/testapp/Podfile b/functions/testapp/Podfile index eb5c0fc8..51c5b50a 100644 --- a/functions/testapp/Podfile +++ b/functions/testapp/Podfile @@ -2,6 +2,6 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' # Cloud Functions for Firebase test application. target 'testapp' do - pod 'Firebase/Functions', '6.24.0' - pod 'Firebase/Auth', '6.24.0' + pod 'Firebase/Functions', '7.0.0' + pod 'Firebase/Auth', '7.0.0' end diff --git a/functions/testapp/testapp.xcodeproj/project.pbxproj b/functions/testapp/testapp.xcodeproj/project.pbxproj index baf45c4c..6c325725 100644 --- a/functions/testapp/testapp.xcodeproj/project.pbxproj +++ b/functions/testapp/testapp.xcodeproj/project.pbxproj @@ -208,7 +208,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -245,7 +245,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/messaging/testapp/Podfile b/messaging/testapp/Podfile index b0f6333b..e6ffc8dc 100644 --- a/messaging/testapp/Podfile +++ b/messaging/testapp/Podfile @@ -2,5 +2,5 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' # FCM test application. target 'testapp' do - pod 'Firebase/Messaging', '6.24.0' + pod 'Firebase/Messaging', '7.0.0' end diff --git a/messaging/testapp/testapp.xcodeproj/project.pbxproj b/messaging/testapp/testapp.xcodeproj/project.pbxproj index da19cde8..096e3825 100644 --- a/messaging/testapp/testapp.xcodeproj/project.pbxproj +++ b/messaging/testapp/testapp.xcodeproj/project.pbxproj @@ -212,7 +212,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -249,7 +249,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/readme.md b/readme.md index 5c7e288c..53fededc 100644 --- a/readme.md +++ b/readme.md @@ -6,6 +6,13 @@ iOS and Android samples for the For more information, see [firebase.google.com](https://firebase.google.com). +## Issue reporting + +This repo no longer accepts issue reporting. For Firebase C++ SDK related +issues, please report to +[Firebase C++ Open-source](https://github.com/firebase/firebase-cpp-sdk/issues). +Please fill in the template to expedite the support. + ## How to make contributions? Please read and follow the steps in [CONTRIBUTING.md](CONTRIBUTING.md). diff --git a/remote_config/testapp/Podfile b/remote_config/testapp/Podfile index d44ec81f..5ce98e6d 100644 --- a/remote_config/testapp/Podfile +++ b/remote_config/testapp/Podfile @@ -2,5 +2,5 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' # Firebase Remote Config test application. target 'testapp' do - pod 'Firebase/RemoteConfig', '6.24.0' + pod 'Firebase/RemoteConfig', '7.0.0' end diff --git a/remote_config/testapp/testapp.xcodeproj/project.pbxproj b/remote_config/testapp/testapp.xcodeproj/project.pbxproj index baf45c4c..6c325725 100644 --- a/remote_config/testapp/testapp.xcodeproj/project.pbxproj +++ b/remote_config/testapp/testapp.xcodeproj/project.pbxproj @@ -208,7 +208,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -245,7 +245,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/storage/testapp/Podfile b/storage/testapp/Podfile index 5dca5c0b..f79f288b 100644 --- a/storage/testapp/Podfile +++ b/storage/testapp/Podfile @@ -2,6 +2,6 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' # Cloud Storage for Firebase test application. target 'testapp' do - pod 'Firebase/Storage', '6.24.0' - pod 'Firebase/Auth', '6.24.0' + pod 'Firebase/Storage', '7.0.0' + pod 'Firebase/Auth', '7.0.0' end diff --git a/storage/testapp/testapp.xcodeproj/project.pbxproj b/storage/testapp/testapp.xcodeproj/project.pbxproj index baf45c4c..6c325725 100644 --- a/storage/testapp/testapp.xcodeproj/project.pbxproj +++ b/storage/testapp/testapp.xcodeproj/project.pbxproj @@ -208,7 +208,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -245,7 +245,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; From 9bb7bde5fd1a3a127997a25f9c237e1fb919eb0e Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Wed, 21 Jul 2021 14:05:02 -0500 Subject: [PATCH 07/57] Apply clang-format (updated). --- firestore/testapp/src/common_main.cc | 34 ++++++++++++++-------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/firestore/testapp/src/common_main.cc b/firestore/testapp/src/common_main.cc index 3f2d05ad..ad77bfd4 100644 --- a/firestore/testapp/src/common_main.cc +++ b/firestore/testapp/src/common_main.cc @@ -65,7 +65,8 @@ class TestEventListener : public Countable, public: explicit TestEventListener(std::string name) : name_(std::move(name)) {} - void OnEvent(const T& value, const firebase::firestore::Error error_code, + void OnEvent(const T& value, + const firebase::firestore::Error error_code, const std::string& error_message) override { event_count_++; if (error_code != firebase::firestore::kErrorOk) { @@ -283,22 +284,21 @@ extern "C" int common_main(int argc, const char* argv[]) { LogMessage("Tested batch write."); LogMessage("Testing transaction."); - Await( - firestore->RunTransaction( - [collection](firebase::firestore::Transaction& transaction, - std::string&) -> firebase::firestore::Error { - transaction.Update( - collection.Document("one"), - firebase::firestore::MapFieldValue{ - {"int", firebase::firestore::FieldValue::Integer(123)}}); - transaction.Delete(collection.Document("two")); - transaction.Set( - collection.Document("three"), - firebase::firestore::MapFieldValue{ - {"int", firebase::firestore::FieldValue::Integer(321)}}); - return firebase::firestore::kErrorOk; - }), - "firestore.RunTransaction"); + Await(firestore->RunTransaction( + [collection](firebase::firestore::Transaction& transaction, + std::string&) -> firebase::firestore::Error { + transaction.Update( + collection.Document("one"), + firebase::firestore::MapFieldValue{ + {"int", firebase::firestore::FieldValue::Integer(123)}}); + transaction.Delete(collection.Document("two")); + transaction.Set( + collection.Document("three"), + firebase::firestore::MapFieldValue{ + {"int", firebase::firestore::FieldValue::Integer(321)}}); + return firebase::firestore::kErrorOk; + }), + "firestore.RunTransaction"); LogMessage("Tested transaction."); LogMessage("Testing query."); From 9ee9260614dc45186cbc413b1155752f0e478162 Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Wed, 21 Jul 2021 14:05:34 -0500 Subject: [PATCH 08/57] Don't use the deprecated EventListener class. --- firestore/testapp/src/common_main.cc | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/firestore/testapp/src/common_main.cc b/firestore/testapp/src/common_main.cc index ad77bfd4..4322d77d 100644 --- a/firestore/testapp/src/common_main.cc +++ b/firestore/testapp/src/common_main.cc @@ -60,14 +60,13 @@ class Countable { }; template -class TestEventListener : public Countable, - public firebase::firestore::EventListener { +class TestEventListener : public Countable { public: explicit TestEventListener(std::string name) : name_(std::move(name)) {} void OnEvent(const T& value, const firebase::firestore::Error error_code, - const std::string& error_message) override { + const std::string& error_message) { event_count_++; if (error_code != firebase::firestore::kErrorOk) { LogMessage("ERROR: EventListener %s got %d (%s).", name_.c_str(), @@ -75,19 +74,13 @@ class TestEventListener : public Countable, } } - // Hides the STLPort-related quirk that `AddSnapshotListener` has different - // signatures depending on whether `std::function` is available. template firebase::firestore::ListenerRegistration AttachTo(U* ref) { -#if !defined(STLPORT) return ref->AddSnapshotListener( [this](const T& result, firebase::firestore::Error error_code, const std::string& error_message) { OnEvent(result, error_code, error_message); }); -#else - return ref->AddSnapshotListener(this); -#endif } private: From 0b490c0ba3700696b45f623fc0d3acfc5f84ab1c Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Wed, 21 Jul 2021 14:57:55 -0500 Subject: [PATCH 09/57] Add .clang-format. --- firestore/.clang-format | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 firestore/.clang-format diff --git a/firestore/.clang-format b/firestore/.clang-format new file mode 100644 index 00000000..e2412319 --- /dev/null +++ b/firestore/.clang-format @@ -0,0 +1,9 @@ +BasedOnStyle: Google +Standard: Cpp11 +ColumnLimit: 80 +BinPackParameters: false +AllowAllParametersOfDeclarationOnNextLine: true +SpacesInContainerLiterals: true +DerivePointerAlignment: false +PointerAlignment: Left +IncludeBlocks: Preserve From 1d220911b5a94d90101ad5812b0acbff35b92cec Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Wed, 21 Jul 2021 15:42:45 -0500 Subject: [PATCH 10/57] Update README to reflect changes in the frameworks. --- firestore/testapp/README.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/firestore/testapp/README.md b/firestore/testapp/README.md index 90578cad..5594b6f4 100644 --- a/firestore/testapp/README.md +++ b/firestore/testapp/README.md @@ -33,6 +33,14 @@ Building and Running the testapp sudo gem install cocoapods --pre ``` + - Update the pod versions in the Podfile to match the C++ SDK version that you are using. + For instance: if you're using SDK version 8.2.0, use the following in the Podfile: + + ``` + pod 'Firebase/Firestore', '8.2.0' + pod 'Firebase/Auth', '8.2.0' + ``` + - From the testapp directory, install the CocoaPods listed in the Podfile by running, @@ -71,15 +79,15 @@ Building and Running the testapp - Add the following frameworks from the Firebase C++ SDK to the project: - - frameworks/ios/universal/firebase.framework - - frameworks/ios/universal/firebase_auth.framework - - frameworks/ios/universal/firebase_firestore.framework + - xcframeworks/firebase.xcframework/ios-arm64_armv7/firebase.framework + - xcframeworks/firebase_firestore.xcframework/ios-arm64_armv7/firebase_firestore.framework + - xcframeworks/firebase_auth.xcframework/ios-arm64_armv7/firebase_auth.framework - You will need to either, 1. Check "Copy items if needed" when adding the frameworks, or 2. Add the framework path in "Framework Search Paths" - e.g. If you downloaded the Firebase C++ SDK to `/Users/me/firebase_cpp_sdk`, then you would add the path - `/Users/me/firebase_cpp_sdk/frameworks/ios/universal`. + `/Users/me/firebase_cpp_sdk/xcframeworks/**`. - To add the path, in XCode, select your project in the project navigator, then select your target in the main window. Select the "Build Settings" tab, and click "All" to see all the build From 7193c581568b18622499d9082026c1308a6eb88f Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Wed, 21 Jul 2021 15:50:12 -0500 Subject: [PATCH 11/57] Update the Podfile. - The minimum target had to be bumped up. - Firebase/Analytics is no longer needed for this app to work. --- firestore/testapp/Podfile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/firestore/testapp/Podfile b/firestore/testapp/Podfile index b4fb49d8..31e20c7c 100644 --- a/firestore/testapp/Podfile +++ b/firestore/testapp/Podfile @@ -1,8 +1,7 @@ source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' +platform :ios, '10.0' # Firebase Firestore test application. target 'testapp' do - pod 'Firebase/Analytics', '7.0.0' - pod 'Firebase/Firestore', '7.0.0' - pod 'Firebase/Auth', '7.0.0' + pod 'Firebase/Firestore', '8.2.0' + pod 'Firebase/Auth', '8.2.0' end From 7576b1f27a4b974bcf2111395613fad9ceca34ce Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Thu, 22 Jul 2021 10:18:09 -0500 Subject: [PATCH 12/57] Add more info to README. --- firestore/testapp/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/firestore/testapp/README.md b/firestore/testapp/README.md index 5594b6f4..2254c47e 100644 --- a/firestore/testapp/README.md +++ b/firestore/testapp/README.md @@ -34,6 +34,8 @@ Building and Running the testapp ``` - Update the pod versions in the Podfile to match the C++ SDK version that you are using. + For the latest version of the C++ SDK, you can find the associated pod versions on the + [`Add Firebase to your project` page](https://firebase.google.com/docs/cpp/setup?platform=ios#libraries-ios). For instance: if you're using SDK version 8.2.0, use the following in the Podfile: ``` From 78ae4919c1a624337f924585f063454734d25d92 Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Thu, 22 Jul 2021 11:27:29 -0500 Subject: [PATCH 13/57] Update the TODOs in the README. --- firestore/testapp/README.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/firestore/testapp/README.md b/firestore/testapp/README.md index 90578cad..e258a51c 100644 --- a/firestore/testapp/README.md +++ b/firestore/testapp/README.md @@ -13,7 +13,19 @@ The testapp performs the following: - Gets a pointer to firebase::Auth, and signs in anonymously. This allows the testapp to access a Firebase Firestore instance with authentication rules enabled. -- TODO(varconst): describe the Firestore-specific logic +- Initializes a Firestore instance, and sets its logging level to + `kLogLevelDebug` in order to see debug messages in the logs. +- Tests that it can create Timestamp, SnapshotMetadata, and GeoPoint objects. +- Creates a collection, and a document inside that collection. +- Writes initial data to the document (`Set`), updates the document content + (`Update`), reads the document back (`Get`), and checks that the contents + match our expectation. +- Deletes the document. +- Performs a batch write to two documents. +- Performs a Transaction containing three operations (`Update`, `Delete`, and + `Set`) on three different documents. +- Queries documents in the collection that match a certain condition. Ensures + the documents returned via the query match our expectation. Introduction ------------ @@ -220,11 +232,6 @@ Building and Running the testapp - The testapp has no user interface, but the output can be viewed via the console. -Known issues ------------- - -TODO(varconst) - Support ------- From b71ac8f39ed51803e4b3d7ea8addf1a68d4aed41 Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Thu, 22 Jul 2021 13:59:16 -0500 Subject: [PATCH 14/57] Address code review --- firestore/testapp/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/firestore/testapp/README.md b/firestore/testapp/README.md index e258a51c..beb93221 100644 --- a/firestore/testapp/README.md +++ b/firestore/testapp/README.md @@ -13,10 +13,11 @@ The testapp performs the following: - Gets a pointer to firebase::Auth, and signs in anonymously. This allows the testapp to access a Firebase Firestore instance with authentication rules enabled. -- Initializes a Firestore instance, and sets its logging level to +- Initializes a Firestore instance and sets its logging level to `kLogLevelDebug` in order to see debug messages in the logs. -- Tests that it can create Timestamp, SnapshotMetadata, and GeoPoint objects. -- Creates a collection, and a document inside that collection. +- Tests that it can create `Timestamp`, `SnapshotMetadata`, and `GeoPoint` + objects. +- Creates a collection and a document inside that collection. - Writes initial data to the document (`Set`), updates the document content (`Update`), reads the document back (`Get`), and checks that the contents match our expectation. From bf3b0298a44a71890fad7e4ba93376d4070c300b Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Wed, 28 Jul 2021 10:53:40 -0500 Subject: [PATCH 15/57] Address comments. --- firestore/testapp/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/firestore/testapp/README.md b/firestore/testapp/README.md index 2254c47e..87de3f2c 100644 --- a/firestore/testapp/README.md +++ b/firestore/testapp/README.md @@ -37,6 +37,7 @@ Building and Running the testapp For the latest version of the C++ SDK, you can find the associated pod versions on the [`Add Firebase to your project` page](https://firebase.google.com/docs/cpp/setup?platform=ios#libraries-ios). For instance: if you're using SDK version 8.2.0, use the following in the Podfile: + (but note that pod versions may not always match the C++ SDK version) ``` pod 'Firebase/Firestore', '8.2.0' From a94a30df2cf31dce2b8f99947486ec640b142c7a Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Wed, 28 Jul 2021 14:30:01 -0500 Subject: [PATCH 16/57] Address comments. --- firestore/testapp/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firestore/testapp/README.md b/firestore/testapp/README.md index 87de3f2c..266a52bb 100644 --- a/firestore/testapp/README.md +++ b/firestore/testapp/README.md @@ -36,8 +36,8 @@ Building and Running the testapp - Update the pod versions in the Podfile to match the C++ SDK version that you are using. For the latest version of the C++ SDK, you can find the associated pod versions on the [`Add Firebase to your project` page](https://firebase.google.com/docs/cpp/setup?platform=ios#libraries-ios). - For instance: if you're using SDK version 8.2.0, use the following in the Podfile: - (but note that pod versions may not always match the C++ SDK version) + For instance: if you're using SDK version 8.2.0, use the following in the Podfile + (but note that pod versions may not always match the C++ SDK version): ``` pod 'Firebase/Firestore', '8.2.0' From d8f77e2f2fd1f6ce5f19371bbde54fa502b77ffb Mon Sep 17 00:00:00 2001 From: Vimanyu Date: Thu, 5 Aug 2021 10:14:18 -0700 Subject: [PATCH 17/57] update to use job intent service --- messaging/testapp/AndroidManifest.xml | 1 + .../java/com/google/firebase/example/TestappNativeActivity.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/messaging/testapp/AndroidManifest.xml b/messaging/testapp/AndroidManifest.xml index ae648799..b1cc6a55 100644 --- a/messaging/testapp/AndroidManifest.xml +++ b/messaging/testapp/AndroidManifest.xml @@ -52,6 +52,7 @@ android:exported="false" > diff --git a/messaging/testapp/src/android/java/com/google/firebase/example/TestappNativeActivity.java b/messaging/testapp/src/android/java/com/google/firebase/example/TestappNativeActivity.java index 290a030e..e504595a 100644 --- a/messaging/testapp/src/android/java/com/google/firebase/example/TestappNativeActivity.java +++ b/messaging/testapp/src/android/java/com/google/firebase/example/TestappNativeActivity.java @@ -54,7 +54,7 @@ protected void onNewIntent(Intent intent) { message.setAction(MessageForwardingService.ACTION_REMOTE_INTENT); message.putExtras(intent); message.setData(intent.getData()); - startService(message); + MessageForwardingService.enqueueWork(this, message); } setIntent(intent); } From 05d7b6a1f56e736e0edeae1c2110283b5054f549 Mon Sep 17 00:00:00 2001 From: Vimanyu Date: Thu, 5 Aug 2021 10:14:51 -0700 Subject: [PATCH 18/57] add compatibility with java8 bytecode --- messaging/testapp/build.gradle | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/messaging/testapp/build.gradle b/messaging/testapp/build.gradle index 2f8eaf46..0971c57b 100644 --- a/messaging/testapp/build.gradle +++ b/messaging/testapp/build.gradle @@ -25,6 +25,13 @@ android { compileSdkVersion 28 buildToolsVersion '28.0.3' + android { + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } + } + sourceSets { main { jniLibs.srcDirs = ['libs'] From 9cb1268630c5e745735e45b0c63c239662b428c5 Mon Sep 17 00:00:00 2001 From: Vimanyu Date: Tue, 10 Aug 2021 10:14:15 -0700 Subject: [PATCH 19/57] for consistency with firebase-cpp-sdk android manifest Didn't see any difference on adding this in quickstart but it is good for consistency sake. --- messaging/testapp/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/messaging/testapp/AndroidManifest.xml b/messaging/testapp/AndroidManifest.xml index b1cc6a55..f0f9b9c8 100644 --- a/messaging/testapp/AndroidManifest.xml +++ b/messaging/testapp/AndroidManifest.xml @@ -49,6 +49,7 @@ Date: Tue, 5 Apr 2022 10:11:57 -0400 Subject: [PATCH 20/57] Android build --- gma/testapp/AndroidManifest.xml | 26 + gma/testapp/CMakeLists.txt | 111 +++++ gma/testapp/LICENSE | 202 ++++++++ gma/testapp/LaunchScreen.storyboard | 7 + gma/testapp/Podfile | 7 + gma/testapp/build.gradle | 71 +++ gma/testapp/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 49896 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + gma/testapp/gradlew | 164 +++++++ gma/testapp/gradlew.bat | 90 ++++ gma/testapp/proguard.pro | 2 + gma/testapp/readme.md | 194 ++++++++ gma/testapp/res/values/strings.xml | 4 + gma/testapp/settings.gradle | 36 ++ gma/testapp/src/android/android_main.cc | 255 ++++++++++ .../google/firebase/example/LoggingUtils.java | 55 +++ gma/testapp/src/common_main.cc | 463 ++++++++++++++++++ gma/testapp/src/desktop/desktop_main.cc | 125 +++++ gma/testapp/src/ios/ios_main.mm | 119 +++++ gma/testapp/src/main.h | 63 +++ gma/testapp/testapp.xcodeproj/project.pbxproj | 312 ++++++++++++ .../AppIcon.appiconset/Contents.json | 73 +++ .../LaunchImage.launchimage/Contents.json | 36 ++ gma/testapp/testapp/Info.plist | 28 ++ 24 files changed, 2449 insertions(+) create mode 100644 gma/testapp/AndroidManifest.xml create mode 100644 gma/testapp/CMakeLists.txt create mode 100644 gma/testapp/LICENSE create mode 100644 gma/testapp/LaunchScreen.storyboard create mode 100644 gma/testapp/Podfile create mode 100644 gma/testapp/build.gradle create mode 100644 gma/testapp/gradle/wrapper/gradle-wrapper.jar create mode 100644 gma/testapp/gradle/wrapper/gradle-wrapper.properties create mode 100755 gma/testapp/gradlew create mode 100644 gma/testapp/gradlew.bat create mode 100644 gma/testapp/proguard.pro create mode 100644 gma/testapp/readme.md create mode 100644 gma/testapp/res/values/strings.xml create mode 100644 gma/testapp/settings.gradle create mode 100644 gma/testapp/src/android/android_main.cc create mode 100644 gma/testapp/src/android/java/com/google/firebase/example/LoggingUtils.java create mode 100644 gma/testapp/src/common_main.cc create mode 100644 gma/testapp/src/desktop/desktop_main.cc create mode 100644 gma/testapp/src/ios/ios_main.mm create mode 100644 gma/testapp/src/main.h create mode 100644 gma/testapp/testapp.xcodeproj/project.pbxproj create mode 100644 gma/testapp/testapp/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 gma/testapp/testapp/Images.xcassets/LaunchImage.launchimage/Contents.json create mode 100644 gma/testapp/testapp/Info.plist diff --git a/gma/testapp/AndroidManifest.xml b/gma/testapp/AndroidManifest.xml new file mode 100644 index 00000000..092181fa --- /dev/null +++ b/gma/testapp/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + diff --git a/gma/testapp/CMakeLists.txt b/gma/testapp/CMakeLists.txt new file mode 100644 index 00000000..2132660c --- /dev/null +++ b/gma/testapp/CMakeLists.txt @@ -0,0 +1,111 @@ +cmake_minimum_required(VERSION 2.8) + +# User settings for Firebase samples. +# Path to Firebase SDK. +# Try to read the path to the Firebase C++ SDK from an environment variable. +if (NOT "$ENV{FIREBASE_CPP_SDK_DIR}" STREQUAL "") + set(DEFAULT_FIREBASE_CPP_SDK_DIR "$ENV{FIREBASE_CPP_SDK_DIR}") +else() + set(DEFAULT_FIREBASE_CPP_SDK_DIR "firebase_cpp_sdk") +endif() +if ("${FIREBASE_CPP_SDK_DIR}" STREQUAL "") + set(FIREBASE_CPP_SDK_DIR ${DEFAULT_FIREBASE_CPP_SDK_DIR}) +endif() +if(NOT EXISTS ${FIREBASE_CPP_SDK_DIR}) + message(FATAL_ERROR "The Firebase C++ SDK directory does not exist: ${FIREBASE_CPP_SDK_DIR}. See the readme.md for more information") +endif() + +# Sample source files. +set(FIREBASE_SAMPLE_COMMON_SRCS + src/main.h + src/common_main.cc +) + +# The include directory for the testapp. +include_directories(src) + +# Sample uses some features that require C++ 11, such as lambdas. +set (CMAKE_CXX_STANDARD 11) + +if(ANDROID) + # Build an Android application. + + # Source files used for the Android build. + set(FIREBASE_SAMPLE_ANDROID_SRCS + src/android/android_main.cc + ) + + # Build native_app_glue as a static lib + add_library(native_app_glue STATIC + ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) + + # Export ANativeActivity_onCreate(), + # Refer to: https://github.com/android-ndk/ndk/issues/381. + set(CMAKE_SHARED_LINKER_FLAGS + "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") + + # Define the target as a shared library, as that is what gradle expects. + set(target_name "android_main") + add_library(${target_name} SHARED + ${FIREBASE_SAMPLE_ANDROID_SRCS} + ${FIREBASE_SAMPLE_COMMON_SRCS} + ) + + target_link_libraries(${target_name} + log android atomic native_app_glue + ) + + target_include_directories(${target_name} PRIVATE + ${ANDROID_NDK}/sources/android/native_app_glue) + + set(ADDITIONAL_LIBS) +else() + # Build a desktop application. + + # Windows runtime mode, either MD or MT depending on whether you are using + # /MD or /MT. For more information see: + # https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx + set(MSVC_RUNTIME_MODE MD) + + # Platform abstraction layer for the desktop sample. + set(FIREBASE_SAMPLE_DESKTOP_SRCS + src/desktop/desktop_main.cc + ) + + set(target_name "desktop_testapp") + add_executable(${target_name} + ${FIREBASE_SAMPLE_DESKTOP_SRCS} + ${FIREBASE_SAMPLE_COMMON_SRCS} + ) + + if(APPLE) + set(ADDITIONAL_LIBS pthread) + elseif(MSVC) + set(ADDITIONAL_LIBS) + else() + set(ADDITIONAL_LIBS pthread) + endif() + + # If a config file is present, copy it into the binary location so that it's + # possible to create the default Firebase app. + set(FOUND_JSON_FILE FALSE) + foreach(config "google-services-desktop.json" "google-services.json") + if (EXISTS ${config}) + add_custom_command( + TARGET ${target_name} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${config} $) + set(FOUND_JSON_FILE TRUE) + break() + endif() + endforeach() + if(NOT FOUND_JSON_FILE) + message(WARNING "Failed to find either google-services-desktop.json or google-services.json. See the readme.md for more information.") + endif() +endif() + +# Add the Firebase libraries to the target using the function from the SDK. +add_subdirectory(${FIREBASE_CPP_SDK_DIR} bin/ EXCLUDE_FROM_ALL) +# Note that firebase_app needs to be last in the list. +set(firebase_libs firebase_gma firebase_app) +target_link_libraries(${target_name} "${firebase_libs}" ${ADDITIONAL_LIBS}) diff --git a/gma/testapp/LICENSE b/gma/testapp/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/gma/testapp/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/gma/testapp/LaunchScreen.storyboard b/gma/testapp/LaunchScreen.storyboard new file mode 100644 index 00000000..673e0f7e --- /dev/null +++ b/gma/testapp/LaunchScreen.storyboard @@ -0,0 +1,7 @@ + + + + + + + diff --git a/gma/testapp/Podfile b/gma/testapp/Podfile new file mode 100644 index 00000000..3d649e01 --- /dev/null +++ b/gma/testapp/Podfile @@ -0,0 +1,7 @@ +source 'https://github.com/CocoaPods/Specs.git' +platform :ios, '8.0' +# GMA test application. +target 'testapp' do + pod 'Google-Mobile-Ads-SDK', '8.13.0' + pod 'Firebase/Analytics', '8.10.0' +end diff --git a/gma/testapp/build.gradle b/gma/testapp/build.gradle new file mode 100644 index 00000000..e8c75724 --- /dev/null +++ b/gma/testapp/build.gradle @@ -0,0 +1,71 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + mavenLocal() + maven { url 'https://maven.google.com' } + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.3.3' + classpath 'com.google.gms:google-services:4.0.1' } +} + +allprojects { + repositories { + mavenLocal() + maven { url 'https://maven.google.com' } + jcenter() + } +} + +apply plugin: 'com.android.application' + +android { + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } + + compileSdkVersion 28 + buildToolsVersion '28.0.3' + + sourceSets { + main { + jniLibs.srcDirs = ['libs'] + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = ['src/android/java'] + res.srcDirs = ['res'] + } + } + + defaultConfig { + applicationId 'com.google.android.admob.testapp' + minSdkVersion 19 + targetSdkVersion 28 + versionCode 1 + versionName '1.0' + externalNativeBuild.cmake { + arguments "-DFIREBASE_CPP_SDK_DIR=$gradle.firebase_cpp_sdk_dir" + } + } + externalNativeBuild.cmake { + path 'CMakeLists.txt' + } + buildTypes { + release { + minifyEnabled true + proguardFile getDefaultProguardFile('proguard-android.txt') + proguardFile file('proguard.pro') + } + } +} + +apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle" +firebaseCpp.dependencies { + gma +} + +apply plugin: 'com.google.gms.google-services' + +// com.google.gms.googleservices.GoogleServicesPlugin.config.disableVersionCheck = true diff --git a/gma/testapp/gradle/wrapper/gradle-wrapper.jar b/gma/testapp/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..8c0fb64a8698b08ecc4158d828ca593c4928e9dd GIT binary patch literal 49896 zcmagFb986H(k`5d^NVfUwr$(C?M#x1ZQHiZiEVpg+jrjgoQrerx!>1o_ul)D>ebz~ zs=Mmxr&>W81QY-S1PKWQ%N-;H^tS;2*XwVA`dej1RRn1z<;3VgfE4~kaG`A%QSPsR z#ovnZe+tS9%1MfeDyz`RirvdjPRK~p(#^q2(^5@O&NM19EHdvN-A&StN>0g6QA^VN z0Gx%Gq#PD$QMRFzmK+utjS^Y1F0e8&u&^=w5K<;4Rz|i3A=o|IKLY+g`iK6vfr9?+ z-`>gmU&i?FGSL5&F?TXFu`&Js6h;15QFkXp2M1H9|Eq~bpov-GU(uz%mH0n55wUl- zv#~ccAz`F5wlQ>e_KlJS3@{)B?^v*EQM=IxLa&76^y51a((wq|2-`qON>+4dLc{Oo z51}}o^Zen(oAjxDK7b++9_Yg`67p$bPo3~BCpGM7uAWmvIhWc5Gi+gQZ|Pwa-Gll@<1xmcPy z|NZmu6m)g5Ftu~BG&Xdxclw7Cij{xbBMBn-LMII#Slp`AElb&2^Hw+w>(3crLH!;I zN+Vk$D+wP1#^!MDCiad@vM>H#6+`Ct#~6VHL4lzmy;lSdk>`z6)=>Wh15Q2)dQtGqvn0vJU@+(B5{MUc*qs4!T+V=q=wy)<6$~ z!G>e_4dN@lGeF_$q9`Ju6Ncb*x?O7=l{anm7Eahuj_6lA{*#Gv*TaJclevPVbbVYu z(NY?5q+xxbO6%g1xF0r@Ix8fJ~u)VRUp`S%&rN$&e!Od`~s+64J z5*)*WSi*i{k%JjMSIN#X;jC{HG$-^iX+5f5BGOIHWAl*%15Z#!xntpk($-EGKCzKa zT7{siZ9;4TICsWQ$pu&wKZQTCvpI$Xvzwxoi+XkkpeE&&kFb!B?h2hi%^YlXt|-@5 zHJ~%AN!g_^tmn1?HSm^|gCE#!GRtK2(L{9pL#hp0xh zME}|DB>(5)`iE7CM)&_+S}-Bslc#@B5W4_+k4Cp$l>iVyg$KP>CN?SVGZ(&02>iZK zB<^HP$g$Lq*L$BWd?2(F?-MUbNWTJVQdW7$#8a|k_30#vHAD1Z{c#p;bETk0VnU5A zBgLe2HFJ3032$G<`m*OB!KM$*sdM20jm)It5OSru@tXpK5LT>#8)N!*skNu1$TpIw zufjjdp#lyH5bZ%|Iuo|iu9vG1HrIVWLH>278xo>aVBkPN3V$~!=KnlXQ4eDqS7%E% zQ!z^$Q$b^6Q)g#cLpwur(|<0gWHo6A6jc;n`t(V9T;LzTAU{IAu*uEQ%Ort1k+Kn+f_N`9|bxYC+~Z1 zCC1UCWv*Orx$_@ydv9mIe(liLfOr7mhbV@tKw{6)q^1DH1nmvZ0cj215R<~&I<4S| zgnr;9Cdjqpz#o8i0CQjtl`}{c*P)aSdH|abxGdrR)-3z+02-eX(k*B)Uqv6~^nh** z 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 \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gma/testapp/gradlew.bat b/gma/testapp/gradlew.bat new file mode 100644 index 00000000..8a0b282a --- /dev/null +++ b/gma/testapp/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/gma/testapp/proguard.pro b/gma/testapp/proguard.pro new file mode 100644 index 00000000..54cd248b --- /dev/null +++ b/gma/testapp/proguard.pro @@ -0,0 +1,2 @@ +-ignorewarnings +-keep,includedescriptorclasses public class com.google.firebase.example.LoggingUtils { *; } diff --git a/gma/testapp/readme.md b/gma/testapp/readme.md new file mode 100644 index 00000000..018af54d --- /dev/null +++ b/gma/testapp/readme.md @@ -0,0 +1,194 @@ +Firebase GMA Quickstart +============================== + +The Firebase Google Mobile Ads Test Application (testapp) demonstrates +loading and showing AdMob-served banners, interstitials and rewarded ads +using the Firebase GMA C++ SDK. The application has no user interface and +simply logs actions it's performing to the console while displaying the ads. + +Introduction +------------ + +- [Read more about Firebase GMA](https://firebase.google.com/docs/gma) + +Getting Started +--------------- + +### iOS + - Link your iOS app to the Firebase libraries. + - Get CocoaPods version 1 or later by running, + ``` + sudo gem install cocoapods --pre + ``` + - From the testapp directory, install the CocoaPods listed in the Podfile + by running, + ``` + pod install + ``` + - Open the generated Xcode workspace (which now has the CocoaPods), + ``` + open testapp.xcworkspace + ``` + - For further details please refer to the + [general instructions for setting up an iOS app with Firebase](https://firebase.google.com/docs/ios/setup). + - Register your iOS app with Firebase. + - Create a new app on the [Firebase console](https://firebase.google.com/console/), + and attach your iOS app to it. + - You can use "com.google.ios.admob.testapp" as the iOS Bundle ID + while you're testing. You can omit App Store ID while testing. + - Download the Firebase C++ SDK linked from + [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup) + and unzip it to a directory of your choice. + - Add the following frameworks from the Firebase C++ SDK to the project: + - frameworks/ios/universal/firebase.framework + - frameworks/ios/universal/firebase_gma.framework + - You will need to either, + 1. Check "Copy items if needed" when adding the frameworks, or + 2. Add the framework path in "Framework Search Paths" + - For example, if you downloaded the Firebase C++ SDK to + `/Users/me/firebase_cpp_sdk`, + then you would add the path + `/Users/me/firebase_cpp_sdk/frameworks/ios/universal`. + - To add the path, in Xcode, select your project in the project + navigator, then select your target in the main window. + Select the "Build Settings" tab, and click "All" to see all + the build settings. Scroll down to "Search Paths", and add + your path to "Framework Search Paths". + - Update the AdMob App ID: + - In the `testapp/Info.plist`, update `GADApplicationIdentifier` with the + app ID for your iOS app, replacing 'YOUR_IOS_ADMOB_APP_ID'. + - For more information, see + [Update your Info.plist](https://developers.google.com/admob/ios/quick-start#manual_download) + - In Xcode, build & run the sample on an iOS device or simulator. + - The testapp displays a banner ad, an interstitial ad and a rewarded ad. You must + dismiss each ad to see the next. + - The output of the app can be viewed onscreen or via the console. To view + the console in Xcode, select "View --> Debug Area --> Activate Console" + from the menu. + +### Android + - Register your Android app with Firebase. + - Create a new app on the [Firebase console](https://firebase.google.com/console/), + and attach your Android app to it. + - You can use "com.google.android.admob.testapp" as the Package Name + while you're testing. + - To [generate a SHA1](https://developers.google.com/android/guides/client-auth) + run this command on Mac and Linux, + ``` + keytool -exportcert -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore + ``` + or this command on Windows, + ``` + keytool -exportcert -list -v -alias androiddebugkey -keystore %USERPROFILE%\.android\debug.keystore + ``` + - If keytool reports that you do not have a debug.keystore, you can + [create one with](http://developer.android.com/tools/publishing/app-signing.html#signing-manually), + ``` + keytool -genkey -v -keystore ~/.android/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US" + ``` + - Add the `google-services.json` file that you downloaded from Firebase + console to the root directory of testapp. This file identifies your + Android app to the Firebase backend. + - For further details please refer to the + [general instructions for setting up an Android app with Firebase](https://firebase.google.com/docs/android/setup). + - Download the Firebase C++ SDK linked from + [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup) + and unzip it to a directory of your choice. + - Configure the location of the Firebase C++ SDK by setting the + firebase\_cpp\_sdk.dir Gradle property to the SDK install directory. + For example, in the project directory: + ``` + echo "systemProp.firebase\_cpp\_sdk.dir=/User/$USER/firebase\_cpp\_sdk" >> gradle.properties + ``` + - Ensure the Android SDK and NDK locations are set in Android Studio. + - From the Android Studio launch menu, go to `File/Project Structure...` or + `Configure/Project Defaults/Project Structure...` + (Shortcut: Control + Alt + Shift + S on windows, Command + ";" on a mac) + and download the SDK and NDK if the locations are not yet set. + - Open *build.gradle* in Android Studio. + - From the Android Studio launch menu, "Open an existing Android Studio + project", and select `build.gradle`. + - Install the SDK Platforms that Android Studio reports missing. + - Update the GMA App ID: + - In the `AndroidManifest.xml`, update + `com.google.android.gms.ads.APPLICATION_ID` with the same app ID, + replacing 'YOUR_ANDROID_ADMOB_APP_ID'. + - For more information, see + [Update your AndroidManifest.xml](https://developers.google.com/admob/android/quick-start#update_your_androidmanifestxml) + - Build the testapp and run it on an Android device or emulator. + - The testapp will initialize the GMA SDK, then load and display a test + banner ad, interstitial ad and rewarded ad. + - Tapping on an ad to verify the clickthrough process is possible, and the + test app will wait for each ad to be dismissed. + - While this is happening, information from the device log will be written + to an onscreen TextView. + - Logcat can also be used as normal. + +### Desktop + - Note: the testapp has no user interface, but the output can be viewed via + the console. Note that the GMA SDK uses a stubbed implementation on + desktop, so functionality is not expected. + - Register your app with Firebase. + - Create a new app on the [Firebase console](https://firebase.google.com/console/), + following the above instructions for Android or iOS. + - If you have an Android project, add the `google-services.json` file that + you downloaded from the Firebase console to the root directory of the + testapp. + - If you have an iOS project, and don't wish to use an Android project, + you can use the Python script `generate_xml_from_google_services_json.py --plist`, + located in the Firebase C++ SDK, to convert your `GoogleService-Info.plist` + file into a `google-services-desktop.json` file, which can then be + placed in the root directory of the testapp. + - Download the Firebase C++ SDK linked from + [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup) + and unzip it to a directory of your choice. + - Configure the testapp with the location of the Firebase C++ SDK. + This can be done a couple different ways: + - When invoking cmake, pass in the location with + -DFIREBASE_CPP_SDK_DIR=/path/to/firebase_cpp_sdk. + - Set an environment variable for FIREBASE_CPP_SDK_DIR to the path to use. + - Edit the CMakeLists.txt file, changing the FIREBASE_CPP_SDK_DIR path + to the appropriate location. + - From the testapp directory, generate the build files by running, + ``` + cmake . + ``` + If you want to use XCode, you can use -G"Xcode" to generate the project. + Similarly, to use Visual Studio, -G"Visual Studio 15 2017". For more + information, see + [CMake generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html). + - Build the testapp, by either opening the generated project file based on + the platform, or running, + ``` + cmake --build . + ``` + - Execute the testapp by running, + ``` + ./desktop_testapp + ``` + Note that the executable might be under another directory, such as Debug. + +Support +------- + +[https://firebase.google.com/support/](https://firebase.google.com/support/) + +License +------- + +Copyright 2016 Google, Inc. + +Licensed to the Apache Software Foundation (ASF) under one or more contributor +license agreements. See the NOTICE file distributed with this work for +additional information regarding copyright ownership. The ASF licenses this +file to you 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/gma/testapp/res/values/strings.xml b/gma/testapp/res/values/strings.xml new file mode 100644 index 00000000..a9a313a3 --- /dev/null +++ b/gma/testapp/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Firebase GMA Test + diff --git a/gma/testapp/settings.gradle b/gma/testapp/settings.gradle new file mode 100644 index 00000000..2a543b93 --- /dev/null +++ b/gma/testapp/settings.gradle @@ -0,0 +1,36 @@ +// Copyright 2018 Google LLC +// +// 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. + +def firebase_cpp_sdk_dir = System.getProperty('firebase_cpp_sdk.dir') +if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) { + firebase_cpp_sdk_dir = System.getenv('FIREBASE_CPP_SDK_DIR') + if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) { + if ((new File('firebase_cpp_sdk')).exists()) { + firebase_cpp_sdk_dir = 'firebase_cpp_sdk' + } else { + throw new StopActionException( + 'firebase_cpp_sdk.dir property or the FIREBASE_CPP_SDK_DIR ' + + 'environment variable must be set to reference the Firebase C++ ' + + 'SDK install directory. This is used to configure static library ' + + 'and C/C++ include paths for the SDK.') + } + } +} +if (!(new File(firebase_cpp_sdk_dir)).exists()) { + throw new StopActionException( + sprintf('Firebase C++ SDK directory %s does not exist', + firebase_cpp_sdk_dir)) +} +gradle.ext.firebase_cpp_sdk_dir = "$firebase_cpp_sdk_dir" +includeBuild "$firebase_cpp_sdk_dir" \ No newline at end of file diff --git a/gma/testapp/src/android/android_main.cc b/gma/testapp/src/android/android_main.cc new file mode 100644 index 00000000..73cb30e7 --- /dev/null +++ b/gma/testapp/src/android/android_main.cc @@ -0,0 +1,255 @@ +// Copyright 2016 Google Inc. All rights reserved. +// +// 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 +#include + +#include +#include +#include +#include + +#include "main.h" // NOLINT + +// This implementation is derived from http://github.com/google/fplutil + +extern "C" int common_main(int argc, const char* argv[]); + +static struct android_app* g_app_state = nullptr; +static bool g_destroy_requested = false; +static bool g_started = false; +static bool g_restarted = false; +static pthread_mutex_t g_started_mutex; + +// Handle state changes from via native app glue. +static void OnAppCmd(struct android_app* app, int32_t cmd) { + g_destroy_requested |= cmd == APP_CMD_DESTROY; +} + +// Process events pending on the main thread. +// Returns true when the app receives an event requesting exit. +bool ProcessEvents(int msec) { + struct android_poll_source* source = nullptr; + int events; + int looperId = ALooper_pollAll(msec, nullptr, &events, + reinterpret_cast(&source)); + if (looperId >= 0 && source) { + source->process(g_app_state, source); + } + return g_destroy_requested | g_restarted; +} + +// Get the activity. +jobject GetActivity() { return g_app_state->activity->clazz; } + +// Get the window context. For Android, it's a jobject pointing to the Activity. +jobject GetWindowContext() { return g_app_state->activity->clazz; } + +// Find a class, attempting to load the class if it's not found. +jclass FindClass(JNIEnv* env, jobject activity_object, const char* class_name) { + jclass class_object = env->FindClass(class_name); + if (env->ExceptionCheck()) { + env->ExceptionClear(); + // If the class isn't found it's possible NativeActivity is being used by + // the application which means the class path is set to only load system + // classes. The following falls back to loading the class using the + // Activity before retrieving a reference to it. + jclass activity_class = env->FindClass("android/app/Activity"); + jmethodID activity_get_class_loader = env->GetMethodID( + activity_class, "getClassLoader", "()Ljava/lang/ClassLoader;"); + + jobject class_loader_object = + env->CallObjectMethod(activity_object, activity_get_class_loader); + + jclass class_loader_class = env->FindClass("java/lang/ClassLoader"); + jmethodID class_loader_load_class = + env->GetMethodID(class_loader_class, "loadClass", + "(Ljava/lang/String;)Ljava/lang/Class;"); + jstring class_name_object = env->NewStringUTF(class_name); + + class_object = static_cast(env->CallObjectMethod( + class_loader_object, class_loader_load_class, class_name_object)); + + if (env->ExceptionCheck()) { + env->ExceptionClear(); + class_object = nullptr; + } + env->DeleteLocalRef(class_name_object); + env->DeleteLocalRef(class_loader_object); + } + return class_object; +} + +// Vars that we need available for appending text to the log window: +class LoggingUtilsData { + public: + LoggingUtilsData() + : logging_utils_class_(nullptr), + logging_utils_add_log_text_(0), + logging_utils_init_log_window_(0) {} + + ~LoggingUtilsData() { + JNIEnv* env = GetJniEnv(); + assert(env); + if (logging_utils_class_) { + env->DeleteGlobalRef(logging_utils_class_); + } + } + + void Init() { + JNIEnv* env = GetJniEnv(); + assert(env); + + jclass logging_utils_class = FindClass( + env, GetActivity(), "com/google/firebase/example/LoggingUtils"); + assert(logging_utils_class != 0); + + // Need to store as global references so it don't get moved during garbage + // collection. + logging_utils_class_ = + static_cast(env->NewGlobalRef(logging_utils_class)); + env->DeleteLocalRef(logging_utils_class); + + logging_utils_init_log_window_ = env->GetStaticMethodID( + logging_utils_class_, "initLogWindow", "(Landroid/app/Activity;)V"); + logging_utils_add_log_text_ = env->GetStaticMethodID( + logging_utils_class_, "addLogText", "(Ljava/lang/String;)V"); + + env->CallStaticVoidMethod(logging_utils_class_, + logging_utils_init_log_window_, GetActivity()); + } + + void AppendText(const char* text) { + if (logging_utils_class_ == 0) return; // haven't been initted yet + JNIEnv* env = GetJniEnv(); + assert(env); + jstring text_string = env->NewStringUTF(text); + env->CallStaticVoidMethod(logging_utils_class_, logging_utils_add_log_text_, + text_string); + env->DeleteLocalRef(text_string); + } + + private: + jclass logging_utils_class_; + jmethodID logging_utils_add_log_text_; + jmethodID logging_utils_init_log_window_; +}; + +LoggingUtilsData* g_logging_utils_data; + +// Checks if a JNI exception has happened, and if so, logs it to the console. +void CheckJNIException() { + JNIEnv* env = GetJniEnv(); + if (env->ExceptionCheck()) { + // Get the exception text. + jthrowable exception = env->ExceptionOccurred(); + env->ExceptionClear(); + + // Convert the exception to a string. + jclass object_class = env->FindClass("java/lang/Object"); + jmethodID toString = + env->GetMethodID(object_class, "toString", "()Ljava/lang/String;"); + jstring s = (jstring)env->CallObjectMethod(exception, toString); + const char* exception_text = env->GetStringUTFChars(s, nullptr); + + // Log the exception text. + __android_log_print(ANDROID_LOG_INFO, FIREBASE_TESTAPP_NAME, + "-------------------JNI exception:"); + __android_log_print(ANDROID_LOG_INFO, FIREBASE_TESTAPP_NAME, "%s", + exception_text); + __android_log_print(ANDROID_LOG_INFO, FIREBASE_TESTAPP_NAME, + "-------------------"); + + // Also, assert fail. + assert(false); + + // In the event we didn't assert fail, clean up. + env->ReleaseStringUTFChars(s, exception_text); + env->DeleteLocalRef(s); + env->DeleteLocalRef(exception); + } +} + +// Log a message that can be viewed in "adb logcat". +void LogMessage(const char* format, ...) { + static const int kLineBufferSize = 100; + char buffer[kLineBufferSize + 2]; + + va_list list; + va_start(list, format); + int string_len = vsnprintf(buffer, kLineBufferSize, format, list); + string_len = string_len < kLineBufferSize ? string_len : kLineBufferSize; + // append a linebreak to the buffer: + buffer[string_len] = '\n'; + buffer[string_len + 1] = '\0'; + + __android_log_vprint(ANDROID_LOG_INFO, FIREBASE_TESTAPP_NAME, format, list); + g_logging_utils_data->AppendText(buffer); + CheckJNIException(); + va_end(list); +} + +// Get the JNI environment. +JNIEnv* GetJniEnv() { + JavaVM* vm = g_app_state->activity->vm; + JNIEnv* env; + jint result = vm->AttachCurrentThread(&env, nullptr); + return result == JNI_OK ? env : nullptr; +} + +// Execute common_main(), flush pending events and finish the activity. +extern "C" void android_main(struct android_app* state) { + // native_app_glue spawns a new thread, calling android_main() when the + // activity onStart() or onRestart() methods are called. This code handles + // the case where we're re-entering this method on a different thread by + // signalling the existing thread to exit, waiting for it to complete before + // reinitializing the application. + if (g_started) { + g_restarted = true; + // Wait for the existing thread to exit. + pthread_mutex_lock(&g_started_mutex); + pthread_mutex_unlock(&g_started_mutex); + } else { + g_started_mutex = PTHREAD_MUTEX_INITIALIZER; + } + pthread_mutex_lock(&g_started_mutex); + g_started = true; + + // Save native app glue state and setup a callback to track the state. + g_destroy_requested = false; + g_app_state = state; + g_app_state->onAppCmd = OnAppCmd; + + // Create the logging display. + g_logging_utils_data = new LoggingUtilsData(); + g_logging_utils_data->Init(); + + // Execute cross platform entry point. + static const char* argv[] = {FIREBASE_TESTAPP_NAME}; + int return_value = common_main(1, argv); + (void)return_value; // Ignore the return value. + ProcessEvents(10); + + // Clean up logging display. + delete g_logging_utils_data; + g_logging_utils_data = nullptr; + + // Finish the activity. + if (!g_restarted) ANativeActivity_finish(state->activity); + + g_app_state->activity->vm->DetachCurrentThread(); + g_started = false; + g_restarted = false; + pthread_mutex_unlock(&g_started_mutex); +} diff --git a/gma/testapp/src/android/java/com/google/firebase/example/LoggingUtils.java b/gma/testapp/src/android/java/com/google/firebase/example/LoggingUtils.java new file mode 100644 index 00000000..11d67c5b --- /dev/null +++ b/gma/testapp/src/android/java/com/google/firebase/example/LoggingUtils.java @@ -0,0 +1,55 @@ +// Copyright 2016 Google Inc. All rights reserved. +// +// 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. + +package com.google.firebase.example; + +import android.app.Activity; +import android.os.Handler; +import android.os.Looper; +import android.view.Window; +import android.widget.LinearLayout; +import android.widget.ScrollView; +import android.widget.TextView; + +/** + * A utility class, encapsulating the data and methods required to log arbitrary + * text to the screen, via a non-editable TextView. + */ +public class LoggingUtils { + public static TextView sTextView = null; + + public static void initLogWindow(Activity activity) { + LinearLayout linearLayout = new LinearLayout(activity); + ScrollView scrollView = new ScrollView(activity); + TextView textView = new TextView(activity); + textView.setTag("Logger"); + linearLayout.addView(scrollView); + scrollView.addView(textView); + Window window = activity.getWindow(); + window.takeSurface(null); + window.setContentView(linearLayout); + sTextView = textView; + } + + public static void addLogText(final String text) { + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + if (sTextView != null) { + sTextView.append(text); + } + } + }); + } +} diff --git a/gma/testapp/src/common_main.cc b/gma/testapp/src/common_main.cc new file mode 100644 index 00000000..4d51b1b6 --- /dev/null +++ b/gma/testapp/src/common_main.cc @@ -0,0 +1,463 @@ +// Copyright 2022 Google Inc. All rights reserved. +// +// 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 "firebase/gma.h" +#include "firebase/gma/ad_view.h" +#include "firebase/gma/interstitial_ad.h" +#include "firebase/gma/rewarded_ad.h" +#include "firebase/gma/types.h" +#include "firebase/app.h" +#include "firebase/future.h" + +// Thin OS abstraction layer. +#include "main.h" // NOLINT + +// A simple listener that logs changes to an AdView. +class LoggingAdViewListener : public firebase::gma::AdListener { + public: + LoggingAdViewListener() {} + + void OnAdClicked() override { + ::LogMessage("AdView ad clicked."); + } + + void OnAdClosed() override { + ::LogMessage("AdView ad closed."); + } + + void OnAdImpression() override { + ::LogMessage("AdView ad impression."); + } + + void OnAdOpened() override { + ::LogMessage("AdView ad opened."); + } +}; + +// A simple listener that logs changes to an AdView's bounding box. +class LoggingAdViewBoundedBoxListener + : public firebase::gma::AdViewBoundingBoxListener { + public: + void OnBoundingBoxChanged(firebase::gma::AdView* ad_view, + firebase::gma::BoundingBox box) override { + ::LogMessage("AdView bounding box update x: %d y: %d " + "width: %d height: %d", box.x, box.y, box.width, box.height); + } +}; + +// A simple listener track FullScreen content changes. +class LoggingFullScreenContentListener + : public firebase::gma::FullScreenContentListener { + public: + LoggingFullScreenContentListener() : num_ad_dismissed_(0) { } + + void OnAdClicked() override { + ::LogMessage("FullScreenContent ad clicked."); + } + + void OnAdDismissedFullScreenContent() override { + ::LogMessage("FullScreenContent ad dismissed."); + num_ad_dismissed_++; + } + + void OnAdFailedToShowFullScreenContent( + const firebase::gma::AdError& ad_error) override { + ::LogMessage("FullScreenContent ad failed to show full screen content," + " AdErrorCode: %d", ad_error.code()); + } + + void OnAdImpression() override { + ::LogMessage("FullScreenContent ad impression."); + } + + void OnAdShowedFullScreenContent() override { + ::LogMessage("FullScreenContent ad showed content."); + } + + uint32_t num_ad_dismissed() const { return num_ad_dismissed_; } + + private: + uint32_t num_ad_dismissed_; +}; + +// A simple listener track UserEarnedReward events. +class LoggingUserEarnedRewardListener + : public firebase::gma::UserEarnedRewardListener { + public: + LoggingUserEarnedRewardListener() { } + + void OnUserEarnedReward(const firebase::gma::AdReward& reward) override { + ::LogMessage("User earned reward amount: %d type: %s", + reward.amount(), reward.type().c_str()); + } +}; + +// A simple listener track ad pay events. +class LoggingPaidEventListener : public firebase::gma::PaidEventListener { + public: + LoggingPaidEventListener() { } + + void OnPaidEvent(const firebase::gma::AdValue& value) override { + ::LogMessage("PaidEvent value: %lld currency_code: %s", + value.value_micros(), value.currency_code().c_str()); + } +}; + +void LoadAndShowAdView(const firebase::gma::AdRequest& ad_request); +void LoadAndShowInterstitialAd(const firebase::gma::AdRequest& ad_request); +void LoadAndShowRewardedAd(const firebase::gma::AdRequest& ad_request); + +// These ad units IDs have been created specifically for testing, and will +// always return test ads. +#if defined(__ANDROID__) +const char* kBannerAdUnit = "ca-app-pub-3940256099942544/6300978111"; +const char* kInterstitialAdUnit = "ca-app-pub-3940256099942544/1033173712"; +const char* kRewardedAdUnit = "ca-app-pub-3940256099942544/5224354917"; +#else +const char* kBannerAdUnit = "ca-app-pub-3940256099942544/2934735716"; +const char* kInterstitialAdUnit = "ca-app-pub-3940256099942544/4411468910"; +const char* kRewardedAdUnit = "ca-app-pub-3940256099942544/1712485313"; +#endif + +// Sample keywords to use in making the request. +static const std::vector kKeywords({"GMA", "C++", "Fun"}); + +// Sample test device IDs to use in making the request. Add your own here. +const std::vector kTestDeviceIDs = { + "2077ef9a63d2b398840261c8221a0c9b", "098fe087d987c9a878965454a65654d7"}; + +#if defined(ANDROID) +static const char* kAdNetworkExtrasClassName = + "com/google/ads/mediation/admob/AdMobAdapter"; +#else +static const char* kAdNetworkExtrasClassName = "GADExtras"; +#endif + +// Function to wait for the completion of a future, and log the error +// if one is encountered. +static void WaitForFutureCompletion(firebase::FutureBase future) { + while (!ProcessEvents(1000)) { + if (future.status() != firebase::kFutureStatusPending) { + break; + } + } + + if (future.error() != firebase::gma::kAdErrorCodeNone) { + LogMessage("ERROR: Action failed with error code %d and message \"%s\".", + future.error(), future.error_message()); + } +} + +// Inittialize GMA, load a Banner, Interstitial and Rewarded Ad. +extern "C" int common_main(int argc, const char* argv[]) { + firebase::App* app; + LogMessage("Initializing Firebase App."); + +#if defined(__ANDROID__) + app = ::firebase::App::Create(GetJniEnv(), GetActivity()); +#else + app = ::firebase::App::Create(); +#endif // defined(__ANDROID__) + + LogMessage("Created the Firebase App %x.", + static_cast(reinterpret_cast(app))); + + LogMessage("Initializing the GMA with Firebase API."); + firebase::gma::Initialize(*app); + + WaitForFutureCompletion(firebase::gma::InitializeLastResult()); + if(firebase::gma::InitializeLastResult().error() != firebase::gma::kAdErrorCodeNone) { + // Initialization Failure. The error was already logged in WaitForFutureCompletion, + // so simply exit here. + return -1; + } + + // Log mediation adapter initialization status. + for (auto adapter_status : + firebase::gma::GetInitializationStatus().GetAdapterStatusMap()) { + LogMessage("GMA Mediation Adapter '%s' %s (latency %d ms): %s", + adapter_status.first.c_str(), + (adapter_status.second.is_initialized() ? "loaded" : "NOT loaded"), + adapter_status.second.latency(), + adapter_status.second.description().c_str()); + } + + // Configure test device ids before loading ads. + // + // This example uses ad units that are specially configured to return test ads + // for every request. When using your own ad unit IDs, however, it's important + // to register the device IDs associated with any devices that will be used to + // test the app. This ensures that regardless of the ad unit ID, those + // devices will always receive test ads in compliance with AdMob policy. + // + // Device IDs can be obtained by checking the logcat or the Xcode log while + // debugging. They appear as a long string of hex characters. + firebase::gma::RequestConfiguration request_configuration; + request_configuration.test_device_ids = kTestDeviceIDs; + firebase::gma::SetRequestConfiguration(request_configuration); + + // + // Load and Display a Banner Ad using AdView. + // + + // Create an AdRequest. + firebase::gma::AdRequest ad_request; + + // Configure additional keywords to be used in targeting. + for (auto keyword_iter = kKeywords.begin(); keyword_iter != kKeywords.end(); + ++keyword_iter) { + ad_request.add_keyword((*keyword_iter).c_str()); + } + + // "Extra" key value pairs can be added to the request as well. Typically + // these are used when testing new features. + ad_request.add_extra(kAdNetworkExtrasClassName, "the_name_of_an_extra", + "the_value_for_that_extra"); + + LoadAndShowAdView(ad_request); + LoadAndShowInterstitialAd(ad_request); + LoadAndShowRewardedAd(ad_request); + + LogMessage("\nAll ad operations complete, terminating GMA"); + + firebase::gma::Terminate(); + delete app; + + // Wait until the user kills the app. + while (!ProcessEvents(1000)) { } + + return 0; +} + +void LoadAndShowAdView(const firebase::gma::AdRequest& ad_request) { + // Initialize an AdView. + firebase::gma::AdView* ad_view = new firebase::gma::AdView(); + const firebase::gma::AdSize banner_ad_size = firebase::gma::AdSize::kBanner; + ad_view->Initialize(GetWindowContext(), kBannerAdUnit, banner_ad_size); + + // Block until the ad view completes initialization. + WaitForFutureCompletion(ad_view->InitializeLastResult()); + + // Check for errors. + if (ad_view->InitializeLastResult().error() != + firebase::gma::kAdErrorCodeNone) { + LogMessage("AdView initalization failed, error code: %d", + ad_view->InitializeLastResult().error()); + delete ad_view; + ad_view = nullptr; + return; + } + + // Setup the AdView's listeners. + LoggingAdViewListener ad_view_listener; + ad_view->SetAdListener(&ad_view_listener); + LoggingPaidEventListener paid_event_listener; + ad_view->SetPaidEventListener(&paid_event_listener); + LoggingAdViewBoundedBoxListener bounding_box_listener; + ad_view->SetBoundingBoxListener(&bounding_box_listener); + + // Load an ad. + ad_view->LoadAd(ad_request); + WaitForFutureCompletion(ad_view->LoadAdLastResult()); + + // Check for errors. + if (ad_view->LoadAdLastResult().error() != firebase::gma::kAdErrorCodeNone) { + // Log information as to why the loadAd request failed. + const firebase::gma::AdResult* result_ptr = + ad_view->LoadAdLastResult().result(); + if (result_ptr != nullptr) { + LogMessage("AdView::loadAd Failure - Code: %d Message: %s Domain: %s", + result_ptr->ad_error().code(), result_ptr->ad_error().message().c_str(), + result_ptr->ad_error().domain().c_str()); + } + WaitForFutureCompletion(ad_view->Destroy()); + delete ad_view; + ad_view = nullptr; + return; + } + + // Log the loaded ad's dimensions. + const firebase::gma::AdSize ad_size = ad_view->ad_size(); + LogMessage("AdView loaded ad width: %d height: %d", ad_size.width(), + ad_size.height()); + + // Show the ad. + LogMessage("Showing the banner ad."); + WaitForFutureCompletion(ad_view->Show()); + + // Move to each of the six pre-defined positions. + LogMessage("Moving the banner ad to top-center."); + ad_view->SetPosition(firebase::gma::AdView::kPositionTop); + WaitForFutureCompletion(ad_view->SetPositionLastResult()); + + LogMessage("Moving the banner ad to top-left."); + ad_view->SetPosition(firebase::gma::AdView::kPositionTopLeft); + WaitForFutureCompletion(ad_view->SetPositionLastResult()); + + LogMessage("Moving the banner ad to top-right."); + ad_view->SetPosition(firebase::gma::AdView::kPositionTopRight); + WaitForFutureCompletion(ad_view->SetPositionLastResult()); + + LogMessage("Moving the banner ad to bottom-center."); + ad_view->SetPosition(firebase::gma::AdView::kPositionBottom); + WaitForFutureCompletion(ad_view->SetPositionLastResult()); + + LogMessage("Moving the banner ad to bottom-left."); + ad_view->SetPosition(firebase::gma::AdView::kPositionBottomLeft); + WaitForFutureCompletion(ad_view->SetPositionLastResult()); + + LogMessage("Moving the banner ad to bottom-right."); + ad_view->SetPosition(firebase::gma::AdView::kPositionBottomRight); + WaitForFutureCompletion(ad_view->SetPositionLastResult()); + + // Try some coordinate moves. + LogMessage("Moving the banner ad to (100, 300)."); + ad_view->SetPosition(100, 300); + WaitForFutureCompletion(ad_view->SetPositionLastResult()); + + LogMessage("Moving the banner ad to (100, 400)."); + ad_view->SetPosition(100, 400); + WaitForFutureCompletion(ad_view->SetPositionLastResult()); + + // Try hiding and showing the BannerView. + LogMessage("Hiding the banner ad."); + ad_view->Hide(); + WaitForFutureCompletion(ad_view->HideLastResult()); + + LogMessage("Showing the banner ad."); + ad_view->Show(); + WaitForFutureCompletion(ad_view->ShowLastResult()); + + LogMessage("Hiding the banner ad again now that we're done with it."); + ad_view->Hide(); + WaitForFutureCompletion(ad_view->HideLastResult()); + + // Clean up the ad view. + ad_view->Destroy(); + WaitForFutureCompletion(ad_view->DestroyLastResult()); + delete ad_view; + ad_view = nullptr; +} + +void LoadAndShowInterstitialAd(const firebase::gma::AdRequest& ad_request) { + // Initialize an InterstitialAd. + firebase::gma::InterstitialAd* interstitial_ad = new firebase::gma::InterstitialAd(); + interstitial_ad->Initialize(GetWindowContext()); + + // Block until the interstitial ad completes initialization. + WaitForFutureCompletion(interstitial_ad->InitializeLastResult()); + + // Check for errors. + if (interstitial_ad->InitializeLastResult().error() != firebase::gma::kAdErrorCodeNone) { + delete interstitial_ad; + interstitial_ad = nullptr; + return; + } + + // Setup the interstitial ad's listeners. + LoggingFullScreenContentListener fullscreen_content_listener; + interstitial_ad->SetFullScreenContentListener(&fullscreen_content_listener); + LoggingPaidEventListener paid_event_listener; + interstitial_ad->SetPaidEventListener(&paid_event_listener); + + // Load an ad. + interstitial_ad->LoadAd(kInterstitialAdUnit, ad_request); + WaitForFutureCompletion(interstitial_ad->LoadAdLastResult()); + + // Check for errors. + if (interstitial_ad->LoadAdLastResult().error() != firebase::gma::kAdErrorCodeNone) { + // Log information as to why the loadAd request failed. + const firebase::gma::AdResult* result_ptr = + interstitial_ad->LoadAdLastResult().result(); + if (result_ptr != nullptr) { + LogMessage("InterstitialAd::loadAd Failure - Code: %d Message: %s Domain: %s", + result_ptr->ad_error().code(), result_ptr->ad_error().message().c_str(), + result_ptr->ad_error().domain().c_str()); + } + delete interstitial_ad; + interstitial_ad = nullptr; + return; + } + + // Show the ad. + LogMessage("Showing the interstitial ad."); + interstitial_ad->Show(); + WaitForFutureCompletion(interstitial_ad->ShowLastResult()); + + // Wait for the user to close the interstitial. + while (fullscreen_content_listener.num_ad_dismissed() == 0) { + ProcessEvents(1000); + } + + // Clean up the interstitial ad. + delete interstitial_ad; + interstitial_ad = nullptr; +} + +// WIP +void LoadAndShowRewardedAd(const firebase::gma::AdRequest& ad_request) { + // Initialize a RewardedAd. + firebase::gma::RewardedAd* rewarded_ad = new firebase::gma::RewardedAd(); + rewarded_ad->Initialize(GetWindowContext()); + + // Block until the interstitial ad completes initialization. + WaitForFutureCompletion(rewarded_ad->InitializeLastResult()); + + // Check for errors. + if (rewarded_ad->InitializeLastResult().error() != firebase::gma::kAdErrorCodeNone) { + delete rewarded_ad; + rewarded_ad = nullptr; + return; + } + + // Setup the rewarded ad's lifecycle listeners. + LoggingFullScreenContentListener fullscreen_content_listener; + rewarded_ad->SetFullScreenContentListener(&fullscreen_content_listener); + LoggingPaidEventListener paid_event_listener; + rewarded_ad->SetPaidEventListener(&paid_event_listener); + + // Load an ad. + rewarded_ad->LoadAd(kRewardedAdUnit, ad_request); + WaitForFutureCompletion(rewarded_ad->LoadAdLastResult()); + + // Check for errors. + if (rewarded_ad->LoadAdLastResult().error() != firebase::gma::kAdErrorCodeNone) { + // Log information as to why the loadAd request failed. + const firebase::gma::AdResult* result_ptr = + rewarded_ad->LoadAdLastResult().result(); + if (result_ptr != nullptr) { + LogMessage("RewardedAd::loadAd Failure - Code: %d Message: %s Domain: %s", + result_ptr->ad_error().code(), result_ptr->ad_error().message().c_str(), + result_ptr->ad_error().domain().c_str()); + } + delete rewarded_ad; + rewarded_ad = nullptr; + return; + } + + // Show the ad. + LogMessage("Showing the rewarded ad."); + LoggingUserEarnedRewardListener user_earned_reward_listener; + rewarded_ad->Show(&user_earned_reward_listener); + WaitForFutureCompletion(rewarded_ad->ShowLastResult()); + + // Wait for the user to close the interstitial. + while (fullscreen_content_listener.num_ad_dismissed() == 0) { + ProcessEvents(1000); + } + + // Clean up the interstitial ad. + delete rewarded_ad; + rewarded_ad = nullptr; +} \ No newline at end of file diff --git a/gma/testapp/src/desktop/desktop_main.cc b/gma/testapp/src/desktop/desktop_main.cc new file mode 100644 index 00000000..0220c688 --- /dev/null +++ b/gma/testapp/src/desktop/desktop_main.cc @@ -0,0 +1,125 @@ +// Copyright 2016 Google Inc. All rights reserved. +// +// 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 +#include +#include + +#ifdef _WIN32 +#include +#define chdir _chdir +#else +#include +#endif // _WIN32 + +#ifdef _WIN32 +#include +#endif // _WIN32 + +#include +#include + +#include "main.h" // NOLINT + +// The TO_STRING macro is useful for command line defined strings as the quotes +// get stripped. +#define TO_STRING_EXPAND(X) #X +#define TO_STRING(X) TO_STRING_EXPAND(X) + +// Path to the Firebase config file to load. +#ifdef FIREBASE_CONFIG +#define FIREBASE_CONFIG_STRING TO_STRING(FIREBASE_CONFIG) +#else +#define FIREBASE_CONFIG_STRING "" +#endif // FIREBASE_CONFIG + +extern "C" int common_main(int argc, const char* argv[]); + +static bool quit = false; + +#ifdef _WIN32 +static BOOL WINAPI SignalHandler(DWORD event) { + if (!(event == CTRL_C_EVENT || event == CTRL_BREAK_EVENT)) { + return FALSE; + } + quit = true; + return TRUE; +} +#else +static void SignalHandler(int /* ignored */) { quit = true; } +#endif // _WIN32 + +bool ProcessEvents(int msec) { +#ifdef _WIN32 + Sleep(msec); +#else + usleep(msec * 1000); +#endif // _WIN32 + return quit; +} + +std::string PathForResource() { + return std::string(); +} + +void LogMessage(const char* format, ...) { + va_list list; + va_start(list, format); + vprintf(format, list); + va_end(list); + printf("\n"); + fflush(stdout); +} + +WindowContext GetWindowContext() { return nullptr; } + +// Change the current working directory to the directory containing the +// specified file. +void ChangeToFileDirectory(const char* file_path) { + std::string path(file_path); + std::replace(path.begin(), path.end(), '\\', '/'); + auto slash = path.rfind('/'); + if (slash != std::string::npos) { + std::string directory = path.substr(0, slash); + if (!directory.empty()) chdir(directory.c_str()); + } +} + +int main(int argc, const char* argv[]) { + ChangeToFileDirectory( + FIREBASE_CONFIG_STRING[0] != '\0' ? + FIREBASE_CONFIG_STRING : argv[0]); // NOLINT +#ifdef _WIN32 + SetConsoleCtrlHandler((PHANDLER_ROUTINE)SignalHandler, TRUE); +#else + signal(SIGINT, SignalHandler); +#endif // _WIN32 + return common_main(argc, argv); +} + +#if defined(_WIN32) +// Returns the number of microseconds since the epoch. +int64_t WinGetCurrentTimeInMicroseconds() { + FILETIME file_time; + GetSystemTimeAsFileTime(&file_time); + + ULARGE_INTEGER now; + now.LowPart = file_time.dwLowDateTime; + now.HighPart = file_time.dwHighDateTime; + + // Windows file time is expressed in 100s of nanoseconds. + // To convert to microseconds, multiply x10. + return now.QuadPart * 10LL; +} +#endif diff --git a/gma/testapp/src/ios/ios_main.mm b/gma/testapp/src/ios/ios_main.mm new file mode 100644 index 00000000..6ccb2de5 --- /dev/null +++ b/gma/testapp/src/ios/ios_main.mm @@ -0,0 +1,119 @@ +// Copyright 2016 Google Inc. All rights reserved. +// +// 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 + +#include "main.h" + +extern "C" int common_main(int argc, const char* argv[]); + +@interface AppDelegate : UIResponder + +@property(nonatomic, strong) UIWindow *window; + +@end + +@interface FTAViewController : UIViewController + +@end + +static int g_exit_status = 0; +static bool g_shutdown = false; +static NSCondition *g_shutdown_complete; +static NSCondition *g_shutdown_signal; +static UITextView *g_text_view; +static UIView *g_parent_view; + +@implementation FTAViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + g_parent_view = self.view; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + const char *argv[] = {FIREBASE_TESTAPP_NAME}; + [g_shutdown_signal lock]; + g_exit_status = common_main(1, argv); + [g_shutdown_complete signal]; + }); +} + +@end + +bool ProcessEvents(int msec) { + [g_shutdown_signal + waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:static_cast(msec) / 1000.0f]]; + return g_shutdown; +} + +WindowContext GetWindowContext() { + return g_parent_view; +} + +// Log a message that can be viewed in the console. +void LogMessage(const char* format, ...) { + va_list args; + NSString *formatString = @(format); + + va_start(args, format); + NSString *message = [[NSString alloc] initWithFormat:formatString arguments:args]; + va_end(args); + + NSLog(@"%@", message); + message = [message stringByAppendingString:@"\n"]; + + dispatch_async(dispatch_get_main_queue(), ^{ + g_text_view.text = [g_text_view.text stringByAppendingString:message]; + }); +} + +int main(int argc, char* argv[]) { + @autoreleasepool { + UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } + return g_exit_status; +} + +@implementation AppDelegate + +- (BOOL)application:(UIApplication*)application + didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { + g_shutdown_complete = [[NSCondition alloc] init]; + g_shutdown_signal = [[NSCondition alloc] init]; + [g_shutdown_complete lock]; + + self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + FTAViewController *viewController = [[FTAViewController alloc] init]; + self.window.rootViewController = viewController; + [self.window makeKeyAndVisible]; + + g_text_view = [[UITextView alloc] initWithFrame:viewController.view.bounds]; + + g_text_view.editable = NO; + g_text_view.scrollEnabled = YES; + g_text_view.userInteractionEnabled = YES; + + [viewController.view addSubview:g_text_view]; + + return YES; +} + +- (void)applicationWillTerminate:(UIApplication *)application { + g_shutdown = true; + [g_shutdown_signal signal]; + [g_shutdown_complete wait]; +} + +@end diff --git a/gma/testapp/src/main.h b/gma/testapp/src/main.h new file mode 100644 index 00000000..2eda2c10 --- /dev/null +++ b/gma/testapp/src/main.h @@ -0,0 +1,63 @@ +// Copyright 2016 Google Inc. All rights reserved. +// +// 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_TESTAPP_MAIN_H_ // NOLINT +#define FIREBASE_TESTAPP_MAIN_H_ // NOLINT + +#if defined(__ANDROID__) +#include +#include +#elif defined(__APPLE__) +extern "C" { +#include +} // extern "C" +#endif // __ANDROID__ + +// Defined using -DANDROID_MAIN_APP_NAME=some_app_name when compiling this +// file. +#ifndef FIREBASE_TESTAPP_NAME +#define FIREBASE_TESTAPP_NAME "android_main" +#endif // FIREBASE_TESTAPP_NAME + +// Cross platform logging method. +// Implemented by android/android_main.cc or ios/ios_main.mm. +extern "C" void LogMessage(const char* format, ...); + +// Platform-independent method to flush pending events for the main thread. +// Returns true when an event requesting program-exit is received. +bool ProcessEvents(int msec); + +// WindowContext represents the handle to the parent window. It's type +// (and usage) vary based on the OS. +#if defined(__ANDROID__) +typedef jobject WindowContext; // A jobject to the Java Activity. +#elif defined(__APPLE__) +typedef id WindowContext; // A pointer to an iOS UIView. +#else +typedef void* WindowContext; // A void* for any other environments. +#endif + +#if defined(__ANDROID__) +// Get the JNI environment. +JNIEnv* GetJniEnv(); +// Get the activity. +jobject GetActivity(); +#endif // defined(__ANDROID__) + +// Returns a variable that describes the window context for the app. On Android +// this will be a jobject pointing to the Activity. On iOS, it's an id pointing +// to the root view of the view controller. +WindowContext GetWindowContext(); + +#endif // FIREBASE_TESTAPP_MAIN_H_ // NOLINT diff --git a/gma/testapp/testapp.xcodeproj/project.pbxproj b/gma/testapp/testapp.xcodeproj/project.pbxproj new file mode 100644 index 00000000..14a0af7f --- /dev/null +++ b/gma/testapp/testapp.xcodeproj/project.pbxproj @@ -0,0 +1,312 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 4A7C015A1CEAA2480011C504 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4A7C01591CEAA2480011C504 /* Images.xcassets */; }; + 520BC0391C869159008CFBC3 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */; }; + 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D51C85F68000C89379 /* Foundation.framework */; }; + 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D71C85F68000C89379 /* CoreGraphics.framework */; }; + 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D91C85F68000C89379 /* UIKit.framework */; }; + 529227211C85FB6A00C89379 /* common_main.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5292271F1C85FB6A00C89379 /* common_main.cc */; }; + 529227241C85FB7600C89379 /* ios_main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 529227221C85FB7600C89379 /* ios_main.mm */; }; + D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 4A7C01591CEAA2480011C504 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = testapp/Images.xcassets; sourceTree = ""; }; + 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + 529226D21C85F68000C89379 /* testapp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testapp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 529226D51C85F68000C89379 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 529226D71C85F68000C89379 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 529226D91C85F68000C89379 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 529226EE1C85F68000C89379 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + 5292271F1C85FB6A00C89379 /* common_main.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = common_main.cc; path = src/common_main.cc; sourceTree = ""; }; + 529227201C85FB6A00C89379 /* main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = main.h; path = src/main.h; sourceTree = ""; }; + 529227221C85FB7600C89379 /* ios_main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_main.mm; path = src/ios/ios_main.mm; sourceTree = ""; }; + 52FD1FF81C85FFA000BC68E3 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = testapp/Info.plist; sourceTree = ""; }; + D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 529226CF1C85F68000C89379 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */, + 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */, + 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 529226C91C85F68000C89379 = { + isa = PBXGroup; + children = ( + 4A7C01591CEAA2480011C504 /* Images.xcassets */, + D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */, + 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */, + 52FD1FF81C85FFA000BC68E3 /* Info.plist */, + 5292271D1C85FB5500C89379 /* src */, + 529226D41C85F68000C89379 /* Frameworks */, + 529226D31C85F68000C89379 /* Products */, + ); + sourceTree = ""; + }; + 529226D31C85F68000C89379 /* Products */ = { + isa = PBXGroup; + children = ( + 529226D21C85F68000C89379 /* testapp.app */, + ); + name = Products; + sourceTree = ""; + }; + 529226D41C85F68000C89379 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 529226D51C85F68000C89379 /* Foundation.framework */, + 529226D71C85F68000C89379 /* CoreGraphics.framework */, + 529226D91C85F68000C89379 /* UIKit.framework */, + 529226EE1C85F68000C89379 /* XCTest.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 5292271D1C85FB5500C89379 /* src */ = { + isa = PBXGroup; + children = ( + 5292271F1C85FB6A00C89379 /* common_main.cc */, + 529227201C85FB6A00C89379 /* main.h */, + 5292271E1C85FB5B00C89379 /* ios */, + ); + name = src; + sourceTree = ""; + }; + 5292271E1C85FB5B00C89379 /* ios */ = { + isa = PBXGroup; + children = ( + 529227221C85FB7600C89379 /* ios_main.mm */, + ); + name = ios; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 529226D11C85F68000C89379 /* testapp */ = { + isa = PBXNativeTarget; + buildConfigurationList = 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "testapp" */; + buildPhases = ( + 529226CE1C85F68000C89379 /* Sources */, + 529226CF1C85F68000C89379 /* Frameworks */, + 529226D01C85F68000C89379 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = testapp; + productName = testapp; + productReference = 529226D21C85F68000C89379 /* testapp.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 529226CA1C85F68000C89379 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0640; + ORGANIZATIONNAME = Google; + TargetAttributes = { + 529226D11C85F68000C89379 = { + CreatedOnToolsVersion = 6.4; + }; + }; + }; + buildConfigurationList = 529226CD1C85F68000C89379 /* Build configuration list for PBXProject "testapp" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 529226C91C85F68000C89379; + productRefGroup = 529226D31C85F68000C89379 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 529226D11C85F68000C89379 /* testapp */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 529226D01C85F68000C89379 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */, + 4A7C015A1CEAA2480011C504 /* Images.xcassets in Resources */, + 520BC0391C869159008CFBC3 /* GoogleService-Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 529226CE1C85F68000C89379 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 529227241C85FB7600C89379 /* ios_main.mm in Sources */, + 529227211C85FB6A00C89379 /* common_main.cc in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 529226F71C85F68000C89379 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.4; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 529226F81C85F68000C89379 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.4; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 529226FA1C85F68000C89379 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "\"$(SRCROOT)/src\"", + ); + INFOPLIST_FILE = testapp/Info.plist; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 529226FB1C85F68000C89379 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "\"$(SRCROOT)/src\"", + ); + INFOPLIST_FILE = testapp/Info.plist; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 529226CD1C85F68000C89379 /* Build configuration list for PBXProject "testapp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 529226F71C85F68000C89379 /* Debug */, + 529226F81C85F68000C89379 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "testapp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 529226FA1C85F68000C89379 /* Debug */, + 529226FB1C85F68000C89379 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 529226CA1C85F68000C89379 /* Project object */; +} diff --git a/gma/testapp/testapp/Images.xcassets/AppIcon.appiconset/Contents.json b/gma/testapp/testapp/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..eeea76c2 --- /dev/null +++ b/gma/testapp/testapp/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,73 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/gma/testapp/testapp/Images.xcassets/LaunchImage.launchimage/Contents.json b/gma/testapp/testapp/Images.xcassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 00000000..a0ad363c --- /dev/null +++ b/gma/testapp/testapp/Images.xcassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,36 @@ +{ + "images" : [ + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/gma/testapp/testapp/Info.plist b/gma/testapp/testapp/Info.plist new file mode 100644 index 00000000..3f0f944e --- /dev/null +++ b/gma/testapp/testapp/Info.plist @@ -0,0 +1,28 @@ + + + + + GADApplicationIdentifier + YOUR_IOS_ADMOB_APP_ID + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.google.ios.admob.testapp + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + + From 3bbb47285474ba7de46560e6bce77c28ce7468c1 Mon Sep 17 00:00:00 2001 From: "drsanta@google.com" Date: Tue, 5 Apr 2022 11:22:39 -0400 Subject: [PATCH 21/57] iOS build --- gma/testapp/Podfile | 2 +- gma/testapp/src/common_main.cc | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/gma/testapp/Podfile b/gma/testapp/Podfile index 3d649e01..51c73e38 100644 --- a/gma/testapp/Podfile +++ b/gma/testapp/Podfile @@ -1,5 +1,5 @@ source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' +platform :ios, '10.0' # GMA test application. target 'testapp' do pod 'Google-Mobile-Ads-SDK', '8.13.0' diff --git a/gma/testapp/src/common_main.cc b/gma/testapp/src/common_main.cc index 4d51b1b6..e5d61ed5 100644 --- a/gma/testapp/src/common_main.cc +++ b/gma/testapp/src/common_main.cc @@ -241,6 +241,8 @@ extern "C" int common_main(int argc, const char* argv[]) { } void LoadAndShowAdView(const firebase::gma::AdRequest& ad_request) { + LogMessage("\nLoad and show a banner ad in an AdView:"); + LogMessage("==="); // Initialize an AdView. firebase::gma::AdView* ad_view = new firebase::gma::AdView(); const firebase::gma::AdSize banner_ad_size = firebase::gma::AdSize::kBanner; @@ -351,6 +353,8 @@ void LoadAndShowAdView(const firebase::gma::AdRequest& ad_request) { } void LoadAndShowInterstitialAd(const firebase::gma::AdRequest& ad_request) { + LogMessage("\nLoad and show an interstitial ad:"); + LogMessage("==="); // Initialize an InterstitialAd. firebase::gma::InterstitialAd* interstitial_ad = new firebase::gma::InterstitialAd(); interstitial_ad->Initialize(GetWindowContext()); @@ -407,6 +411,8 @@ void LoadAndShowInterstitialAd(const firebase::gma::AdRequest& ad_request) { // WIP void LoadAndShowRewardedAd(const firebase::gma::AdRequest& ad_request) { + LogMessage("\nLoad and show a rewarded ad:"); + LogMessage("==="); // Initialize a RewardedAd. firebase::gma::RewardedAd* rewarded_ad = new firebase::gma::RewardedAd(); rewarded_ad->Initialize(GetWindowContext()); @@ -460,4 +466,4 @@ void LoadAndShowRewardedAd(const firebase::gma::AdRequest& ad_request) { // Clean up the interstitial ad. delete rewarded_ad; rewarded_ad = nullptr; -} \ No newline at end of file +} From a90467bc997ebf18e4fed3f612c952ee60a5392f Mon Sep 17 00:00:00 2001 From: "drsanta@google.com" Date: Tue, 5 Apr 2022 13:24:10 -0400 Subject: [PATCH 22/57] readme updates, formatted source --- gma/testapp/readme.md | 7 +- gma/testapp/src/android/android_main.cc | 57 +++--- .../google/firebase/example/LoggingUtils.java | 12 +- gma/testapp/src/common_main.cc | 188 +++++++++--------- gma/testapp/src/desktop/desktop_main.cc | 35 ++-- gma/testapp/src/ios/ios_main.mm | 36 ++-- gma/testapp/src/main.h | 24 +-- 7 files changed, 183 insertions(+), 176 deletions(-) diff --git a/gma/testapp/readme.md b/gma/testapp/readme.md index 018af54d..4143cb7e 100644 --- a/gma/testapp/readme.md +++ b/gma/testapp/readme.md @@ -126,8 +126,9 @@ Getting Started ### Desktop - Note: the testapp has no user interface, but the output can be viewed via - the console. Note that the GMA SDK uses a stubbed implementation on - desktop, so functionality is not expected. + the console. The GMA SDK uses a stubbed implementation on desktop, so + functionality is not expected, and the app will end waiting for the interstitial + ad to be dismissed. - Register your app with Firebase. - Create a new app on the [Firebase console](https://firebase.google.com/console/), following the above instructions for Android or iOS. @@ -176,7 +177,7 @@ Support License ------- -Copyright 2016 Google, Inc. +Copyright 2022 Google, Inc. Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for diff --git a/gma/testapp/src/android/android_main.cc b/gma/testapp/src/android/android_main.cc index 73cb30e7..7a6de455 100644 --- a/gma/testapp/src/android/android_main.cc +++ b/gma/testapp/src/android/android_main.cc @@ -17,33 +17,33 @@ #include #include -#include #include +#include -#include "main.h" // NOLINT +#include "main.h" // NOLINT // This implementation is derived from http://github.com/google/fplutil -extern "C" int common_main(int argc, const char* argv[]); +extern "C" int common_main(int argc, const char *argv[]); -static struct android_app* g_app_state = nullptr; +static struct android_app *g_app_state = nullptr; static bool g_destroy_requested = false; static bool g_started = false; static bool g_restarted = false; static pthread_mutex_t g_started_mutex; // Handle state changes from via native app glue. -static void OnAppCmd(struct android_app* app, int32_t cmd) { +static void OnAppCmd(struct android_app *app, int32_t cmd) { g_destroy_requested |= cmd == APP_CMD_DESTROY; } // Process events pending on the main thread. // Returns true when the app receives an event requesting exit. bool ProcessEvents(int msec) { - struct android_poll_source* source = nullptr; + struct android_poll_source *source = nullptr; int events; int looperId = ALooper_pollAll(msec, nullptr, &events, - reinterpret_cast(&source)); + reinterpret_cast(&source)); if (looperId >= 0 && source) { source->process(g_app_state, source); } @@ -57,7 +57,7 @@ jobject GetActivity() { return g_app_state->activity->clazz; } jobject GetWindowContext() { return g_app_state->activity->clazz; } // Find a class, attempting to load the class if it's not found. -jclass FindClass(JNIEnv* env, jobject activity_object, const char* class_name) { +jclass FindClass(JNIEnv *env, jobject activity_object, const char *class_name) { jclass class_object = env->FindClass(class_name); if (env->ExceptionCheck()) { env->ExceptionClear(); @@ -93,14 +93,13 @@ jclass FindClass(JNIEnv* env, jobject activity_object, const char* class_name) { // Vars that we need available for appending text to the log window: class LoggingUtilsData { - public: +public: LoggingUtilsData() - : logging_utils_class_(nullptr), - logging_utils_add_log_text_(0), + : logging_utils_class_(nullptr), logging_utils_add_log_text_(0), logging_utils_init_log_window_(0) {} ~LoggingUtilsData() { - JNIEnv* env = GetJniEnv(); + JNIEnv *env = GetJniEnv(); assert(env); if (logging_utils_class_) { env->DeleteGlobalRef(logging_utils_class_); @@ -108,7 +107,7 @@ class LoggingUtilsData { } void Init() { - JNIEnv* env = GetJniEnv(); + JNIEnv *env = GetJniEnv(); assert(env); jclass logging_utils_class = FindClass( @@ -130,9 +129,10 @@ class LoggingUtilsData { logging_utils_init_log_window_, GetActivity()); } - void AppendText(const char* text) { - if (logging_utils_class_ == 0) return; // haven't been initted yet - JNIEnv* env = GetJniEnv(); + void AppendText(const char *text) { + if (logging_utils_class_ == 0) + return; // haven't been initted yet + JNIEnv *env = GetJniEnv(); assert(env); jstring text_string = env->NewStringUTF(text); env->CallStaticVoidMethod(logging_utils_class_, logging_utils_add_log_text_, @@ -140,17 +140,17 @@ class LoggingUtilsData { env->DeleteLocalRef(text_string); } - private: +private: jclass logging_utils_class_; jmethodID logging_utils_add_log_text_; jmethodID logging_utils_init_log_window_; }; -LoggingUtilsData* g_logging_utils_data; +LoggingUtilsData *g_logging_utils_data; // Checks if a JNI exception has happened, and if so, logs it to the console. void CheckJNIException() { - JNIEnv* env = GetJniEnv(); + JNIEnv *env = GetJniEnv(); if (env->ExceptionCheck()) { // Get the exception text. jthrowable exception = env->ExceptionOccurred(); @@ -161,7 +161,7 @@ void CheckJNIException() { jmethodID toString = env->GetMethodID(object_class, "toString", "()Ljava/lang/String;"); jstring s = (jstring)env->CallObjectMethod(exception, toString); - const char* exception_text = env->GetStringUTFChars(s, nullptr); + const char *exception_text = env->GetStringUTFChars(s, nullptr); // Log the exception text. __android_log_print(ANDROID_LOG_INFO, FIREBASE_TESTAPP_NAME, @@ -182,7 +182,7 @@ void CheckJNIException() { } // Log a message that can be viewed in "adb logcat". -void LogMessage(const char* format, ...) { +void LogMessage(const char *format, ...) { static const int kLineBufferSize = 100; char buffer[kLineBufferSize + 2]; @@ -201,15 +201,15 @@ void LogMessage(const char* format, ...) { } // Get the JNI environment. -JNIEnv* GetJniEnv() { - JavaVM* vm = g_app_state->activity->vm; - JNIEnv* env; +JNIEnv *GetJniEnv() { + JavaVM *vm = g_app_state->activity->vm; + JNIEnv *env; jint result = vm->AttachCurrentThread(&env, nullptr); return result == JNI_OK ? env : nullptr; } // Execute common_main(), flush pending events and finish the activity. -extern "C" void android_main(struct android_app* state) { +extern "C" void android_main(struct android_app *state) { // native_app_glue spawns a new thread, calling android_main() when the // activity onStart() or onRestart() methods are called. This code handles // the case where we're re-entering this method on a different thread by @@ -236,9 +236,9 @@ extern "C" void android_main(struct android_app* state) { g_logging_utils_data->Init(); // Execute cross platform entry point. - static const char* argv[] = {FIREBASE_TESTAPP_NAME}; + static const char *argv[] = {FIREBASE_TESTAPP_NAME}; int return_value = common_main(1, argv); - (void)return_value; // Ignore the return value. + (void)return_value; // Ignore the return value. ProcessEvents(10); // Clean up logging display. @@ -246,7 +246,8 @@ extern "C" void android_main(struct android_app* state) { g_logging_utils_data = nullptr; // Finish the activity. - if (!g_restarted) ANativeActivity_finish(state->activity); + if (!g_restarted) + ANativeActivity_finish(state->activity); g_app_state->activity->vm->DetachCurrentThread(); g_started = false; diff --git a/gma/testapp/src/android/java/com/google/firebase/example/LoggingUtils.java b/gma/testapp/src/android/java/com/google/firebase/example/LoggingUtils.java index 11d67c5b..3cb37ecf 100644 --- a/gma/testapp/src/android/java/com/google/firebase/example/LoggingUtils.java +++ b/gma/testapp/src/android/java/com/google/firebase/example/LoggingUtils.java @@ -44,12 +44,12 @@ public static void initLogWindow(Activity activity) { public static void addLogText(final String text) { new Handler(Looper.getMainLooper()).post(new Runnable() { - @Override - public void run() { - if (sTextView != null) { - sTextView.append(text); - } + @Override + public void run() { + if (sTextView != null) { + sTextView.append(text); } - }); + } + }); } } diff --git a/gma/testapp/src/common_main.cc b/gma/testapp/src/common_main.cc index e5d61ed5..10a0a181 100644 --- a/gma/testapp/src/common_main.cc +++ b/gma/testapp/src/common_main.cc @@ -12,59 +12,50 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "firebase/app.h" +#include "firebase/future.h" #include "firebase/gma.h" #include "firebase/gma/ad_view.h" #include "firebase/gma/interstitial_ad.h" #include "firebase/gma/rewarded_ad.h" #include "firebase/gma/types.h" -#include "firebase/app.h" -#include "firebase/future.h" // Thin OS abstraction layer. -#include "main.h" // NOLINT +#include "main.h" // NOLINT // A simple listener that logs changes to an AdView. class LoggingAdViewListener : public firebase::gma::AdListener { - public: +public: LoggingAdViewListener() {} - void OnAdClicked() override { - ::LogMessage("AdView ad clicked."); - } + void OnAdClicked() override { ::LogMessage("AdView ad clicked."); } - void OnAdClosed() override { - ::LogMessage("AdView ad closed."); - } + void OnAdClosed() override { ::LogMessage("AdView ad closed."); } - void OnAdImpression() override { - ::LogMessage("AdView ad impression."); - } + void OnAdImpression() override { ::LogMessage("AdView ad impression."); } - void OnAdOpened() override { - ::LogMessage("AdView ad opened."); - } + void OnAdOpened() override { ::LogMessage("AdView ad opened."); } }; // A simple listener that logs changes to an AdView's bounding box. class LoggingAdViewBoundedBoxListener : public firebase::gma::AdViewBoundingBoxListener { - public: - void OnBoundingBoxChanged(firebase::gma::AdView* ad_view, +public: + void OnBoundingBoxChanged(firebase::gma::AdView *ad_view, firebase::gma::BoundingBox box) override { ::LogMessage("AdView bounding box update x: %d y: %d " - "width: %d height: %d", box.x, box.y, box.width, box.height); + "width: %d height: %d", + box.x, box.y, box.width, box.height); } }; // A simple listener track FullScreen content changes. class LoggingFullScreenContentListener : public firebase::gma::FullScreenContentListener { - public: - LoggingFullScreenContentListener() : num_ad_dismissed_(0) { } +public: + LoggingFullScreenContentListener() : num_ad_dismissed_(0) {} - void OnAdClicked() override { - ::LogMessage("FullScreenContent ad clicked."); - } + void OnAdClicked() override { ::LogMessage("FullScreenContent ad clicked."); } void OnAdDismissedFullScreenContent() override { ::LogMessage("FullScreenContent ad dismissed."); @@ -72,9 +63,10 @@ class LoggingFullScreenContentListener } void OnAdFailedToShowFullScreenContent( - const firebase::gma::AdError& ad_error) override { + const firebase::gma::AdError &ad_error) override { ::LogMessage("FullScreenContent ad failed to show full screen content," - " AdErrorCode: %d", ad_error.code()); + " AdErrorCode: %d", + ad_error.code()); } void OnAdImpression() override { @@ -87,47 +79,47 @@ class LoggingFullScreenContentListener uint32_t num_ad_dismissed() const { return num_ad_dismissed_; } - private: +private: uint32_t num_ad_dismissed_; }; // A simple listener track UserEarnedReward events. class LoggingUserEarnedRewardListener : public firebase::gma::UserEarnedRewardListener { - public: - LoggingUserEarnedRewardListener() { } +public: + LoggingUserEarnedRewardListener() {} - void OnUserEarnedReward(const firebase::gma::AdReward& reward) override { - ::LogMessage("User earned reward amount: %d type: %s", - reward.amount(), reward.type().c_str()); + void OnUserEarnedReward(const firebase::gma::AdReward &reward) override { + ::LogMessage("User earned reward amount: %d type: %s", reward.amount(), + reward.type().c_str()); } }; // A simple listener track ad pay events. class LoggingPaidEventListener : public firebase::gma::PaidEventListener { - public: - LoggingPaidEventListener() { } +public: + LoggingPaidEventListener() {} - void OnPaidEvent(const firebase::gma::AdValue& value) override { + void OnPaidEvent(const firebase::gma::AdValue &value) override { ::LogMessage("PaidEvent value: %lld currency_code: %s", - value.value_micros(), value.currency_code().c_str()); - } + value.value_micros(), value.currency_code().c_str()); + } }; -void LoadAndShowAdView(const firebase::gma::AdRequest& ad_request); -void LoadAndShowInterstitialAd(const firebase::gma::AdRequest& ad_request); -void LoadAndShowRewardedAd(const firebase::gma::AdRequest& ad_request); +void LoadAndShowAdView(const firebase::gma::AdRequest &ad_request); +void LoadAndShowInterstitialAd(const firebase::gma::AdRequest &ad_request); +void LoadAndShowRewardedAd(const firebase::gma::AdRequest &ad_request); // These ad units IDs have been created specifically for testing, and will // always return test ads. #if defined(__ANDROID__) -const char* kBannerAdUnit = "ca-app-pub-3940256099942544/6300978111"; -const char* kInterstitialAdUnit = "ca-app-pub-3940256099942544/1033173712"; -const char* kRewardedAdUnit = "ca-app-pub-3940256099942544/5224354917"; +const char *kBannerAdUnit = "ca-app-pub-3940256099942544/6300978111"; +const char *kInterstitialAdUnit = "ca-app-pub-3940256099942544/1033173712"; +const char *kRewardedAdUnit = "ca-app-pub-3940256099942544/5224354917"; #else -const char* kBannerAdUnit = "ca-app-pub-3940256099942544/2934735716"; -const char* kInterstitialAdUnit = "ca-app-pub-3940256099942544/4411468910"; -const char* kRewardedAdUnit = "ca-app-pub-3940256099942544/1712485313"; +const char *kBannerAdUnit = "ca-app-pub-3940256099942544/2934735716"; +const char *kInterstitialAdUnit = "ca-app-pub-3940256099942544/4411468910"; +const char *kRewardedAdUnit = "ca-app-pub-3940256099942544/1712485313"; #endif // Sample keywords to use in making the request. @@ -138,10 +130,10 @@ const std::vector kTestDeviceIDs = { "2077ef9a63d2b398840261c8221a0c9b", "098fe087d987c9a878965454a65654d7"}; #if defined(ANDROID) -static const char* kAdNetworkExtrasClassName = +static const char *kAdNetworkExtrasClassName = "com/google/ads/mediation/admob/AdMobAdapter"; #else -static const char* kAdNetworkExtrasClassName = "GADExtras"; +static const char *kAdNetworkExtrasClassName = "GADExtras"; #endif // Function to wait for the completion of a future, and log the error @@ -160,15 +152,15 @@ static void WaitForFutureCompletion(firebase::FutureBase future) { } // Inittialize GMA, load a Banner, Interstitial and Rewarded Ad. -extern "C" int common_main(int argc, const char* argv[]) { - firebase::App* app; +extern "C" int common_main(int argc, const char *argv[]) { + firebase::App *app; LogMessage("Initializing Firebase App."); #if defined(__ANDROID__) app = ::firebase::App::Create(GetJniEnv(), GetActivity()); #else app = ::firebase::App::Create(); -#endif // defined(__ANDROID__) +#endif // defined(__ANDROID__) LogMessage("Created the Firebase App %x.", static_cast(reinterpret_cast(app))); @@ -177,20 +169,22 @@ extern "C" int common_main(int argc, const char* argv[]) { firebase::gma::Initialize(*app); WaitForFutureCompletion(firebase::gma::InitializeLastResult()); - if(firebase::gma::InitializeLastResult().error() != firebase::gma::kAdErrorCodeNone) { - // Initialization Failure. The error was already logged in WaitForFutureCompletion, - // so simply exit here. + if (firebase::gma::InitializeLastResult().error() != + firebase::gma::kAdErrorCodeNone) { + // Initialization Failure. The error was already logged in + // WaitForFutureCompletion, so simply exit here. return -1; } // Log mediation adapter initialization status. for (auto adapter_status : firebase::gma::GetInitializationStatus().GetAdapterStatusMap()) { - LogMessage("GMA Mediation Adapter '%s' %s (latency %d ms): %s", - adapter_status.first.c_str(), - (adapter_status.second.is_initialized() ? "loaded" : "NOT loaded"), - adapter_status.second.latency(), - adapter_status.second.description().c_str()); + LogMessage( + "GMA Mediation Adapter '%s' %s (latency %d ms): %s", + adapter_status.first.c_str(), + (adapter_status.second.is_initialized() ? "loaded" : "NOT loaded"), + adapter_status.second.latency(), + adapter_status.second.description().c_str()); } // Configure test device ids before loading ads. @@ -206,11 +200,11 @@ extern "C" int common_main(int argc, const char* argv[]) { firebase::gma::RequestConfiguration request_configuration; request_configuration.test_device_ids = kTestDeviceIDs; firebase::gma::SetRequestConfiguration(request_configuration); - - // + + // // Load and Display a Banner Ad using AdView. // - + // Create an AdRequest. firebase::gma::AdRequest ad_request; @@ -223,7 +217,7 @@ extern "C" int common_main(int argc, const char* argv[]) { // "Extra" key value pairs can be added to the request as well. Typically // these are used when testing new features. ad_request.add_extra(kAdNetworkExtrasClassName, "the_name_of_an_extra", - "the_value_for_that_extra"); + "the_value_for_that_extra"); LoadAndShowAdView(ad_request); LoadAndShowInterstitialAd(ad_request); @@ -235,16 +229,17 @@ extern "C" int common_main(int argc, const char* argv[]) { delete app; // Wait until the user kills the app. - while (!ProcessEvents(1000)) { } + while (!ProcessEvents(1000)) { + } return 0; } -void LoadAndShowAdView(const firebase::gma::AdRequest& ad_request) { +void LoadAndShowAdView(const firebase::gma::AdRequest &ad_request) { LogMessage("\nLoad and show a banner ad in an AdView:"); LogMessage("==="); // Initialize an AdView. - firebase::gma::AdView* ad_view = new firebase::gma::AdView(); + firebase::gma::AdView *ad_view = new firebase::gma::AdView(); const firebase::gma::AdSize banner_ad_size = firebase::gma::AdSize::kBanner; ad_view->Initialize(GetWindowContext(), kBannerAdUnit, banner_ad_size); @@ -253,9 +248,9 @@ void LoadAndShowAdView(const firebase::gma::AdRequest& ad_request) { // Check for errors. if (ad_view->InitializeLastResult().error() != - firebase::gma::kAdErrorCodeNone) { + firebase::gma::kAdErrorCodeNone) { LogMessage("AdView initalization failed, error code: %d", - ad_view->InitializeLastResult().error()); + ad_view->InitializeLastResult().error()); delete ad_view; ad_view = nullptr; return; @@ -268,7 +263,7 @@ void LoadAndShowAdView(const firebase::gma::AdRequest& ad_request) { ad_view->SetPaidEventListener(&paid_event_listener); LoggingAdViewBoundedBoxListener bounding_box_listener; ad_view->SetBoundingBoxListener(&bounding_box_listener); - + // Load an ad. ad_view->LoadAd(ad_request); WaitForFutureCompletion(ad_view->LoadAdLastResult()); @@ -276,12 +271,13 @@ void LoadAndShowAdView(const firebase::gma::AdRequest& ad_request) { // Check for errors. if (ad_view->LoadAdLastResult().error() != firebase::gma::kAdErrorCodeNone) { // Log information as to why the loadAd request failed. - const firebase::gma::AdResult* result_ptr = - ad_view->LoadAdLastResult().result(); + const firebase::gma::AdResult *result_ptr = + ad_view->LoadAdLastResult().result(); if (result_ptr != nullptr) { LogMessage("AdView::loadAd Failure - Code: %d Message: %s Domain: %s", - result_ptr->ad_error().code(), result_ptr->ad_error().message().c_str(), - result_ptr->ad_error().domain().c_str()); + result_ptr->ad_error().code(), + result_ptr->ad_error().message().c_str(), + result_ptr->ad_error().domain().c_str()); } WaitForFutureCompletion(ad_view->Destroy()); delete ad_view; @@ -292,7 +288,7 @@ void LoadAndShowAdView(const firebase::gma::AdRequest& ad_request) { // Log the loaded ad's dimensions. const firebase::gma::AdSize ad_size = ad_view->ad_size(); LogMessage("AdView loaded ad width: %d height: %d", ad_size.width(), - ad_size.height()); + ad_size.height()); // Show the ad. LogMessage("Showing the banner ad."); @@ -352,18 +348,20 @@ void LoadAndShowAdView(const firebase::gma::AdRequest& ad_request) { ad_view = nullptr; } -void LoadAndShowInterstitialAd(const firebase::gma::AdRequest& ad_request) { +void LoadAndShowInterstitialAd(const firebase::gma::AdRequest &ad_request) { LogMessage("\nLoad and show an interstitial ad:"); LogMessage("==="); // Initialize an InterstitialAd. - firebase::gma::InterstitialAd* interstitial_ad = new firebase::gma::InterstitialAd(); + firebase::gma::InterstitialAd *interstitial_ad = + new firebase::gma::InterstitialAd(); interstitial_ad->Initialize(GetWindowContext()); // Block until the interstitial ad completes initialization. WaitForFutureCompletion(interstitial_ad->InitializeLastResult()); // Check for errors. - if (interstitial_ad->InitializeLastResult().error() != firebase::gma::kAdErrorCodeNone) { + if (interstitial_ad->InitializeLastResult().error() != + firebase::gma::kAdErrorCodeNone) { delete interstitial_ad; interstitial_ad = nullptr; return; @@ -380,14 +378,17 @@ void LoadAndShowInterstitialAd(const firebase::gma::AdRequest& ad_request) { WaitForFutureCompletion(interstitial_ad->LoadAdLastResult()); // Check for errors. - if (interstitial_ad->LoadAdLastResult().error() != firebase::gma::kAdErrorCodeNone) { + if (interstitial_ad->LoadAdLastResult().error() != + firebase::gma::kAdErrorCodeNone) { // Log information as to why the loadAd request failed. - const firebase::gma::AdResult* result_ptr = - interstitial_ad->LoadAdLastResult().result(); + const firebase::gma::AdResult *result_ptr = + interstitial_ad->LoadAdLastResult().result(); if (result_ptr != nullptr) { - LogMessage("InterstitialAd::loadAd Failure - Code: %d Message: %s Domain: %s", - result_ptr->ad_error().code(), result_ptr->ad_error().message().c_str(), - result_ptr->ad_error().domain().c_str()); + LogMessage( + "InterstitialAd::loadAd Failure - Code: %d Message: %s Domain: %s", + result_ptr->ad_error().code(), + result_ptr->ad_error().message().c_str(), + result_ptr->ad_error().domain().c_str()); } delete interstitial_ad; interstitial_ad = nullptr; @@ -410,18 +411,19 @@ void LoadAndShowInterstitialAd(const firebase::gma::AdRequest& ad_request) { } // WIP -void LoadAndShowRewardedAd(const firebase::gma::AdRequest& ad_request) { +void LoadAndShowRewardedAd(const firebase::gma::AdRequest &ad_request) { LogMessage("\nLoad and show a rewarded ad:"); LogMessage("==="); // Initialize a RewardedAd. - firebase::gma::RewardedAd* rewarded_ad = new firebase::gma::RewardedAd(); + firebase::gma::RewardedAd *rewarded_ad = new firebase::gma::RewardedAd(); rewarded_ad->Initialize(GetWindowContext()); // Block until the interstitial ad completes initialization. WaitForFutureCompletion(rewarded_ad->InitializeLastResult()); // Check for errors. - if (rewarded_ad->InitializeLastResult().error() != firebase::gma::kAdErrorCodeNone) { + if (rewarded_ad->InitializeLastResult().error() != + firebase::gma::kAdErrorCodeNone) { delete rewarded_ad; rewarded_ad = nullptr; return; @@ -438,17 +440,19 @@ void LoadAndShowRewardedAd(const firebase::gma::AdRequest& ad_request) { WaitForFutureCompletion(rewarded_ad->LoadAdLastResult()); // Check for errors. - if (rewarded_ad->LoadAdLastResult().error() != firebase::gma::kAdErrorCodeNone) { + if (rewarded_ad->LoadAdLastResult().error() != + firebase::gma::kAdErrorCodeNone) { // Log information as to why the loadAd request failed. - const firebase::gma::AdResult* result_ptr = - rewarded_ad->LoadAdLastResult().result(); + const firebase::gma::AdResult *result_ptr = + rewarded_ad->LoadAdLastResult().result(); if (result_ptr != nullptr) { LogMessage("RewardedAd::loadAd Failure - Code: %d Message: %s Domain: %s", - result_ptr->ad_error().code(), result_ptr->ad_error().message().c_str(), - result_ptr->ad_error().domain().c_str()); + result_ptr->ad_error().code(), + result_ptr->ad_error().message().c_str(), + result_ptr->ad_error().domain().c_str()); } delete rewarded_ad; - rewarded_ad = nullptr; + rewarded_ad = nullptr; return; } diff --git a/gma/testapp/src/desktop/desktop_main.cc b/gma/testapp/src/desktop/desktop_main.cc index 0220c688..0a318786 100644 --- a/gma/testapp/src/desktop/desktop_main.cc +++ b/gma/testapp/src/desktop/desktop_main.cc @@ -21,16 +21,16 @@ #define chdir _chdir #else #include -#endif // _WIN32 +#endif // _WIN32 #ifdef _WIN32 #include -#endif // _WIN32 +#endif // _WIN32 #include #include -#include "main.h" // NOLINT +#include "main.h" // NOLINT // The TO_STRING macro is useful for command line defined strings as the quotes // get stripped. @@ -42,9 +42,9 @@ #define FIREBASE_CONFIG_STRING TO_STRING(FIREBASE_CONFIG) #else #define FIREBASE_CONFIG_STRING "" -#endif // FIREBASE_CONFIG +#endif // FIREBASE_CONFIG -extern "C" int common_main(int argc, const char* argv[]); +extern "C" int common_main(int argc, const char *argv[]); static bool quit = false; @@ -58,22 +58,20 @@ static BOOL WINAPI SignalHandler(DWORD event) { } #else static void SignalHandler(int /* ignored */) { quit = true; } -#endif // _WIN32 +#endif // _WIN32 bool ProcessEvents(int msec) { #ifdef _WIN32 Sleep(msec); #else usleep(msec * 1000); -#endif // _WIN32 +#endif // _WIN32 return quit; } -std::string PathForResource() { - return std::string(); -} +std::string PathForResource() { return std::string(); } -void LogMessage(const char* format, ...) { +void LogMessage(const char *format, ...) { va_list list; va_start(list, format); vprintf(format, list); @@ -86,25 +84,26 @@ WindowContext GetWindowContext() { return nullptr; } // Change the current working directory to the directory containing the // specified file. -void ChangeToFileDirectory(const char* file_path) { +void ChangeToFileDirectory(const char *file_path) { std::string path(file_path); std::replace(path.begin(), path.end(), '\\', '/'); auto slash = path.rfind('/'); if (slash != std::string::npos) { std::string directory = path.substr(0, slash); - if (!directory.empty()) chdir(directory.c_str()); + if (!directory.empty()) + chdir(directory.c_str()); } } -int main(int argc, const char* argv[]) { - ChangeToFileDirectory( - FIREBASE_CONFIG_STRING[0] != '\0' ? - FIREBASE_CONFIG_STRING : argv[0]); // NOLINT +int main(int argc, const char *argv[]) { + ChangeToFileDirectory(FIREBASE_CONFIG_STRING[0] != '\0' + ? FIREBASE_CONFIG_STRING + : argv[0]); // NOLINT #ifdef _WIN32 SetConsoleCtrlHandler((PHANDLER_ROUTINE)SignalHandler, TRUE); #else signal(SIGINT, SignalHandler); -#endif // _WIN32 +#endif // _WIN32 return common_main(argc, argv); } diff --git a/gma/testapp/src/ios/ios_main.mm b/gma/testapp/src/ios/ios_main.mm index 6ccb2de5..4c226d5e 100644 --- a/gma/testapp/src/ios/ios_main.mm +++ b/gma/testapp/src/ios/ios_main.mm @@ -18,9 +18,9 @@ #include "main.h" -extern "C" int common_main(int argc, const char* argv[]); +extern "C" int common_main(int argc, const char *argv[]); -@interface AppDelegate : UIResponder +@interface AppDelegate : UIResponder @property(nonatomic, strong) UIWindow *window; @@ -42,33 +42,35 @@ @implementation FTAViewController - (void)viewDidLoad { [super viewDidLoad]; g_parent_view = self.view; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - const char *argv[] = {FIREBASE_TESTAPP_NAME}; - [g_shutdown_signal lock]; - g_exit_status = common_main(1, argv); - [g_shutdown_complete signal]; - }); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), + ^{ + const char *argv[] = {FIREBASE_TESTAPP_NAME}; + [g_shutdown_signal lock]; + g_exit_status = common_main(1, argv); + [g_shutdown_complete signal]; + }); } @end bool ProcessEvents(int msec) { [g_shutdown_signal - waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:static_cast(msec) / 1000.0f]]; + waitUntilDate:[NSDate + dateWithTimeIntervalSinceNow:static_cast(msec) / + 1000.0f]]; return g_shutdown; } -WindowContext GetWindowContext() { - return g_parent_view; -} +WindowContext GetWindowContext() { return g_parent_view; } // Log a message that can be viewed in the console. -void LogMessage(const char* format, ...) { +void LogMessage(const char *format, ...) { va_list args; NSString *formatString = @(format); va_start(args, format); - NSString *message = [[NSString alloc] initWithFormat:formatString arguments:args]; + NSString *message = [[NSString alloc] initWithFormat:formatString + arguments:args]; va_end(args); NSLog(@"%@", message); @@ -79,7 +81,7 @@ void LogMessage(const char* format, ...) { }); } -int main(int argc, char* argv[]) { +int main(int argc, char *argv[]) { @autoreleasepool { UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } @@ -88,8 +90,8 @@ int main(int argc, char* argv[]) { @implementation AppDelegate -- (BOOL)application:(UIApplication*)application - didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { g_shutdown_complete = [[NSCondition alloc] init]; g_shutdown_signal = [[NSCondition alloc] init]; [g_shutdown_complete lock]; diff --git a/gma/testapp/src/main.h b/gma/testapp/src/main.h index 2eda2c10..d41017a7 100644 --- a/gma/testapp/src/main.h +++ b/gma/testapp/src/main.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef FIREBASE_TESTAPP_MAIN_H_ // NOLINT -#define FIREBASE_TESTAPP_MAIN_H_ // NOLINT +#ifndef FIREBASE_TESTAPP_MAIN_H_ // NOLINT +#define FIREBASE_TESTAPP_MAIN_H_ // NOLINT #if defined(__ANDROID__) #include @@ -21,18 +21,18 @@ #elif defined(__APPLE__) extern "C" { #include -} // extern "C" -#endif // __ANDROID__ +} // extern "C" +#endif // __ANDROID__ // Defined using -DANDROID_MAIN_APP_NAME=some_app_name when compiling this // file. #ifndef FIREBASE_TESTAPP_NAME #define FIREBASE_TESTAPP_NAME "android_main" -#endif // FIREBASE_TESTAPP_NAME +#endif // FIREBASE_TESTAPP_NAME // Cross platform logging method. // Implemented by android/android_main.cc or ios/ios_main.mm. -extern "C" void LogMessage(const char* format, ...); +extern "C" void LogMessage(const char *format, ...); // Platform-independent method to flush pending events for the main thread. // Returns true when an event requesting program-exit is received. @@ -41,23 +41,23 @@ bool ProcessEvents(int msec); // WindowContext represents the handle to the parent window. It's type // (and usage) vary based on the OS. #if defined(__ANDROID__) -typedef jobject WindowContext; // A jobject to the Java Activity. +typedef jobject WindowContext; // A jobject to the Java Activity. #elif defined(__APPLE__) -typedef id WindowContext; // A pointer to an iOS UIView. +typedef id WindowContext; // A pointer to an iOS UIView. #else -typedef void* WindowContext; // A void* for any other environments. +typedef void *WindowContext; // A void* for any other environments. #endif #if defined(__ANDROID__) // Get the JNI environment. -JNIEnv* GetJniEnv(); +JNIEnv *GetJniEnv(); // Get the activity. jobject GetActivity(); -#endif // defined(__ANDROID__) +#endif // defined(__ANDROID__) // Returns a variable that describes the window context for the app. On Android // this will be a jobject pointing to the Activity. On iOS, it's an id pointing // to the root view of the view controller. WindowContext GetWindowContext(); -#endif // FIREBASE_TESTAPP_MAIN_H_ // NOLINT +#endif // FIREBASE_TESTAPP_MAIN_H_ // NOLINT From b56f77712b70ab9253215869d28afa7ce33736b7 Mon Sep 17 00:00:00 2001 From: "drsanta@google.com" Date: Sat, 25 Jun 2022 10:40:40 -0400 Subject: [PATCH 23/57] update gradle wrapper properties --- gma/testapp/gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gma/testapp/gradle/wrapper/gradle-wrapper.properties b/gma/testapp/gradle/wrapper/gradle-wrapper.properties index 6349b295..9e09cdb6 100644 --- a/gma/testapp/gradle/wrapper/gradle-wrapper.properties +++ b/gma/testapp/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip +distributionUrl=https://services.gradle.org/distributions/gradle-5.6.4-all.zip From fa6ffee5e199ad2080ab85afd55303615a099d4b Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Fri, 1 Jul 2022 13:12:50 -0400 Subject: [PATCH 24/57] Direct users to create branches off of main (#101) Update user docs to have contributions be branched off of main. --- CONTRIBUTING.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 02f251e9..c02eddc2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -109,7 +109,7 @@ Before you submit your pull request consider the following guidelines: * Make your changes in a new git branch: ```shell - git checkout -b my-fix-branch master + git checkout -b my-fix-branch main ``` * Create your patch, **including appropriate test cases**. @@ -133,14 +133,14 @@ Before you submit your pull request consider the following guidelines: git push origin my-fix-branch ``` -* In GitHub, send a pull request to `firebase/quickstart-cpp:master`. +* In GitHub, send a pull request to `firebase/quickstart-cpp:main`. * If we suggest changes then: * Make the required updates. * Rebase your branch and force push to your GitHub repository (this will update your Pull Request): ```shell - git rebase master -i + git rebase main -i git push origin my-fix-branch -f ``` @@ -158,10 +158,10 @@ the changes from the main (upstream) repository: git push origin --delete my-fix-branch ``` -* Check out the master branch: +* Check out the main branch: ```shell - git checkout master -f + git checkout main -f ``` * Delete the local branch: @@ -170,10 +170,10 @@ the changes from the main (upstream) repository: git branch -D my-fix-branch ``` -* Update your master with the latest upstream version: +* Update your main with the latest upstream version: ```shell - git pull --ff upstream master + git pull --ff upstream main ``` ## Coding Rules @@ -186,7 +186,7 @@ Please sign our [Contributor License Agreement][google-cla] (CLA) before sending pull requests. For any code changes to be accepted, the CLA must be signed. It's a quick process, we promise! -*This guide was inspired by the [AngularJS contribution guidelines](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md).* +*This guide was inspired by the [AngularJS contribution guidelines](https://github.com/angular/angular.js/blob/main/CONTRIBUTING.md).* [github]: https://github.com/firebase/quickstart-cpp [google-cla]: https://cla.developers.google.com From 8e20c72271974b8cadab80ec3ac300353bb0500d Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Wed, 6 Jul 2022 15:16:23 -0400 Subject: [PATCH 25/57] Update Android build config and source fixes (#102) A pass of the android build process to ensure the testapps can build prior to adding CI to the repo. --- admob/testapp/build.gradle | 4 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- analytics/testapp/build.gradle | 6 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- analytics/testapp/src/common_main.cc | 6 +- auth/testapp/build.gradle | 9 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- database/testapp/build.gradle | 8 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- dynamic_links/testapp/build.gradle | 6 +- .../gradle/wrapper/gradle-wrapper.properties | 3 +- firestore/testapp/build.gradle | 14 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- functions/testapp/build.gradle | 8 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- messaging/testapp/build.gradle | 15 +-- .../gradle/wrapper/gradle-wrapper.properties | 2 +- remote_config/testapp/build.gradle | 8 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- remote_config/testapp/src/common_main.cc | 124 +++++++++--------- storage/testapp/build.gradle | 8 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- 22 files changed, 137 insertions(+), 100 deletions(-) diff --git a/admob/testapp/build.gradle b/admob/testapp/build.gradle index 4562ea56..a6697fca 100644 --- a/admob/testapp/build.gradle +++ b/admob/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.3.3' classpath 'com.google.gms:google-services:4.0.1' } } @@ -36,7 +36,7 @@ android { defaultConfig { applicationId 'com.google.android.admob.testapp' - minSdkVersion 16 + minSdkVersion 26 targetSdkVersion 28 versionCode 1 versionName '1.0' diff --git a/admob/testapp/gradle/wrapper/gradle-wrapper.properties b/admob/testapp/gradle/wrapper/gradle-wrapper.properties index 35732b09..9e09cdb6 100644 --- a/admob/testapp/gradle/wrapper/gradle-wrapper.properties +++ b/admob/testapp/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/analytics/testapp/build.gradle b/analytics/testapp/build.gradle index 95aa238b..6928009e 100644 --- a/analytics/testapp/build.gradle +++ b/analytics/testapp/build.gradle @@ -22,6 +22,10 @@ allprojects { apply plugin: 'com.android.application' android { + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } compileSdkVersion 28 buildToolsVersion '28.0.3' @@ -36,7 +40,7 @@ android { defaultConfig { applicationId 'com.google.android.analytics.testapp' - minSdkVersion 16 + minSdkVersion 19 targetSdkVersion 28 versionCode 1 versionName '1.0' diff --git a/analytics/testapp/gradle/wrapper/gradle-wrapper.properties b/analytics/testapp/gradle/wrapper/gradle-wrapper.properties index 35732b09..9e09cdb6 100644 --- a/analytics/testapp/gradle/wrapper/gradle-wrapper.properties +++ b/analytics/testapp/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/analytics/testapp/src/common_main.cc b/analytics/testapp/src/common_main.cc index ee7f15da..e063e416 100644 --- a/analytics/testapp/src/common_main.cc +++ b/analytics/testapp/src/common_main.cc @@ -63,9 +63,9 @@ extern "C" int common_main(int argc, const char* argv[]) { // Set the user ID. analytics::SetUserId("uber_user_510"); - LogMessage("Set current screen."); - // Set the user's current screen. - analytics::SetCurrentScreen("Firebase Analytics C++ testapp", "testapp"); + LogMessage("Log current screen."); + // Log the user's current screen. + analytics::LogEvent(analytics::kEventScreenView, "Firebase Analytics C++ testapp", "testapp" ); // Log an event with no parameters. LogMessage("Log login event."); diff --git a/auth/testapp/build.gradle b/auth/testapp/build.gradle index 64cdb605..7a6525e4 100644 --- a/auth/testapp/build.gradle +++ b/auth/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.3.3' classpath 'com.google.gms:google-services:4.0.1' } } @@ -22,6 +22,11 @@ allprojects { apply plugin: 'com.android.application' android { + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } + compileSdkVersion 28 buildToolsVersion '28.0.3' @@ -36,7 +41,7 @@ android { defaultConfig { applicationId 'com.google.android.auth.testapp' - minSdkVersion 16 + minSdkVersion 19 targetSdkVersion 28 versionCode 1 versionName '1.0' diff --git a/auth/testapp/gradle/wrapper/gradle-wrapper.properties b/auth/testapp/gradle/wrapper/gradle-wrapper.properties index 35732b09..9e09cdb6 100644 --- a/auth/testapp/gradle/wrapper/gradle-wrapper.properties +++ b/auth/testapp/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/database/testapp/build.gradle b/database/testapp/build.gradle index 464c7d34..b109c884 100644 --- a/database/testapp/build.gradle +++ b/database/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.3.3' classpath 'com.google.gms:google-services:4.0.1' } } @@ -22,6 +22,10 @@ allprojects { apply plugin: 'com.android.application' android { + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } compileSdkVersion 28 buildToolsVersion '28.0.3' @@ -36,7 +40,7 @@ android { defaultConfig { applicationId 'com.google.firebase.cpp.database.testapp' - minSdkVersion 16 + minSdkVersion 19 targetSdkVersion 28 versionCode 1 versionName '1.0' diff --git a/database/testapp/gradle/wrapper/gradle-wrapper.properties b/database/testapp/gradle/wrapper/gradle-wrapper.properties index 35732b09..9e09cdb6 100644 --- a/database/testapp/gradle/wrapper/gradle-wrapper.properties +++ b/database/testapp/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/dynamic_links/testapp/build.gradle b/dynamic_links/testapp/build.gradle index c3961d97..bf4eff96 100644 --- a/dynamic_links/testapp/build.gradle +++ b/dynamic_links/testapp/build.gradle @@ -22,6 +22,10 @@ allprojects { apply plugin: 'com.android.application' android { + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } compileSdkVersion 28 buildToolsVersion '28.0.3' @@ -36,7 +40,7 @@ android { defaultConfig { applicationId 'com.google.android.dynamiclinks.testapp' - minSdkVersion 16 + minSdkVersion 19 targetSdkVersion 28 versionCode 1 versionName '1.0' diff --git a/dynamic_links/testapp/gradle/wrapper/gradle-wrapper.properties b/dynamic_links/testapp/gradle/wrapper/gradle-wrapper.properties index 35732b09..5aa7f761 100644 --- a/dynamic_links/testapp/gradle/wrapper/gradle-wrapper.properties +++ b/dynamic_links/testapp/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https://services.gradle.org/distributions/gradle-5.6.4-all.zip + diff --git a/firestore/testapp/build.gradle b/firestore/testapp/build.gradle index 37ed5818..11751d34 100644 --- a/firestore/testapp/build.gradle +++ b/firestore/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.3.3' classpath 'com.google.gms:google-services:4.0.1' } } @@ -22,8 +22,12 @@ allprojects { apply plugin: 'com.android.application' android { - compileSdkVersion 29 - buildToolsVersion "29.0.0" + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } + compileSdkVersion 28 + buildToolsVersion "28.0.3" sourceSets { main { @@ -36,8 +40,8 @@ android { defaultConfig { applicationId 'com.google.firebase.cpp.firestore.testapp' - minSdkVersion 16 - targetSdkVersion 29 + minSdkVersion 19 + targetSdkVersion 28 versionCode 1 versionName '1.0' externalNativeBuild.cmake { diff --git a/firestore/testapp/gradle/wrapper/gradle-wrapper.properties b/firestore/testapp/gradle/wrapper/gradle-wrapper.properties index 35732b09..9e09cdb6 100644 --- a/firestore/testapp/gradle/wrapper/gradle-wrapper.properties +++ b/firestore/testapp/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/functions/testapp/build.gradle b/functions/testapp/build.gradle index 28d47fc1..70632871 100644 --- a/functions/testapp/build.gradle +++ b/functions/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.3.3' classpath 'com.google.gms:google-services:4.0.1' } } @@ -22,6 +22,10 @@ allprojects { apply plugin: 'com.android.application' android { + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } compileSdkVersion 28 buildToolsVersion '28.0.3' @@ -36,7 +40,7 @@ android { defaultConfig { applicationId 'com.google.firebase.cpp.functions.testapp' - minSdkVersion 16 + minSdkVersion 19 targetSdkVersion 28 versionCode 1 versionName '1.0' diff --git a/functions/testapp/gradle/wrapper/gradle-wrapper.properties b/functions/testapp/gradle/wrapper/gradle-wrapper.properties index 35732b09..9e09cdb6 100644 --- a/functions/testapp/gradle/wrapper/gradle-wrapper.properties +++ b/functions/testapp/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/messaging/testapp/build.gradle b/messaging/testapp/build.gradle index 0971c57b..d0565e63 100644 --- a/messaging/testapp/build.gradle +++ b/messaging/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.3.3' classpath 'com.google.gms:google-services:4.0.1' } } @@ -22,16 +22,13 @@ allprojects { apply plugin: 'com.android.application' android { + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } compileSdkVersion 28 buildToolsVersion '28.0.3' - android { - compileOptions { - sourceCompatibility 1.8 - targetCompatibility 1.8 - } - } - sourceSets { main { jniLibs.srcDirs = ['libs'] @@ -43,7 +40,7 @@ android { defaultConfig { applicationId 'com.google.android.messaging.testapp' - minSdkVersion 16 + minSdkVersion 19 targetSdkVersion 28 versionCode 1 versionName '1.0' diff --git a/messaging/testapp/gradle/wrapper/gradle-wrapper.properties b/messaging/testapp/gradle/wrapper/gradle-wrapper.properties index 35732b09..9e09cdb6 100644 --- a/messaging/testapp/gradle/wrapper/gradle-wrapper.properties +++ b/messaging/testapp/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/remote_config/testapp/build.gradle b/remote_config/testapp/build.gradle index 650a11af..acce9ee7 100644 --- a/remote_config/testapp/build.gradle +++ b/remote_config/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.3.3' classpath 'com.google.gms:google-services:4.0.1' } } @@ -22,6 +22,10 @@ allprojects { apply plugin: 'com.android.application' android { + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } compileSdkVersion 28 buildToolsVersion '28.0.3' @@ -36,7 +40,7 @@ android { defaultConfig { applicationId 'com.google.android.remoteconfig.testapp' - minSdkVersion 16 + minSdkVersion 19 targetSdkVersion 28 versionCode 1 versionName '1.0' diff --git a/remote_config/testapp/gradle/wrapper/gradle-wrapper.properties b/remote_config/testapp/gradle/wrapper/gradle-wrapper.properties index 35732b09..9e09cdb6 100644 --- a/remote_config/testapp/gradle/wrapper/gradle-wrapper.properties +++ b/remote_config/testapp/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/remote_config/testapp/src/common_main.cc b/remote_config/testapp/src/common_main.cc index 66a7039e..3bc35e2c 100644 --- a/remote_config/testapp/src/common_main.cc +++ b/remote_config/testapp/src/common_main.cc @@ -19,22 +19,26 @@ #include "firebase/util.h" // Thin OS abstraction layer. -#include "main.h" // NOLINT +#include "main.h" // NOLINT + +using firebase::remote_config::RemoteConfig; // Convert remote_config::ValueSource to a string. -const char* ValueSourceToString(firebase::remote_config::ValueSource source) { - static const char* kSourceToString[] = { - "Static", // kValueSourceStaticValue - "Remote", // kValueSourceRemoteValue - "Default", // kValueSourceDefaultValue +const char *ValueSourceToString(firebase::remote_config::ValueSource source) { + static const char *kSourceToString[] = { + "Static", // kValueSourceStaticValue + "Remote", // kValueSourceRemoteValue + "Default", // kValueSourceDefaultValue }; return kSourceToString[source]; } +RemoteConfig *rc_ = nullptr; + // Execute all methods of the C++ Remote Config API. -extern "C" int common_main(int argc, const char* argv[]) { +extern "C" int common_main(int argc, const char *argv[]) { namespace remote_config = ::firebase::remote_config; - ::firebase::App* app; + ::firebase::App *app; // Initialization @@ -43,20 +47,28 @@ extern "C" int common_main(int argc, const char* argv[]) { app = ::firebase::App::Create(GetJniEnv(), GetActivity()); #else app = ::firebase::App::Create(); -#endif // defined(__ANDROID__) +#endif // defined(__ANDROID__) LogMessage("Created the Firebase app %x", static_cast(reinterpret_cast(app))); ::firebase::ModuleInitializer initializer; - initializer.Initialize(app, nullptr, [](::firebase::App* app, void*) { - LogMessage("Try to initialize Remote Config"); - return ::firebase::remote_config::Initialize(*app); + + void *ptr = nullptr; + ptr = &rc_; + initializer.Initialize(app, ptr, [](::firebase::App *app, void *target) { + LogMessage("Try to initialize Firebase RemoteConfig"); + RemoteConfig **rc_ptr = reinterpret_cast(target); + *rc_ptr = RemoteConfig::GetInstance(app); + return firebase::kInitResultSuccess; }); + while (initializer.InitializeLastResult().status() != firebase::kFutureStatusComplete) { - if (ProcessEvents(100)) return 1; // exit if requested + if (ProcessEvents(100)) + return 1; // exit if requested } + if (initializer.InitializeLastResult().error() != 0) { LogMessage("Failed to initialize Firebase Remote Config: %s", initializer.InitializeLastResult().error_message()); @@ -79,47 +91,45 @@ extern "C" int common_main(int argc, const char* argv[]) { sizeof(kBinaryDefaults))}, {"TestDefaultOnly", "Default value that won't be overridden"}}; size_t default_count = sizeof(defaults) / sizeof(defaults[0]); - remote_config::SetDefaults(defaults, default_count); + rc_->SetDefaults(defaults, default_count); // The return values may not be the set defaults, if a fetch was previously // completed for the app that set them. remote_config::ValueInfo value_info; { - bool result = remote_config::GetBoolean("TestBoolean", &value_info); + bool result = rc_->GetBoolean("TestBoolean", &value_info); LogMessage("Get TestBoolean %d %s", result ? 1 : 0, ValueSourceToString(value_info.source)); } { - int64_t result = remote_config::GetLong("TestLong", &value_info); + int64_t result = rc_->GetLong("TestLong", &value_info); LogMessage("Get TestLong %lld %s", result, ValueSourceToString(value_info.source)); } { - double result = remote_config::GetDouble("TestDouble", &value_info); + double result = rc_->GetDouble("TestDouble", &value_info); LogMessage("Get TestDouble %f %s", result, ValueSourceToString(value_info.source)); } { - std::string result = remote_config::GetString("TestString", &value_info); + std::string result = rc_->GetString("TestString", &value_info); LogMessage("Get TestString \"%s\" %s", result.c_str(), ValueSourceToString(value_info.source)); } { - std::vector result = remote_config::GetData("TestData"); + std::vector result = rc_->GetData("TestData"); for (size_t i = 0; i < result.size(); ++i) { const unsigned char value = result[i]; LogMessage("TestData[%d] = 0x%02x", i, value); } } { - std::string result = remote_config::GetString("TestDefaultOnly", - &value_info); + std::string result = rc_->GetString("TestDefaultOnly", &value_info); LogMessage("Get TestDefaultOnly \"%s\" %s", result.c_str(), ValueSourceToString(value_info.source)); } { - std::string result = remote_config::GetString("TestNotSet", - &value_info); + std::string result = rc_->GetString("TestNotSet", &value_info); LogMessage("Get TestNotSet \"%s\" %s", result.c_str(), ValueSourceToString(value_info.source)); } @@ -127,30 +137,21 @@ extern "C" int common_main(int argc, const char* argv[]) { // Test the existence of the keys by name. { // Print out the keys with default values. - std::vector keys = remote_config::GetKeys(); + std::vector keys = rc_->GetKeys(); LogMessage("GetKeys:"); for (auto s = keys.begin(); s != keys.end(); ++s) { LogMessage(" %s", s->c_str()); } - keys = remote_config::GetKeysByPrefix("TestD"); + keys = rc_->GetKeysByPrefix("TestD"); LogMessage("GetKeysByPrefix(\"TestD\"):"); for (auto s = keys.begin(); s != keys.end(); ++s) { LogMessage(" %s", s->c_str()); } } - // Enable developer mode and verified it's enabled. - // NOTE: Developer mode should not be enabled in production applications. - remote_config::SetConfigSetting(remote_config::kConfigSettingDeveloperMode, - "1"); - if ((*remote_config::GetConfigSetting( - remote_config::kConfigSettingDeveloperMode) - .c_str()) != '1') { - LogMessage("Failed to enable developer mode"); - } // Test Fetch... LogMessage("Fetch..."); - auto future_result = remote_config::Fetch(0); + auto future_result = rc_->Fetch(0); while (future_result.status() == firebase::kFutureStatusPending) { if (ProcessEvents(1000)) { break; @@ -159,67 +160,71 @@ extern "C" int common_main(int argc, const char* argv[]) { if (future_result.status() == firebase::kFutureStatusComplete) { LogMessage("Fetch Complete"); - bool activate_result = remote_config::ActivateFetched(); - LogMessage("ActivateFetched %s", activate_result ? "succeeded" : "failed"); - - const remote_config::ConfigInfo& info = remote_config::GetInfo(); - LogMessage( - "Info last_fetch_time_ms=%d (year=%.2f) fetch_status=%d " - "failure_reason=%d throttled_end_time=%d", - static_cast(info.fetch_time), - 1970.0f + static_cast(info.fetch_time) / - (1000.0f * 60.0f * 60.0f * 24.0f * 365.0f), - info.last_fetch_status, info.last_fetch_failure_reason, - info.throttled_end_time); + auto activate_future_result = rc_->Activate(); + while (future_result.status() == firebase::kFutureStatusPending) { + if (ProcessEvents(1000)) { + break; + } + } + + bool activate_result = activate_future_result.result(); + LogMessage("Activate %s", activate_result ? "succeeded" : "failed"); + + const remote_config::ConfigInfo &info = rc_->GetInfo(); + LogMessage("Info last_fetch_time_ms=%d (year=%.2f) fetch_status=%d " + "failure_reason=%d throttled_end_time=%d", + static_cast(info.fetch_time), + 1970.0f + static_cast(info.fetch_time) / + (1000.0f * 60.0f * 60.0f * 24.0f * 365.0f), + info.last_fetch_status, info.last_fetch_failure_reason, + info.throttled_end_time); // Print out the new values, which may be updated from the Fetch. { - bool result = remote_config::GetBoolean("TestBoolean", &value_info); + bool result = rc_->GetBoolean("TestBoolean", &value_info); LogMessage("Updated TestBoolean %d %s", result ? 1 : 0, ValueSourceToString(value_info.source)); } { - int64_t result = remote_config::GetLong("TestLong", &value_info); + int64_t result = rc_->GetLong("TestLong", &value_info); LogMessage("Updated TestLong %lld %s", result, ValueSourceToString(value_info.source)); } { - double result = remote_config::GetDouble("TestDouble", &value_info); + double result = rc_->GetDouble("TestDouble", &value_info); LogMessage("Updated TestDouble %f %s", result, ValueSourceToString(value_info.source)); } { - std::string result = remote_config::GetString("TestString", &value_info); + std::string result = rc_->GetString("TestString", &value_info); LogMessage("Updated TestString \"%s\" %s", result.c_str(), ValueSourceToString(value_info.source)); } { - std::vector result = remote_config::GetData("TestData"); + std::vector result = rc_->GetData("TestData"); for (size_t i = 0; i < result.size(); ++i) { const unsigned char value = result[i]; LogMessage("TestData[%d] = 0x%02x", i, value); } } { - std::string result = remote_config::GetString("TestDefaultOnly", - &value_info); + std::string result = rc_->GetString("TestDefaultOnly", &value_info); LogMessage("Get TestDefaultOnly \"%s\" %s", result.c_str(), ValueSourceToString(value_info.source)); } { - std::string result = remote_config::GetString("TestNotSet", - &value_info); + std::string result = rc_->GetString("TestNotSet", &value_info); LogMessage("Get TestNotSet \"%s\" %s", result.c_str(), ValueSourceToString(value_info.source)); } { // Print out the keys that are now tied to data - std::vector keys = remote_config::GetKeys(); + std::vector keys = rc_->GetKeys(); LogMessage("GetKeys:"); for (auto s = keys.begin(); s != keys.end(); ++s) { LogMessage(" %s", s->c_str()); } - keys = remote_config::GetKeysByPrefix("TestD"); + keys = rc_->GetKeysByPrefix("TestD"); LogMessage("GetKeysByPrefix(\"TestD\"):"); for (auto s = keys.begin(); s != keys.end(); ++s) { LogMessage(" %s", s->c_str()); @@ -237,7 +242,8 @@ extern "C" int common_main(int argc, const char* argv[]) { while (!ProcessEvents(1000)) { } - remote_config::Terminate(); + delete rc_; + rc_ = nullptr; delete app; return 0; diff --git a/storage/testapp/build.gradle b/storage/testapp/build.gradle index 264b2a34..c47942ed 100644 --- a/storage/testapp/build.gradle +++ b/storage/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.3.3' classpath 'com.google.gms:google-services:4.0.1' } } @@ -22,6 +22,10 @@ allprojects { apply plugin: 'com.android.application' android { + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } compileSdkVersion 28 buildToolsVersion '28.0.3' @@ -36,7 +40,7 @@ android { defaultConfig { applicationId 'com.google.firebase.cpp.storage.testapp' - minSdkVersion 16 + minSdkVersion 19 targetSdkVersion 28 versionCode 1 versionName '1.0' diff --git a/storage/testapp/gradle/wrapper/gradle-wrapper.properties b/storage/testapp/gradle/wrapper/gradle-wrapper.properties index 35732b09..9e09cdb6 100644 --- a/storage/testapp/gradle/wrapper/gradle-wrapper.properties +++ b/storage/testapp/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https://services.gradle.org/distributions/gradle-5.6.4-all.zip From 5f8dc7e67cbb9f105f849d13bd98708044e3d24f Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Thu, 7 Jul 2022 17:09:08 -0400 Subject: [PATCH 26/57] Add github action workflows for Android and iOS (#104) This change adds benign workflows for Android and iOS builds. --- .github/workflows/android.yml | 14 ++++++++++++++ .github/workflows/ios.yml | 14 ++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 .github/workflows/android.yml create mode 100644 .github/workflows/ios.yml diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml new file mode 100644 index 00000000..af35d584 --- /dev/null +++ b/.github/workflows/android.yml @@ -0,0 +1,14 @@ +name: Android builds + +on: + workflow_dispatch: + inputs: + apis: + description: 'CSV of apis whose quickstart examples we should build' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: noop + run: true diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml new file mode 100644 index 00000000..72c85f64 --- /dev/null +++ b/.github/workflows/ios.yml @@ -0,0 +1,14 @@ +name: iOS builds + +on: + workflow_dispatch: + inputs: + apis: + description: 'CSV of apis whose quickstart examples we should build' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: noop + run: true From b74606b76c997e25acc05079b2ffd7618b3fcddc Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Fri, 8 Jul 2022 12:52:32 -0400 Subject: [PATCH 27/57] added encrypted google services files (#103) Add the secrets for the test apps. This one step in many working toward creating CI builds of our testapps for all platforms. --- scripts/gha-encrypted/README | 4 ++++ .../admob/GoogleService-Info.plist.gpg | Bin 0 -> 671 bytes .../gha-encrypted/admob/google-services.json.gpg | Bin 0 -> 1002 bytes .../analytics/GoogleService-Info.plist.gpg | Bin 0 -> 683 bytes .../analytics/google-services.json.gpg | Bin 0 -> 958 bytes .../auth/GoogleService-Info.plist.gpg | Bin 0 -> 691 bytes .../gha-encrypted/auth/google-services.json.gpg | Bin 0 -> 1014 bytes .../database/GoogleService-Info.plist.gpg | Bin 0 -> 711 bytes .../database/google-services.json.gpg | Bin 0 -> 719 bytes .../dynamic_links/GoogleService-Info.plist.gpg | Bin 0 -> 736 bytes .../dynamic_links/google-services.json.gpg | Bin 0 -> 712 bytes .../firestore/GoogleService-Info.plist.gpg | Bin 0 -> 610 bytes .../firestore/google-services.json.gpg | Bin 0 -> 534 bytes .../functions/GoogleService-Info.plist.gpg | Bin 0 -> 688 bytes .../functions/google-services.json.gpg | Bin 0 -> 850 bytes .../gma/GoogleService-Info.plist.gpg | Bin 0 -> 672 bytes .../gha-encrypted/gma/google-services.json.gpg | Bin 0 -> 1002 bytes .../messaging/GoogleService-Info.plist.gpg | Bin 0 -> 692 bytes .../messaging/google-services.json.gpg | Bin 0 -> 911 bytes .../remote_config/GoogleService-Info.plist.gpg | Bin 0 -> 720 bytes .../remote_config/google-services.json.gpg | Bin 0 -> 1013 bytes .../storage/GoogleService-Info.plist.gpg | Bin 0 -> 682 bytes .../storage/google-services.json.gpg | Bin 0 -> 816 bytes 23 files changed, 4 insertions(+) create mode 100644 scripts/gha-encrypted/README create mode 100644 scripts/gha-encrypted/admob/GoogleService-Info.plist.gpg create mode 100644 scripts/gha-encrypted/admob/google-services.json.gpg create mode 100644 scripts/gha-encrypted/analytics/GoogleService-Info.plist.gpg create mode 100644 scripts/gha-encrypted/analytics/google-services.json.gpg create mode 100644 scripts/gha-encrypted/auth/GoogleService-Info.plist.gpg create mode 100644 scripts/gha-encrypted/auth/google-services.json.gpg create mode 100644 scripts/gha-encrypted/database/GoogleService-Info.plist.gpg create mode 100644 scripts/gha-encrypted/database/google-services.json.gpg create mode 100644 scripts/gha-encrypted/dynamic_links/GoogleService-Info.plist.gpg create mode 100644 scripts/gha-encrypted/dynamic_links/google-services.json.gpg create mode 100644 scripts/gha-encrypted/firestore/GoogleService-Info.plist.gpg create mode 100644 scripts/gha-encrypted/firestore/google-services.json.gpg create mode 100644 scripts/gha-encrypted/functions/GoogleService-Info.plist.gpg create mode 100644 scripts/gha-encrypted/functions/google-services.json.gpg create mode 100644 scripts/gha-encrypted/gma/GoogleService-Info.plist.gpg create mode 100644 scripts/gha-encrypted/gma/google-services.json.gpg create mode 100644 scripts/gha-encrypted/messaging/GoogleService-Info.plist.gpg create mode 100644 scripts/gha-encrypted/messaging/google-services.json.gpg create mode 100644 scripts/gha-encrypted/remote_config/GoogleService-Info.plist.gpg create mode 100644 scripts/gha-encrypted/remote_config/google-services.json.gpg create mode 100644 scripts/gha-encrypted/storage/GoogleService-Info.plist.gpg create mode 100644 scripts/gha-encrypted/storage/google-services.json.gpg diff --git a/scripts/gha-encrypted/README b/scripts/gha-encrypted/README new file mode 100644 index 00000000..eb31d713 --- /dev/null +++ b/scripts/gha-encrypted/README @@ -0,0 +1,4 @@ +See https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets + +Googlers: code search firebase/cpp/Secrets/quickstart to find the sources. + diff --git a/scripts/gha-encrypted/admob/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/admob/GoogleService-Info.plist.gpg new file mode 100644 index 0000000000000000000000000000000000000000..7a8dd56b43dacbfaf599257dc3c7228deffe524e GIT binary patch literal 671 zcmV;Q0$}}&4Fm}T0-Lp(S*XbSzyH$d0ccQ3S6V1c>`Vq{v@eT;(WXE&Mg7Sm$!4&< z@!pq8juOCk>c~ub=-BY`=|$N%sL8OnJhQx3;)u5G_mI7lb7x&|tZJ`xmU6Y|4}M`o-pzpt>cC;cW3n(fm#lMj0q5qrw#iXV@hH3!~0EURh?^Y}bnKHD}=G$)7BL6z=wX z61wI zU^IG4E^8z{RtfF8iGTe6w0ms+K{j{aCnwrF zQ(W`X)ryzv4IjF(R2}7emWWn?aS5FZaWa8+4BoL4^j}#qP{bD(UkyP^~9$knrMTAClQ`y;xhD(q}xeIq+JpqL8h^2E> zH%l>NZN>i!)bm8tWMoH+{9-#))^qYDF~q_RhG(d*n*RRsaoQ+$jVH Fi_{?GSk3?d literal 0 HcmV?d00001 diff --git a/scripts/gha-encrypted/admob/google-services.json.gpg b/scripts/gha-encrypted/admob/google-services.json.gpg new file mode 100644 index 0000000000000000000000000000000000000000..b62f63cbd715bac8245378fe906b83c40f168bbe GIT binary patch literal 1002 zcmV|*kk0})|U8{>`vX{A^rB0mUfNRZ3b@0(nBs0uCLT5=f&CS7md#Vj&Q8(kxYI|_37n{ zJ}{jbQu@aHPH&_>z`JK!8@DwEYY^&yKTQ0dvkSeP*eUR(u1Uo5TYJf*^mDeGN9duk z8nii0zNRM>G4S=ub?k1o&K;x!!c%~Je;MAmq2m7_C;TP?FoA#-0aF-v#3`vetun(a%*PI# z-YEo)EDP?8qw7I;P;${whXK)^q5UYT`namLHDbE zv1#5*IDnu2pd4ACmBp^Av6(*@k|^+B^yML1DV_j+UAG*8?ovqQRQ{ z*{e3BDhx2%z*jOvllCRg!51fA0cDg$ymDS0b4BXgU#W)*kg69Ayb`d;C#Wt^5{Oxq z&LG)P>~?QI7BYDLKMlfL)Vfa5RqCvDdHuuNtN_H{y1h}xPGJ`#eM^_A@Ft#VHnP+m z+%l8o45e`Ql2}r~?NdQmIz2Cfvi(t9!^Ne-*o*|f*iIre@_eihE5slG-9_xHNlR54 zd|>Y0(rKpKTGZ%-lt}y({)arrs8Snc4GBf48&t1I`HN5o-?>I%-_i#MU@L9n$_}Lt z%>~;AA;Z13$f5C(fNXk8&Aox%LXL&b0Dp4Cm?d6wEb_1Q`}{2%m43+QSioY9j*9lx zfi&XaUSG~Qp_EOTU31bi0Z)!OzzJP4Qu|9Isy=iG>pi_|m;h2(U0A=U=Zs^MQ0Eig z@>P&AdHOoJG;=J0xZA>?(KL1xCX)wctgo1|yv@!RTFChPvNK(K!bUox+U6aQ5gAXd zipi1IvmVTR+>zj$82f9Y0>mLfFf5C1&+q|X!Fg%ST!JNNvbNXO*b-PoZ63MT5sxiV z&S&PyOhi6OBMXcedg~ut+-5@gSV|E4;bP8(z467TvcX;x`x0hYO{WmPoKO$Z_8Ey* Yboa4XrsEr5lqq?)xW4iT*rtkxy%%)*%m4rY literal 0 HcmV?d00001 diff --git a/scripts/gha-encrypted/analytics/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/analytics/GoogleService-Info.plist.gpg new file mode 100644 index 0000000000000000000000000000000000000000..094a665cff13969b6a82cb9a4ffc017316aae368 GIT binary patch literal 683 zcmV;c0#yBs4Fm}T0$9EM+5(-VK>yO|0i2OGg6KgFaNq@Qa0xP)ug||uQE}`=`2k86 zz`Ol|O@_9$cQym3YRKN#BX!RvOO_DMuG?3Z3GeV|BCO`>=2UkEU_MMw2%BivP=uiV zVm|E-o5EJH+F!8i+@yKeuq-3jP#Z?J_OcIriJ`|?j(M92cGr{iKX5XIThZ|?U`0)_M9FFE0)N13828W(5SyTxb;KeC=PI8jZ6avy? z8%tBEv8W99m)Fy;wNGjei88@E?p7Vx5dXSh7nDnt640O?PG4wy2&7r}=d)L7@d?); z+JHmXHFS<+K}$_SNEts5k(?}#MWu>{NdQpRmJUk?@x8zHpTfG~JLP@FtV<_M7iuon zS7Pw<+b?9!0mqll6c;D$MUl96OpKtPVd1pvSB$uwKK_u@8u&{qkX8gaP{{t6wqFW6 z{Qa#JYc#BT-UDlr`AZy}tBm{BxHANZ6%%eozM%NbU=GklVvM}CYs@vuKt)}940KPx zWuXnGzti=BXdHpj9iP%xvJHOG6!LlZ1efvOX7>qH(~{J9im(b1HZ|T1b-w1ye|5il zH|v5@00QR#0eukrPE9uTDL+S4O_y{GM+-@G-hHX#RX)xlDFR{a%FfYwYKX-pcOPsbPG{u!oPt_P(IcQOUB&{Ml$Hr1=~^m3-C1A z2+!JO<9GG(5BVP;_fvEQeO7H>+9)lpDp8{!_0 RUmC{{rNp@RriZN!T-3M=P}%?h literal 0 HcmV?d00001 diff --git a/scripts/gha-encrypted/analytics/google-services.json.gpg b/scripts/gha-encrypted/analytics/google-services.json.gpg new file mode 100644 index 0000000000000000000000000000000000000000..58d461365e9d4a8c78e6ba066a36ddc91e212659 GIT binary patch literal 958 zcmV;v13~T!1C6|W5>d-`i}bU6bA{|IG`5R zQK%DNYAwaq57z|kLC#*^RMa>!u&xPi+r9jLD<~bCqhQ^FE{Ese@uZPen3?v>*;>@< z-Ui5zxdFkXoEK`Aui(c47d#?&&E692D*xmcsT`6ddfh#x7A9U&bB!v6&Xv$aPYF!O zqn+K@wwH`7{w@|(*l>P-`+4@v>2|_FyazJ$y@Z?MW{h{dsZ$Jk# zIHn?v1D4efSn%9@xMVYYCugM%(qoutO{_21}S;!0QpC5-UJl2aeo0^?iwlL&f`|4Xi7zOc&Qrh<_vOA0(C_7s1DW zK`@GoM&l@(B6{xY$=Di$7W!7rcRH17{f3T{dlL98uIZaE;^6epw1O!5@kU_x2Ee?&ZA9pwH~v@DzjE{j2IM5M*vreO3))AeAax z&L>NtX;1M#WKBI8-}FywR%b-Y2&ogHBFSD=qg7mp(@d+)`bUzhJwmueo_^=+A zA;DO*eirh=OQ}pjI}8}Qvn>567FBtJH2JbDS@FWWA$Iu!YJ_gn=?i-}W)aJU^+`C{lh!8$qjHNuFGV4L~$9?sg-PKb=(_y7O^ literal 0 HcmV?d00001 diff --git a/scripts/gha-encrypted/auth/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/auth/GoogleService-Info.plist.gpg new file mode 100644 index 0000000000000000000000000000000000000000..03490af4d0a7d8e6b73326e72709402670e41656 GIT binary patch literal 691 zcmV;k0!;mk4Fm}T0w?MSpTF7wZU55g0hFNOJ#vCjDV*7UC84++3FtMB)|!-2Y&d2# z4zA+i^!R#IkL|)QzRbI9@%;RdZF%EnOgI%WWA1{S)-XG_n~jPdcNmZUy5HsYM<2$< zbQQt~Z|(C&CFnV|zv#?eeu&IILcUZSSJAuz!3wb><*T%r9|=Pw*{dD9oenq%xPt}x zZohS$^X4lsLS}utirGsEzD{}&#g6scx4+nPx%H@~E(9+2{P+WO6@_*S<5>*)iEYBx zO5PA3mo?c!P5qM;4o6Oq+vAUr<+9V**PGTof#f6z>ydrZqK@rQr#kLfUCfA%Wp3d1P5>y+K?ntnpEzv|3NC~1F^^>%M<@0UXrW@qE*+M@iOP@mT|Gd1F@uR zmtxbpx}2aM7sj_~Q1<&I&`GoTa0e@Yykh7WQmk!U`1+UU#^dENB#Hj*efF|pQ0)Q3 za<0_gkOs+^1g%{!mNXF6h_`M$a(Trf7$c=(%20YmfDE}b#*Criw2=F(uVH|9Z_5Xy z3nMw8ScGIZ7X4YarR~a$O`}<^^36$2)dfZK3~V>FZt&7R2Ceg#d#7?J8?_d4s$<$+ zpg^q;YubOaxOJ)EiUZEQiK)bRAL>8^0{Vo$&&t1M3gsx%3!&4Onz}7GgP%^H$$L5+`QQp;Y4qR$6k)FDa*b1Kal-JuQ%;IOOS+5 ZL01p~douxq(TboFv_+~H0P(i1k1AEvVGRHP literal 0 HcmV?d00001 diff --git a/scripts/gha-encrypted/auth/google-services.json.gpg b/scripts/gha-encrypted/auth/google-services.json.gpg new file mode 100644 index 0000000000000000000000000000000000000000..dab68319270549a5feae30e2acbcb3299c7ded9c GIT binary patch literal 1014 zcmVL+WaXk?c zq*3kUynx<@M#=c@bk6dFVqn;6)ZBtB)Wwn5fcn1EvV-XPRFLVvqy4LGEuuYRa$lRv zyBsj80xKu49y!e9E+OW02mJ1BMTzC|*|XXG7v5>Bw`*yd6!(*$Hvf`8$_k4M;ev0- z7awGnaBFSRaVznrM}6yo_L<{-FL*wcOI!O0^Ata#RrFkB|?7LItTZv|eOY7wP+w>={~Jf%C(g21cPg zX|Mvab+=EgQBj+U#vETzaXZLXrr_P-UJJsZe7vBTAJO27 z-BteNGd+X?peYpy?U11xL)A5`LifKSDb@VK1TE;YkeI=2e=B^k2jiw69tbOX)?CAX z?AAp(G9!5}F5CK8Z6^6^Ap6^U;gtz~H?#ktH)!%2^~q+7%JL1^o9$={h@dkn+oV)= zEh6r-s#+gMQ8zXGQe@dE)IZbvVXVz8n zKC03CdF4!zxcskORJJQ!t7Qo{9fmJZmkwMN1kMAaHQD(-?(e)$olg1UB~Kx6<(1sJ kR+oCUDSlOJ$ZZ4zWZ!VAr$Sp_hSGH|$scxe{CmA+ApOk* z*AcJ9sh^H-4Y~JV3Ck26vB5BNaqheDd{-KqxxS9G?R<~O&vpSx>P1I(^nw;PczR!k zsFMY7EgTi|*GmA6EXrD)o>OwdCY@iY{h&>B1M^? z;T90c0fXV>`|TfoN)QWJNr+DsAWK8H7G0%&+2c@S5#OyeA>kmb9(alX8ONFnOc&+s z>1n%zgZ$`|4$$H-BQX@}vj*W>$zf~~?Mn7Q(_qE4@ZcL~EX?IzPHK@;Yv7f3(73Yf z3za5ER(%9uG&Va4bwRwIAqi%dBq8?M5+&?v6I@skmF*k*} z?rU{J>>BKpviowaGkUV`)<_S4q^8x^3pkQ+c6LVU7#~ZNF?I-lfLsH8=_HTq8H)TD z;Yr6hYz%`-)R%??jKCW$iMbm3aSM@YdXgqI(}lduq2GRB@Xy2NSk((zni8v$XykUb zw8JLO`AIA52|*#WU15yA+?L$F@bl8zyea!cN`LnHeaHanIDaQ8%mum`UsUx?Nx^sr zKDdv(_*56ScLp?@{(tQEh;J$DY~#4SR%@r z(hek?DkYFR;EPv69{Efcs~{pA#1`Pj%0(?6^g%^C@Fb21BnFF8BqF(c=A$u&ooC)s zbjFHc`gAB*^gXRx9-$n#ZSN5C#eIlgVgwdLqcm*CT1>{H(~wM?-olk~90Sn5!dTho zeOTUEyNv;^raBh_XolvWN$(-yyBIG15u440aPXMWqC5|f9FCXVN|9(wS`hT|;Az>y zs@n;ad+ipmQpP0Gw6Y(Dt+uYwvhJBqQCSFcw4=IT*U7}&y1!$>0wOk?M>GF~kM+)u z@!ME-Kn}_k22-~n1;UrIq6hs`g)e}0p;GDl|1G0-X^Dr?2Pp)?yCiEbtl-0|TzTdk zkZ?b#95c;Hb{UO?Iq(@I{jb7IKvgkux1Q2Q1w7)0gFLHb63S*g&-BOW)4J#DGz1I{ z@4jpWTrg6;qo+7Cdqi@2>y-@^Ahq1_(|#)y-xqV&0p=@jpxcQ4QR+`a6nm`U^*y#L zx#RMkGKkt?aVK3^LqmCjr9Y=?JO%a06tygu@a9;lW}Nl!=1XEkD8KG@Xm>UqJ@&NZ zH1K56y}?TgW4FSK3eHG(y#=7iMyx?zyYB?sSxL%uAp7Q2RU}7H1gU3kn3_|*Jl-|z-TtiD)i~cf_QIF1;C`k6 zE{PCqjgsZ5n&EryV%QAvg37X;v5ektJ4DC%1hb~fnKmKVwXe`bGdw21y7YN)CRam1 z!EG{$hct?=x!w^6PIW%|zV)@!!$%njIkgzgW^%I-4kM=+tvZ(>P9(QA(IEEAQe>Zb BWBC98 literal 0 HcmV?d00001 diff --git a/scripts/gha-encrypted/dynamic_links/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/dynamic_links/GoogleService-Info.plist.gpg new file mode 100644 index 0000000000000000000000000000000000000000..871ee6e1b6d0ffed52db74b79cc38f0bb04b760f GIT binary patch literal 736 zcmV<60w4X14Fm}T0-a>Pk%V-U0sqqJ0gQULn-+z*r~OT~&p>@Ip;(%)zYa_Lj8#!a z*bw+An6v=*wjbxj@N0;LkhyiS=}>KZ1NIe(U~?HHQ5DzF@9lQe%zl9qB$q|_#*_CH z=Z(TytDjxU?w=KNC2V}W(9-18*R{~j%hA%7YuoUggxxIuIS3ZbpiieZ(2onuhM_G1KNZf}sb=#`e&piw;sU)05Bee-KkI(5v$+CPlrTt}^D(_dLpmlG+u zdV3^pNsrqQ&QrxwFfNrt-O3;xRyL4ap>#T-ifDIU3G5v$^8Jo;a3$3SlZ-bv4%jHi z*Ub^TE-?}#OHRgFGQNAZ=N%d^5($um1(+jAdpVK-tRUd_pWKcE3Q*FTnNJ85g-($7 zQcWF+C~C=JH_)6Ut6=T9tv7nTE)#`l;^vRbpc;Qnc)59+?lR%aMO%43X^>5m=j-I=QBP(Zg3DA_)3^+wZR#XHsbf% zSR#7b_?aIrl&N@`w=)&`;MwYB{7oPOz|OJ}e=NEQ{Q)ZZIu7y0tRO~Gp%WwTIlP77 z;I)RJ8Xcm0f@E)R;QqY0c$Q&VuU1UJtq<=f#k{O&PcBKtP>Ig)x{0A=?ILn z5R4Jgk$I`2m{oC>tuEukzzy;#*;gS)dqV9R(+;6pu0YlusFY$vXyh3v)xGjT zA^3$ZcQIM!H{W$Q%go9KAB81=8(ay)dsn;cEZ>v&<4&E{LVI3SQX=boIOd#*tMFG) SzZ_K7y2`7uphu8mqCB-8c5L1N literal 0 HcmV?d00001 diff --git a/scripts/gha-encrypted/dynamic_links/google-services.json.gpg b/scripts/gha-encrypted/dynamic_links/google-services.json.gpg new file mode 100644 index 0000000000000000000000000000000000000000..846543f60e983f1a137e51e0507045d05d1283ce GIT binary patch literal 712 zcmV;(0yq7P4Fm}T0=!ac4)@c#1pm_M0R%J&734OnZvXV#^!SR)4))}YPv{aV{{=)DLjeUF#+jC>>09SBzkk^)ALBo#EFP0)GObqCkRYE zSVnRoR`>BI4;$0_mU8)iH{{=k|~lmu8vN1O*D47 zgK@Mqx6E`%cBbZIYGaCsP!8q@dx*c@`ZovCtA7zf5j3LLrqJ~JAuoj4DOnF9 z17)4Ip7wJ3k^>@58&?OxBvku;%UfVO8}jI1G8~w<5Ky+a?9MlNf?2iCkr^Qv4~dv`c@hq4?aWM!-=pM`&=r=nQ?BG0_qZ|*1B^$5Fv#BvPoC}>#1}z`l^Ny z3xsc3>rVtnz%vK06b6icE(M$+ON^!nnWdlAD843Yo1o-hAa`4Oo$Oy3ZXeI42K^LF ubm?XGZzX5!($>B!R4x@>1V+ZJtXoIH$qYp!*P95aNyp?RgcLU{(Zi>x1zpJi literal 0 HcmV?d00001 diff --git a/scripts/gha-encrypted/firestore/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/firestore/GoogleService-Info.plist.gpg new file mode 100644 index 0000000000000000000000000000000000000000..15ce08669627292013ee908e87fac31acaff9eef GIT binary patch literal 610 zcmV-o0-gPg4Fm}T0xc2w(rnNZ1pm_M0ov7uKoVB}O2oLRGmQ|u6O0Fa->Q!HM!sKL zcj=Ua)ec_!&!8yf4x#T^0@LcL|7Y^6d=5O*7wE8nn0`m-$0zS2n$GyuIr#buX(P56zqFy{+8cj-^nm z7Hr`-^1Ib|&hdg`jqOnMzS{wJLETZv)ILql7fJ4G8Y9sm3Kw#ZXk`z*0p=Gz{^_Q9 zD6XXqLvp3{QB#$}{p)qKRF5EGv)^rRw>Y3U!k43tVFI1<>U=FZ>ZIY#%VNTF)W6TA zMy&V^A7JF3Nt+PflxJa$K)p%xXxfM13>}@#tsyVPUmcW(m*5LBWH}HWK2wMoi~!i< zX%*|jXBuPpnwyYnEv{OZYt*7qD_o;^i+1o4(KPIl`@F!S_hoFWQ*$1>XACe|Q}8e+ zmtW@+Pbu$gS0F4zJi|Ft@1goj7YKAH>34mCp_YNpQ_Rwso$l$=fti$RO9exDwpXZ- zw+Z4>8m5|Kv#N45#nqmb(xNqQd=d-tj7nkf&BzrkB-3CID;WU-PLjstJGpfU5}SaV z;gxqdeulvxNduT_2~RMoEcXPVpu9Nt4t|QVPS?YVbKP9h!_G7~ev%)APM8n6o&Fd0 zfyrWrZYQl4kWTL|qoBhtQ0%<~HckpxK2&C}b?%>)!PE{X(xCeaGpz0V47jqZSlHYr w$ffhj1DuNqC%2YWTH+>#c<2nOvA-Bxn>ei(bn*{vGHYAZx-li$$u9-F3)^EXtpET3 literal 0 HcmV?d00001 diff --git a/scripts/gha-encrypted/firestore/google-services.json.gpg b/scripts/gha-encrypted/firestore/google-services.json.gpg new file mode 100644 index 0000000000000000000000000000000000000000..9067b0d5720e88b7e5627be95bb7897e258cf234 GIT binary patch literal 534 zcmV+x0_pvX4Fm}T0{*~q9{iWGv;WfR0s0HDOIVBGy4RwLz=KOkGZl<#eRes!xNxZH zEr9T5qJao+Z+qJD_H3R37DAFN~B8iJrg!)5d;nTvU>cz{{a0p>{2E*r1Ry~k8yXT?!E)gV`d1X za}VXAa$QY6m-fVmlmyK)k?2j_j2?KQH}#N-@~-=wNAMpM9GzBRoBg;PaoxaJG+u)MOH z!+mlgVZ7+2%gSzc?S?Ap%;AhZoP%EO9-8$w(|H~~ieCi2Kwdc~vPMKm({%&y6#3!q zL_g#P==9VHc5J6~FH1|Xu374+o7WTwz}lk~zFUF^yjjUDFz@JP2i6gQ5@7h{Vs)CGwSuv8y0yJg!xEF!H6d5b&yxvHMdm12%;^qJ?Ajpf+fxN2SCg zZ&-!)Z^`wH7+C@2MsFn#yLG``)2k1~e;V%pRh=dHai9KsMyXNhqZiFkm$-Q3lG+K2 z+^m;&ONh=g6DQ@3GQ{V6II|y)589iPvtn_D<3P1x->V=wPLyt=ALGGkur6H{HO=Ji6AzGA!@h|n;F7Sw&dU^R*x$Ll>dfA+*;))2Y)!E-z%sg$L?t{)enbUV?& z`hSA57Z@*U!wC{Y%%v3%h!zk>YxL7Z3w2-%5gEcEWTUFQh$Xw)VHuZ@6BjZDyyh&$;=UV%*9$kt6 literal 0 HcmV?d00001 diff --git a/scripts/gha-encrypted/functions/google-services.json.gpg b/scripts/gha-encrypted/functions/google-services.json.gpg new file mode 100644 index 0000000000000000000000000000000000000000..41eed7b7e5c5ae888e7b53b148e46c2935ae3802 GIT binary patch literal 850 zcmV-Y1Figw4Fm}T0<5<~zsUPs`Tx@C0g9{?M|q!2!(7*n{|}12)Isp^j$OFXkE4=I z5Sz>kwv`%#X)qzKTSVergpNoTNMu*U(|=K30aZ&T>+cv(q;@;8*>lyC=!3`cmuwN^u(~OVmAGK?y({HVgkh>ccYX(j{AShDmYSxu_R_OmaxO!U9=oDD9hf!~lU`^g4cfYn*WZ*k>s-@jTs;-<2e)0rQ6$*9EYj{}dg;ec8X5@t=6 z=r%5ID0`_n@XJTIcM1a*kWhQ=FBrhQHN1&0@<=o{vC5qI1~l_`+2=kGIMN)RS#R3z z$xTBx-~Qp}z<(JMTQl{QKzIWT(O`S2LJ(U^a z*Z$XxwsvZCBn=3%IPbatNFZVoWa^Qfp_b3Q7_Xm5c??~obpZUHoPRJ}ah<;WMDJqn z!x3q2rck+`M3Xiq_?C3~NJg-kAy9vsh8aVs?7}Slp~R(vh2ude;vHR3Dyg%PlxYyY zp@c=X~7{>A-v>tpsvfc(4}wdaA7;5IP)&gyl24ZypZ_f*w@{ zPG(Wdu5Vqm>_ZYJrkV}OPMCvOnM=az9CGeGv5GN-`z_0uhj&A9U0;f+gWxrt7>46p cn&8@9NHxUxA72=_ZY(Z2$lO literal 0 HcmV?d00001 diff --git a/scripts/gha-encrypted/gma/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/gma/GoogleService-Info.plist.gpg new file mode 100644 index 0000000000000000000000000000000000000000..58896342a9fe3079458eb8aa63a9e806e139d62d GIT binary patch literal 672 zcmV;R0$=@%4Fm}T0_%(Zwo`_NuK&{M0fc3b`Gu6#?+=rYlG&2v>SbN1s>zvyX}l#I z8j1Vm4I$k9@A8oRrn0q!CqDY?S1kilKw9M(bN+vFy@RA?O(K290W&ez+sgu$mdk=muyM$D6neiHbIBQkqmGzi(akogx z#+3L0oIAG3zErL(tN8;f(XbBq4Fw3zJRk>+BhhHuPFo8a|weImAK9D5a>qRDK!X`y_2xCziolhO?|G zP_C?h%S2(VBU7>ci6Q=!bZkjqQQ?CcVN)2cfWzeyv4!}PRO|>jkKhLu)>M&1cO1}> z9R+cbFf-W#wE!Gk-nheNj;Zb`h@jOLmT3@rTwdXI7~>!{){q+aofdyoKhAYJh7{)& zVa^db&^D=$E#%?8!Gg2a8m<_TM5ALeV>Y#JT4KCxRUCF{5F;%fy=fX>JKd6bwIB GtRThF2}+Rw literal 0 HcmV?d00001 diff --git a/scripts/gha-encrypted/gma/google-services.json.gpg b/scripts/gha-encrypted/gma/google-services.json.gpg new file mode 100644 index 0000000000000000000000000000000000000000..b118a4cb346e8149418cf8fa86ab5a616d648a3e GIT binary patch literal 1002 zcmVFe&;$LD*U2V6jbw7A0UT^9NN8WQ= zL!01j1k_|^rv{=>;&kSH`%sP)Jy8+TO4R42x+jJ^{Q!FNY^pj@%BNQl3hSE>k?G?o zFuv2|$LYzUe{;GREk-smY>;EG@<+uV{)giF;8tP_h+-w#(wV8RWYhq3$M^RkS68PT zu$KB_Hrp&Y^TP3m+spKMuk_zU#q6_0KMP$R$o zwqE-{!H)SNDumqbBP1ngESQYS3Rgw9gE)*eLl2b~0l%50U*(83nS{7qXGe>Crz4w$ z@=i(ek~StY#h7hX?gL0)y{8=ZxXPflsJMJ&29Y-z7WG4&vI-R6l5n3E{~NaTEcdb! zs|*VCeRf#XKF_L@9B6As!50I`ahtj*yb8U7Ma3xl+gp_@7(NvTv)=~4YIVNnT@)&1 z)<5pNDkgT+yM69s*%Qg5SbcaSA!VWUuO2ZtFV75jjc~lKPM;)uRw|*%0L}5R5J@?%!9@* z{~04Fr5G@3^4mufbyGeaB>+-i@(KBkP*-S;oRSgJ9AijFhJ!$66D)<N6-G#<{<}U;MLm~VQ7gG2cXwSZ$Yc@%Ho6;OE*_DK+q4Xg{xmEBx`>Ug3!?V8 z_&qr0#OkxP4^l!&F*-MFswC*V#eDlIZAa2IpO>Awj&iYgt+K4j+BHKD@JFri)DtJj zcx-VH-Q|!NYo0ebe%T{?@QE>z*y4xFB@yCYQG`B=$8jixSNHWY(ng}IQF?K9K0ngd zW;_sIr8*^J&W|b8@Y`bjXTVS}+TPxGwOZXBMq;L|9qah*s>f(e>@k(+Cl;R;mpkM0 z{%YydGK@kl`8padeC6Ma`@0SG>Yp#+g-s6wp8J#2Y_sLBV;_Q@p4@bi?D{CW20|W$p^>asU7T literal 0 HcmV?d00001 diff --git a/scripts/gha-encrypted/messaging/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/messaging/GoogleService-Info.plist.gpg new file mode 100644 index 0000000000000000000000000000000000000000..f8581e8822441373c038c20ddd7ce20b58e81c76 GIT binary patch literal 692 zcmV;l0!#gj4Fm}T0!Qr(8PpM5Q~%QG0iufd%S9@{ip$Prq%TT$>!08&@sQV14q?--w70#e3P*g0Fgn{F@t1QMLrUwdX9@RK%s*F<-PoM{#L!|q-MU$lj)v-t?i6NW z16$JzO$57WEn}f0tl2b|7fM!6G1w?4JtfM14uluB{JM`Gclo3CSgJ%`@(i3 z$3R3FD^_52ESBC6U58IY;8aALAu8M}MHdg94Ltq6KRosurqpqw!#B zaI6MxLL+j}M*;wg>+smq8b&YZCAk2Ks4Bx^EL4#A%@Px2l`AoQ;d!qy~V znsI<3LX_-OxBjoQs1j;NcOzFMEUvI172wL$4svH`;_T zC(C|(rC#WaZwHQubwrUw$Mn@ZXeXq<``kE=oAMgUIm9ij@&L;y?FePfLYm%I6u~ZcE9k$avopDHeC+k!Gf0{^@$L&F)@1*Gj2{gIZ{6E@N{4v$YS;%Q!*MF@L*MN{$=c55>HY1-LER12MGAZ;_&6AouH}hQRXz(goDsP8S{33 z1BD}81eO)Daae5AmPRUy+6a0`hqO^c&Sif^&C9^-=m1UMfnZ0;=7=ME=SKzHE^&6- zwG~-V*d5_5Wv{PZ6zEvmkOtXsO-=hY1_qcFKt3SPs5>}XKUj@Jf^*d+)BYF8C@6UL+3Dg;j5V$fss|w2>}y@Ca3KIW#&Fi&N)c2UP+pSLc7f- zr;{M(n#C3Jzr1q#qn;a>_|P_6IKVT^y-5W;E9m&|w7Zf4BP*-(biYdQD=B?joPef& z@ItJN^I1Y*{!cMDlPBKSMRpwcn_|z>YaPa0E~Vedr4`cICx98(?Scayu{`(~G7=r=)+GI}i!`gNZiPViR7G0kb}UNA|MOx$QZ zeOnvxg-j(m$vUm(8pvR!YhzEvR2mvacg=XFb(U4sLs^Qe3M$KVR|a8LP+H#}!9SBi zQ0r8NC$8JPw3RIqnApv&r;QuhGP65x9R2dP;~V#G(b9ZZ>Y^8DTOYpadqW}@kOoh@ zA3x%P+4WlIAAqHI6z%#5odl#>Oh>h&cRMu#cDraU)7=hIUP2xG*oW{GQB2U`!=;&odZ=Bl62`TF)_{9k;n(cXE l?=3pxlZ=9HYOa1P=pe1Y+YnnzXD&){J}f3+zbi0-yi6L{yQ}~J literal 0 HcmV?d00001 diff --git a/scripts/gha-encrypted/remote_config/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/remote_config/GoogleService-Info.plist.gpg new file mode 100644 index 0000000000000000000000000000000000000000..67535e90eb6aab32f1b9456bff223a7de20d5302 GIT binary patch literal 720 zcmV;>0x$iH4Fm}T0=^8^*~I=}N&nL60rw$}bMwNO=&7@TbiLg|!F%^?VFL9!Ij|Yv zlId#GD!R4GB(k9ZL087&vLAiP!4VzDRV18~b7ccc`es=y>ptcZeA0wNr*I@@j(?($ zB>qY{E*litsZJOk=saq-vTjjR;P^+1qA#zhAh(1QX56xThw>DKzn5#6q2;)!BQ7iN z8K#x*B>oTkvtes%mUp(L$N+R?%XH@?!r4$rlPdkXqiS+Xdb}vrs03LQp_3CRG^Ub9 z%4R4_v?sde90iAAVVKOSrRyJkACGRuasEoO7PzF?z~3-IGNdMtIXm)H+cg!}6$7vq zu#5J(6b}`D8v}*!`xI)_pf^5<6j1pGWz9yzw#J(P(om_g%`KhtS@{2!Dp7QI+DEIc6`TuCEL zFfcSd={;8v-+^wJ@0T$|Na|7`9j?gRa%!Gi1ey+mb-Yn$cLpHGUU9Q;+Zf}}iO;or z`Sudx@%P>LU8RJnbQ^V+hCFjRar?_G=d`9;CXM)4e-~-)F!U*k&K`73 z#i+^z{_resHsWoY1T6g^T+9x%Z*CnQC-KO3mw(7zLZ0{H_Y@4tTNp)K%Vi>#K#saZ`(5 zfG52v4akYo4e=E|q>atMcp^y+v09yf&{g8<8DSKx)>B3b4hlGH(dAUJ!?ze9TH*rO zq;J52BtOup$i$JVvw?c?)MST6igt!>A1bdU_F?aH+Rc>r_hezs4V+4=%et0kig@49 z)bjciZ(5@3#}*VA40yO;4$8+}2Z|8dA-P7+FIvz4xJfWco~B zn7;Q{wI2%&|5Vd1g7Q%_lQsYt0Q{uX55z1<7ptSDh*bsP7;5U+bCWN1kL>~Mb0nw2 zN+6oV+s zwCMVhU6tp5opfCTVZaEiR~AD~Z5SEAY?-@1(tgc3A}U@wduJxb`Ay3eg`ltGyu$nU zy`RHPqMm-Q&z$UvM(mW4!6M+=koY*J9)J6q{-!FddT+^ap{WaM$3*!mFi{jiY|#yg z^EUAJi|XE8wLx3-t4BoKBq6um;|aRgXUhs|nH}$nXorEcBF?W`HWtZ%;<7bmcsaT!$ek#vqx0` z|EM@zba;246$iSz3WlTtQ89EFozI+CQ4i7NQg00PZsAezumz~8oT$YHyVS#M+B;Zy zB$JL+ktITHorf|}GLKI&6 zuiZ*29RM;*19IiNE`eBJE@XyHv3y^6408JGL&J)kitFVGj$E-giszDeASqUmTMzFQ zh>&cDFiBj03LP!u$9G@^0#OW!ymA;nd$UNr8dqP5a=uC{VmXC8C7IIpg}nO$Ju=c{ zB~sfm^v)mya=8)D!to|y>^0zyUb-R}8JdBH>?kKWgpSQ<1ODF<2d|-_|9TEO1 literal 0 HcmV?d00001 diff --git a/scripts/gha-encrypted/storage/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/storage/GoogleService-Info.plist.gpg new file mode 100644 index 0000000000000000000000000000000000000000..de4c9c060ef900c64209cf477719da2b2b6e3847 GIT binary patch literal 682 zcmV;b0#*Ht4Fm}T0v!pkCXcJ+#sAXj0Z@8>?Hh4R@FkB5D3Uypi7`t7BSeCWHt?KO zg8Fy%ocVvr@D@~SMZLWa(L=^0g*WAmz3v$JWvi(defSRf7zRvQ+x;eBLu`JUOPSMw zn*TK-xVS+nChk}-XFq`yMa6?I@{k$$kq zza1!Pd~g&%NCJ-ze#J97&Eq2prlN)5-PT_yq0WO6HJW<-_3zlltL*I^x;?p^Fbv!K zG~Qno?;uL*Yc{`c{-)$ay}~6c4ty}{$kP3-i!2NkwD`~IW(XYILwijf5x9X8GO&$= zQ%&nV%m3c!?1>{`v7FyZ<#AW=DbxwgIUm1IAg|NdsTsih#F|x_jy0_C{TFM93r&mb zeg}TnkolFtEPvZvdPx5#D$qRGSU_5+S=yx$zsDwJ5`yW0lxk?mv(;$FsxsY(vTYR5 z7VPo5y&B%{tN_(W6=m{%xM$y-iE`=aCM5&*3PFm&+lR6K1io;UFD3Sy&V00Xu;M;M z650@GYf*prNbc3Ek1OcQm>(%l?rreoTwM_X0ICasoJUx;K6mf7qh@=Z|ACz`6(RC) z_p>Q-9LF*fV-?81bEkBMLFUX0@szZw)0a8};;D`;Q2|U!>X$$3wDJ?kUKDvumBDNX ze`2dhU6N3Mp9JX6339M;RO4Y?A#Waw6#GN%c5s@e+%O31FNCY8z$6_Va4>D@oBB^r Q@RD4!kXrp;=I5_ED>va;vj6}9 literal 0 HcmV?d00001 diff --git a/scripts/gha-encrypted/storage/google-services.json.gpg b/scripts/gha-encrypted/storage/google-services.json.gpg new file mode 100644 index 0000000000000000000000000000000000000000..1393dce3671f22a200dcc706133d0b4f95f23b5a GIT binary patch literal 816 zcmV-01JC@74Fm}T0+C7+B&Suz`~TAE0fHW-zaTRl)Of`7Ux-~>I{cifK?&2Cmvoph zVeX}Y2=EdIRM6+7s%-E;SPq~+L|oB#|GH6KI>Z+}JN#ayQovGuJg>igmM8$SD_rAj zy}5T+JM%kx4Ob`Cio}}uNR@u{>WS1rleQk_>GZuRp>2cXkr2#-h+O;E@QYwR5}81< zvfhaN$GE-*ATt67HE4i5L+8PImT7=M9~yX)Dyi}!t7(fumWFTDhJfvMdn;R{77Z3= z%sAFx`Qt zqW2YZ2jy7db)!C&hI3#aJ>%>>*-X~$YL9^fDFDYH^5?WQw#ON=5E=RW$>#XXL})YX z&SrDEOL}R;m0>YEC$iaM@EHt`O@3F|Y$Cp}t$jKtGu&^6Tm?ON%$~5)y;-MpXS~eX^3ptoq^@303CA))iMYnA2!@j`?`p=u#P8R0b)9@a9svQy`21NY6oNM+aUs)mO z{!$JyC$Ze9+$EJ literal 0 HcmV?d00001 From 84c6f1e7d0140de999823739e2c7bd701125e7ca Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Fri, 22 Jul 2022 08:37:54 -0400 Subject: [PATCH 28/57] Add CI Android targets (#105) Adds a CI Workflow to build the testapps against the publicly available packaged SDK. --- .github/workflows/android.yml | 205 ++++- analytics/testapp/build.gradle | 2 +- dynamic_links/testapp/build.gradle | 2 +- .../build_scripts/android/install_prereqs.sh | 75 ++ scripts/build_scripts/build_testapps.json | 183 +++++ scripts/build_scripts/build_testapps.py | 718 ++++++++++++++++++ scripts/build_scripts/config_reader.py | 139 ++++ scripts/build_scripts/python_requirements.txt | 2 + scripts/build_scripts/utils.py | 94 +++ scripts/build_scripts/xcodebuild.py | 119 +++ scripts/restore_secrets.py | 186 +++++ 11 files changed, 1718 insertions(+), 7 deletions(-) create mode 100755 scripts/build_scripts/android/install_prereqs.sh create mode 100644 scripts/build_scripts/build_testapps.json create mode 100644 scripts/build_scripts/build_testapps.py create mode 100644 scripts/build_scripts/config_reader.py create mode 100644 scripts/build_scripts/python_requirements.txt create mode 100644 scripts/build_scripts/utils.py create mode 100644 scripts/build_scripts/xcodebuild.py create mode 100644 scripts/restore_secrets.py diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index af35d584..d8876f55 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -1,14 +1,209 @@ -name: Android builds +name: Android Builds on: + schedule: + - cron: "0 9 * * *" # 9am UTC = 1am PST / 2am PDT. for all testapps except firestore + pull_request: + types: [opened, reopened, synchronize] workflow_dispatch: inputs: apis: - description: 'CSV of apis whose quickstart examples we should build' + description: 'CSV of apis to build and test' + default: 'admob,analytics,auth,database,dynamic_links,firestore,functions,gma,messaging,remote_config,storage' + required: true + +env: + CCACHE_DIR: ${{ github.workspace }}/ccache_dir + GITHUB_TOKEN: ${{ github.token }} + xcodeVersion: "13.3.1" # Only affects Mac runners, and only for prerequisites. + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true jobs: - build: + check_and_prepare: runs-on: ubuntu-latest + outputs: + apis: ${{ steps.set_outputs.outputs.apis }} steps: - - name: noop - run: true + - id: set_outputs + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + apis="${{ github.event.inputs.apis }}" + else + apis="admob,analytics,auth,database,dynamic_links,firestore,functions,gma,messaging,remote_config,storage" + fi + echo apis: ${apis} + echo "::set-output name=apis::${apis}" + + build: + name: android-${{ matrix.os }}-${{ matrix.architecture }}-${{ matrix.python_version }} + runs-on: ${{ matrix.os }} + needs: [check_and_prepare] + strategy: + fail-fast: false + matrix: + os: [macos-12, ubuntu-latest, windows-latest] + architecture: [x64] + python_version: [3.7] + steps: + - name: setup Xcode version (macos) + if: runner.os == 'macOS' + run: sudo xcode-select -s /Applications/Xcode_${{ env.xcodeVersion }}.app/Contents/Developer + + - name: Store git credentials for all git commands + # Forces all git commands to use authenticated https, to prevent throttling. + shell: bash + run: | + git config --global credential.helper 'store --file /tmp/git-credentials' + echo 'https://${{ github.token }}@github.com' > /tmp/git-credentials + + - name: Enable Git Long-paths Support + if: runner.os == 'Windows' + run: git config --system core.longpaths true + + - uses: actions/checkout@v2 + with: + submodules: true + + - name: Set env variables for subsequent steps (all) + shell: bash + run: | + echo "MATRIX_UNIQUE_NAME=${{ matrix.os }}-${{ matrix.architecture }}" >> $GITHUB_ENV + echo "GHA_INSTALL_CCACHE=1" >> $GITHUB_ENV + + - name: Setup python + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python_version }} + architecture: ${{ matrix.architecture }} + + - name: Add msbuild to PATH + if: startsWith(matrix.os, 'windows') + uses: microsoft/setup-msbuild@v1.0.2 + + - name: Cache NDK + id: cache_ndk + uses: actions/cache@v2 + with: + path: /tmp/android-ndk-r21e + key: android-ndk-${{ matrix.os }}-r21e + + - name: Check cached NDK + shell: bash + if: steps.cache_ndk.outputs.cache-hit != 'true' + run: | + # If the NDK failed to download from the cache, but there is a + # /tmp/android-ndk-r21e directory, it's incomplete, so remove it. + if [[ -d "/tmp/android-ndk-r21e" ]]; then + echo "Removing incomplete download of NDK" + rm -rf /tmp/android-ndk-r21e + fi + + - name: Update homebrew (avoid bintray errors) + uses: nick-invision/retry@v2 + if: startsWith(matrix.os, 'macos') + with: + timeout_minutes: 10 + max_attempts: 3 + command: | + # Temporarily here until Github runners have updated their version of + # homebrew. This prevents errors arising from the shut down of + # binutils, used by older version of homebrew for hosting packages. + brew update + + - name: Install prerequisites + uses: nick-invision/retry@v2 + with: + timeout_minutes: 10 + max_attempts: 3 + shell: bash + command: | + scripts/build_scripts/android/install_prereqs.sh + echo "NDK_ROOT=/tmp/android-ndk-r21e" >> $GITHUB_ENV + echo "ANDROID_NDK_HOME=/tmp/android-ndk-r21e" >> $GITHUB_ENV + pip install -r scripts/build_scripts/python_requirements.txt + python scripts/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" + + - name: Download C++ SDK + shell: bash + run: | + set +e + # Retry up to 10 times because Curl has a tendency to timeout on + # Github runners. + for retry in {1..10} error; do + if [[ $retry == "error" ]]; then exit 5; fi + curl -LSs \ + "https://firebase.google.com/download/cpp" \ + --output firebase_cpp_sdk.zip && break + sleep 300 + done + set -e + mkdir /tmp/downloaded_sdk + unzip -q firebase_cpp_sdk.zip -d /tmp/downloaded_sdk/ + rm -f firebase_cpp_sdk.zip + + - name: Cache ccache files + id: cache_ccache + uses: actions/cache@v2 + with: + path: ccache_dir + key: dev-test-ccache-${{ env.MATRIX_UNIQUE_NAME }} + + - name: Build testapp + shell: bash + run: | + set -x + python scripts/build_scripts/build_testapps.py --p Android \ + --t ${{ needs.check_and_prepare.outputs.apis }} \ + --output_directory "${{ github.workspace }}" \ + --artifact_name "android-${{ matrix.os }}" \ + --noadd_timestamp \ + --short_output_paths \ + --gha_build \ + --packaged_sdk /tmp/downloaded_sdk/firebase_cpp_sdk + + - name: Stats for ccache (mac and linux) + if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') + run: ccache -s + + - name: Prepare results summary artifact + if: ${{ !cancelled() }} + shell: bash + run: | + if [ ! -f build-results-android-${{ matrix.os }}.log.json ]; then + echo "__SUMMARY_MISSING__" > build-results-android-${{ matrix.os }}.log.json + fi + + - name: Upload Android integration tests artifact + uses: actions/upload-artifact@v3 + if: ${{ !cancelled() }} + with: + name: testapps-android-${{ matrix.os }} + path: testapps-android-${{ matrix.os }} + retention-days: ${{ env.artifactRetentionDays }} + + - name: Upload Android build results artifact + uses: actions/upload-artifact@v3 + if: ${{ !cancelled() }} + with: + name: log-artifact + path: build-results-android-${{ matrix.os }}* + retention-days: ${{ env.artifactRetentionDays }} + + - name: Download log artifacts + if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }} + uses: actions/download-artifact@v3 + with: + path: test_results + name: log-artifact + + - name: Summarize build results + if: ${{ !cancelled() }} + shell: bash + run: | + cat build-results-android-${{ matrix.os }}.log + if [[ "${{ job.status }}" != "success" ]]; then + exit 1 + fi diff --git a/analytics/testapp/build.gradle b/analytics/testapp/build.gradle index 6928009e..7b5d686e 100644 --- a/analytics/testapp/build.gradle +++ b/analytics/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.3.3' classpath 'com.google.gms:google-services:4.0.1' } } diff --git a/dynamic_links/testapp/build.gradle b/dynamic_links/testapp/build.gradle index bf4eff96..49bcf71b 100644 --- a/dynamic_links/testapp/build.gradle +++ b/dynamic_links/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.3.3' classpath 'com.google.gms:google-services:4.0.1' } } diff --git a/scripts/build_scripts/android/install_prereqs.sh b/scripts/build_scripts/android/install_prereqs.sh new file mode 100755 index 00000000..f5d6efe9 --- /dev/null +++ b/scripts/build_scripts/android/install_prereqs.sh @@ -0,0 +1,75 @@ +#!/bin/bash -e + +# Copyright 2022 Google LLC + +if [[ $(uname) == "Darwin" ]]; then + platform=darwin + if [[ ! -z "${GHA_INSTALL_CCACHE}" ]]; then + brew install ccache + echo "CCACHE_INSTALLED=1" >> $GITHUB_ENV + fi +elif [[ $(uname) == "Linux" ]]; then + platform=linux + if [[ ! -z "${GHA_INSTALL_CCACHE}" ]]; then + sudo apt install ccache + echo "CCACHE_INSTALLED=1" >> $GITHUB_ENV + fi +else + platform=windows +fi + +if [[ -z $(which cmake) ]]; then + echo "Error, cmake is not installed or is not in the PATH." + exit 1 +fi + +if [[ -z $(which python) ]]; then + echo "Error, python is not installed or is not in the PATH." + exit 1 +else + updated_pip=0 + if ! $(echo "import absl"$'\n' | python - 2> /dev/null); then + echo "Installing python packages." + set -x + # On Windows bash shell, sudo doesn't exist + if [[ $(uname) == "Linux" ]] || [[ $(uname) == "Darwin" ]]; then + sudo python -m pip install --upgrade pip + else + python -m pip install --upgrade pip + fi + pip install absl-py + set +x + fi +fi + +if [[ -z "${ANDROID_HOME}" ]]; then + echo "Error, ANDROID_HOME environment variable is not set." + exit 1 +fi + +if [[ -z "${NDK_ROOT}" || -z $(grep "Pkg\.Revision = 21\." "${NDK_ROOT}/source.properties") ]]; then + if [[ -d /tmp/android-ndk-r21e && \ + -n $(grep "Pkg\.Revision = 21\." "/tmp/android-ndk-r21e/source.properties") ]]; then + echo "Using NDK r21e in /tmp/android-ndk-r21e". + else + echo "NDK_ROOT environment variable is not set, or NDK version is incorrect." + echo "This build recommends NDK r21e, downloading..." + if [[ -z $(which curl) ]]; then + echo "Error, could not run 'curl' to download NDK. Is it in your PATH?" + exit 1 + fi + set +e + # Retry up to 10 times because Curl has a tendency to timeout on + # Github runners. + for retry in {1..10} error; do + if [[ $retry == "error" ]]; then exit 5; fi + curl --http1.1 -LSs \ + "https://dl.google.com/android/repository/android-ndk-r21e-${platform}-x86_64.zip" \ + --output /tmp/android-ndk-r21e.zip && break + sleep 300 + done + set -e + (cd /tmp && unzip -oq android-ndk-r21e.zip && rm -f android-ndk-r21e.zip) + echo "NDK r21e has been downloaded into /tmp/android-ndk-r21e" + fi +fi diff --git a/scripts/build_scripts/build_testapps.json b/scripts/build_scripts/build_testapps.json new file mode 100644 index 00000000..7dc1d078 --- /dev/null +++ b/scripts/build_scripts/build_testapps.json @@ -0,0 +1,183 @@ +{ + "apis": [ + { + "name": "admob", + "full_name": "FirebaseAdmob", + "bundle_id": "com.google.ios.admob.testapp", + "ios_target": "testapp", + "tvos_target": "", + "testapp_path": "admob/testapp", + "frameworks": [ + "firebase_admob.xcframework", + "firebase.xcframework" + ], + "provision": "Google_Development.mobileprovision" + }, + { + "name": "analytics", + "full_name": "FirebaseAnalytics", + "bundle_id": "com.google.ios.analytics.testapp", + "ios_target": "testapp", + "tvos_target": "", + "testapp_path": "analytics/testapp", + "frameworks": [ + "firebase_analytics.xcframework", + "firebase.xcframework" + ], + "provision": "Google_Development.mobileprovision" + }, + { + "name": "auth", + "full_name": "FirebaseAuth", + "bundle_id": "com.google.FirebaseCppAuthTestApp.dev", + "ios_target": "testapp", + "tvos_target": "", + "testapp_path": "auth/testapp", + "frameworks": [ + "firebase_auth.xcframework", + "firebase.xcframework" + ], + "provision": "Firebase_Cpp_Auth_Test_App_Dev.mobileprovision" + }, + { + "name": "database", + "full_name": "FirebaseDatabase", + "bundle_id": "com.google.firebase.cpp.database.testapp", + "ios_target": "testapp", + "tvos_target": "", + "testapp_path": "database/testapp", + "frameworks": [ + "firebase_auth.xcframework", + "firebase_database.xcframework", + "firebase.xcframework" + ], + "provision": "Firebase_Dev_Wildcard.mobileprovision" + }, + { + "name": "dynamic_links", + "full_name": "FirebaseDynamicLinks", + "bundle_id": "com.google.FirebaseCppDynamicLinksTestApp.dev", + "ios_target": "testapp", + "tvos_target": "", + "testapp_path": "dynamic_links/testapp", + "frameworks": [ + "firebase_dynamic_links.xcframework", + "firebase.xcframework" + ], + "provision": "Firebase_Cpp_Dynamic_Links_Test_App_Dev.mobileprovision" + }, + { + "name": "functions", + "full_name": "FirebaseFunctions", + "bundle_id": "com.google.firebase.cpp.functions.testapp", + "ios_target": "testapp", + "tvos_target": "", + "testapp_path": "functions/testapp", + "frameworks": [ + "firebase_auth.xcframework", + "firebase_functions.xcframework", + "firebase.xcframework" + ], + "provision": "Firebase_Dev_Wildcard.mobileprovision" + }, + { + "name": "gma", + "full_name": "FirebaseGma", + "bundle_id": "com.google.ios.admob.testapp", + "ios_target": "testapp", + "tvos_target": "", + "testapp_path": "gma/testapp", + "frameworks": [ + "firebase_gma.xcframework", + "firebase.xcframework" + ], + "provision": "Google_Development.mobileprovision" + }, + { + "name": "messaging", + "full_name": "FirebaseMessaging", + "bundle_id": "com.google.FirebaseCppMessagingTestApp.dev", + "ios_target": "testapp", + "tvos_target": "", + "testapp_path": "messaging/testapp", + "frameworks": [ + "firebase_messaging.xcframework", + "firebase.xcframework" + ], + "provision": "Firebase_Cpp_Messaging_Test_App_Dev.mobileprovision" + }, + { + "name": "remote_config", + "full_name": "FirebaseRemoteConfig", + "bundle_id": "com.google.ios.remoteconfig.testapp", + "ios_target": "testapp", + "tvos_target": "", + "testapp_path": "remote_config/testapp", + "frameworks": [ + "firebase_remote_config.xcframework", + "firebase.xcframework" + ], + "provision": "Google_Development.mobileprovision" + }, + { + "name": "storage", + "full_name": "FirebaseStorage", + "bundle_id": "com.google.firebase.cpp.storage.testapp", + "ios_target": "testapp", + "tvos_target": "", + "testapp_path": "storage/testapp", + "frameworks": [ + "firebase_storage.xcframework", + "firebase_auth.xcframework", + "firebase.xcframework" + ], + "provision": "Firebase_Dev_Wildcard.mobileprovision" + }, + { + "name": "firestore", + "full_name": "FirebaseFirestore", + "bundle_id": "com.google.firebase.cpp.firestore.testapp", + "ios_target": "testapp", + "tvos_target": "", + "testapp_path": "firestore/testapp", + "frameworks": [ + "firebase_firestore.xcframework", + "firebase_auth.xcframework", + "firebase.xcframework" + ], + "provision": "Firebase_Dev_Wildcard.mobileprovision", + "minify": "proguard" + } + ], + "apple_team_id": "REPLACE_ME_TEMP_INVALID_ID", + "compiler_dict": { + "gcc-4.8": [ + "-DCMAKE_C_COMPILER=gcc-4.8", + "-DCMAKE_CXX_COMPILER=g++-4.8" + ], + "gcc-7": [ + "-DCMAKE_C_COMPILER=gcc-7", + "-DCMAKE_CXX_COMPILER=g++-7" + ], + "gcc-9": [ + "-DCMAKE_C_COMPILER=gcc-9", + "-DCMAKE_CXX_COMPILER=g++-9" + ], + "clang-5.0": [ + "-DCMAKE_C_COMPILER=clang-5.0", + "-DCMAKE_CXX_COMPILER=clang++-5.0" + ], + "VisualStudio2015": [ + "-G", + "Visual Studio 14 2015 Win64" + ], + "VisualStudio2017": [ + "-G", + "Visual Studio 15 2017 Win64" + ], + "VisualStudio2019": [ + "-G", + "Visual Studio 16 2019" + ] + } + } diff --git a/scripts/build_scripts/build_testapps.py b/scripts/build_scripts/build_testapps.py new file mode 100644 index 00000000..3caf85f0 --- /dev/null +++ b/scripts/build_scripts/build_testapps.py @@ -0,0 +1,718 @@ +# Copyright 2022 Google LLC +# +# 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. + +r"""Build automation tool for Firebase C++ testapps for desktop and mobile. + +USAGE: + +This tool has a number of dependencies (listed below). Once those are taken +care of, here is an example of an execution of the tool (on MacOS): + +python build_testapps.py --t auth,messaging --p iOS --s /tmp/firebase-cpp-sdk + +Critical flags: +--t (full name: testapps, default: None) +--p (full name: platforms, default: None) +--s (full name: packaged_sdk, default: None) + +By default, this tool will build integration tests from source, which involves + +Under most circumstances the other flags don't need to be set, but can be +seen by running --help. Note that all path flags will forcefully expand +the user ~. + + +DEPENDENCIES: + +----Firebase Repo---- +The Firebase C++ Quickstart repo must be locally present. +Path specified by the flag: + + --repo_dir (default: current working directory) + +----Python Dependencies---- +The requirements.txt file has the required dependencies for this Python tool. + + pip install -r requirements.txt + +----CMake (Desktop only)---- +CMake must be installed and on the system path. + +----Environment Variables (Android only)---- +If building for Android, gradle requires several environment variables. +The following lists expected variables, and examples of what +a configured value may look like on MacOS: + + JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-8-latest/Contents/Home + ANDROID_HOME=/Users/user_name/Library/Android/sdk + ANDROID_SDK_HOME=/Users/user_name/Library/Android/sdk + ANDROID_NDK_HOME=/Users/user_name/Library/Android/sdk/ndk-bundle + +Or on Linux: + JAVA_HOME=/usr/local/buildtools/java/jdk/ + ANDROID_HOME=~/Android/Sdk + ANDROID_SDK_HOME=~/Android/Sdk + ANDROID_NDK_HOME=~/Android/Sdk/ndk + +If using this tool frequently, you will likely find it convenient to +modify your bashrc file to automatically set these variables. + +""" + +import attr +import datetime +import json +import os +import platform +import shutil +import stat +import subprocess +import sys +import tempfile + +from absl import app +from absl import flags +from absl import logging +from distutils import dir_util + +import utils +import config_reader +import xcodebuild + +# Environment variables +_JAVA_HOME = "JAVA_HOME" +_ANDROID_HOME = "ANDROID_HOME" +_ANDROID_SDK_HOME = "ANDROID_SDK_HOME" +_NDK_ROOT = "NDK_ROOT" +_ANDROID_NDK_HOME = "ANDROID_NDK_HOME" + +# Platforms +_ANDROID = "Android" +_IOS = "iOS" +_TVOS = "tvOS" +_DESKTOP = "Desktop" +_SUPPORTED_PLATFORMS = (_ANDROID, _IOS, _TVOS, _DESKTOP) + +# Architecture +_SUPPORTED_ARCHITECTURES = ("x64", "x86", "arm64") + +# Values for iOS SDK flag (where the iOS app will run) +_APPLE_SDK_DEVICE = "real" +_APPLE_SDK_SIMULATOR = "virtual" +_SUPPORTED_APPLE_SDK = (_APPLE_SDK_DEVICE, _APPLE_SDK_SIMULATOR) + +_DEFAULT_RUN_TIMEOUT_SECONDS = 4800 # 1 hour 20 min + +FLAGS = flags.FLAGS + +flags.DEFINE_string( + "packaged_sdk", None, "Firebase SDK directory.") + +flags.DEFINE_string( + "output_directory", "~", + "Build output will be placed in this directory.") + +flags.DEFINE_string( + "artifact_name", "local-build", + "artifacts will be created and placed in output_directory." + " testapps artifact is testapps-$artifact_name;" + " build log artifact is build-results-$artifact_name.log.") + +flags.DEFINE_string( + "repo_dir", os.getcwd(), + "Firebase C++ Quickstart Git repository. Current directory by default.") + +flags.DEFINE_list( + "testapps", None, "Which testapps (Firebase APIs) to build, e.g." + " 'analytics,auth'.", + short_name="t") + +flags.DEFINE_list( + "platforms", None, "Which platforms to build. Can be Android, iOS and/or" + " Desktop", short_name="p") + +flags.DEFINE_bool( + "add_timestamp", True, + "Add a timestamp to the output directory for disambiguation." + " Recommended when running locally, so each execution gets its own " + " directory.") + +flags.DEFINE_list( + "ios_sdk", _APPLE_SDK_DEVICE, + "(iOS only) Build for real device (.ipa), virtual device / simulator (.app), " + "or both. Building for both will produce both an .app and an .ipa.") + +flags.DEFINE_list( + "tvos_sdk", _APPLE_SDK_SIMULATOR, + "(tvOS only) Build for real device (.ipa), virtual device / simulator (.app), " + "or both. Building for both will produce both an .app and an .ipa.") + +flags.DEFINE_bool( + "update_pod_repo", True, + "(iOS/tvOS only) Will run 'pod repo update' before building for iOS/tvOS to update" + " the local spec repos available on this machine. Must also include iOS/tvOS" + " in platforms flag.") + +flags.DEFINE_string( + "compiler", None, + "(Desktop only) Specify the compiler with CMake during the testapps build." + " Check the config file to see valid choices for this flag." + " If none, will invoke cmake without specifying a compiler.") + +flags.DEFINE_string( + "arch", "x64", + "(Desktop only) Which architecture to build: x64 (all), x86 (Windows/Linux), " + "or arm64 (Mac only).") + +# Get the number of CPUs for the default value of FLAGS.jobs +CPU_COUNT = os.cpu_count(); +# If CPU count couldn't be determined, default to 2. +DEFAULT_CPU_COUNT = 2 +if CPU_COUNT is None: CPU_COUNT = DEFAULT_CPU_COUNT +# Cap at 4 CPUs. +MAX_CPU_COUNT = 4 +if CPU_COUNT > MAX_CPU_COUNT: CPU_COUNT = MAX_CPU_COUNT + +flags.DEFINE_integer( + "jobs", CPU_COUNT, + "(Desktop only) If > 0, pass in -j to make CMake parallelize the" + " build. Defaults to the system's CPU count (max %s)." % MAX_CPU_COUNT) + +flags.DEFINE_multi_string( + "cmake_flag", None, + "Pass an additional flag to the CMake configure step." + " This option can be specified multiple times.") + +flags.register_validator( + "platforms", + lambda p: all(platform in _SUPPORTED_PLATFORMS for platform in p), + message="Valid platforms: " + ",".join(_SUPPORTED_PLATFORMS), + flag_values=FLAGS) + +flags.register_validator( + "ios_sdk", + lambda s: all(ios_sdk in _SUPPORTED_APPLE_SDK for ios_sdk in s), + message="Valid platforms: " + ",".join(_SUPPORTED_APPLE_SDK), + flag_values=FLAGS) + +flags.register_validator( + "tvos_sdk", + lambda s: all(tvos_sdk in _SUPPORTED_APPLE_SDK for tvos_sdk in s), + message="Valid platforms: " + ",".join(_SUPPORTED_APPLE_SDK), + flag_values=FLAGS) + +flags.DEFINE_bool( + "short_output_paths", False, + "Use short directory names for output paths. Useful to avoid hitting file " + "path limits on Windows.") + +flags.DEFINE_bool( + "gha_build", False, + "Set to true if this is a GitHub Actions build.") + +def main(argv): + if len(argv) > 1: + raise app.UsageError("Too many command-line arguments.") + + platforms = FLAGS.platforms + testapps = FLAGS.testapps + + sdk_dir = _fix_path(FLAGS.packaged_sdk) + root_output_dir = _fix_path(FLAGS.output_directory) + repo_dir = _fix_path(FLAGS.repo_dir) + + update_pod_repo = FLAGS.update_pod_repo + if FLAGS.add_timestamp: + timestamp = datetime.datetime.now().strftime("%Y_%m_%d-%H_%M_%S") + else: + timestamp = "" + + if FLAGS.short_output_paths: + output_dir = os.path.join(root_output_dir, "ta") + else: + output_dir = os.path.join(root_output_dir, "testapps" + timestamp) + + config = config_reader.read_config() + + xcframework_dir = os.path.join(sdk_dir, "xcframeworks") + xcframework_exist = os.path.isdir(xcframework_dir) + if not xcframework_exist: + if _IOS in platforms: + _build_xcframework_from_repo(repo_dir, "ios", testapps, config) + if _TVOS in platforms: + _build_xcframework_from_repo(repo_dir, "tvos", testapps, config) + + if update_pod_repo and (_IOS in platforms or _TVOS in platforms): + _run(["pod", "repo", "update"]) + + cmake_flags = _get_desktop_compiler_flags(FLAGS.compiler, config.compilers) + + if (_DESKTOP in platforms and utils.is_linux_os() and FLAGS.arch == "x86"): + # Write out a temporary toolchain file to force 32-bit Linux builds, as + # the SDK-included toolchain file may not be present when building against + # the packaged SDK. + temp_toolchain_file = tempfile.NamedTemporaryFile("w+", suffix=".cmake") + temp_toolchain_file.writelines([ + 'set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")\n', + 'set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")\n', + 'set(CMAKE_LIBRARY_PATH "/usr/lib/i386-linux-gnu")\n', + 'set(INCLUDE_DIRECTORIES ${INCLUDE_DIRECTORIES} "/usr/include/i386-linux-gnu")\n']) + temp_toolchain_file.flush() + # Leave the file open, as it will be deleted on close, i.e. when this script exits. + # (On Linux, the file can be opened a second time by cmake while still open by + # this script) + cmake_flags.extend(["-DCMAKE_TOOLCHAIN_FILE=%s" % temp_toolchain_file.name]) + + if FLAGS.cmake_flag: + cmake_flags.extend(FLAGS.cmake_flag) + + failures = [] + for testapp in testapps: + api_config = config.get_api(testapp) + testapp_dirs = [api_config.testapp_path] + for testapp_dir in testapp_dirs: + logging.info("BEGIN building for %s: %s", testapp, testapp_dir) + failures += _build( + testapp=testapp, + platforms=platforms, + api_config=config.get_api(testapp), + testapp_dir=testapp_dir, + output_dir=output_dir, + sdk_dir=sdk_dir, + xcframework_exist=xcframework_exist, + repo_dir=repo_dir, + ios_sdk=FLAGS.ios_sdk, + tvos_sdk=FLAGS.tvos_sdk, + cmake_flags=cmake_flags, + short_output_paths=FLAGS.short_output_paths) + logging.info("END building for %s", testapp) + + _collect_integration_tests(testapps, root_output_dir, output_dir, FLAGS.artifact_name) + + _summarize_results(testapps, platforms, failures, root_output_dir, FLAGS.artifact_name) + return 1 if failures else 0 + + +def _build( + testapp, platforms, api_config, testapp_dir, output_dir, sdk_dir, xcframework_exist, + repo_dir, ios_sdk, tvos_sdk, cmake_flags, short_output_paths): + """Builds one testapp on each of the specified platforms.""" + os.chdir(repo_dir) + project_dir = os.path.join(output_dir, api_config.name) + if short_output_paths: + # Combining the first letter of every part separated by underscore for + # testapp paths. This is a trick to reduce file path length as we were + # exceeding the limit on Windows. + testapp_dir_parts = os.path.basename(testapp_dir).split('_') + output_testapp_dir = ''.join([x[0] for x in testapp_dir_parts]) + else: + output_testapp_dir = os.path.basename(testapp_dir) + + project_dir = os.path.join(project_dir, output_testapp_dir) + + logging.info("Copying testapp project to %s", project_dir) + os.makedirs(project_dir) + dir_util.copy_tree(testapp_dir, project_dir) + + logging.info("Changing directory to %s", project_dir) + os.chdir(project_dir) + + # TODO(DDB): remove + # _run_setup_script(repo_dir, project_dir) + + failures = [] + + if _DESKTOP in platforms: + logging.info("BEGIN %s, %s", testapp, _DESKTOP) + try: + _build_desktop(sdk_dir, cmake_flags) + except subprocess.SubprocessError as e: + failures.append( + Failure(testapp=testapp, platform=_DESKTOP, error_message=str(e))) + _rm_dir_safe(os.path.join(project_dir, "bin")) + logging.info("END %s, %s", testapp, _DESKTOP) + + if _ANDROID in platforms: + logging.info("BEGIN %s, %s", testapp, _ANDROID) + try: + _validate_android_environment_variables() + _build_android(project_dir, sdk_dir) + except subprocess.SubprocessError as e: + failures.append( + Failure(testapp=testapp, platform=_ANDROID, error_message=str(e))) + _rm_dir_safe(os.path.join(project_dir, "build", "intermediates")) + _rm_dir_safe(os.path.join(project_dir, ".externalNativeBuild")) + logging.info("END %s, %s", testapp, _ANDROID) + + if _IOS in platforms: + logging.info("BEGIN %s, %s", testapp, _IOS) + try: + _build_apple( + sdk_dir=sdk_dir, + xcframework_exist=xcframework_exist, + project_dir=project_dir, + repo_dir=repo_dir, + api_config=api_config, + target=api_config.ios_target, + scheme=api_config.ios_scheme, + apple_platfrom=_IOS, + apple_sdk=ios_sdk) + + except subprocess.SubprocessError as e: + failures.append( + Failure(testapp=testapp, platform=_IOS, error_message=str(e))) + logging.info("END %s, %s", testapp, _IOS) + + if _TVOS in platforms and api_config.tvos_target: + logging.info("BEGIN %s, %s", testapp, _TVOS) + try: + _build_apple( + sdk_dir=sdk_dir, + xcframework_exist=xcframework_exist, + project_dir=project_dir, + repo_dir=repo_dir, + api_config=api_config, + target=api_config.tvos_target, + scheme=api_config.tvos_scheme, + apple_platfrom=_TVOS, + apple_sdk=tvos_sdk) + except subprocess.SubprocessError as e: + failures.append( + Failure(testapp=testapp, platform=_TVOS, error_message=str(e))) + logging.info("END %s, %s", testapp, _TVOS) + + return failures + + +def _collect_integration_tests(testapps, root_output_dir, output_dir, artifact_name): + testapps_artifact_dir = "testapps-" + artifact_name + android_testapp_extension = ".apk" + ios_testapp_extension = ".ipa" + ios_simualtor_testapp_extension = ".app" + desktop_testapp_name = "testapp" + if platform.system() == "Windows": + desktop_testapp_name += ".exe" + + testapp_paths = [] + testapp_google_services = {} + for file_dir, directories, file_names in os.walk(output_dir): + for directory in directories: + if directory.endswith(ios_simualtor_testapp_extension): + testapp_paths.append(os.path.join(file_dir, directory)) + for file_name in file_names: + if ((file_name == desktop_testapp_name and "ios_build" not in file_dir) + or file_name.endswith(android_testapp_extension) + or file_name.endswith(ios_testapp_extension)): + testapp_paths.append(os.path.join(file_dir, file_name)) + if (file_name == "google-services.json"): + testapp_google_services[file_dir.split(os.path.sep)[-2]] = os.path.join(file_dir, file_name) + + artifact_path = os.path.join(root_output_dir, testapps_artifact_dir) + _rm_dir_safe(artifact_path) + for testapp in testapps: + os.makedirs(os.path.join(artifact_path, testapp)) + for path in testapp_paths: + for testapp in testapps: + if testapp in path: + if os.path.isfile(path): + shutil.copy(path, os.path.join(artifact_path, testapp)) + if path.endswith(desktop_testapp_name) and testapp_google_services.get(testapp): + shutil.copy(testapp_google_services[testapp], os.path.join(artifact_path, testapp)) + else: + dir_util.copy_tree(path, os.path.join(artifact_path, testapp, os.path.basename(path))) + break + + +def _write_summary(testapp_dir, summary, file_name="summary.log"): + with open(os.path.join(testapp_dir, file_name), "a") as f: + timestamp = datetime.datetime.now().strftime("%Y_%m_%d-%H_%M_%S") + f.write("\n%s\n%s\n" % (timestamp, summary)) + + +def _summarize_results(testapps, platforms, failures, root_output_dir, artifact_name): + """Logs a readable summary of the results of the build.""" + file_name = "build-results-" + artifact_name + ".log" + + summary = [] + summary.append("BUILD SUMMARY:") + summary.append("TRIED TO BUILD: " + ",".join(testapps)) + summary.append("ON PLATFORMS: " + ",".join(platforms)) + + if not failures: + summary.append("ALL BUILDS SUCCEEDED") + else: + summary.append("SOME ERRORS OCCURRED:") + for i, failure in enumerate(failures, start=1): + summary.append("%d: %s" % (i, failure.describe())) + summary = "\n".join(summary) + + logging.info(summary) + _write_summary(root_output_dir, summary, file_name=file_name) + + summary_json = {} + summary_json["type"] = "build" + summary_json["testapps"] = testapps + summary_json["errors"] = {failure.testapp:failure.error_message for failure in failures} + with open(os.path.join(root_output_dir, file_name+".json"), "a") as f: + f.write(json.dumps(summary_json, indent=2)) + + +def _build_desktop(sdk_dir, cmake_flags): + cmake_configure_cmd = ["cmake", ".", "-DCMAKE_BUILD_TYPE=Debug", + "-DFIREBASE_CPP_SDK_DIR=" + sdk_dir] + if utils.is_windows_os(): + cmake_configure_cmd += ["-A", + "Win32" if FLAGS.arch == "x86" else FLAGS.arch] + elif utils.is_mac_os(): + # Ensure that correct Mac architecture is built. + cmake_configure_cmd += ["-DCMAKE_OSX_ARCHITECTURES=%s" % + ("arm64" if FLAGS.arch == "arm64" else "x86_64")] + + _run(cmake_configure_cmd + cmake_flags) + _run(["cmake", "--build", ".", "--config", "Debug"] + + ["-j", str(FLAGS.jobs)] if FLAGS.jobs > 0 else []) + + +def _get_desktop_compiler_flags(compiler, compiler_table): + """Returns the command line flags for this compiler.""" + if not compiler: # None is an acceptable default value + return [] + try: + return compiler_table[compiler] + except KeyError: + valid_keys = ", ".join(compiler_table.keys()) + raise ValueError( + "Given compiler: %s. Valid compilers: %s" % (compiler, valid_keys)) + + +def _build_android(project_dir, sdk_dir): + """Builds an Android binary (apk).""" + if platform.system() == "Windows": + gradlew = "gradlew.bat" + sdk_dir = sdk_dir.replace("\\", "/") # Gradle misinterprets backslashes. + else: + gradlew = "./gradlew" + logging.info("Patching gradle properties with path to SDK") + gradle_properties = os.path.join(project_dir, "gradle.properties") + with open(gradle_properties, "a+") as f: + f.write("systemProp.firebase_cpp_sdk.dir=" + sdk_dir + "\n") + f.write("http.keepAlive=false\n") + f.write("maven.wagon.http.pool=false\n") + f.write("maven.wagon.httpconnectionManager.ttlSeconds=120") + # This will log the versions of dependencies for debugging purposes. + _run([gradlew, "dependencies", "--configuration", "debugCompileClasspath",]) + _run([gradlew, "assembleDebug", "--stacktrace"]) + + +def _validate_android_environment_variables(): + """Checks environment variables that may be required for Android.""" + # Ultimately we let the gradle build be the source of truth on what env vars + # are required, but try to repair holes and log warnings if we can't. + android_home = os.environ.get(_ANDROID_HOME) + if not os.environ.get(_JAVA_HOME): + logging.warning("%s not set", _JAVA_HOME) + if not os.environ.get(_ANDROID_SDK_HOME): + if android_home: # Use ANDROID_HOME as backup for ANDROID_SDK_HOME + os.environ[_ANDROID_SDK_HOME] = android_home + logging.info("%s not found, using %s", _ANDROID_SDK_HOME, _ANDROID_HOME) + else: + logging.warning("Missing: %s and %s", _ANDROID_SDK_HOME, _ANDROID_HOME) + # Different environments may have different NDK env vars specified. We look + # for these, in this order, and set the others to the first found. + # If none are set, we check the default location for the ndk. + ndk_path = None + ndk_vars = [_NDK_ROOT, _ANDROID_NDK_HOME] + for env_var in ndk_vars: + val = os.environ.get(env_var) + if val: + ndk_path = val + break + if not ndk_path: + if android_home: + default_ndk_path = os.path.join(android_home, "ndk-bundle") + if os.path.isdir(default_ndk_path): + ndk_path = default_ndk_path + if ndk_path: + logging.info("Found ndk: %s", ndk_path) + for env_var in ndk_vars: + if os.environ.get(env_var) != ndk_path: + logging.info("Setting %s to %s", env_var, ndk_path) + os.environ[env_var] = ndk_path + else: + logging.warning("No NDK env var set. Set one of %s", ", ".join(ndk_vars)) + +# build required ios xcframeworks based on makefiles +# the xcframeworks locates at repo_dir/ios_build +def _build_xcframework_from_repo(repo_dir, apple_platform, testapps, config): + """Builds xcframework from SDK source.""" + output_path = os.path.join(repo_dir, apple_platform + "_build") + _rm_dir_safe(output_path) + xcframework_builder = os.path.join( + repo_dir, "scripts", "gha", "build_ios_tvos.py") + + # build only required targets to save time + target = set() + for testapp in testapps: + api_config = config.get_api(testapp) + if apple_platform == "ios" or (apple_platform == "tvos" and api_config.tvos_target): + for framework in api_config.frameworks: + # firebase_analytics.framework -> firebase_analytics + target.add(os.path.splitext(framework)[0]) + + # firebase is not a target in CMake, firebase_app is the target + # firebase_app will be built by other target as well + target.remove("firebase") + + framework_builder_args = [ + sys.executable, xcframework_builder, + "-b", output_path, + "-s", repo_dir, + "-o", apple_platform, + "-t" + ] + framework_builder_args.extend(target) + _run(framework_builder_args) + + +def _build_apple( + sdk_dir, xcframework_exist, project_dir, repo_dir, api_config, + target, scheme, apple_platfrom, apple_sdk): + """Builds an iOS application (.app, .ipa or both).""" + build_dir = apple_platfrom.lower() + "_build" + if not xcframework_exist: + sdk_dir = os.path.join(repo_dir, build_dir) + + build_dir = os.path.join(project_dir, build_dir) + os.makedirs(build_dir) + + logging.info("Copying XCFrameworks") + framework_src_dir = os.path.join(sdk_dir, "xcframeworks") + framework_paths = [] # Paths to the copied frameworks. + for framework in api_config.frameworks: + framework_src_path = os.path.join(framework_src_dir, framework) + framework_dest_path = os.path.join(project_dir, "Frameworks", framework) + dir_util.copy_tree(framework_src_path, framework_dest_path) + framework_paths.append(framework_dest_path) + + _run(["pod", "install"]) + + entitlements_path = os.path.join( + project_dir, api_config.ios_target + ".entitlements") + xcode_tool_path = os.path.join( + repo_dir, "scripts", "gha", "integration_testing", "xcode_tool.rb") + xcode_patcher_args = [ + "ruby", xcode_tool_path, + "--XCodeCPP.xcodeProjectDir", project_dir, + "--XCodeCPP.target", target, + "--XCodeCPP.frameworks", ",".join(framework_paths) + ] + # Internal integration tests require the SDK root as an include path. + if repo_dir and api_config.internal_testapp_path: + xcode_patcher_args.extend(("--XCodeCPP.include", repo_dir)) + if os.path.isfile(entitlements_path): # Not all testapps require entitlements + logging.info("Entitlements file detected.") + xcode_patcher_args.extend(("--XCodeCPP.entitlement", entitlements_path)) + else: + logging.info("No entitlements found at %s.", entitlements_path) + _run(xcode_patcher_args) + + xcode_path = os.path.join(project_dir, "integration_test.xcworkspace") + if _APPLE_SDK_SIMULATOR in apple_sdk: + _run( + xcodebuild.get_args_for_build( + path=xcode_path, + scheme=scheme, + output_dir=build_dir, + apple_platfrom=apple_platfrom, + apple_sdk=_APPLE_SDK_SIMULATOR, + configuration="Debug")) + + if _APPLE_SDK_DEVICE in apple_sdk: + _run( + xcodebuild.get_args_for_build( + path=xcode_path, + scheme=scheme, + output_dir=build_dir, + apple_platfrom=apple_platfrom, + apple_sdk=_APPLE_SDK_DEVICE, + configuration="Debug")) + + xcodebuild.generate_unsigned_ipa( + output_dir=build_dir, configuration="Debug") + + +# This should be executed before performing any builds. +def _run_setup_script(root_dir, testapp_dir): + """Runs the setup_integration_tests.py script.""" + # This script will download gtest to its own directory. + # The CMake projects were configured to download gtest, but this was + # found to be flaky and errors didn't propagate up the build system + # layers. The workaround is to download gtest with this script and copy it. + downloader_dir = os.path.join(root_dir, "testing", "test_framework") + _run([sys.executable, os.path.join(downloader_dir, "download_googletest.py")]) + # Copies shared test framework files into the project, including gtest. + script_path = os.path.join(root_dir, "setup_integration_tests.py") + _run([sys.executable, script_path, testapp_dir]) + + +def _run(args, timeout=_DEFAULT_RUN_TIMEOUT_SECONDS, capture_output=False, text=None, check=True): + """Executes a command in a subprocess.""" + logging.info("Running in subprocess: %s", " ".join(args)) + return subprocess.run( + args=args, + timeout=timeout, + capture_output=capture_output, + text=text, + check=check) + + +def _handle_readonly_file(func, path, excinfo): + """Function passed into shutil.rmtree to handle Access Denied error""" + os.chmod(path, stat.S_IWRITE) + func(path) # will re-throw if a different error occurrs + + +def _rm_dir_safe(directory_path): + """Removes directory at given path. No error if dir doesn't exist.""" + logging.info("Deleting %s...", directory_path) + try: + shutil.rmtree(directory_path, onerror=_handle_readonly_file) + except OSError as e: + # There are two known cases where this can happen: + # The directory doesn't exist (FileNotFoundError) + # A file in the directory is open in another process (PermissionError) + logging.warning("Failed to remove directory:\n%s", e.strerror) + + +def _fix_path(path): + """Expands ~, normalizes slashes, and converts relative paths to absolute.""" + return os.path.abspath(os.path.expanduser(path)) + + +@attr.s(frozen=True, eq=False) +class Failure(object): + """Holds context for the failure of a testapp to build/run.""" + testapp = attr.ib() + platform = attr.ib() + error_message = attr.ib() + + def describe(self): + return "%s, %s: %s" % (self.testapp, self.platform, self.error_message) + + +if __name__ == "__main__": + flags.mark_flag_as_required("testapps") + flags.mark_flag_as_required("platforms") + flags.mark_flag_as_required("packaged_sdk") + app.run(main) diff --git a/scripts/build_scripts/config_reader.py b/scripts/build_scripts/config_reader.py new file mode 100644 index 00000000..a24f5d7a --- /dev/null +++ b/scripts/build_scripts/config_reader.py @@ -0,0 +1,139 @@ +# Copyright 2022 Google LLC +# +# 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. + +"""A utility for working with testapp builder JSON files. + +This module handles loading the central configuration file for a testapp +builder, returning a 'Config' object that exposes all the data. + +The motivation for loading the config into a class as opposed to returning +the loaded JSON directly is to validate the data upfront, to fail fast if +anything is missing or formatted incorrectly. + +Example of such a configuration file: + +{ + "apis": [ + { + "name": "analytics", + "full_name": "FirebaseAnalytics", + "bundle_id": "com.google.ios.analytics.testapp", + "ios_target": "testapp", + "tvos_target": "", + "testapp_path": "analytics/testapp", + "frameworks": [ + "firebase_analytics.framework", + "firebase.framework" + ], + "provision": "Google_Development.mobileprovision" + }, + { + "name": "admob", + "full_name": "FirebaseAdmob", + "bundle_id": "com.google.ios.admob.testapp", + "ios_target": "testapp", + "tvos_target": "", + "testapp_path": "admob/testapp", + "frameworks": [ + "firebase_admob.framework", + "firebase.framework" + ], + "provision": "Google_Development.mobileprovision" + } + ], + "dev_team": "ABCDEFGHIJK" +} + +""" + +import json +import os +import pathlib + +import attr + +_DEFAULT_CONFIG_NAME = "build_testapps.json" + + +def read_config(path=None): + """Creates an in-memory 'Config' object out of a testapp config file. + + Args: + path (str): Path to a testapp builder config file. If not specified, will + look for 'build_testapps.json' in the same directory as this file. + + Returns: + Config: All of the testapp builder's configuration. + + """ + if not path: + directory = pathlib.Path(__file__).parent.absolute() + path = os.path.join(directory, _DEFAULT_CONFIG_NAME) + with open(path, "r") as config: + config = json.load(config) + api_configs = dict() + try: + for api in config["apis"]: + api_name = api["name"] + api_configs[api_name] = APIConfig( + name=api_name, + full_name=api["full_name"], + bundle_id=api["bundle_id"], + ios_target=api["ios_target"], + tvos_target=api["tvos_target"], + ios_scheme=api["ios_target"], # Scheme assumed to be same as target. + tvos_scheme=api["tvos_target"], + testapp_path=api["testapp_path"], + internal_testapp_path=api.get("internal_testapp_path", None), + frameworks=api["frameworks"], + provision=api["provision"], + minify=api.get("minify", None)) + return Config( + apis=api_configs, + compilers=config["compiler_dict"]) + except (KeyError, TypeError, IndexError): + # The error will be cryptic on its own, so we dump the JSON to + # offer context, then reraise the error. + print( + "Error occurred while parsing config. Full config dump:\n" + + json.dumps(config, sort_keys=True, indent=4, separators=(",", ":"))) + raise + + +@attr.s(frozen=True, eq=False) +class Config(object): + apis = attr.ib() # Mapping of str: APIConfig + compilers = attr.ib() + + def get_api(self, api): + """Returns the APIConfig object for the given api, e.g. 'analytics'.""" + return self.apis[api] + + +@attr.s(frozen=True, eq=False) +class APIConfig(object): + """Holds all the configuration for a single testapp project.""" + name = attr.ib() + full_name = attr.ib() + bundle_id = attr.ib() + ios_target = attr.ib() + tvos_target = attr.ib() + ios_scheme = attr.ib() + tvos_scheme = attr.ib() + testapp_path = attr.ib() # testapp dir relative to sdk root + internal_testapp_path = attr.ib() # Internal testdir dir relative to sdk root + frameworks = attr.ib() # Required custom xcode frameworks + provision = attr.ib() # Path to the local mobile provision + minify = attr.ib() # (Optional) Android minification. + diff --git a/scripts/build_scripts/python_requirements.txt b/scripts/build_scripts/python_requirements.txt new file mode 100644 index 00000000..214a8aac --- /dev/null +++ b/scripts/build_scripts/python_requirements.txt @@ -0,0 +1,2 @@ +attrs +absl-py diff --git a/scripts/build_scripts/utils.py b/scripts/build_scripts/utils.py new file mode 100644 index 00000000..631dc8df --- /dev/null +++ b/scripts/build_scripts/utils.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python + +# Copyright 2022 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. + +""" +Helper functions that are shared amongst prereqs and build scripts across various +platforms. +""" + +import distutils.spawn +import platform +import shutil +import subprocess +import os +import urllib.request + +def run_command(cmd, capture_output=False, cwd=None, check=False, as_root=False, + print_cmd=True): + """Run a command. + + Args: + cmd (list(str)): Command to run as a list object. + Eg: ['ls', '-l']. + capture_output (bool): Capture the output of this command. + Output can be accessed as .stdout + cwd (str): Directory to execute the command from. + check (bool): Raises a CalledProcessError if True and the command errored out + as_root (bool): Run command as root user with admin priveleges (supported on mac and linux). + print_cmd (bool): Print the command we are running to stdout. + + Raises: + (subprocess.CalledProcessError): If command errored out and `text=True` + + Returns: + (`subprocess.CompletedProcess`): object containing information from + command execution + """ + + if as_root and (is_mac_os() or is_linux_os()): + cmd.insert(0, 'sudo') + + cmd_string = ' '.join(cmd) + if print_cmd: + print('Running cmd: {0}\n'.format(cmd_string)) + # If capture_output is requested, we also set text=True to store the returned value of the + # command as a string instead of bytes object + return subprocess.run(cmd, capture_output=capture_output, cwd=cwd, + check=check, text=capture_output) + + +def is_command_installed(tool): + """Check if a command is installed on the system.""" + return distutils.spawn.find_executable(tool) + + +def delete_directory(dir_path): + """Recursively delete a valid directory""" + if os.path.exists(dir_path): + shutil.rmtree(dir_path) + + +def download_file(url, file_path): + """Download from url and save to specified file path.""" + with urllib.request.urlopen(url) as response, open(file_path, 'wb') as out_file: + shutil.copyfileobj(response, out_file) + + +def unpack_files(archive_file_path, output_dir=None): + """Unpack/extract an archive to specified output_directory""" + shutil.unpack_archive(archive_file_path, output_dir) + + +def is_windows_os(): + return platform.system() == 'Windows' + + +def is_mac_os(): + return platform.system() == 'Darwin' + + +def is_linux_os(): + return platform.system() == 'Linux' diff --git a/scripts/build_scripts/xcodebuild.py b/scripts/build_scripts/xcodebuild.py new file mode 100644 index 00000000..b60c70dc --- /dev/null +++ b/scripts/build_scripts/xcodebuild.py @@ -0,0 +1,119 @@ +# Copyright 2020 Google LLC +# +# 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. + +"""Helper module for working with xcode projects. + +The tool xcodebuild provides support to build xcode projects from the command +line. The motivation was to simplify usage of xcodebuild, since it was non-trivial +to figure out which flags were needed to get it working in a CI environment. +The options required by the methods in this module were found to work both +locally and on CI, with both the Unity and C++ projects. + +get_args_for_build() method doesn't performing operations with xcodebuild directly, +this module returns arg sequences. These sequences can be passed to e.g. +subprocess.run to execute the operations. + +get_args_for_build() support either device or simulator builds. For simulator +builds, it suffices to use get_args_for_build() to create a .app that can be +used with simulators. For unsigned device builds, generate .app via +get_args_for_build() step and then use generate_unsigned_ipa() to package +the .app to .ipa. + +""" + +import os +import shutil + +def get_args_for_build( + path, scheme, output_dir, apple_platfrom, apple_sdk, configuration): + """Constructs subprocess args for an unsigned xcode build. + + Args: + path (str): Full path to the project or workspace to build. Must end in + either .xcodeproj or .xcworkspace. + scheme (str): Name of the scheme to build. + output_dir (str): Directory for the resulting build artifacts. Will be + created if it doesn't already exist. + apple_platfrom (str): iOS or tvOS. + apple_sdk (str): Where this build will be run: real device or virtual device (simulator). + configuration (str): Value for the -configuration flag. + + Returns: + Sequence of strings, corresponding to valid args for a subprocess call. + + """ + args = [ + "xcodebuild", + "-sdk", _get_apple_env_from_target(apple_platfrom, apple_sdk), + "-scheme", scheme, + "-configuration", configuration, + "-quiet", + "BUILD_DIR=" + output_dir + ] + + if apple_sdk == "real": + args.extend(['CODE_SIGN_IDENTITY=""', + "CODE_SIGNING_REQUIRED=NO", + "CODE_SIGNING_ALLOWED=NO"]) + elif apple_sdk == "virtual" and apple_platfrom == "tvOS": + args.extend(['-arch', "x86_64"]) + + if not path: + raise ValueError("Must supply a path.") + if path.endswith(".xcworkspace"): + args.extend(("-workspace", path)) + elif path.endswith(".xcodeproj"): + args.extend(("-project", path)) + else: + raise ValueError("Path must end with .xcworkspace or .xcodeproj: %s" % path) + return args + + +def _get_apple_env_from_target(apple_platfrom, apple_sdk): + """Return a value for the -sdk flag based on the target (device/simulator).""" + if apple_platfrom == "iOS": + if apple_sdk == "real": + return "iphoneos" + elif apple_sdk == "virtual": + return "iphonesimulator" + else: + raise ValueError("Unrecognized apple_sdk: %s" % apple_sdk) + elif apple_platfrom == "tvOS": + if apple_sdk == "real": + return "appletvos" + elif apple_sdk == "virtual": + return "appletvsimulator" + else: + raise ValueError("Unrecognized apple_sdk: %s" % apple_sdk) + else: + raise ValueError("Unrecognized apple_sdk: %s" % apple_sdk) + + +def generate_unsigned_ipa(output_dir, configuration): + """create unsigned .ipa from .app, then remove .app afterwards + + Args: + output_dir (str): Same value as get_args_for_build. generated unsigned .ipa + will be placed within the subdirectory "Debug-iphoneos" or "Release-iphoneos". + configuration (str): Same value as get_args_for_build. + """ + iphone_build_dir = os.path.join(output_dir, configuration + "-iphoneos") + payload_path = os.path.join(iphone_build_dir, "Payload") + app_path = os.path.join(iphone_build_dir, "integration_test.app") + ipa_path = os.path.join(iphone_build_dir, "integration_test.ipa") + os.mkdir(payload_path) + shutil.move(app_path, payload_path) + shutil.make_archive(payload_path, 'zip', root_dir=iphone_build_dir, base_dir='Payload') + shutil.move('%s.%s'%(payload_path, 'zip'), ipa_path) + shutil.rmtree(payload_path) diff --git a/scripts/restore_secrets.py b/scripts/restore_secrets.py new file mode 100644 index 00000000..cd72cf58 --- /dev/null +++ b/scripts/restore_secrets.py @@ -0,0 +1,186 @@ +# Copyright 2022 Google LLC +# +# 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. + +"""Script for restoring secrets into the testapp projects. + +Usage: + +python restore_secrets.py --passphrase [--repo_dir ] +python restore_secrets.py --passphrase_file [--repo_dir ] + +--passphrase: Passphrase to decrypt the files. This option is insecure on a + multi-user machine; use the --passphrase_file option instead. +--passphrase_file: Specify a file to read the passphrase from (only reads the + first line). Use "-" (without quotes) for stdin. +--repo_dir: Path to C++ Quickstart Github repository. Defaults to current + directory. +--apis: Specify a list of particular product APIs and retrieve only their + secrets. + +This script will perform the following: + +- Google Service files (plist and json) will be restored into the + testapp directories. +- The reverse id will be patched into all Info.plist files, using the value from + the decrypted Google Service plist files as the source of truth. + +""" + +import os +import plistlib +import subprocess + +from absl import app +from absl import flags + + +FLAGS = flags.FLAGS + +flags.DEFINE_string("repo_dir", os.getcwd(), "Path to C++ SDK Github repo.") +flags.DEFINE_string("passphrase", None, "The passphrase itself.") +flags.DEFINE_string("passphrase_file", None, + "Path to file with passphrase. Use \"-\" (without quotes) for stdin.") +flags.DEFINE_string("artifact", None, "Artifact Path, google-services.json will be placed here.") +flags.DEFINE_list("apis",[], "Optional comma-separated list of APIs for which to retreive " + " secrets. All secrets will be fetched if this is flag is not defined.") + + +def main(argv): + if len(argv) > 1: + raise app.UsageError("Too many command-line arguments.") + + repo_dir = FLAGS.repo_dir + # The passphrase is sensitive, do not log. + if FLAGS.passphrase: + passphrase = FLAGS.passphrase + elif FLAGS.passphrase_file == "-": + passphrase = input() + elif FLAGS.passphrase_file: + with open(FLAGS.passphrase_file, "r") as f: + passphrase = f.readline().strip() + else: + raise ValueError("Must supply passphrase or passphrase_file arg.") + + if FLAGS.apis: + print("Retrieving secrets for product APIs: ", FLAGS.apis) + + secrets_dir = os.path.join(repo_dir, "scripts", "gha-encrypted") + encrypted_files = _find_encrypted_files(secrets_dir) + print("Found these encrypted files:\n%s" % "\n".join(encrypted_files)) + + for path in encrypted_files: + if "google-services" in path or "GoogleService" in path: + # We infer the destination from the file's directory, example: + # /scripts/gha-encrypted/auth/google-services.json.gpg turns into + # //auth/testapp/google-services.json + api = os.path.basename(os.path.dirname(path)) + if FLAGS.apis and api not in FLAGS.apis: + print("Skipping secret found in product api", api) + continue + print("Encrypted Google Service file found: %s" % path) + file_name = os.path.basename(path).replace(".gpg", "") + dest_paths = [os.path.join(repo_dir, api, "testapp", file_name)] + if FLAGS.artifact: + # ///auth/google-services.json + if "google-services" in path and os.path.isdir(os.path.join(repo_dir, FLAGS.artifact, api)): + dest_paths = [os.path.join(repo_dir, FLAGS.artifact, api, file_name)] + else: + continue + + decrypted_text = _decrypt(path, passphrase) + for dest_path in dest_paths: + with open(dest_path, "w") as f: + f.write(decrypted_text) + print("Copied decrypted google service file to %s" % dest_path) + # We use a Google Service file as the source of truth for the reverse id + # that needs to be patched into the Info.plist files. + if dest_path.endswith(".plist"): + _patch_reverse_id(dest_path) + _patch_bundle_id(dest_path) + + if FLAGS.artifact: + return + +def _find_encrypted_files(directory_to_search): + """Returns a list of full paths to all files encrypted with gpg.""" + encrypted_files = [] + for prefix, _, files in os.walk(directory_to_search): + for relative_path in files: + if relative_path.endswith(".gpg"): + encrypted_files.append(os.path.join(prefix, relative_path)) + return encrypted_files + + +def _decrypt(encrypted_file, passphrase): + """Returns the decrypted contents of the given .gpg file.""" + print("Decrypting %s" % encrypted_file) + # Note: if setting check=True, be sure to catch the error and not rethrow it + # or print a traceback, as the message will include the passphrase. + result = subprocess.run( + args=[ + "gpg", + "--passphrase", passphrase, + "--quiet", + "--batch", + "--yes", + "--decrypt", + encrypted_file], + check=False, + text=True, + capture_output=True) + if result.returncode: + # Remove any instances of the passphrase from error before logging it. + raise RuntimeError(result.stderr.replace(passphrase, "****")) + print("Decryption successful") + # rstrip to eliminate a linebreak that GPG may introduce. + return result.stdout.rstrip() + + +def _patch_reverse_id(service_plist_path): + """Patches the Info.plist file with the reverse id from the Service plist.""" + print("Attempting to patch reverse id in Info.plist") + with open(service_plist_path, "rb") as f: + service_plist = plistlib.load(f) + _patch_file( + path=os.path.join(os.path.dirname(service_plist_path), "testapp", "Info.plist"), + placeholder="REPLACE_WITH_REVERSED_CLIENT_ID", + value=service_plist["REVERSED_CLIENT_ID"]) + + +def _patch_bundle_id(service_plist_path): + """Patches the Info.plist file with the bundle id from the Service plist.""" + print("Attempting to patch bundle id in Info.plist") + with open(service_plist_path, "rb") as f: + service_plist = plistlib.load(f) + _patch_file( + path=os.path.join(os.path.dirname(service_plist_path), "testapp", "Info.plist"), + placeholder="$(PRODUCT_BUNDLE_IDENTIFIER)", + value=service_plist["BUNDLE_ID"]) + + +def _patch_file(path, placeholder, value): + """Patches instances of the placeholder with the given value.""" + # Note: value may be sensitive, so do not log. + with open(path, "r") as f_read: + text = f_read.read() + # Count number of times placeholder appears for debugging purposes. + replacements = text.count(placeholder) + patched_text = text.replace(placeholder, value) + with open(path, "w") as f_write: + f_write.write(patched_text) + print("Patched %d instances of %s in %s" % (replacements, placeholder, path)) + + +if __name__ == "__main__": + app.run(main) From c33b2c18a3205aa3dbab7006c0e2c5c7b5ae7806 Mon Sep 17 00:00:00 2001 From: Morgan Chen Date: Thu, 18 Jan 2024 14:37:10 -0800 Subject: [PATCH 29/57] Deprecate Dynamic Links --- dynamic_links/testapp/readme.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dynamic_links/testapp/readme.md b/dynamic_links/testapp/readme.md index df15e578..66190975 100644 --- a/dynamic_links/testapp/readme.md +++ b/dynamic_links/testapp/readme.md @@ -1,6 +1,11 @@ Firebase Dynamic Links Quickstart ================================= +> [!IMPORTANT] +> Firebase Dynamic Links is **deprecated** and should not be used in new projects. The service will shut down on August 25, 2025. +> +> Please see our [Dynamic Links Deprecation FAQ documentation](https://firebase.google.com/support/dynamic-links-faq) for more guidance. + The Firebase Dynamic Links Quickstart demonstrates logging a range of different events using the Firebase Dynamic Links C++ SDK. The application has no user interface and simply logs actions it's performing to the console. From 2a169779a0f20d34fc8aee38b93d3635b7a0cbf3 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 22 May 2024 10:46:29 -0700 Subject: [PATCH 30/57] Update testapp for breaking changes. --- auth/testapp/src/common_main.cc | 352 ++++++++++++++++---------------- 1 file changed, 174 insertions(+), 178 deletions(-) diff --git a/auth/testapp/src/common_main.cc b/auth/testapp/src/common_main.cc index 8907bcc4..d7be0ca9 100644 --- a/auth/testapp/src/common_main.cc +++ b/auth/testapp/src/common_main.cc @@ -32,6 +32,7 @@ using ::firebase::Variant; using ::firebase::auth::AdditionalUserInfo; using ::firebase::auth::Auth; using ::firebase::auth::AuthError; +using ::firebase::auth::AuthResult; using ::firebase::auth::Credential; using ::firebase::auth::EmailAuthProvider; using ::firebase::auth::FacebookAuthProvider; @@ -43,8 +44,8 @@ using ::firebase::auth::kAuthErrorInvalidProviderId; using ::firebase::auth::kAuthErrorNone; using ::firebase::auth::OAuthProvider; using ::firebase::auth::PhoneAuthProvider; +using ::firebase::auth::PhoneAuthCredential; using ::firebase::auth::PlayGamesAuthProvider; -using ::firebase::auth::SignInResult; using ::firebase::auth::TwitterAuthProvider; using ::firebase::auth::User; using ::firebase::auth::UserInfoInterface; @@ -118,39 +119,38 @@ static bool WaitForFuture(const FutureBase& future, const char* fn, return false; } -static bool WaitForSignInFuture(Future sign_in_future, const char* fn, +static bool WaitForSignInFuture(Future sign_in_future, const char* fn, AuthError expected_error, Auth* auth) { if (WaitForFuture(sign_in_future, fn, expected_error)) return true; - const User* const* sign_in_user_ptr = sign_in_future.result(); - const User* sign_in_user = - sign_in_user_ptr == nullptr ? nullptr : *sign_in_user_ptr; - const User* auth_user = auth->current_user(); + const User sign_in_user = sign_in_future.result() ? *sign_in_future.result() : + User(); + const User auth_user = auth->current_user(); if (expected_error == ::firebase::auth::kAuthErrorNone && sign_in_user != auth_user) { - LogMessage("ERROR: future's user (%x) and current_user (%x) don't match", - static_cast(reinterpret_cast(sign_in_user)), - static_cast(reinterpret_cast(auth_user))); + LogMessage("ERROR: future's user (%s) and current_user (%s) don't match", + sign_in_user.uid().c_str(), + auth_user.uid().c_str()); } return false; } -static bool WaitForSignInFuture(const Future& sign_in_future, +static bool WaitForSignInFuture(const Future& sign_in_future, const char* fn, AuthError expected_error, Auth* auth) { if (WaitForFuture(sign_in_future, fn, expected_error)) return true; - const SignInResult* sign_in_result = sign_in_future.result(); - const User* sign_in_user = sign_in_result ? sign_in_result->user : nullptr; - const User* auth_user = auth->current_user(); + const AuthResult* auth_result = sign_in_future.result(); + const User sign_in_user = auth_result ? auth_result->user : User(); + const User auth_user = auth->current_user(); if (expected_error == ::firebase::auth::kAuthErrorNone && sign_in_user != auth_user) { - LogMessage("ERROR: future's user (%x) and current_user (%x) don't match", - static_cast(reinterpret_cast(sign_in_user)), - static_cast(reinterpret_cast(auth_user))); + LogMessage("ERROR: future's user (%s) and current_user (%s) don't match", + sign_in_user.uid().c_str(), + auth_user.uid().c_str()); } return false; @@ -159,7 +159,7 @@ static bool WaitForSignInFuture(const Future& sign_in_future, // Wait for the current user to sign out. Typically you should use the // state listener to determine whether the user has signed out. static bool WaitForSignOut(firebase::auth::Auth* auth) { - while (auth->current_user() != nullptr) { + while (!auth->current_user().is_valid()) { if (ProcessEvents(100)) return true; } // Wait - hopefully - long enough for listeners to be signalled. @@ -251,17 +251,17 @@ static void LogVariantMap(const std::map& variant_map, } // Display the sign-in result. -static void LogSignInResult(const SignInResult& result) { - if (!result.user) { +static void LogAuthResult(const AuthResult result) { + if (!result.user.is_valid()) { LogMessage("ERROR: User not signed in"); return; } - LogMessage("* User ID %s", result.user->uid().c_str()); - const AdditionalUserInfo& info = result.info; + LogMessage("* User ID %s", result.user.uid().c_str()); + const AdditionalUserInfo& info = result.additional_user_info; LogMessage("* Provider ID %s", info.provider_id.c_str()); LogMessage("* User Name %s", info.user_name.c_str()); LogVariantMap(info.profile, 0); - const UserMetadata& metadata = result.meta; + UserMetadata metadata = result.user.metadata(); LogMessage("* Sign in timestamp %d", static_cast(metadata.last_sign_in_timestamp)); LogMessage("* Creation timestamp %d", @@ -274,8 +274,8 @@ class AuthStateChangeCounter : public firebase::auth::AuthStateListener { virtual void OnAuthStateChanged(Auth* auth) { // NOLINT num_state_changes_++; - LogMessage("OnAuthStateChanged User %p (state changes %d)", - auth->current_user(), num_state_changes_); + LogMessage("OnAuthStateChanged User %s (state changes %d)", + auth->current_user().uid().c_str(), num_state_changes_); } void CompleteTest(const char* test_name, int expected_state_changes) { @@ -302,8 +302,8 @@ class IdTokenChangeCounter : public firebase::auth::IdTokenListener { virtual void OnIdTokenChanged(Auth* auth) { // NOLINT num_token_changes_++; - LogMessage("OnIdTokenChanged User %p (token changes %d)", - auth->current_user(), num_token_changes_); + LogMessage("OnIdTokenChanged User %s (token changes %d)", + auth->current_user().uid().c_str(), num_token_changes_); } void CompleteTest(const char* test_name, int token_changes) { @@ -331,7 +331,6 @@ class UserLogin { : auth_(auth), email_(email), password_(password), - user_(nullptr), log_errors_(true) {} explicit UserLogin(Auth* auth) : auth_(auth) { @@ -340,48 +339,48 @@ class UserLogin { } ~UserLogin() { - if (user_ != nullptr) { + if (user_.is_valid()) { log_errors_ = false; Delete(); } } void Register() { - Future register_test_account = + Future register_test_account = auth_->CreateUserWithEmailAndPassword(email(), password()); WaitForSignInFuture(register_test_account, "CreateUserWithEmailAndPassword() to create temp user", kAuthErrorNone, auth_); - user_ = register_test_account.result() ? *register_test_account.result() - : nullptr; + user_ = register_test_account.result() ? register_test_account.result()->user + : User(); } void Login() { Credential email_cred = EmailAuthProvider::GetCredential(email(), password()); - Future sign_in_cred = auth_->SignInWithCredential(email_cred); + Future sign_in_cred = auth_->SignInWithCredential(email_cred); WaitForSignInFuture(sign_in_cred, "Auth::SignInWithCredential() for UserLogin", kAuthErrorNone, auth_); } void Delete() { - if (user_ != nullptr) { - Future delete_future = user_->Delete(); + if (user_.is_valid()) { + Future delete_future = user_.Delete(); if (delete_future.status() == ::firebase::kFutureStatusInvalid) { Login(); - delete_future = user_->Delete(); + delete_future = user_.Delete(); } WaitForFuture(delete_future, "User::Delete()", kAuthErrorNone, log_errors_); } - user_ = nullptr; + user_ = User(); } const char* email() const { return email_.c_str(); } const char* password() const { return password_.c_str(); } - User* user() const { return user_; } + User user() const { return user_; } void set_email(const char* email) { email_ = email; } void set_password(const char* password) { password_ = password; } @@ -389,7 +388,7 @@ class UserLogin { Auth* auth_; std::string email_; std::string password_; - User* user_; + User user_; bool log_errors_; }; @@ -401,7 +400,7 @@ class PhoneListener : public PhoneAuthProvider::Listener { num_calls_on_code_sent_(0), num_calls_on_code_auto_retrieval_time_out_(0) {} - void OnVerificationCompleted(Credential /*credential*/) override { + void OnVerificationCompleted(PhoneAuthCredential /*credential*/) override { LogMessage("PhoneListener: successful automatic verification."); num_calls_on_verification_complete_++; } @@ -493,13 +492,13 @@ extern "C" int common_main(int argc, const char* argv[]) { // It's possible for current_user() to be non-null if the previous run // left us in a signed-in state. - if (auth->current_user() == nullptr) { + if (!auth->current_user().is_valid()) { LogMessage("No user signed in at creation time."); } else { LogMessage( "Current user uid(%s) name(%s) already signed in, so signing them out.", - auth->current_user()->uid().c_str(), - auth->current_user()->display_name().c_str()); + auth->current_user().uid().c_str(), + auth->current_user().display_name().c_str()); auth->SignOut(); } @@ -523,7 +522,7 @@ extern "C" int common_main(int argc, const char* argv[]) { if (kTestCustomEmail) { // Test Auth::SignInWithEmailAndPassword(). // Sign in with email and password that have already been registered. - Future sign_in_future = + Future sign_in_future = auth->SignInWithEmailAndPassword(kCustomEmail, kCustomPassword); WaitForSignInFuture(sign_in_future, "Auth::SignInWithEmailAndPassword() existing " @@ -532,11 +531,11 @@ extern "C" int common_main(int argc, const char* argv[]) { // Test SignOut() after signed in with email and password. if (sign_in_future.status() == ::firebase::kFutureStatusComplete) { auth->SignOut(); - if (auth->current_user() != nullptr) { + if (auth->current_user().is_valid()) { LogMessage( - "ERROR: current_user() returning %x instead of nullptr after " + "ERROR: current_user() returning %s instead of nullptr after " "SignOut()", - auth->current_user()); + auth->current_user().uid().c_str()); } } } @@ -560,7 +559,7 @@ extern "C" int common_main(int argc, const char* argv[]) { token_counter.CompleteTest("SignOut() when already signed-out", 0); // Test notification on SignIn(). - Future sign_in_future = auth->SignInAnonymously(); + Future sign_in_future = auth->SignInAnonymously(); WaitForSignInFuture(sign_in_future, "Auth::SignInAnonymously()", kAuthErrorNone, auth); // Notified when the user is about to change and after the user has @@ -569,21 +568,21 @@ extern "C" int common_main(int argc, const char* argv[]) { token_counter.CompleteTest("SignInAnonymously()", 1, 5); // Refresh the token. - if (auth->current_user() != nullptr) { - Future token_future = auth->current_user()->GetToken(true); + if (auth->current_user().is_valid()) { + Future token_future = auth->current_user().GetToken(true); WaitForFuture(token_future, "GetToken()", kAuthErrorNone); counter.CompleteTest("GetToken()", 0); token_counter.CompleteTest("GetToken()", 1); } // Test notification on SignOut(), when signed-in. - LogMessage("Current user %p", auth->current_user()); // DEBUG + LogMessage("Current user %s", auth->current_user().uid().c_str()); // DEBUG auth->SignOut(); // Wait for the sign out to complete. WaitForSignOut(auth); counter.CompleteTest("SignOut()", 1); token_counter.CompleteTest("SignOut()", 1); - LogMessage("Current user %p", auth->current_user()); // DEBUG + LogMessage("Current user %s", auth->current_user().uid().c_str()); // DEBUG auth->RemoveAuthStateListener(&counter); auth->RemoveIdTokenListener(&token_counter); @@ -638,18 +637,18 @@ extern "C" int common_main(int argc, const char* argv[]) { const Credential phone_credential = phone_provider.GetCredential( listener.verification_id().c_str(), verification_code.c_str()); - Future phone_future = + Futurephone_future = auth->SignInWithCredential(phone_credential); WaitForSignInFuture(phone_future, "Auth::SignInWithCredential() phone credential", kAuthErrorNone, auth); if (phone_future.error() == kAuthErrorNone) { - User* user = *phone_future.result(); - Future update_future = - user->UpdatePhoneNumberCredential(phone_credential); + User user = *phone_future.result(); + Future update_future = + user.UpdatePhoneNumberCredential(phone_credential); WaitForSignInFuture( update_future, - "user->UpdatePhoneNumberCredential(phone_credential)", + "user.UpdatePhoneNumberCredential(phone_credential)", kAuthErrorNone, auth); } @@ -664,12 +663,12 @@ extern "C" int common_main(int argc, const char* argv[]) { { UserLogin user_login(auth); // Generate a random name/password user_login.Register(); - if (!user_login.user()) { + if (!user_login.user().is_valid()) { LogMessage("ERROR: Could not register new user."); } else { // Test Auth::SignInAnonymously(). { - Future sign_in_future = auth->SignInAnonymously(); + Future sign_in_future = auth->SignInAnonymously(); WaitForSignInFuture(sign_in_future, "Auth::SignInAnonymously()", kAuthErrorNone, auth); ExpectTrue("SignInAnonymouslyLastResult matches returned Future", @@ -678,11 +677,11 @@ extern "C" int common_main(int argc, const char* argv[]) { // Test SignOut() after signed in anonymously. if (sign_in_future.status() == ::firebase::kFutureStatusComplete) { auth->SignOut(); - if (auth->current_user() != nullptr) { + if (auth->current_user().is_valid()) { LogMessage( - "ERROR: current_user() returning %x instead of nullptr after " + "ERROR: current_user() returning valid user %s instead of invalid user after " "SignOut()", - auth->current_user()); + auth->current_user().uid().c_str()); } } } @@ -711,7 +710,7 @@ extern "C" int common_main(int argc, const char* argv[]) { // Test Auth::SignInWithEmailAndPassword(). // Sign in with email and password that have already been registered. { - Future sign_in_future = auth->SignInWithEmailAndPassword( + Future sign_in_future = auth->SignInWithEmailAndPassword( user_login.email(), user_login.password()); WaitForSignInFuture( sign_in_future, @@ -724,39 +723,38 @@ extern "C" int common_main(int argc, const char* argv[]) { // Test SignOut() after signed in with email and password. if (sign_in_future.status() == ::firebase::kFutureStatusComplete) { auth->SignOut(); - if (auth->current_user() != nullptr) { + if (auth->current_user().is_valid()) { LogMessage( - "ERROR: current_user() returning %x instead of nullptr after " - "SignOut()", - auth->current_user()); + "ERROR: current_user() returning valid user %s instead of invalid user after " + "SignOut()", auth->current_user().uid().c_str()); } } } // Test User::UpdateUserProfile { - Future sign_in_future = auth->SignInWithEmailAndPassword( + Future sign_in_future = auth->SignInWithEmailAndPassword( user_login.email(), user_login.password()); WaitForSignInFuture( sign_in_future, "Auth::SignInWithEmailAndPassword() existing email and password", kAuthErrorNone, auth); if (sign_in_future.error() == kAuthErrorNone) { - User* user = *sign_in_future.result(); + User user = sign_in_future.result()->user; const char* kDisplayName = "Hello World"; const char* kPhotoUrl = "http://test.com/image.jpg"; User::UserProfile user_profile; user_profile.display_name = kDisplayName; user_profile.photo_url = kPhotoUrl; Future update_profile_future = - user->UpdateUserProfile(user_profile); + user.UpdateUserProfile(user_profile); WaitForFuture(update_profile_future, "User::UpdateUserProfile", kAuthErrorNone); if (update_profile_future.error() == kAuthErrorNone) { ExpectStringsEqual("User::display_name", kDisplayName, - user->display_name().c_str()); + user.display_name().c_str()); ExpectStringsEqual("User::photo_url", kPhotoUrl, - user->photo_url().c_str()); + user.photo_url().c_str()); } } } @@ -764,33 +762,33 @@ extern "C" int common_main(int argc, const char* argv[]) { // Sign in anonymously, link an email credential, reauthenticate with the // credential, unlink the credential and finally sign out. { - Future sign_in_anonymously_future = auth->SignInAnonymously(); + Future sign_in_anonymously_future = auth->SignInAnonymously(); WaitForSignInFuture(sign_in_anonymously_future, "Auth::SignInAnonymously", kAuthErrorNone, auth); if (sign_in_anonymously_future.error() == kAuthErrorNone) { - User* user = *sign_in_anonymously_future.result(); + User user = sign_in_anonymously_future.result()->user; std::string email = CreateNewEmail(); Credential credential = EmailAuthProvider::GetCredential(email.c_str(), kTestPassword); // Link with an email / password credential. - Future link_future = - user->LinkAndRetrieveDataWithCredential(credential); + Future link_future = + user.LinkWithCredential(credential); WaitForSignInFuture(link_future, "User::LinkAndRetrieveDataWithCredential", kAuthErrorNone, auth); if (link_future.error() == kAuthErrorNone) { - LogSignInResult(*link_future.result()); - Future reauth_future = - user->ReauthenticateAndRetrieveData(credential); + LogAuthResult(*link_future.result()); + Future reauth_future = + user.ReauthenticateAndRetrieveData(credential); WaitForSignInFuture(reauth_future, "User::ReauthenticateAndRetrieveData", kAuthErrorNone, auth); if (reauth_future.error() == kAuthErrorNone) { - LogSignInResult(*reauth_future.result()); + LogAuthResult(*reauth_future.result()); } // Unlink email / password from credential. - Future unlink_future = - user->Unlink(credential.provider().c_str()); + Future unlink_future = + user.Unlink(credential.provider().c_str()); WaitForSignInFuture(unlink_future, "User::Unlink", kAuthErrorNone, auth); } @@ -800,7 +798,7 @@ extern "C" int common_main(int argc, const char* argv[]) { // Sign in user with bad email. Should fail. { - Future sign_in_future_bad_email = + Future sign_in_future_bad_email = auth->SignInWithEmailAndPassword(kTestEmailBad, kTestPassword); WaitForSignInFuture(sign_in_future_bad_email, "Auth::SignInWithEmailAndPassword() bad email", @@ -809,7 +807,7 @@ extern "C" int common_main(int argc, const char* argv[]) { // Sign in user with correct email but bad password. Should fail. { - Future sign_in_future_bad_password = + Future sign_in_future_bad_password = auth->SignInWithEmailAndPassword(user_login.email(), kTestPasswordBad); WaitForSignInFuture(sign_in_future_bad_password, @@ -819,7 +817,7 @@ extern "C" int common_main(int argc, const char* argv[]) { // Try to create with existing email. Should fail. { - Future create_future_bad = auth->CreateUserWithEmailAndPassword( + Future create_future_bad = auth->CreateUserWithEmailAndPassword( user_login.email(), user_login.password()); WaitForSignInFuture( create_future_bad, @@ -836,13 +834,11 @@ extern "C" int common_main(int argc, const char* argv[]) { { Credential email_cred_ok = EmailAuthProvider::GetCredential( user_login.email(), user_login.password()); - Future sign_in_cred_ok = + Futuresign_in_cred_ok = auth->SignInWithCredential(email_cred_ok); WaitForSignInFuture(sign_in_cred_ok, "Auth::SignInWithCredential() existing email", kAuthErrorNone, auth); - ExpectTrue("SignInWithCredentialLastResult matches returned Future", - sign_in_cred_ok == auth->SignInWithCredentialLastResult()); } // Test Auth::SignInAndRetrieveDataWithCredential using email & password. @@ -850,7 +846,7 @@ extern "C" int common_main(int argc, const char* argv[]) { { Credential email_cred = EmailAuthProvider::GetCredential( user_login.email(), user_login.password()); - Future sign_in_future = + Future sign_in_future = auth->SignInAndRetrieveDataWithCredential(email_cred); WaitForSignInFuture(sign_in_future, "Auth::SignInAndRetrieveDataWithCredential " @@ -862,10 +858,10 @@ extern "C" int common_main(int argc, const char* argv[]) { sign_in_future == auth->SignInAndRetrieveDataWithCredentialLastResult()); if (sign_in_future.error() == kAuthErrorNone) { - const SignInResult* sign_in_result = sign_in_future.result(); - if (sign_in_result != nullptr && sign_in_result->user) { + const AuthResult* sign_in_result = sign_in_future.result(); + if (sign_in_result != nullptr && sign_in_result->user.is_valid()) { LogMessage("SignInAndRetrieveDataWithCredential"); - LogSignInResult(*sign_in_result); + LogAuthResult(*sign_in_result); } else { LogMessage( "ERROR: SignInAndRetrieveDataWithCredential returned no " @@ -878,7 +874,7 @@ extern "C" int common_main(int argc, const char* argv[]) { { Credential facebook_cred_bad = FacebookAuthProvider::GetCredential(kTestAccessTokenBad); - Future facebook_bad = + Futurefacebook_bad = auth->SignInWithCredential(facebook_cred_bad); WaitForSignInFuture( facebook_bad, @@ -890,7 +886,7 @@ extern "C" int common_main(int argc, const char* argv[]) { { Credential git_hub_cred_bad = GitHubAuthProvider::GetCredential(kTestAccessTokenBad); - Future git_hub_bad = + Futuregit_hub_bad = auth->SignInWithCredential(git_hub_cred_bad); WaitForSignInFuture( git_hub_bad, "Auth::SignInWithCredential() bad GitHub credentials", @@ -901,7 +897,7 @@ extern "C" int common_main(int argc, const char* argv[]) { { Credential google_cred_bad = GoogleAuthProvider::GetCredential( kTestIdTokenBad, kTestAccessTokenBad); - Future google_bad = auth->SignInWithCredential(google_cred_bad); + Futuregoogle_bad = auth->SignInWithCredential(google_cred_bad); WaitForSignInFuture( google_bad, "Auth::SignInWithCredential() bad Google credentials", kAuthErrorInvalidCredential, auth); @@ -911,7 +907,7 @@ extern "C" int common_main(int argc, const char* argv[]) { { Credential google_cred_bad = GoogleAuthProvider::GetCredential(kTestIdTokenBad, nullptr); - Future google_bad = auth->SignInWithCredential(google_cred_bad); + Futuregoogle_bad = auth->SignInWithCredential(google_cred_bad); WaitForSignInFuture( google_bad, "Auth::SignInWithCredential() bad Google credentials", kAuthErrorInvalidCredential, auth); @@ -922,7 +918,7 @@ extern "C" int common_main(int argc, const char* argv[]) { { Credential play_games_cred_bad = PlayGamesAuthProvider::GetCredential(kTestServerAuthCodeBad); - Future play_games_bad = + Futureplay_games_bad = auth->SignInWithCredential(play_games_cred_bad); WaitForSignInFuture( play_games_bad, @@ -959,7 +955,7 @@ extern "C" int common_main(int argc, const char* argv[]) { if (gc_credential_ptr == nullptr) { LogMessage("Failed to retrieve Game Center credential."); } else { - Future game_center_user = + Futuregame_center_user = auth->SignInWithCredential(*gc_credential_ptr); WaitForFuture(game_center_user, "Auth::SignInWithCredential() test Game Center " @@ -974,7 +970,7 @@ extern "C" int common_main(int argc, const char* argv[]) { { Credential twitter_cred_bad = TwitterAuthProvider::GetCredential( kTestIdTokenBad, kTestAccessTokenBad); - Future twitter_bad = + Futuretwitter_bad = auth->SignInWithCredential(twitter_cred_bad); WaitForSignInFuture( twitter_bad, "Auth::SignInWithCredential() bad Twitter credentials", @@ -999,7 +995,7 @@ extern "C" int common_main(int argc, const char* argv[]) { { Credential oauth_cred_bad = OAuthProvider::GetCredential( kTestIdProviderIdBad, kTestIdTokenBad, kTestAccessTokenBad); - Future oauth_bad = auth->SignInWithCredential(oauth_cred_bad); + Futureoauth_bad = auth->SignInWithCredential(oauth_cred_bad); WaitForSignInFuture( oauth_bad, "Auth::SignInWithCredential() bad OAuth credentials", kAuthErrorFailure, auth); @@ -1010,7 +1006,7 @@ extern "C" int common_main(int argc, const char* argv[]) { Credential oauth_cred_bad = OAuthProvider::GetCredential(kTestIdProviderIdBad, kTestIdTokenBad, kTestNonceBad, kTestAccessTokenBad); - Future oauth_bad = auth->SignInWithCredential(oauth_cred_bad); + Futureoauth_bad = auth->SignInWithCredential(oauth_cred_bad); WaitForSignInFuture( oauth_bad, "Auth::SignInWithCredential() bad OAuth credentials", kAuthErrorFailure, auth); @@ -1042,48 +1038,48 @@ extern "C" int common_main(int argc, const char* argv[]) { // --- User tests ------------------------------------------------------------ // Test anonymous user info strings. { - Future anon_sign_in_for_user = auth->SignInAnonymously(); + Future anon_sign_in_for_user = auth->SignInAnonymously(); WaitForSignInFuture(anon_sign_in_for_user, "Auth::SignInAnonymously() for User", kAuthErrorNone, auth); if (anon_sign_in_for_user.status() == ::firebase::kFutureStatusComplete) { - User* anonymous_user = anon_sign_in_for_user.result() - ? *anon_sign_in_for_user.result() - : nullptr; - if (anonymous_user != nullptr) { - LogMessage("Anonymous uid is %s", anonymous_user->uid().c_str()); + User anonymous_user = anon_sign_in_for_user.result() + ? anon_sign_in_for_user.result()->user + : User(); + if (anonymous_user.is_valid()) { + LogMessage("Anonymous uid is %s", anonymous_user.uid().c_str()); ExpectStringsEqual("Anonymous user email", "", - anonymous_user->email().c_str()); + anonymous_user.email().c_str()); ExpectStringsEqual("Anonymous user display_name", "", - anonymous_user->display_name().c_str()); + anonymous_user.display_name().c_str()); ExpectStringsEqual("Anonymous user photo_url", "", - anonymous_user->photo_url().c_str()); + anonymous_user.photo_url().c_str()); ExpectStringsEqual("Anonymous user provider_id", kFirebaseProviderId, - anonymous_user->provider_id().c_str()); + anonymous_user.provider_id().c_str()); ExpectTrue("Anonymous user is_anonymous()", - anonymous_user->is_anonymous()); + anonymous_user.is_anonymous()); ExpectFalse("Anonymous user is_email_verified()", - anonymous_user->is_email_verified()); + anonymous_user.is_email_verified()); ExpectTrue("Anonymous user metadata().last_sign_in_timestamp != 0", - anonymous_user->metadata().last_sign_in_timestamp != 0); + anonymous_user.metadata().last_sign_in_timestamp != 0); ExpectTrue("Anonymous user metadata().creation_timestamp != 0", - anonymous_user->metadata().creation_timestamp != 0); + anonymous_user.metadata().creation_timestamp != 0); // Test User::LinkWithCredential(), linking with email & password. const std::string newer_email = CreateNewEmail(); Credential user_cred = EmailAuthProvider::GetCredential( newer_email.c_str(), kTestPassword); { - Future link_future = - anonymous_user->LinkWithCredential(user_cred); + Future link_future = + anonymous_user.LinkWithCredential(user_cred); WaitForSignInFuture(link_future, "User::LinkWithCredential()", kAuthErrorNone, auth); } // Test User::LinkWithCredential(), linking with same email & password. { - Future link_future = - anonymous_user->LinkWithCredential(user_cred); + Future link_future = + anonymous_user.LinkWithCredential(user_cred); WaitForSignInFuture(link_future, "User::LinkWithCredential() again", ::firebase::auth::kAuthErrorProviderAlreadyLinked, auth); @@ -1092,14 +1088,14 @@ extern "C" int common_main(int argc, const char* argv[]) { // Test User::LinkWithCredential(), linking with bad credential. // Call should fail and Auth's current user should be maintained. { - const User* pre_link_user = auth->current_user(); + const User pre_link_user = auth->current_user(); ExpectTrue("Test precondition requires active user", - pre_link_user != nullptr); + pre_link_user.is_valid()); Credential twitter_cred_bad = TwitterAuthProvider::GetCredential( kTestIdTokenBad, kTestAccessTokenBad); - Future link_bad_future = - anonymous_user->LinkWithCredential(twitter_cred_bad); + Future link_bad_future = + anonymous_user.LinkWithCredential(twitter_cred_bad); WaitForFuture(link_bad_future, "User::LinkWithCredential() with bad credential", kAuthErrorInvalidCredential); @@ -1110,12 +1106,12 @@ extern "C" int common_main(int argc, const char* argv[]) { // Test Auth::SignInWithCredential(), signing in with bad credential. // Call should fail, and Auth's current user should be maintained. { - const User* pre_signin_user = auth->current_user(); + const User pre_signin_user = auth->current_user(); ExpectTrue("Test precondition requires active user", - pre_signin_user != nullptr); + pre_signin_user.is_valid()); Credential twitter_cred_bad = TwitterAuthProvider::GetCredential( kTestIdTokenBad, kTestAccessTokenBad); - Future signin_bad_future = + Futuresignin_bad_future = auth->SignInWithCredential(twitter_cred_bad); WaitForFuture(signin_bad_future, "Auth::SignInWithCredential() with bad credential", @@ -1127,41 +1123,41 @@ extern "C" int common_main(int argc, const char* argv[]) { UserLogin user_login(auth); user_login.Register(); - if (!user_login.user()) { + if (!user_login.user().is_valid()) { LogMessage("Error - Could not create new user."); } else { // Test email user info strings. - Future email_sign_in_for_user = + Future email_sign_in_for_user = auth->SignInWithEmailAndPassword(user_login.email(), user_login.password()); WaitForSignInFuture(email_sign_in_for_user, "Auth::SignInWithEmailAndPassword() for User", kAuthErrorNone, auth); - User* email_user = email_sign_in_for_user.result() - ? *email_sign_in_for_user.result() - : nullptr; - if (email_user != nullptr) { - LogMessage("Email uid is %s", email_user->uid().c_str()); + User email_user = email_sign_in_for_user.result() + ? email_sign_in_for_user.result()->user + : User(); + if (email_user.is_valid()) { + LogMessage("Email uid is %s", email_user.uid().c_str()); ExpectStringsEqual("Email user email", user_login.email(), - email_user->email().c_str()); + email_user.email().c_str()); ExpectStringsEqual("Email user display_name", "", - email_user->display_name().c_str()); + email_user.display_name().c_str()); ExpectStringsEqual("Email user photo_url", "", - email_user->photo_url().c_str()); + email_user.photo_url().c_str()); ExpectStringsEqual("Email user provider_id", kFirebaseProviderId, - email_user->provider_id().c_str()); + email_user.provider_id().c_str()); ExpectFalse("Email user is_anonymous()", - email_user->is_anonymous()); + email_user.is_anonymous()); ExpectFalse("Email user is_email_verified()", - email_user->is_email_verified()); + email_user.is_email_verified()); ExpectTrue("Email user metadata().last_sign_in_timestamp != 0", - email_user->metadata().last_sign_in_timestamp != 0); + email_user.metadata().last_sign_in_timestamp != 0); ExpectTrue("Email user metadata().creation_timestamp != 0", - email_user->metadata().creation_timestamp != 0); + email_user.metadata().creation_timestamp != 0); // Test User::GetToken(). // with force_refresh = false. - Future token_no_refresh = email_user->GetToken(false); + Future token_no_refresh = email_user.GetToken(false); WaitForFuture(token_no_refresh, "User::GetToken(false)", kAuthErrorNone); LogMessage("User::GetToken(false) = %s", @@ -1171,7 +1167,7 @@ extern "C" int common_main(int argc, const char* argv[]) { // with force_refresh = true. Future token_force_refresh = - email_user->GetToken(true); + email_user.GetToken(true); WaitForFuture(token_force_refresh, "User::GetToken(true)", kAuthErrorNone); LogMessage("User::GetToken(true) = %s", @@ -1180,59 +1176,59 @@ extern "C" int common_main(int argc, const char* argv[]) { : ""); // Test Reload(). - Future reload_future = email_user->Reload(); + Future reload_future = email_user.Reload(); WaitForFuture(reload_future, "User::Reload()", kAuthErrorNone); // Test User::Unlink(). - Future unlink_future = email_user->Unlink("firebase"); + Future unlink_future = email_user.Unlink("firebase"); WaitForSignInFuture(unlink_future, "User::Unlink()", ::firebase::auth::kAuthErrorNoSuchProvider, auth); // Sign in again if user is now invalid. - if (auth->current_user() == nullptr) { - Future email_sign_in_again = + if (!auth->current_user().is_valid()) { + Future email_sign_in_again = auth->SignInWithEmailAndPassword(user_login.email(), user_login.password()); WaitForSignInFuture(email_sign_in_again, "Auth::SignInWithEmailAndPassword() again", kAuthErrorNone, auth); email_user = email_sign_in_again.result() - ? *email_sign_in_again.result() - : nullptr; + ? email_sign_in_again.result()->user + : User(); } } - if (email_user != nullptr) { + if (email_user.is_valid()) { // Test User::provider_data(). - const std::vector& provider_data = - email_user->provider_data(); + const std::vector provider_data = + email_user.provider_data(); LogMessage("User::provider_data() returned %d interface%s", provider_data.size(), provider_data.size() == 1 ? "" : "s"); for (size_t i = 0; i < provider_data.size(); ++i) { - const UserInfoInterface* user_info = provider_data[i]; + const UserInfoInterface user_info = provider_data[i]; LogMessage( " UID() = %s\n" " Email() = %s\n" " DisplayName() = %s\n" " PhotoUrl() = %s\n" " ProviderId() = %s", - user_info->uid().c_str(), user_info->email().c_str(), - user_info->display_name().c_str(), - user_info->photo_url().c_str(), - user_info->provider_id().c_str()); + user_info.uid().c_str(), user_info.email().c_str(), + user_info.display_name().c_str(), + user_info.photo_url().c_str(), + user_info.provider_id().c_str()); } // Test User::UpdateEmail(). const std::string newest_email = CreateNewEmail(); Future update_email_future = - email_user->UpdateEmail(newest_email.c_str()); + email_user.UpdateEmail(newest_email.c_str()); WaitForFuture(update_email_future, "User::UpdateEmail()", kAuthErrorNone); // Test User::UpdatePassword(). Future update_password_future = - email_user->UpdatePassword(kTestPasswordUpdated); + email_user.UpdatePassword(kTestPasswordUpdated); WaitForFuture(update_password_future, "User::UpdatePassword()", kAuthErrorNone); @@ -1240,13 +1236,13 @@ extern "C" int common_main(int argc, const char* argv[]) { Credential email_cred_reauth = EmailAuthProvider::GetCredential( newest_email.c_str(), kTestPasswordUpdated); Future reauthenticate_future = - email_user->Reauthenticate(email_cred_reauth); + email_user.Reauthenticate(email_cred_reauth); WaitForFuture(reauthenticate_future, "User::Reauthenticate()", kAuthErrorNone); // Test User::SendEmailVerification(). Future send_email_verification_future = - email_user->SendEmailVerification(); + email_user.SendEmailVerification(); WaitForFuture(send_email_verification_future, "User::SendEmailVerification()", kAuthErrorNone); } @@ -1256,29 +1252,29 @@ extern "C" int common_main(int argc, const char* argv[]) { // Test User::Delete(). const std::string new_email_for_delete = CreateNewEmail(); - Future create_future_for_delete = + Future create_future_for_delete = auth->CreateUserWithEmailAndPassword(new_email_for_delete.c_str(), kTestPassword); WaitForSignInFuture( create_future_for_delete, "Auth::CreateUserWithEmailAndPassword() new email for delete", kAuthErrorNone, auth); - User* email_user_for_delete = create_future_for_delete.result() - ? *create_future_for_delete.result() - : nullptr; - if (email_user_for_delete != nullptr) { - Future delete_future = email_user_for_delete->Delete(); + User email_user_for_delete = create_future_for_delete.result() + ? create_future_for_delete.result()->user + : User(); + if (email_user_for_delete.is_valid()) { + Future delete_future = email_user_for_delete.Delete(); WaitForFuture(delete_future, "User::Delete()", kAuthErrorNone); } } { // We end with a login so that we can test if a second run will detect // that we're already logged-in. - Future sign_in_future = auth->SignInAnonymously(); + Future sign_in_future = auth->SignInAnonymously(); WaitForSignInFuture(sign_in_future, "Auth::SignInAnonymously() at end", kAuthErrorNone, auth); - LogMessage("Anonymous uid(%s)", auth->current_user()->uid().c_str()); + LogMessage("Anonymous uid(%s)", auth->current_user().uid().c_str()); } #ifdef INTERNAL_EXPERIMENTAL @@ -1305,13 +1301,13 @@ extern "C" int common_main(int argc, const char* argv[]) { firebase::auth::FederatedOAuthProvider provider; provider.SetProviderData(provider_data); LogMessage("invoking linkwithprovider"); - Future sign_in_future = - user_login.user()->LinkWithProvider(&provider); + Future sign_in_future = + user_login.user().LinkWithProvider(&provider); WaitForSignInFuture(sign_in_future, "LinkWithProvider", kAuthErrorNone, auth); if (sign_in_future.error() == kAuthErrorNone) { - const SignInResult* result_ptr = sign_in_future.result(); - LogMessage("user email %s", result_ptr->user->email().c_str()); + const AuthResult* result_ptr = sign_in_future.result(); + LogMessage("user email %s", result_ptr->user.email().c_str()); LogMessage("Additonal user info provider_id: %s", result_ptr->info.provider_id.c_str()); LogMessage("LinkWithProviderDone"); @@ -1330,12 +1326,12 @@ extern "C" int common_main(int argc, const char* argv[]) { firebase::auth::FederatedOAuthProvider provider; provider.SetProviderData(provider_data); LogMessage("SignInWithProvider SETUP COMPLETE"); - Future sign_in_future = auth->SignInWithProvider(&provider); + Future sign_in_future = auth->SignInWithProvider(&provider); WaitForSignInFuture(sign_in_future, "SignInWithProvider", kAuthErrorNone, auth); if (sign_in_future.error() == kAuthErrorNone && sign_in_future.result() != nullptr) { - LogSignInResult(*sign_in_future.result()); + LogAuthResult(*sign_in_future.result()); } } @@ -1351,13 +1347,13 @@ extern "C" int common_main(int argc, const char* argv[]) { firebase::auth::FederatedOAuthProvider provider; provider.SetProviderData(provider_data); - Future sign_in_future = - auth->current_user()->ReauthenticateWithProvider(&provider); + Future sign_in_future = + auth->current_user().ReauthenticateWithProvider(&provider); WaitForSignInFuture(sign_in_future, "ReauthenticateWithProvider", kAuthErrorNone, auth); if (sign_in_future.error() == kAuthErrorNone && sign_in_future.result() != nullptr) { - LogSignInResult(*sign_in_future.result()); + LogAuthResult(*sign_in_future.result()); } } } @@ -1365,7 +1361,7 @@ extern "C" int common_main(int argc, const char* argv[]) { // Clean up provider-linked user so we can run the test app again // and not get "user with that email already exists" errors. if (auth->current_user()) { - WaitForFuture(auth->current_user()->Delete(), "Delete User", + WaitForFuture(auth->current_user().Delete(), "Delete User", kAuthErrorNone, /*log_error=*/true); } From c44177e940241ccb7aa2f80aa9de6b4250792881 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 22 May 2024 10:53:42 -0700 Subject: [PATCH 31/57] Update gradle wrapper and minSdk versions. --- admob/testapp/AndroidManifest.xml | 2 +- admob/testapp/build.gradle | 2 +- admob/testapp/gradle/wrapper/gradle-wrapper.properties | 2 +- analytics/testapp/AndroidManifest.xml | 2 +- analytics/testapp/build.gradle | 2 +- analytics/testapp/gradle/wrapper/gradle-wrapper.properties | 2 +- auth/testapp/AndroidManifest.xml | 2 +- auth/testapp/build.gradle | 2 +- auth/testapp/gradle/wrapper/gradle-wrapper.properties | 2 +- database/testapp/AndroidManifest.xml | 2 +- database/testapp/build.gradle | 2 +- database/testapp/gradle/wrapper/gradle-wrapper.properties | 2 +- dynamic_links/testapp/AndroidManifest.xml | 2 +- dynamic_links/testapp/build.gradle | 2 +- dynamic_links/testapp/gradle/wrapper/gradle-wrapper.properties | 2 +- firestore/testapp/AndroidManifest.xml | 2 +- firestore/testapp/build.gradle | 2 +- firestore/testapp/gradle/wrapper/gradle-wrapper.properties | 2 +- functions/testapp/AndroidManifest.xml | 2 +- functions/testapp/build.gradle | 2 +- functions/testapp/gradle/wrapper/gradle-wrapper.properties | 2 +- gma/testapp/AndroidManifest.xml | 2 +- gma/testapp/build.gradle | 2 +- gma/testapp/gradle/wrapper/gradle-wrapper.properties | 2 +- messaging/testapp/AndroidManifest.xml | 2 +- messaging/testapp/build.gradle | 2 +- messaging/testapp/gradle/wrapper/gradle-wrapper.properties | 2 +- remote_config/testapp/AndroidManifest.xml | 2 +- remote_config/testapp/build.gradle | 2 +- remote_config/testapp/gradle/wrapper/gradle-wrapper.properties | 2 +- storage/testapp/AndroidManifest.xml | 2 +- storage/testapp/build.gradle | 2 +- storage/testapp/gradle/wrapper/gradle-wrapper.properties | 2 +- 33 files changed, 33 insertions(+), 33 deletions(-) diff --git a/admob/testapp/AndroidManifest.xml b/admob/testapp/AndroidManifest.xml index e62e6385..aa6b115d 100644 --- a/admob/testapp/AndroidManifest.xml +++ b/admob/testapp/AndroidManifest.xml @@ -6,7 +6,7 @@ - + - + - + - + - + - + - + - + - + diff --git a/messaging/testapp/build.gradle b/messaging/testapp/build.gradle index d0565e63..a2b2a9c6 100644 --- a/messaging/testapp/build.gradle +++ b/messaging/testapp/build.gradle @@ -26,7 +26,7 @@ android { sourceCompatibility 1.8 targetCompatibility 1.8 } - compileSdkVersion 28 + compileSdkVersion 34 buildToolsVersion '28.0.3' sourceSets { diff --git a/messaging/testapp/gradle/wrapper/gradle-wrapper.properties b/messaging/testapp/gradle/wrapper/gradle-wrapper.properties index 9e09cdb6..65340c1b 100644 --- a/messaging/testapp/gradle/wrapper/gradle-wrapper.properties +++ b/messaging/testapp/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https://services.gradle.org/distributions/gradle-5.6.4-all.zip +distributionUrl=https://services.gradle.org/distributions/gradle-6.7.1-all.zip diff --git a/remote_config/testapp/AndroidManifest.xml b/remote_config/testapp/AndroidManifest.xml index e449f7ee..326d45b5 100644 --- a/remote_config/testapp/AndroidManifest.xml +++ b/remote_config/testapp/AndroidManifest.xml @@ -6,7 +6,7 @@ - + - + Date: Wed, 22 May 2024 10:55:39 -0700 Subject: [PATCH 32/57] Update minSdk and targetSdk versions. --- auth/testapp/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auth/testapp/build.gradle b/auth/testapp/build.gradle index 6dec5bf1..f1f97cfc 100644 --- a/auth/testapp/build.gradle +++ b/auth/testapp/build.gradle @@ -41,8 +41,8 @@ android { defaultConfig { applicationId 'com.google.android.auth.testapp' - minSdkVersion 19 - targetSdkVersion 28 + minSdkVersion 21 + targetSdkVersion 34 versionCode 1 versionName '1.0' externalNativeBuild.cmake { From 49c7b767736b1497461575b7cbf13014cdd8d689 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 22 May 2024 10:57:03 -0700 Subject: [PATCH 33/57] Add google services files to ignore list. --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c4f78aab --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +GoogleService-Info.plist +google-services.json From 5b223690c10757aa794cd3d61fb8040e82ff3885 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 22 May 2024 11:01:10 -0700 Subject: [PATCH 34/57] Update gradle plugin and build tools versions. --- admob/testapp/build.gradle | 4 ++-- analytics/testapp/build.gradle | 4 ++-- auth/testapp/build.gradle | 4 ++-- database/testapp/build.gradle | 4 ++-- dynamic_links/testapp/build.gradle | 4 ++-- firestore/testapp/build.gradle | 4 ++-- functions/testapp/build.gradle | 4 ++-- gma/testapp/build.gradle | 4 ++-- messaging/testapp/build.gradle | 4 ++-- remote_config/testapp/build.gradle | 4 ++-- storage/testapp/build.gradle | 4 ++-- 11 files changed, 22 insertions(+), 22 deletions(-) diff --git a/admob/testapp/build.gradle b/admob/testapp/build.gradle index 4729245e..5c5bc306 100644 --- a/admob/testapp/build.gradle +++ b/admob/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.3' + classpath 'com.android.tools.build:gradle:4.2.1' classpath 'com.google.gms:google-services:4.0.1' } } @@ -23,7 +23,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion 34 - buildToolsVersion '28.0.3' + buildToolsVersion '30.0.2' sourceSets { main { diff --git a/analytics/testapp/build.gradle b/analytics/testapp/build.gradle index ebb85736..b0096e32 100644 --- a/analytics/testapp/build.gradle +++ b/analytics/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.3' + classpath 'com.android.tools.build:gradle:4.2.1' classpath 'com.google.gms:google-services:4.0.1' } } @@ -27,7 +27,7 @@ android { targetCompatibility 1.8 } compileSdkVersion 34 - buildToolsVersion '28.0.3' + buildToolsVersion '30.0.2' sourceSets { main { diff --git a/auth/testapp/build.gradle b/auth/testapp/build.gradle index f1f97cfc..084921d3 100644 --- a/auth/testapp/build.gradle +++ b/auth/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.3' + classpath 'com.android.tools.build:gradle:4.2.1' classpath 'com.google.gms:google-services:4.0.1' } } @@ -28,7 +28,7 @@ android { } compileSdkVersion 34 - buildToolsVersion '28.0.3' + buildToolsVersion '30.0.2' sourceSets { main { diff --git a/database/testapp/build.gradle b/database/testapp/build.gradle index 6943b414..1881f441 100644 --- a/database/testapp/build.gradle +++ b/database/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.3' + classpath 'com.android.tools.build:gradle:4.2.1' classpath 'com.google.gms:google-services:4.0.1' } } @@ -27,7 +27,7 @@ android { targetCompatibility 1.8 } compileSdkVersion 34 - buildToolsVersion '28.0.3' + buildToolsVersion '30.0.2' sourceSets { main { diff --git a/dynamic_links/testapp/build.gradle b/dynamic_links/testapp/build.gradle index 82962584..742d0e74 100644 --- a/dynamic_links/testapp/build.gradle +++ b/dynamic_links/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.3' + classpath 'com.android.tools.build:gradle:4.2.1' classpath 'com.google.gms:google-services:4.0.1' } } @@ -27,7 +27,7 @@ android { targetCompatibility 1.8 } compileSdkVersion 34 - buildToolsVersion '28.0.3' + buildToolsVersion '30.0.2' sourceSets { main { diff --git a/firestore/testapp/build.gradle b/firestore/testapp/build.gradle index d8499acf..75525a31 100644 --- a/firestore/testapp/build.gradle +++ b/firestore/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.3' + classpath 'com.android.tools.build:gradle:4.2.1' classpath 'com.google.gms:google-services:4.0.1' } } @@ -27,7 +27,7 @@ android { targetCompatibility 1.8 } compileSdkVersion 34 - buildToolsVersion "28.0.3" + buildToolsVersion '30.0.2' sourceSets { main { diff --git a/functions/testapp/build.gradle b/functions/testapp/build.gradle index d7d54ee5..83891d53 100644 --- a/functions/testapp/build.gradle +++ b/functions/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.3' + classpath 'com.android.tools.build:gradle:4.2.1' classpath 'com.google.gms:google-services:4.0.1' } } @@ -27,7 +27,7 @@ android { targetCompatibility 1.8 } compileSdkVersion 34 - buildToolsVersion '28.0.3' + buildToolsVersion '30.0.2' sourceSets { main { diff --git a/gma/testapp/build.gradle b/gma/testapp/build.gradle index d3c1e57b..d878a2df 100644 --- a/gma/testapp/build.gradle +++ b/gma/testapp/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.3' + classpath 'com.android.tools.build:gradle:4.2.1' classpath 'com.google.gms:google-services:4.0.1' } } @@ -28,7 +28,7 @@ android { } compileSdkVersion 34 - buildToolsVersion '28.0.3' + buildToolsVersion '30.0.2' sourceSets { main { diff --git a/messaging/testapp/build.gradle b/messaging/testapp/build.gradle index a2b2a9c6..a21cb697 100644 --- a/messaging/testapp/build.gradle +++ b/messaging/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.3' + classpath 'com.android.tools.build:gradle:4.2.1' classpath 'com.google.gms:google-services:4.0.1' } } @@ -27,7 +27,7 @@ android { targetCompatibility 1.8 } compileSdkVersion 34 - buildToolsVersion '28.0.3' + buildToolsVersion '30.0.2' sourceSets { main { diff --git a/remote_config/testapp/build.gradle b/remote_config/testapp/build.gradle index b0f051d6..c854c778 100644 --- a/remote_config/testapp/build.gradle +++ b/remote_config/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.3' + classpath 'com.android.tools.build:gradle:4.2.1' classpath 'com.google.gms:google-services:4.0.1' } } @@ -27,7 +27,7 @@ android { targetCompatibility 1.8 } compileSdkVersion 34 - buildToolsVersion '28.0.3' + buildToolsVersion '30.0.2' sourceSets { main { diff --git a/storage/testapp/build.gradle b/storage/testapp/build.gradle index 78975f74..94355c6e 100644 --- a/storage/testapp/build.gradle +++ b/storage/testapp/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.3' + classpath 'com.android.tools.build:gradle:4.2.1' classpath 'com.google.gms:google-services:4.0.1' } } @@ -27,7 +27,7 @@ android { targetCompatibility 1.8 } compileSdkVersion 34 - buildToolsVersion '28.0.3' + buildToolsVersion '30.0.2' sourceSets { main { From 4349efd9d8b84db2a1ca45eff1973717829554a5 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 22 May 2024 11:03:11 -0700 Subject: [PATCH 35/57] Add NDK path environment variable. --- admob/testapp/build.gradle | 1 + analytics/testapp/build.gradle | 1 + auth/testapp/build.gradle | 1 + database/testapp/build.gradle | 1 + dynamic_links/testapp/build.gradle | 1 + firestore/testapp/build.gradle | 1 + functions/testapp/build.gradle | 1 + gma/testapp/build.gradle | 1 + messaging/testapp/build.gradle | 1 + remote_config/testapp/build.gradle | 1 + storage/testapp/build.gradle | 1 + 11 files changed, 11 insertions(+) diff --git a/admob/testapp/build.gradle b/admob/testapp/build.gradle index 5c5bc306..570ddee6 100644 --- a/admob/testapp/build.gradle +++ b/admob/testapp/build.gradle @@ -23,6 +23,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion 34 + ndkPath System.getenv('ANDROID_NDK_HOME') buildToolsVersion '30.0.2' sourceSets { diff --git a/analytics/testapp/build.gradle b/analytics/testapp/build.gradle index b0096e32..37c97b80 100644 --- a/analytics/testapp/build.gradle +++ b/analytics/testapp/build.gradle @@ -27,6 +27,7 @@ android { targetCompatibility 1.8 } compileSdkVersion 34 + ndkPath System.getenv('ANDROID_NDK_HOME') buildToolsVersion '30.0.2' sourceSets { diff --git a/auth/testapp/build.gradle b/auth/testapp/build.gradle index 084921d3..10042b88 100644 --- a/auth/testapp/build.gradle +++ b/auth/testapp/build.gradle @@ -28,6 +28,7 @@ android { } compileSdkVersion 34 + ndkPath System.getenv('ANDROID_NDK_HOME') buildToolsVersion '30.0.2' sourceSets { diff --git a/database/testapp/build.gradle b/database/testapp/build.gradle index 1881f441..0f57b575 100644 --- a/database/testapp/build.gradle +++ b/database/testapp/build.gradle @@ -27,6 +27,7 @@ android { targetCompatibility 1.8 } compileSdkVersion 34 + ndkPath System.getenv('ANDROID_NDK_HOME') buildToolsVersion '30.0.2' sourceSets { diff --git a/dynamic_links/testapp/build.gradle b/dynamic_links/testapp/build.gradle index 742d0e74..a4f09573 100644 --- a/dynamic_links/testapp/build.gradle +++ b/dynamic_links/testapp/build.gradle @@ -27,6 +27,7 @@ android { targetCompatibility 1.8 } compileSdkVersion 34 + ndkPath System.getenv('ANDROID_NDK_HOME') buildToolsVersion '30.0.2' sourceSets { diff --git a/firestore/testapp/build.gradle b/firestore/testapp/build.gradle index 75525a31..9195dbf1 100644 --- a/firestore/testapp/build.gradle +++ b/firestore/testapp/build.gradle @@ -27,6 +27,7 @@ android { targetCompatibility 1.8 } compileSdkVersion 34 + ndkPath System.getenv('ANDROID_NDK_HOME') buildToolsVersion '30.0.2' sourceSets { diff --git a/functions/testapp/build.gradle b/functions/testapp/build.gradle index 83891d53..9977f3f7 100644 --- a/functions/testapp/build.gradle +++ b/functions/testapp/build.gradle @@ -27,6 +27,7 @@ android { targetCompatibility 1.8 } compileSdkVersion 34 + ndkPath System.getenv('ANDROID_NDK_HOME') buildToolsVersion '30.0.2' sourceSets { diff --git a/gma/testapp/build.gradle b/gma/testapp/build.gradle index d878a2df..5c8972e4 100644 --- a/gma/testapp/build.gradle +++ b/gma/testapp/build.gradle @@ -28,6 +28,7 @@ android { } compileSdkVersion 34 + ndkPath System.getenv('ANDROID_NDK_HOME') buildToolsVersion '30.0.2' sourceSets { diff --git a/messaging/testapp/build.gradle b/messaging/testapp/build.gradle index a21cb697..38131c52 100644 --- a/messaging/testapp/build.gradle +++ b/messaging/testapp/build.gradle @@ -27,6 +27,7 @@ android { targetCompatibility 1.8 } compileSdkVersion 34 + ndkPath System.getenv('ANDROID_NDK_HOME') buildToolsVersion '30.0.2' sourceSets { diff --git a/remote_config/testapp/build.gradle b/remote_config/testapp/build.gradle index c854c778..97bf0a50 100644 --- a/remote_config/testapp/build.gradle +++ b/remote_config/testapp/build.gradle @@ -27,6 +27,7 @@ android { targetCompatibility 1.8 } compileSdkVersion 34 + ndkPath System.getenv('ANDROID_NDK_HOME') buildToolsVersion '30.0.2' sourceSets { diff --git a/storage/testapp/build.gradle b/storage/testapp/build.gradle index 94355c6e..f128fcf7 100644 --- a/storage/testapp/build.gradle +++ b/storage/testapp/build.gradle @@ -27,6 +27,7 @@ android { targetCompatibility 1.8 } compileSdkVersion 34 + ndkPath System.getenv('ANDROID_NDK_HOME') buildToolsVersion '30.0.2' sourceSets { From 6f245c28cb3fae32acc0502e89fa13259fd43b5d Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 22 May 2024 11:05:28 -0700 Subject: [PATCH 36/57] Add AndroidX to properties file. --- admob/testapp/gradle.properties | 1 + analytics/testapp/gradle.properties | 1 + auth/testapp/gradle.properties | 1 + database/testapp/gradle.properties | 1 + dynamic_links/testapp/gradle.properties | 1 + firestore/testapp/gradle.properties | 1 + functions/testapp/gradle.properties | 1 + gma/testapp/gradle.properties | 1 + messaging/testapp/gradle.properties | 1 + remote_config/testapp/gradle.properties | 1 + storage/testapp/gradle.properties | 1 + 11 files changed, 11 insertions(+) create mode 100644 admob/testapp/gradle.properties create mode 100644 analytics/testapp/gradle.properties create mode 100644 auth/testapp/gradle.properties create mode 100644 database/testapp/gradle.properties create mode 100644 dynamic_links/testapp/gradle.properties create mode 100644 firestore/testapp/gradle.properties create mode 100644 functions/testapp/gradle.properties create mode 100644 gma/testapp/gradle.properties create mode 100644 messaging/testapp/gradle.properties create mode 100644 remote_config/testapp/gradle.properties create mode 100644 storage/testapp/gradle.properties diff --git a/admob/testapp/gradle.properties b/admob/testapp/gradle.properties new file mode 100644 index 00000000..d7ba8f42 --- /dev/null +++ b/admob/testapp/gradle.properties @@ -0,0 +1 @@ +android.useAndroidX = true diff --git a/analytics/testapp/gradle.properties b/analytics/testapp/gradle.properties new file mode 100644 index 00000000..d7ba8f42 --- /dev/null +++ b/analytics/testapp/gradle.properties @@ -0,0 +1 @@ +android.useAndroidX = true diff --git a/auth/testapp/gradle.properties b/auth/testapp/gradle.properties new file mode 100644 index 00000000..d7ba8f42 --- /dev/null +++ b/auth/testapp/gradle.properties @@ -0,0 +1 @@ +android.useAndroidX = true diff --git a/database/testapp/gradle.properties b/database/testapp/gradle.properties new file mode 100644 index 00000000..d7ba8f42 --- /dev/null +++ b/database/testapp/gradle.properties @@ -0,0 +1 @@ +android.useAndroidX = true diff --git a/dynamic_links/testapp/gradle.properties b/dynamic_links/testapp/gradle.properties new file mode 100644 index 00000000..d7ba8f42 --- /dev/null +++ b/dynamic_links/testapp/gradle.properties @@ -0,0 +1 @@ +android.useAndroidX = true diff --git a/firestore/testapp/gradle.properties b/firestore/testapp/gradle.properties new file mode 100644 index 00000000..d7ba8f42 --- /dev/null +++ b/firestore/testapp/gradle.properties @@ -0,0 +1 @@ +android.useAndroidX = true diff --git a/functions/testapp/gradle.properties b/functions/testapp/gradle.properties new file mode 100644 index 00000000..d7ba8f42 --- /dev/null +++ b/functions/testapp/gradle.properties @@ -0,0 +1 @@ +android.useAndroidX = true diff --git a/gma/testapp/gradle.properties b/gma/testapp/gradle.properties new file mode 100644 index 00000000..d7ba8f42 --- /dev/null +++ b/gma/testapp/gradle.properties @@ -0,0 +1 @@ +android.useAndroidX = true diff --git a/messaging/testapp/gradle.properties b/messaging/testapp/gradle.properties new file mode 100644 index 00000000..d7ba8f42 --- /dev/null +++ b/messaging/testapp/gradle.properties @@ -0,0 +1 @@ +android.useAndroidX = true diff --git a/remote_config/testapp/gradle.properties b/remote_config/testapp/gradle.properties new file mode 100644 index 00000000..d7ba8f42 --- /dev/null +++ b/remote_config/testapp/gradle.properties @@ -0,0 +1 @@ +android.useAndroidX = true diff --git a/storage/testapp/gradle.properties b/storage/testapp/gradle.properties new file mode 100644 index 00000000..d7ba8f42 --- /dev/null +++ b/storage/testapp/gradle.properties @@ -0,0 +1 @@ +android.useAndroidX = true From 6ff962569affc44d8f680343e0064098f93cb769 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 22 May 2024 11:08:01 -0700 Subject: [PATCH 37/57] Add android:exported to manifest file, update min SDK again. --- admob/testapp/AndroidManifest.xml | 7 ++++--- admob/testapp/build.gradle | 2 +- analytics/testapp/AndroidManifest.xml | 3 ++- analytics/testapp/build.gradle | 2 +- auth/testapp/AndroidManifest.xml | 3 ++- auth/testapp/build.gradle | 2 +- database/testapp/AndroidManifest.xml | 3 ++- database/testapp/build.gradle | 2 +- dynamic_links/testapp/AndroidManifest.xml | 3 ++- dynamic_links/testapp/build.gradle | 2 +- firestore/testapp/AndroidManifest.xml | 3 ++- firestore/testapp/build.gradle | 2 +- functions/testapp/AndroidManifest.xml | 3 ++- functions/testapp/build.gradle | 2 +- gma/testapp/AndroidManifest.xml | 7 ++++--- gma/testapp/build.gradle | 2 +- messaging/testapp/AndroidManifest.xml | 3 ++- messaging/testapp/build.gradle | 2 +- remote_config/testapp/AndroidManifest.xml | 3 ++- remote_config/testapp/build.gradle | 2 +- storage/testapp/AndroidManifest.xml | 3 ++- storage/testapp/build.gradle | 2 +- 22 files changed, 37 insertions(+), 26 deletions(-) diff --git a/admob/testapp/AndroidManifest.xml b/admob/testapp/AndroidManifest.xml index aa6b115d..72ec9ea1 100644 --- a/admob/testapp/AndroidManifest.xml +++ b/admob/testapp/AndroidManifest.xml @@ -6,15 +6,16 @@ - + + android:exported = "true" + android:screenOrientation="portrait" + android:configChanges="orientation|screenSize"> diff --git a/admob/testapp/build.gradle b/admob/testapp/build.gradle index 570ddee6..c5b19b62 100644 --- a/admob/testapp/build.gradle +++ b/admob/testapp/build.gradle @@ -37,7 +37,7 @@ android { defaultConfig { applicationId 'com.google.android.admob.testapp' - minSdkVersion 26 + minSdkVersion 23 targetSdkVersion 28 versionCode 1 versionName '1.0' diff --git a/analytics/testapp/AndroidManifest.xml b/analytics/testapp/AndroidManifest.xml index 2d4a9f35..a0b94e79 100644 --- a/analytics/testapp/AndroidManifest.xml +++ b/analytics/testapp/AndroidManifest.xml @@ -6,9 +6,10 @@ - + - + - + - + - + - + - + + android:exported = "true" + android:screenOrientation="portrait" + android:configChanges="orientation|screenSize"> diff --git a/gma/testapp/build.gradle b/gma/testapp/build.gradle index 5c8972e4..f073766d 100644 --- a/gma/testapp/build.gradle +++ b/gma/testapp/build.gradle @@ -42,7 +42,7 @@ android { defaultConfig { applicationId 'com.google.android.admob.testapp' - minSdkVersion 19 + minSdkVersion 23 targetSdkVersion 28 versionCode 1 versionName '1.0' diff --git a/messaging/testapp/AndroidManifest.xml b/messaging/testapp/AndroidManifest.xml index 80d522d0..2d86d2c0 100644 --- a/messaging/testapp/AndroidManifest.xml +++ b/messaging/testapp/AndroidManifest.xml @@ -3,7 +3,7 @@ package="com.google.android.messaging.testapp" android:versionCode="1" android:versionName="1.0"> - + @@ -19,6 +19,7 @@ work around a known issue when receiving notification data payloads in the background. --> diff --git a/messaging/testapp/build.gradle b/messaging/testapp/build.gradle index 38131c52..89070d57 100644 --- a/messaging/testapp/build.gradle +++ b/messaging/testapp/build.gradle @@ -41,7 +41,7 @@ android { defaultConfig { applicationId 'com.google.android.messaging.testapp' - minSdkVersion 19 + minSdkVersion 23 targetSdkVersion 28 versionCode 1 versionName '1.0' diff --git a/remote_config/testapp/AndroidManifest.xml b/remote_config/testapp/AndroidManifest.xml index 326d45b5..6ba5e57f 100644 --- a/remote_config/testapp/AndroidManifest.xml +++ b/remote_config/testapp/AndroidManifest.xml @@ -6,9 +6,10 @@ - + - + Date: Wed, 22 May 2024 11:13:01 -0700 Subject: [PATCH 38/57] Fix phone auth deprecated methods usage. --- auth/testapp/src/common_main.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/auth/testapp/src/common_main.cc b/auth/testapp/src/common_main.cc index d7be0ca9..f630b41e 100644 --- a/auth/testapp/src/common_main.cc +++ b/auth/testapp/src/common_main.cc @@ -43,6 +43,7 @@ using ::firebase::auth::kAuthErrorInvalidCredential; using ::firebase::auth::kAuthErrorInvalidProviderId; using ::firebase::auth::kAuthErrorNone; using ::firebase::auth::OAuthProvider; +using ::firebase::auth::PhoneAuthOptions; using ::firebase::auth::PhoneAuthProvider; using ::firebase::auth::PhoneAuthCredential; using ::firebase::auth::PlayGamesAuthProvider; @@ -601,8 +602,10 @@ extern "C" int common_main(int argc, const char* argv[]) { "Phone Number", "Please enter your phone number", "+12345678900"); PhoneListener listener; PhoneAuthProvider& phone_provider = PhoneAuthProvider::GetInstance(auth); - phone_provider.VerifyPhoneNumber(phone_number.c_str(), kPhoneAuthTimeoutMs, - nullptr, &listener); + PhoneAuthOptions options; + options.phone_number = phone_number; + options.timeout_milliseconds = kPhoneAuthTimeoutMs; + phone_provider.VerifyPhoneNumber(options, &listener); // Wait for OnCodeSent() callback. int wait_ms = 0; @@ -634,7 +637,7 @@ extern "C" int common_main(int argc, const char* argv[]) { LogMessage("."); } if (listener.num_calls_on_code_auto_retrieval_time_out() > 0) { - const Credential phone_credential = phone_provider.GetCredential( + const PhoneAuthCredential phone_credential = phone_provider.GetCredential( listener.verification_id().c_str(), verification_code.c_str()); Futurephone_future = From 85cd69aec9d170abb8d9227add44431b402962bd Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 22 May 2024 11:22:46 -0700 Subject: [PATCH 39/57] Fix build error and add coroutines fix and lint ignore. --- admob/testapp/build.gradle | 6 ++++++ analytics/testapp/build.gradle | 6 ++++++ auth/testapp/build.gradle | 6 ++++++ auth/testapp/src/common_main.cc | 2 +- database/testapp/build.gradle | 6 ++++++ dynamic_links/testapp/build.gradle | 6 ++++++ firestore/testapp/build.gradle | 6 ++++++ functions/testapp/build.gradle | 6 ++++++ gma/testapp/build.gradle | 6 ++++++ messaging/testapp/build.gradle | 6 ++++++ remote_config/testapp/build.gradle | 6 ++++++ storage/testapp/build.gradle | 6 ++++++ 12 files changed, 67 insertions(+), 1 deletion(-) diff --git a/admob/testapp/build.gradle b/admob/testapp/build.gradle index c5b19b62..daa94140 100644 --- a/admob/testapp/build.gradle +++ b/admob/testapp/build.gradle @@ -55,6 +55,12 @@ android { proguardFile file('proguard.pro') } } + packagingOptions { + pickFirst 'META-INF/**/coroutines.pro' + } + lintOptions { + abortOnError false + } } apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle" diff --git a/analytics/testapp/build.gradle b/analytics/testapp/build.gradle index cae14877..90067866 100644 --- a/analytics/testapp/build.gradle +++ b/analytics/testapp/build.gradle @@ -59,6 +59,12 @@ android { proguardFile file('proguard.pro') } } + packagingOptions { + pickFirst 'META-INF/**/coroutines.pro' + } + lintOptions { + abortOnError false + } } apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle" diff --git a/auth/testapp/build.gradle b/auth/testapp/build.gradle index b519358f..11b622d8 100644 --- a/auth/testapp/build.gradle +++ b/auth/testapp/build.gradle @@ -60,6 +60,12 @@ android { proguardFile file('proguard.pro') } } + packagingOptions { + pickFirst 'META-INF/**/coroutines.pro' + } + lintOptions { + abortOnError false + } } apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle" diff --git a/auth/testapp/src/common_main.cc b/auth/testapp/src/common_main.cc index f630b41e..f0d12c7b 100644 --- a/auth/testapp/src/common_main.cc +++ b/auth/testapp/src/common_main.cc @@ -647,7 +647,7 @@ extern "C" int common_main(int argc, const char* argv[]) { kAuthErrorNone, auth); if (phone_future.error() == kAuthErrorNone) { User user = *phone_future.result(); - Future update_future = + Future update_future = user.UpdatePhoneNumberCredential(phone_credential); WaitForSignInFuture( update_future, diff --git a/database/testapp/build.gradle b/database/testapp/build.gradle index 62461c4a..5d49d735 100644 --- a/database/testapp/build.gradle +++ b/database/testapp/build.gradle @@ -59,6 +59,12 @@ android { proguardFile file('proguard.pro') } } + packagingOptions { + pickFirst 'META-INF/**/coroutines.pro' + } + lintOptions { + abortOnError false + } } apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle" diff --git a/dynamic_links/testapp/build.gradle b/dynamic_links/testapp/build.gradle index c195d525..34b3f78c 100644 --- a/dynamic_links/testapp/build.gradle +++ b/dynamic_links/testapp/build.gradle @@ -59,6 +59,12 @@ android { proguardFile file('proguard.pro') } } + packagingOptions { + pickFirst 'META-INF/**/coroutines.pro' + } + lintOptions { + abortOnError false + } } apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle" diff --git a/firestore/testapp/build.gradle b/firestore/testapp/build.gradle index b12ff5bf..b3cb8b26 100644 --- a/firestore/testapp/build.gradle +++ b/firestore/testapp/build.gradle @@ -60,6 +60,12 @@ android { proguardFile file('proguard.pro') } } + packagingOptions { + pickFirst 'META-INF/**/coroutines.pro' + } + lintOptions { + abortOnError false + } } apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle" diff --git a/functions/testapp/build.gradle b/functions/testapp/build.gradle index ae4fe14a..bc3a4f63 100644 --- a/functions/testapp/build.gradle +++ b/functions/testapp/build.gradle @@ -59,6 +59,12 @@ android { proguardFile file('proguard.pro') } } + packagingOptions { + pickFirst 'META-INF/**/coroutines.pro' + } + lintOptions { + abortOnError false + } } apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle" diff --git a/gma/testapp/build.gradle b/gma/testapp/build.gradle index f073766d..10384b95 100644 --- a/gma/testapp/build.gradle +++ b/gma/testapp/build.gradle @@ -60,6 +60,12 @@ android { proguardFile file('proguard.pro') } } + packagingOptions { + pickFirst 'META-INF/**/coroutines.pro' + } + lintOptions { + abortOnError false + } } apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle" diff --git a/messaging/testapp/build.gradle b/messaging/testapp/build.gradle index 89070d57..de72535c 100644 --- a/messaging/testapp/build.gradle +++ b/messaging/testapp/build.gradle @@ -59,6 +59,12 @@ android { proguardFile file('proguard.pro') } } + packagingOptions { + pickFirst 'META-INF/**/coroutines.pro' + } + lintOptions { + abortOnError false + } } apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle" diff --git a/remote_config/testapp/build.gradle b/remote_config/testapp/build.gradle index d68b7c63..c6d494cd 100644 --- a/remote_config/testapp/build.gradle +++ b/remote_config/testapp/build.gradle @@ -59,6 +59,12 @@ android { proguardFile file('proguard.pro') } } + packagingOptions { + pickFirst 'META-INF/**/coroutines.pro' + } + lintOptions { + abortOnError false + } } apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle" diff --git a/storage/testapp/build.gradle b/storage/testapp/build.gradle index 25e33231..daa0f354 100644 --- a/storage/testapp/build.gradle +++ b/storage/testapp/build.gradle @@ -59,6 +59,12 @@ android { proguardFile file('proguard.pro') } } + packagingOptions { + pickFirst 'META-INF/**/coroutines.pro' + } + lintOptions { + abortOnError false + } } apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle" From 6ad262ebda2c34205f3014db1b0dd8f3d89f766e Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 22 May 2024 11:33:34 -0700 Subject: [PATCH 40/57] Remove minSdk from manifest (fixing a lint issue) and then turn off the linter for the rest of the lint issues. --- admob/testapp/AndroidManifest.xml | 2 +- admob/testapp/build.gradle | 1 + analytics/testapp/AndroidManifest.xml | 2 +- analytics/testapp/build.gradle | 1 + auth/testapp/AndroidManifest.xml | 2 +- auth/testapp/build.gradle | 1 + database/testapp/AndroidManifest.xml | 2 +- database/testapp/build.gradle | 1 + dynamic_links/testapp/AndroidManifest.xml | 2 +- dynamic_links/testapp/build.gradle | 1 + firestore/testapp/AndroidManifest.xml | 2 +- firestore/testapp/build.gradle | 1 + functions/testapp/AndroidManifest.xml | 2 +- functions/testapp/build.gradle | 1 + gma/testapp/AndroidManifest.xml | 2 +- gma/testapp/build.gradle | 1 + messaging/testapp/AndroidManifest.xml | 2 +- messaging/testapp/build.gradle | 1 + remote_config/testapp/AndroidManifest.xml | 2 +- remote_config/testapp/build.gradle | 1 + storage/testapp/AndroidManifest.xml | 2 +- storage/testapp/build.gradle | 1 + 22 files changed, 22 insertions(+), 11 deletions(-) diff --git a/admob/testapp/AndroidManifest.xml b/admob/testapp/AndroidManifest.xml index 72ec9ea1..a6e324fa 100644 --- a/admob/testapp/AndroidManifest.xml +++ b/admob/testapp/AndroidManifest.xml @@ -6,7 +6,7 @@ - + - + - + - + - + - + - + - + - + diff --git a/messaging/testapp/build.gradle b/messaging/testapp/build.gradle index de72535c..4f607fe3 100644 --- a/messaging/testapp/build.gradle +++ b/messaging/testapp/build.gradle @@ -64,6 +64,7 @@ android { } lintOptions { abortOnError false + checkReleaseBuilds false } } diff --git a/remote_config/testapp/AndroidManifest.xml b/remote_config/testapp/AndroidManifest.xml index 6ba5e57f..a7a904df 100644 --- a/remote_config/testapp/AndroidManifest.xml +++ b/remote_config/testapp/AndroidManifest.xml @@ -6,7 +6,7 @@ - + - + Date: Wed, 22 May 2024 11:37:23 -0700 Subject: [PATCH 41/57] Update iphone deployment target version. --- admob/testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- analytics/testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- auth/testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- database/testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- dynamic_links/testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- firestore/testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- functions/testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- gma/testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- messaging/testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- remote_config/testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- storage/testapp/testapp.xcodeproj/project.pbxproj | 4 ++-- 11 files changed, 22 insertions(+), 22 deletions(-) diff --git a/admob/testapp/testapp.xcodeproj/project.pbxproj b/admob/testapp/testapp.xcodeproj/project.pbxproj index 14a0af7f..3afd2dea 100644 --- a/admob/testapp/testapp.xcodeproj/project.pbxproj +++ b/admob/testapp/testapp.xcodeproj/project.pbxproj @@ -208,7 +208,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -245,7 +245,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/analytics/testapp/testapp.xcodeproj/project.pbxproj b/analytics/testapp/testapp.xcodeproj/project.pbxproj index 6c325725..5769362c 100644 --- a/analytics/testapp/testapp.xcodeproj/project.pbxproj +++ b/analytics/testapp/testapp.xcodeproj/project.pbxproj @@ -208,7 +208,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -245,7 +245,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/auth/testapp/testapp.xcodeproj/project.pbxproj b/auth/testapp/testapp.xcodeproj/project.pbxproj index 6c325725..5769362c 100644 --- a/auth/testapp/testapp.xcodeproj/project.pbxproj +++ b/auth/testapp/testapp.xcodeproj/project.pbxproj @@ -208,7 +208,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -245,7 +245,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/database/testapp/testapp.xcodeproj/project.pbxproj b/database/testapp/testapp.xcodeproj/project.pbxproj index 6c325725..5769362c 100644 --- a/database/testapp/testapp.xcodeproj/project.pbxproj +++ b/database/testapp/testapp.xcodeproj/project.pbxproj @@ -208,7 +208,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -245,7 +245,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/dynamic_links/testapp/testapp.xcodeproj/project.pbxproj b/dynamic_links/testapp/testapp.xcodeproj/project.pbxproj index 6c325725..5769362c 100644 --- a/dynamic_links/testapp/testapp.xcodeproj/project.pbxproj +++ b/dynamic_links/testapp/testapp.xcodeproj/project.pbxproj @@ -208,7 +208,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -245,7 +245,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/firestore/testapp/testapp.xcodeproj/project.pbxproj b/firestore/testapp/testapp.xcodeproj/project.pbxproj index 81ed36ca..ed7634b5 100644 --- a/firestore/testapp/testapp.xcodeproj/project.pbxproj +++ b/firestore/testapp/testapp.xcodeproj/project.pbxproj @@ -284,7 +284,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -321,7 +321,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/functions/testapp/testapp.xcodeproj/project.pbxproj b/functions/testapp/testapp.xcodeproj/project.pbxproj index 6c325725..5769362c 100644 --- a/functions/testapp/testapp.xcodeproj/project.pbxproj +++ b/functions/testapp/testapp.xcodeproj/project.pbxproj @@ -208,7 +208,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -245,7 +245,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/gma/testapp/testapp.xcodeproj/project.pbxproj b/gma/testapp/testapp.xcodeproj/project.pbxproj index 14a0af7f..3afd2dea 100644 --- a/gma/testapp/testapp.xcodeproj/project.pbxproj +++ b/gma/testapp/testapp.xcodeproj/project.pbxproj @@ -208,7 +208,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -245,7 +245,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/messaging/testapp/testapp.xcodeproj/project.pbxproj b/messaging/testapp/testapp.xcodeproj/project.pbxproj index 096e3825..c5f566b4 100644 --- a/messaging/testapp/testapp.xcodeproj/project.pbxproj +++ b/messaging/testapp/testapp.xcodeproj/project.pbxproj @@ -212,7 +212,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -249,7 +249,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/remote_config/testapp/testapp.xcodeproj/project.pbxproj b/remote_config/testapp/testapp.xcodeproj/project.pbxproj index 6c325725..5769362c 100644 --- a/remote_config/testapp/testapp.xcodeproj/project.pbxproj +++ b/remote_config/testapp/testapp.xcodeproj/project.pbxproj @@ -208,7 +208,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -245,7 +245,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/storage/testapp/testapp.xcodeproj/project.pbxproj b/storage/testapp/testapp.xcodeproj/project.pbxproj index 6c325725..5769362c 100644 --- a/storage/testapp/testapp.xcodeproj/project.pbxproj +++ b/storage/testapp/testapp.xcodeproj/project.pbxproj @@ -208,7 +208,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -245,7 +245,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; From 520e4d712666d9e00fecad9207f764379d597f23 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 22 May 2024 12:57:08 -0700 Subject: [PATCH 42/57] Update other testapps that use Auth. --- database/testapp/src/common_main.cc | 2 +- firestore/testapp/src/common_main.cc | 4 ++-- functions/testapp/src/common_main.cc | 2 +- storage/testapp/src/common_main.cc | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/database/testapp/src/common_main.cc b/database/testapp/src/common_main.cc index 1d985d7d..3a35179b 100644 --- a/database/testapp/src/common_main.cc +++ b/database/testapp/src/common_main.cc @@ -199,7 +199,7 @@ extern "C" int common_main(int argc, const char* argv[]) { // work as long as your project's Authentication permissions allow anonymous // signin. { - firebase::Future sign_in_future = + firebase::Future sign_in_future = auth->SignInAnonymously(); WaitForCompletion(sign_in_future, "SignInAnonymously"); if (sign_in_future.error() == firebase::auth::kAuthErrorNone) { diff --git a/firestore/testapp/src/common_main.cc b/firestore/testapp/src/common_main.cc index 4322d77d..335ff86b 100644 --- a/firestore/testapp/src/common_main.cc +++ b/firestore/testapp/src/common_main.cc @@ -126,8 +126,8 @@ extern "C" int common_main(int argc, const char* argv[]) { auto login_future = auth->SignInAnonymously(); Await(login_future, "Auth sign-in"); auto* login_result = login_future.result(); - if (login_result && *login_result) { - const firebase::auth::User* user = *login_result; + if (login_result) { + const firebase::auth::AuthResult user = *login_result.user; LogMessage("Signed in as %s user, uid: %s, email: %s.\n", user->is_anonymous() ? "an anonymous" : "a non-anonymous", user->uid().c_str(), user->email().c_str()); diff --git a/functions/testapp/src/common_main.cc b/functions/testapp/src/common_main.cc index 98277ccc..5e5e0019 100644 --- a/functions/testapp/src/common_main.cc +++ b/functions/testapp/src/common_main.cc @@ -97,7 +97,7 @@ extern "C" int common_main(int argc, const char* argv[]) { // Optionally, sign in using Auth before accessing Functions. { - firebase::Future sign_in_future = + firebase::Future sign_in_future = auth->SignInAnonymously(); WaitForCompletion(sign_in_future, "SignInAnonymously"); if (sign_in_future.error() == firebase::auth::kAuthErrorNone) { diff --git a/storage/testapp/src/common_main.cc b/storage/testapp/src/common_main.cc index 9dbade62..a333c4fb 100644 --- a/storage/testapp/src/common_main.cc +++ b/storage/testapp/src/common_main.cc @@ -116,7 +116,7 @@ extern "C" int common_main(int argc, const char* argv[]) { // work as long as your project's Authentication permissions allow anonymous // signin. { - firebase::Future sign_in_future = + firebase::Future sign_in_future = auth->SignInAnonymously(); WaitForCompletion(sign_in_future, "SignInAnonymously"); if (sign_in_future.error() == firebase::auth::kAuthErrorNone) { From 2a6c727f01a9e6dd0c25ff3f01c3917a540bf99d Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 22 May 2024 12:57:33 -0700 Subject: [PATCH 43/57] Remove Admob build. --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index d8876f55..d7542560 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -9,7 +9,7 @@ on: inputs: apis: description: 'CSV of apis to build and test' - default: 'admob,analytics,auth,database,dynamic_links,firestore,functions,gma,messaging,remote_config,storage' + default: 'analytics,auth,database,dynamic_links,firestore,functions,gma,messaging,remote_config,storage' required: true env: From 74b4a30068569f9191e194e23a994d0760d5fb0d Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 23 May 2024 12:04:14 -0700 Subject: [PATCH 44/57] Fix build error. --- firestore/testapp/src/common_main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firestore/testapp/src/common_main.cc b/firestore/testapp/src/common_main.cc index 335ff86b..d191349d 100644 --- a/firestore/testapp/src/common_main.cc +++ b/firestore/testapp/src/common_main.cc @@ -127,7 +127,7 @@ extern "C" int common_main(int argc, const char* argv[]) { Await(login_future, "Auth sign-in"); auto* login_result = login_future.result(); if (login_result) { - const firebase::auth::AuthResult user = *login_result.user; + const firebase::auth::User user = login_result->user; LogMessage("Signed in as %s user, uid: %s, email: %s.\n", user->is_anonymous() ? "an anonymous" : "a non-anonymous", user->uid().c_str(), user->email().c_str()); From ced418bf1a0aa26f136a5e99c6661374c1666e16 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 23 May 2024 12:51:45 -0700 Subject: [PATCH 45/57] Fix build issue. --- firestore/testapp/src/common_main.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firestore/testapp/src/common_main.cc b/firestore/testapp/src/common_main.cc index d191349d..0de5d39b 100644 --- a/firestore/testapp/src/common_main.cc +++ b/firestore/testapp/src/common_main.cc @@ -129,8 +129,8 @@ extern "C" int common_main(int argc, const char* argv[]) { if (login_result) { const firebase::auth::User user = login_result->user; LogMessage("Signed in as %s user, uid: %s, email: %s.\n", - user->is_anonymous() ? "an anonymous" : "a non-anonymous", - user->uid().c_str(), user->email().c_str()); + user.is_anonymous() ? "an anonymous" : "a non-anonymous", + user.uid().c_str(), user.email().c_str()); } else { LogMessage("ERROR: could not sign in"); } From 3397f4976f8aba1f1b6e0df374400f514ed3d56e Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 23 May 2024 13:47:18 -0700 Subject: [PATCH 46/57] Remove old AdMob quickstart. --- .github/workflows/android.yml | 2 +- admob/testapp/AndroidManifest.xml | 27 -- admob/testapp/CMakeLists.txt | 111 ------ admob/testapp/LICENSE | 202 ---------- admob/testapp/LaunchScreen.storyboard | 7 - admob/testapp/Podfile | 6 - admob/testapp/build.gradle | 72 ---- admob/testapp/gradle.properties | 1 - .../testapp/gradle/wrapper/gradle-wrapper.jar | Bin 49896 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 - admob/testapp/gradlew | 164 -------- admob/testapp/gradlew.bat | 90 ----- admob/testapp/proguard.pro | 2 - admob/testapp/readme.md | 200 ---------- admob/testapp/res/values/strings.xml | 4 - admob/testapp/settings.gradle | 36 -- admob/testapp/src/android/android_main.cc | 255 ------------- .../google/firebase/example/LoggingUtils.java | 55 --- admob/testapp/src/common_main.cc | 359 ------------------ admob/testapp/src/desktop/desktop_main.cc | 125 ------ admob/testapp/src/ios/ios_main.mm | 119 ------ admob/testapp/src/main.h | 63 --- .../testapp/testapp.xcodeproj/project.pbxproj | 312 --------------- .../AppIcon.appiconset/Contents.json | 73 ---- .../LaunchImage.launchimage/Contents.json | 36 -- admob/testapp/testapp/Info.plist | 28 -- scripts/build_scripts/build_testapps.json | 13 - .../admob/GoogleService-Info.plist.gpg | Bin 671 -> 0 bytes .../admob/google-services.json.gpg | Bin 1002 -> 0 bytes 29 files changed, 1 insertion(+), 2367 deletions(-) delete mode 100644 admob/testapp/AndroidManifest.xml delete mode 100644 admob/testapp/CMakeLists.txt delete mode 100644 admob/testapp/LICENSE delete mode 100644 admob/testapp/LaunchScreen.storyboard delete mode 100644 admob/testapp/Podfile delete mode 100644 admob/testapp/build.gradle delete mode 100644 admob/testapp/gradle.properties delete mode 100644 admob/testapp/gradle/wrapper/gradle-wrapper.jar delete mode 100644 admob/testapp/gradle/wrapper/gradle-wrapper.properties delete mode 100755 admob/testapp/gradlew delete mode 100644 admob/testapp/gradlew.bat delete mode 100644 admob/testapp/proguard.pro delete mode 100644 admob/testapp/readme.md delete mode 100644 admob/testapp/res/values/strings.xml delete mode 100644 admob/testapp/settings.gradle delete mode 100644 admob/testapp/src/android/android_main.cc delete mode 100644 admob/testapp/src/android/java/com/google/firebase/example/LoggingUtils.java delete mode 100644 admob/testapp/src/common_main.cc delete mode 100644 admob/testapp/src/desktop/desktop_main.cc delete mode 100644 admob/testapp/src/ios/ios_main.mm delete mode 100644 admob/testapp/src/main.h delete mode 100644 admob/testapp/testapp.xcodeproj/project.pbxproj delete mode 100644 admob/testapp/testapp/Images.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 admob/testapp/testapp/Images.xcassets/LaunchImage.launchimage/Contents.json delete mode 100644 admob/testapp/testapp/Info.plist delete mode 100644 scripts/gha-encrypted/admob/GoogleService-Info.plist.gpg delete mode 100644 scripts/gha-encrypted/admob/google-services.json.gpg diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index d7542560..e086d3f9 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -32,7 +32,7 @@ jobs: if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then apis="${{ github.event.inputs.apis }}" else - apis="admob,analytics,auth,database,dynamic_links,firestore,functions,gma,messaging,remote_config,storage" + apis="analytics,auth,database,dynamic_links,firestore,functions,gma,messaging,remote_config,storage" fi echo apis: ${apis} echo "::set-output name=apis::${apis}" diff --git a/admob/testapp/AndroidManifest.xml b/admob/testapp/AndroidManifest.xml deleted file mode 100644 index a6e324fa..00000000 --- a/admob/testapp/AndroidManifest.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/admob/testapp/CMakeLists.txt b/admob/testapp/CMakeLists.txt deleted file mode 100644 index 3a7d02dd..00000000 --- a/admob/testapp/CMakeLists.txt +++ /dev/null @@ -1,111 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -# User settings for Firebase samples. -# Path to Firebase SDK. -# Try to read the path to the Firebase C++ SDK from an environment variable. -if (NOT "$ENV{FIREBASE_CPP_SDK_DIR}" STREQUAL "") - set(DEFAULT_FIREBASE_CPP_SDK_DIR "$ENV{FIREBASE_CPP_SDK_DIR}") -else() - set(DEFAULT_FIREBASE_CPP_SDK_DIR "firebase_cpp_sdk") -endif() -if ("${FIREBASE_CPP_SDK_DIR}" STREQUAL "") - set(FIREBASE_CPP_SDK_DIR ${DEFAULT_FIREBASE_CPP_SDK_DIR}) -endif() -if(NOT EXISTS ${FIREBASE_CPP_SDK_DIR}) - message(FATAL_ERROR "The Firebase C++ SDK directory does not exist: ${FIREBASE_CPP_SDK_DIR}. See the readme.md for more information") -endif() - -# Sample source files. -set(FIREBASE_SAMPLE_COMMON_SRCS - src/main.h - src/common_main.cc -) - -# The include directory for the testapp. -include_directories(src) - -# Sample uses some features that require C++ 11, such as lambdas. -set (CMAKE_CXX_STANDARD 11) - -if(ANDROID) - # Build an Android application. - - # Source files used for the Android build. - set(FIREBASE_SAMPLE_ANDROID_SRCS - src/android/android_main.cc - ) - - # Build native_app_glue as a static lib - add_library(native_app_glue STATIC - ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - - # Export ANativeActivity_onCreate(), - # Refer to: https://github.com/android-ndk/ndk/issues/381. - set(CMAKE_SHARED_LINKER_FLAGS - "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - - # Define the target as a shared library, as that is what gradle expects. - set(target_name "android_main") - add_library(${target_name} SHARED - ${FIREBASE_SAMPLE_ANDROID_SRCS} - ${FIREBASE_SAMPLE_COMMON_SRCS} - ) - - target_link_libraries(${target_name} - log android atomic native_app_glue - ) - - target_include_directories(${target_name} PRIVATE - ${ANDROID_NDK}/sources/android/native_app_glue) - - set(ADDITIONAL_LIBS) -else() - # Build a desktop application. - - # Windows runtime mode, either MD or MT depending on whether you are using - # /MD or /MT. For more information see: - # https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx - set(MSVC_RUNTIME_MODE MD) - - # Platform abstraction layer for the desktop sample. - set(FIREBASE_SAMPLE_DESKTOP_SRCS - src/desktop/desktop_main.cc - ) - - set(target_name "desktop_testapp") - add_executable(${target_name} - ${FIREBASE_SAMPLE_DESKTOP_SRCS} - ${FIREBASE_SAMPLE_COMMON_SRCS} - ) - - if(APPLE) - set(ADDITIONAL_LIBS pthread) - elseif(MSVC) - set(ADDITIONAL_LIBS) - else() - set(ADDITIONAL_LIBS pthread) - endif() - - # If a config file is present, copy it into the binary location so that it's - # possible to create the default Firebase app. - set(FOUND_JSON_FILE FALSE) - foreach(config "google-services-desktop.json" "google-services.json") - if (EXISTS ${config}) - add_custom_command( - TARGET ${target_name} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - ${config} $) - set(FOUND_JSON_FILE TRUE) - break() - endif() - endforeach() - if(NOT FOUND_JSON_FILE) - message(WARNING "Failed to find either google-services-desktop.json or google-services.json. See the readme.md for more information.") - endif() -endif() - -# Add the Firebase libraries to the target using the function from the SDK. -add_subdirectory(${FIREBASE_CPP_SDK_DIR} bin/ EXCLUDE_FROM_ALL) -# Note that firebase_app needs to be last in the list. -set(firebase_libs firebase_admob firebase_app) -target_link_libraries(${target_name} "${firebase_libs}" ${ADDITIONAL_LIBS}) diff --git a/admob/testapp/LICENSE b/admob/testapp/LICENSE deleted file mode 100644 index d6456956..00000000 --- a/admob/testapp/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - 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/admob/testapp/LaunchScreen.storyboard b/admob/testapp/LaunchScreen.storyboard deleted file mode 100644 index 673e0f7e..00000000 --- a/admob/testapp/LaunchScreen.storyboard +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/admob/testapp/Podfile b/admob/testapp/Podfile deleted file mode 100644 index 9759f528..00000000 --- a/admob/testapp/Podfile +++ /dev/null @@ -1,6 +0,0 @@ -source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' -# AdMob test application. -target 'testapp' do - pod 'Firebase/AdMob', '7.0.0' -end diff --git a/admob/testapp/build.gradle b/admob/testapp/build.gradle deleted file mode 100644 index 744b80e4..00000000 --- a/admob/testapp/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. -buildscript { - repositories { - mavenLocal() - maven { url 'https://maven.google.com' } - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:4.2.1' - classpath 'com.google.gms:google-services:4.0.1' - } -} - -allprojects { - repositories { - mavenLocal() - maven { url 'https://maven.google.com' } - jcenter() - } -} - -apply plugin: 'com.android.application' - -android { - compileSdkVersion 34 - ndkPath System.getenv('ANDROID_NDK_HOME') - buildToolsVersion '30.0.2' - - sourceSets { - main { - jniLibs.srcDirs = ['libs'] - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['src/android/java'] - res.srcDirs = ['res'] - } - } - - defaultConfig { - applicationId 'com.google.android.admob.testapp' - minSdkVersion 23 - targetSdkVersion 28 - versionCode 1 - versionName '1.0' - externalNativeBuild.cmake { - arguments "-DFIREBASE_CPP_SDK_DIR=$gradle.firebase_cpp_sdk_dir" - } - } - externalNativeBuild.cmake { - path 'CMakeLists.txt' - } - buildTypes { - release { - minifyEnabled true - proguardFile getDefaultProguardFile('proguard-android.txt') - proguardFile file('proguard.pro') - } - } - packagingOptions { - pickFirst 'META-INF/**/coroutines.pro' - } - lintOptions { - abortOnError false - checkReleaseBuilds false - } -} - -apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle" -firebaseCpp.dependencies { - admob -} - -apply plugin: 'com.google.gms.google-services' diff --git a/admob/testapp/gradle.properties b/admob/testapp/gradle.properties deleted file mode 100644 index d7ba8f42..00000000 --- a/admob/testapp/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -android.useAndroidX = true diff --git a/admob/testapp/gradle/wrapper/gradle-wrapper.jar b/admob/testapp/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 8c0fb64a8698b08ecc4158d828ca593c4928e9dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49896 zcmagFb986H(k`5d^NVfUwr$(C?M#x1ZQHiZiEVpg+jrjgoQrerx!>1o_ul)D>ebz~ zs=Mmxr&>W81QY-S1PKWQ%N-;H^tS;2*XwVA`dej1RRn1z<;3VgfE4~kaG`A%QSPsR z#ovnZe+tS9%1MfeDyz`RirvdjPRK~p(#^q2(^5@O&NM19EHdvN-A&StN>0g6QA^VN z0Gx%Gq#PD$QMRFzmK+utjS^Y1F0e8&u&^=w5K<;4Rz|i3A=o|IKLY+g`iK6vfr9?+ z-`>gmU&i?FGSL5&F?TXFu`&Js6h;15QFkXp2M1H9|Eq~bpov-GU(uz%mH0n55wUl- zv#~ccAz`F5wlQ>e_KlJS3@{)B?^v*EQM=IxLa&76^y51a((wq|2-`qON>+4dLc{Oo z51}}o^Zen(oAjxDK7b++9_Yg`67p$bPo3~BCpGM7uAWmvIhWc5Gi+gQZ|Pwa-Gll@<1xmcPy z|NZmu6m)g5Ftu~BG&Xdxclw7Cij{xbBMBn-LMII#Slp`AElb&2^Hw+w>(3crLH!;I zN+Vk$D+wP1#^!MDCiad@vM>H#6+`Ct#~6VHL4lzmy;lSdk>`z6)=>Wh15Q2)dQtGqvn0vJU@+(B5{MUc*qs4!T+V=q=wy)<6$~ z!G>e_4dN@lGeF_$q9`Ju6Ncb*x?O7=l{anm7Eahuj_6lA{*#Gv*TaJclevPVbbVYu z(NY?5q+xxbO6%g1xF0r@Ix8fJ~u)VRUp`S%&rN$&e!Od`~s+64J z5*)*WSi*i{k%JjMSIN#X;jC{HG$-^iX+5f5BGOIHWAl*%15Z#!xntpk($-EGKCzKa zT7{siZ9;4TICsWQ$pu&wKZQTCvpI$Xvzwxoi+XkkpeE&&kFb!B?h2hi%^YlXt|-@5 zHJ~%AN!g_^tmn1?HSm^|gCE#!GRtK2(L{9pL#hp0xh zME}|DB>(5)`iE7CM)&_+S}-Bslc#@B5W4_+k4Cp$l>iVyg$KP>CN?SVGZ(&02>iZK zB<^HP$g$Lq*L$BWd?2(F?-MUbNWTJVQdW7$#8a|k_30#vHAD1Z{c#p;bETk0VnU5A zBgLe2HFJ3032$G<`m*OB!KM$*sdM20jm)It5OSru@tXpK5LT>#8)N!*skNu1$TpIw zufjjdp#lyH5bZ%|Iuo|iu9vG1HrIVWLH>278xo>aVBkPN3V$~!=KnlXQ4eDqS7%E% zQ!z^$Q$b^6Q)g#cLpwur(|<0gWHo6A6jc;n`t(V9T;LzTAU{IAu*uEQ%Ort1k+Kn+f_N`9|bxYC+~Z1 zCC1UCWv*Orx$_@ydv9mIe(liLfOr7mhbV@tKw{6)q^1DH1nmvZ0cj215R<~&I<4S| zgnr;9Cdjqpz#o8i0CQjtl`}{c*P)aSdH|abxGdrR)-3z+02-eX(k*B)Uqv6~^nh** z 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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/admob/testapp/gradlew.bat b/admob/testapp/gradlew.bat deleted file mode 100644 index 8a0b282a..00000000 --- a/admob/testapp/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/admob/testapp/proguard.pro b/admob/testapp/proguard.pro deleted file mode 100644 index 54cd248b..00000000 --- a/admob/testapp/proguard.pro +++ /dev/null @@ -1,2 +0,0 @@ --ignorewarnings --keep,includedescriptorclasses public class com.google.firebase.example.LoggingUtils { *; } diff --git a/admob/testapp/readme.md b/admob/testapp/readme.md deleted file mode 100644 index e8f45f80..00000000 --- a/admob/testapp/readme.md +++ /dev/null @@ -1,200 +0,0 @@ -Firebase AdMob Quickstart -============================== - -The Firebase AdMob Test Application (testapp) demonstrates loading and showing -banners and interstitials using the Firebase AdMob C++ SDK. The application -has no user interface and simply logs actions it's performing to the console -while displaying the ads. - -Introduction ------------- - -- [Read more about Firebase AdMob](https://firebase.google.com/docs/admob) - -Getting Started ---------------- - -### iOS - - Link your iOS app to the Firebase libraries. - - Get CocoaPods version 1 or later by running, - ``` - sudo gem install cocoapods --pre - ``` - - From the testapp directory, install the CocoaPods listed in the Podfile - by running, - ``` - pod install - ``` - - Open the generated Xcode workspace (which now has the CocoaPods), - ``` - open testapp.xcworkspace - ``` - - For further details please refer to the - [general instructions for setting up an iOS app with Firebase](https://firebase.google.com/docs/ios/setup). - - Register your iOS app with Firebase. - - Create a new app on the [Firebase console](https://firebase.google.com/console/), - and attach your iOS app to it. - - You can use "com.google.ios.admob.testapp" as the iOS Bundle ID - while you're testing. You can omit App Store ID while testing. - - Download the Firebase C++ SDK linked from - [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup) - and unzip it to a directory of your choice. - - Add the following frameworks from the Firebase C++ SDK to the project: - - frameworks/ios/universal/firebase.framework - - frameworks/ios/universal/firebase_admob.framework - - You will need to either, - 1. Check "Copy items if needed" when adding the frameworks, or - 2. Add the framework path in "Framework Search Paths" - - For example, if you downloaded the Firebase C++ SDK to - `/Users/me/firebase_cpp_sdk`, - then you would add the path - `/Users/me/firebase_cpp_sdk/frameworks/ios/universal`. - - To add the path, in Xcode, select your project in the project - navigator, then select your target in the main window. - Select the "Build Settings" tab, and click "All" to see all - the build settings. Scroll down to "Search Paths", and add - your path to "Framework Search Paths". - - Update the AdMob App ID: - - In the `src/common_main.cc`, update `kAdMobAppID` with the app ID for - your iOS app, replacing 'YOUR_IOS_ADMOB_APP_ID'. - - In the `testapp/Info.plist`, update `GADApplicationIdentifier` with the - same app ID, replacing 'YOUR_IOS_ADMOB_APP_ID'. - - For more information, see - [Update your Info.plist](https://developers.google.com/admob/ios/quick-start#manual_download) - - In Xcode, build & run the sample on an iOS device or simulator. - - The testapp displays a banner ad and an interstitial ad. You can dismiss - the interstitial ad to see the banner ad. - - Afterwards, the testapp will display a Rewarded Video test ad. - - The output of the app can be viewed onscreen or via the console. To view - the console in Xcode, select "View --> Debug Area --> Activate Console" - from the menu. - -### Android - - Register your Android app with Firebase. - - Create a new app on the [Firebase console](https://firebase.google.com/console/), - and attach your Android app to it. - - You can use "com.google.android.admob.testapp" as the Package Name - while you're testing. - - To [generate a SHA1](https://developers.google.com/android/guides/client-auth) - run this command on Mac and Linux, - ``` - keytool -exportcert -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore - ``` - or this command on Windows, - ``` - keytool -exportcert -list -v -alias androiddebugkey -keystore %USERPROFILE%\.android\debug.keystore - ``` - - If keytool reports that you do not have a debug.keystore, you can - [create one with](http://developer.android.com/tools/publishing/app-signing.html#signing-manually), - ``` - keytool -genkey -v -keystore ~/.android/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US" - ``` - - Add the `google-services.json` file that you downloaded from Firebase - console to the root directory of testapp. This file identifies your - Android app to the Firebase backend. - - For further details please refer to the - [general instructions for setting up an Android app with Firebase](https://firebase.google.com/docs/android/setup). - - Download the Firebase C++ SDK linked from - [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup) - and unzip it to a directory of your choice. - - Configure the location of the Firebase C++ SDK by setting the - firebase\_cpp\_sdk.dir Gradle property to the SDK install directory. - For example, in the project directory: - ``` - echo "systemProp.firebase\_cpp\_sdk.dir=/User/$USER/firebase\_cpp\_sdk" >> gradle.properties - ``` - - Ensure the Android SDK and NDK locations are set in Android Studio. - - From the Android Studio launch menu, go to `File/Project Structure...` or - `Configure/Project Defaults/Project Structure...` - (Shortcut: Control + Alt + Shift + S on windows, Command + ";" on a mac) - and download the SDK and NDK if the locations are not yet set. - - Open *build.gradle* in Android Studio. - - From the Android Studio launch menu, "Open an existing Android Studio - project", and select `build.gradle`. - - Install the SDK Platforms that Android Studio reports missing. - - Update the AdMob App ID: - - In the `src/common_main.cc`, update `kAdMobAppID` with the app ID for - your Android app, replacing 'YOUR_ANDROID_ADMOB_APP_ID'. - - In the `AndroidManifest.xml`, update - `com.google.android.gms.ads.APPLICATION_ID` with the same app ID, - replacing 'YOUR_ANDROID_ADMOB_APP_ID'. - - For more information, see - [Update your AndroidManifest.xml](https://developers.google.com/admob/android/quick-start#update_your_androidmanifestxml) - - Build the testapp and run it on an Android device or emulator. - - The testapp will initialize AdMob, then load and display a test banner and - a test interstitial. - - Tapping on an ad to verify the clickthrough process is possible, and the - interstitial will wait to be closed by the user. - - Afterwards, the testapp will display a Rewarded Video test ad. - - While this is happening, information from the device log will be written - to an onscreen TextView. - - Logcat can also be used as normal. - -### Desktop - - Register your app with Firebase. - - Create a new app on the [Firebase console](https://firebase.google.com/console/), - following the above instructions for Android or iOS. - - If you have an Android project, add the `google-services.json` file that - you downloaded from the Firebase console to the root directory of the - testapp. - - If you have an iOS project, and don't wish to use an Android project, - you can use the Python script `generate_xml_from_google_services_json.py --plist`, - located in the Firebase C++ SDK, to convert your `GoogleService-Info.plist` - file into a `google-services-desktop.json` file, which can then be - placed in the root directory of the testapp. - - Download the Firebase C++ SDK linked from - [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup) - and unzip it to a directory of your choice. - - Configure the testapp with the location of the Firebase C++ SDK. - This can be done a couple different ways: - - When invoking cmake, pass in the location with - -DFIREBASE_CPP_SDK_DIR=/path/to/firebase_cpp_sdk. - - Set an environment variable for FIREBASE_CPP_SDK_DIR to the path to use. - - Edit the CMakeLists.txt file, changing the FIREBASE_CPP_SDK_DIR path - to the appropriate location. - - From the testapp directory, generate the build files by running, - ``` - cmake . - ``` - If you want to use XCode, you can use -G"Xcode" to generate the project. - Similarly, to use Visual Studio, -G"Visual Studio 15 2017". For more - information, see - [CMake generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html). - - Build the testapp, by either opening the generated project file based on - the platform, or running, - ``` - cmake --build . - ``` - - Execute the testapp by running, - ``` - ./desktop_testapp - ``` - Note that the executable might be under another directory, such as Debug. - - The testapp has no user interface, but the output can be viewed via the - console. Note that Admob uses a stubbed implementation on desktop, - so functionality is not expected. - -Support -------- - -[https://firebase.google.com/support/](https://firebase.google.com/support/) - -License -------- - -Copyright 2016 Google, Inc. - -Licensed to the Apache Software Foundation (ASF) under one or more contributor -license agreements. See the NOTICE file distributed with this work for -additional information regarding copyright ownership. The ASF licenses this -file to you 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/admob/testapp/res/values/strings.xml b/admob/testapp/res/values/strings.xml deleted file mode 100644 index 8589bd2c..00000000 --- a/admob/testapp/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Firebase AdMob Test - diff --git a/admob/testapp/settings.gradle b/admob/testapp/settings.gradle deleted file mode 100644 index 2a543b93..00000000 --- a/admob/testapp/settings.gradle +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2018 Google LLC -// -// 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. - -def firebase_cpp_sdk_dir = System.getProperty('firebase_cpp_sdk.dir') -if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) { - firebase_cpp_sdk_dir = System.getenv('FIREBASE_CPP_SDK_DIR') - if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) { - if ((new File('firebase_cpp_sdk')).exists()) { - firebase_cpp_sdk_dir = 'firebase_cpp_sdk' - } else { - throw new StopActionException( - 'firebase_cpp_sdk.dir property or the FIREBASE_CPP_SDK_DIR ' + - 'environment variable must be set to reference the Firebase C++ ' + - 'SDK install directory. This is used to configure static library ' + - 'and C/C++ include paths for the SDK.') - } - } -} -if (!(new File(firebase_cpp_sdk_dir)).exists()) { - throw new StopActionException( - sprintf('Firebase C++ SDK directory %s does not exist', - firebase_cpp_sdk_dir)) -} -gradle.ext.firebase_cpp_sdk_dir = "$firebase_cpp_sdk_dir" -includeBuild "$firebase_cpp_sdk_dir" \ No newline at end of file diff --git a/admob/testapp/src/android/android_main.cc b/admob/testapp/src/android/android_main.cc deleted file mode 100644 index 73cb30e7..00000000 --- a/admob/testapp/src/android/android_main.cc +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// -// 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 -#include - -#include -#include -#include -#include - -#include "main.h" // NOLINT - -// This implementation is derived from http://github.com/google/fplutil - -extern "C" int common_main(int argc, const char* argv[]); - -static struct android_app* g_app_state = nullptr; -static bool g_destroy_requested = false; -static bool g_started = false; -static bool g_restarted = false; -static pthread_mutex_t g_started_mutex; - -// Handle state changes from via native app glue. -static void OnAppCmd(struct android_app* app, int32_t cmd) { - g_destroy_requested |= cmd == APP_CMD_DESTROY; -} - -// Process events pending on the main thread. -// Returns true when the app receives an event requesting exit. -bool ProcessEvents(int msec) { - struct android_poll_source* source = nullptr; - int events; - int looperId = ALooper_pollAll(msec, nullptr, &events, - reinterpret_cast(&source)); - if (looperId >= 0 && source) { - source->process(g_app_state, source); - } - return g_destroy_requested | g_restarted; -} - -// Get the activity. -jobject GetActivity() { return g_app_state->activity->clazz; } - -// Get the window context. For Android, it's a jobject pointing to the Activity. -jobject GetWindowContext() { return g_app_state->activity->clazz; } - -// Find a class, attempting to load the class if it's not found. -jclass FindClass(JNIEnv* env, jobject activity_object, const char* class_name) { - jclass class_object = env->FindClass(class_name); - if (env->ExceptionCheck()) { - env->ExceptionClear(); - // If the class isn't found it's possible NativeActivity is being used by - // the application which means the class path is set to only load system - // classes. The following falls back to loading the class using the - // Activity before retrieving a reference to it. - jclass activity_class = env->FindClass("android/app/Activity"); - jmethodID activity_get_class_loader = env->GetMethodID( - activity_class, "getClassLoader", "()Ljava/lang/ClassLoader;"); - - jobject class_loader_object = - env->CallObjectMethod(activity_object, activity_get_class_loader); - - jclass class_loader_class = env->FindClass("java/lang/ClassLoader"); - jmethodID class_loader_load_class = - env->GetMethodID(class_loader_class, "loadClass", - "(Ljava/lang/String;)Ljava/lang/Class;"); - jstring class_name_object = env->NewStringUTF(class_name); - - class_object = static_cast(env->CallObjectMethod( - class_loader_object, class_loader_load_class, class_name_object)); - - if (env->ExceptionCheck()) { - env->ExceptionClear(); - class_object = nullptr; - } - env->DeleteLocalRef(class_name_object); - env->DeleteLocalRef(class_loader_object); - } - return class_object; -} - -// Vars that we need available for appending text to the log window: -class LoggingUtilsData { - public: - LoggingUtilsData() - : logging_utils_class_(nullptr), - logging_utils_add_log_text_(0), - logging_utils_init_log_window_(0) {} - - ~LoggingUtilsData() { - JNIEnv* env = GetJniEnv(); - assert(env); - if (logging_utils_class_) { - env->DeleteGlobalRef(logging_utils_class_); - } - } - - void Init() { - JNIEnv* env = GetJniEnv(); - assert(env); - - jclass logging_utils_class = FindClass( - env, GetActivity(), "com/google/firebase/example/LoggingUtils"); - assert(logging_utils_class != 0); - - // Need to store as global references so it don't get moved during garbage - // collection. - logging_utils_class_ = - static_cast(env->NewGlobalRef(logging_utils_class)); - env->DeleteLocalRef(logging_utils_class); - - logging_utils_init_log_window_ = env->GetStaticMethodID( - logging_utils_class_, "initLogWindow", "(Landroid/app/Activity;)V"); - logging_utils_add_log_text_ = env->GetStaticMethodID( - logging_utils_class_, "addLogText", "(Ljava/lang/String;)V"); - - env->CallStaticVoidMethod(logging_utils_class_, - logging_utils_init_log_window_, GetActivity()); - } - - void AppendText(const char* text) { - if (logging_utils_class_ == 0) return; // haven't been initted yet - JNIEnv* env = GetJniEnv(); - assert(env); - jstring text_string = env->NewStringUTF(text); - env->CallStaticVoidMethod(logging_utils_class_, logging_utils_add_log_text_, - text_string); - env->DeleteLocalRef(text_string); - } - - private: - jclass logging_utils_class_; - jmethodID logging_utils_add_log_text_; - jmethodID logging_utils_init_log_window_; -}; - -LoggingUtilsData* g_logging_utils_data; - -// Checks if a JNI exception has happened, and if so, logs it to the console. -void CheckJNIException() { - JNIEnv* env = GetJniEnv(); - if (env->ExceptionCheck()) { - // Get the exception text. - jthrowable exception = env->ExceptionOccurred(); - env->ExceptionClear(); - - // Convert the exception to a string. - jclass object_class = env->FindClass("java/lang/Object"); - jmethodID toString = - env->GetMethodID(object_class, "toString", "()Ljava/lang/String;"); - jstring s = (jstring)env->CallObjectMethod(exception, toString); - const char* exception_text = env->GetStringUTFChars(s, nullptr); - - // Log the exception text. - __android_log_print(ANDROID_LOG_INFO, FIREBASE_TESTAPP_NAME, - "-------------------JNI exception:"); - __android_log_print(ANDROID_LOG_INFO, FIREBASE_TESTAPP_NAME, "%s", - exception_text); - __android_log_print(ANDROID_LOG_INFO, FIREBASE_TESTAPP_NAME, - "-------------------"); - - // Also, assert fail. - assert(false); - - // In the event we didn't assert fail, clean up. - env->ReleaseStringUTFChars(s, exception_text); - env->DeleteLocalRef(s); - env->DeleteLocalRef(exception); - } -} - -// Log a message that can be viewed in "adb logcat". -void LogMessage(const char* format, ...) { - static const int kLineBufferSize = 100; - char buffer[kLineBufferSize + 2]; - - va_list list; - va_start(list, format); - int string_len = vsnprintf(buffer, kLineBufferSize, format, list); - string_len = string_len < kLineBufferSize ? string_len : kLineBufferSize; - // append a linebreak to the buffer: - buffer[string_len] = '\n'; - buffer[string_len + 1] = '\0'; - - __android_log_vprint(ANDROID_LOG_INFO, FIREBASE_TESTAPP_NAME, format, list); - g_logging_utils_data->AppendText(buffer); - CheckJNIException(); - va_end(list); -} - -// Get the JNI environment. -JNIEnv* GetJniEnv() { - JavaVM* vm = g_app_state->activity->vm; - JNIEnv* env; - jint result = vm->AttachCurrentThread(&env, nullptr); - return result == JNI_OK ? env : nullptr; -} - -// Execute common_main(), flush pending events and finish the activity. -extern "C" void android_main(struct android_app* state) { - // native_app_glue spawns a new thread, calling android_main() when the - // activity onStart() or onRestart() methods are called. This code handles - // the case where we're re-entering this method on a different thread by - // signalling the existing thread to exit, waiting for it to complete before - // reinitializing the application. - if (g_started) { - g_restarted = true; - // Wait for the existing thread to exit. - pthread_mutex_lock(&g_started_mutex); - pthread_mutex_unlock(&g_started_mutex); - } else { - g_started_mutex = PTHREAD_MUTEX_INITIALIZER; - } - pthread_mutex_lock(&g_started_mutex); - g_started = true; - - // Save native app glue state and setup a callback to track the state. - g_destroy_requested = false; - g_app_state = state; - g_app_state->onAppCmd = OnAppCmd; - - // Create the logging display. - g_logging_utils_data = new LoggingUtilsData(); - g_logging_utils_data->Init(); - - // Execute cross platform entry point. - static const char* argv[] = {FIREBASE_TESTAPP_NAME}; - int return_value = common_main(1, argv); - (void)return_value; // Ignore the return value. - ProcessEvents(10); - - // Clean up logging display. - delete g_logging_utils_data; - g_logging_utils_data = nullptr; - - // Finish the activity. - if (!g_restarted) ANativeActivity_finish(state->activity); - - g_app_state->activity->vm->DetachCurrentThread(); - g_started = false; - g_restarted = false; - pthread_mutex_unlock(&g_started_mutex); -} diff --git a/admob/testapp/src/android/java/com/google/firebase/example/LoggingUtils.java b/admob/testapp/src/android/java/com/google/firebase/example/LoggingUtils.java deleted file mode 100644 index 11d67c5b..00000000 --- a/admob/testapp/src/android/java/com/google/firebase/example/LoggingUtils.java +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// -// 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. - -package com.google.firebase.example; - -import android.app.Activity; -import android.os.Handler; -import android.os.Looper; -import android.view.Window; -import android.widget.LinearLayout; -import android.widget.ScrollView; -import android.widget.TextView; - -/** - * A utility class, encapsulating the data and methods required to log arbitrary - * text to the screen, via a non-editable TextView. - */ -public class LoggingUtils { - public static TextView sTextView = null; - - public static void initLogWindow(Activity activity) { - LinearLayout linearLayout = new LinearLayout(activity); - ScrollView scrollView = new ScrollView(activity); - TextView textView = new TextView(activity); - textView.setTag("Logger"); - linearLayout.addView(scrollView); - scrollView.addView(textView); - Window window = activity.getWindow(); - window.takeSurface(null); - window.setContentView(linearLayout); - sTextView = textView; - } - - public static void addLogText(final String text) { - new Handler(Looper.getMainLooper()).post(new Runnable() { - @Override - public void run() { - if (sTextView != null) { - sTextView.append(text); - } - } - }); - } -} diff --git a/admob/testapp/src/common_main.cc b/admob/testapp/src/common_main.cc deleted file mode 100644 index eae4f5c4..00000000 --- a/admob/testapp/src/common_main.cc +++ /dev/null @@ -1,359 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// -// 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 "firebase/admob.h" -#include "firebase/admob/banner_view.h" -#include "firebase/admob/interstitial_ad.h" -#include "firebase/admob/rewarded_video.h" -#include "firebase/admob/types.h" -#include "firebase/app.h" -#include "firebase/future.h" - -// Thin OS abstraction layer. -#include "main.h" // NOLINT - -// A simple listener that logs changes to a BannerView. -class LoggingBannerViewListener : public firebase::admob::BannerView::Listener { - public: - LoggingBannerViewListener() {} - void OnPresentationStateChanged( - firebase::admob::BannerView* banner_view, - firebase::admob::BannerView::PresentationState state) override { - ::LogMessage("BannerView PresentationState has changed to %d.", state); - } - void OnBoundingBoxChanged(firebase::admob::BannerView* banner_view, - firebase::admob::BoundingBox box) override { - ::LogMessage( - "BannerView BoundingBox has changed to (x: %d, y: %d, width: %d, " - "height %d).", - box.x, box.y, box.width, box.height); - } -}; - -// A simple listener that logs changes to an InterstitialAd. -class LoggingInterstitialAdListener - : public firebase::admob::InterstitialAd::Listener { - public: - LoggingInterstitialAdListener() {} - void OnPresentationStateChanged( - firebase::admob::InterstitialAd* interstitial_ad, - firebase::admob::InterstitialAd::PresentationState state) override { - ::LogMessage("InterstitialAd PresentationState has changed to %d.", state); - } -}; - -// A simple listener that logs changes to rewarded video state. -class LoggingRewardedVideoListener - : public firebase::admob::rewarded_video::Listener { - public: - LoggingRewardedVideoListener() {} - void OnRewarded(firebase::admob::rewarded_video::RewardItem reward) override { - ::LogMessage("Rewarding user with %f %s.", reward.amount, - reward.reward_type.c_str()); - } - void OnPresentationStateChanged( - firebase::admob::rewarded_video::PresentationState state) override { - ::LogMessage("Rewarded video PresentationState has changed to %d.", state); - } -}; - -// The AdMob app IDs for the test app. -#if defined(__ANDROID__) -// If you change the AdMob app ID for your Android app, make sure to change it -// in AndroidManifest.xml as well. -const char* kAdMobAppID = "YOUR_ANDROID_ADMOB_APP_ID"; -#else -// If you change the AdMob app ID for your iOS app, make sure to change the -// value for "GADApplicationIdentifier" in your Info.plist as well. -const char* kAdMobAppID = "YOUR_IOS_ADMOB_APP_ID"; -#endif - -// These ad units IDs have been created specifically for testing, and will -// always return test ads. -#if defined(__ANDROID__) -const char* kBannerAdUnit = "ca-app-pub-3940256099942544/6300978111"; -const char* kInterstitialAdUnit = "ca-app-pub-3940256099942544/1033173712"; -const char* kRewardedVideoAdUnit = "ca-app-pub-3940256099942544/5224354917"; -#else -const char* kBannerAdUnit = "ca-app-pub-3940256099942544/2934735716"; -const char* kInterstitialAdUnit = "ca-app-pub-3940256099942544/4411468910"; -const char* kRewardedVideoAdUnit = "ca-app-pub-3940256099942544/1712485313"; -#endif - -// Standard mobile banner size is 320x50. -static const int kBannerWidth = 320; -static const int kBannerHeight = 50; - -// Sample keywords to use in making the request. -static const char* kKeywords[] = {"AdMob", "C++", "Fun"}; - -// Sample test device IDs to use in making the request. -static const char* kTestDeviceIDs[] = {"2077ef9a63d2b398840261c8221a0c9b", - "098fe087d987c9a878965454a65654d7"}; - -// Sample birthday value to use in making the request. -static const int kBirthdayDay = 10; -static const int kBirthdayMonth = 11; -static const int kBirthdayYear = 1976; - -static void WaitForFutureCompletion(firebase::FutureBase future) { - while (!ProcessEvents(1000)) { - if (future.status() != firebase::kFutureStatusPending) { - break; - } - } - - if (future.error() != firebase::admob::kAdMobErrorNone) { - LogMessage("ERROR: Action failed with error code %d and message \"%s\".", - future.error(), future.error_message()); - } -} - -// Execute all methods of the C++ admob API. -extern "C" int common_main(int argc, const char* argv[]) { - firebase::App* app; - LogMessage("Initializing the AdMob library."); - -#if defined(__ANDROID__) - app = ::firebase::App::Create(GetJniEnv(), GetActivity()); -#else - app = ::firebase::App::Create(); -#endif // defined(__ANDROID__) - - LogMessage("Created the Firebase App %x.", - static_cast(reinterpret_cast(app))); - - LogMessage("Initializing the AdMob with Firebase API."); - firebase::admob::Initialize(*app, kAdMobAppID); - - firebase::admob::AdRequest request; - // If the app is aware of the user's gender, it can be added to the targeting - // information. Otherwise, "unknown" should be used. - request.gender = firebase::admob::kGenderUnknown; - - // This value allows publishers to specify whether they would like the request - // to be treated as child-directed for purposes of the Children’s Online - // Privacy Protection Act (COPPA). - // See http://business.ftc.gov/privacy-and-security/childrens-privacy. - request.tagged_for_child_directed_treatment = - firebase::admob::kChildDirectedTreatmentStateTagged; - - // The user's birthday, if known. Note that months are indexed from one. - request.birthday_day = kBirthdayDay; - request.birthday_month = kBirthdayMonth; - request.birthday_year = kBirthdayYear; - - // Additional keywords to be used in targeting. - request.keyword_count = sizeof(kKeywords) / sizeof(kKeywords[0]); - request.keywords = kKeywords; - - // "Extra" key value pairs can be added to the request as well. Typically - // these are used when testing new features. - static const firebase::admob::KeyValuePair kRequestExtras[] = { - {"the_name_of_an_extra", "the_value_for_that_extra"}}; - request.extras_count = sizeof(kRequestExtras) / sizeof(kRequestExtras[0]); - request.extras = kRequestExtras; - - // This example uses ad units that are specially configured to return test ads - // for every request. When using your own ad unit IDs, however, it's important - // to register the device IDs associated with any devices that will be used to - // test the app. This ensures that regardless of the ad unit ID, those - // devices will always receive test ads in compliance with AdMob policy. - // - // Device IDs can be obtained by checking the logcat or the Xcode log while - // debugging. They appear as a long string of hex characters. - request.test_device_id_count = - sizeof(kTestDeviceIDs) / sizeof(kTestDeviceIDs[0]); - request.test_device_ids = kTestDeviceIDs; - - // Create an ad size for the BannerView. - firebase::admob::AdSize banner_ad_size; - banner_ad_size.ad_size_type = firebase::admob::kAdSizeStandard; - banner_ad_size.width = kBannerWidth; - banner_ad_size.height = kBannerHeight; - - LogMessage("Creating the BannerView."); - firebase::admob::BannerView* banner = new firebase::admob::BannerView(); - banner->Initialize(GetWindowContext(), kBannerAdUnit, banner_ad_size); - - WaitForFutureCompletion(banner->InitializeLastResult()); - - // Set the listener. - LoggingBannerViewListener banner_listener; - banner->SetListener(&banner_listener); - - // Load the banner ad. - LogMessage("Loading a banner ad."); - banner->LoadAd(request); - - WaitForFutureCompletion(banner->LoadAdLastResult()); - - // Make the BannerView visible. - LogMessage("Showing the banner ad."); - banner->Show(); - - WaitForFutureCompletion(banner->ShowLastResult()); - - // Move to each of the six pre-defined positions. - LogMessage("Moving the banner ad to top-center."); - banner->MoveTo(firebase::admob::BannerView::kPositionTop); - - WaitForFutureCompletion(banner->MoveToLastResult()); - - LogMessage("Moving the banner ad to top-left."); - banner->MoveTo(firebase::admob::BannerView::kPositionTopLeft); - - WaitForFutureCompletion(banner->MoveToLastResult()); - - LogMessage("Moving the banner ad to top-right."); - banner->MoveTo(firebase::admob::BannerView::kPositionTopRight); - - WaitForFutureCompletion(banner->MoveToLastResult()); - - LogMessage("Moving the banner ad to bottom-center."); - banner->MoveTo(firebase::admob::BannerView::kPositionBottom); - - WaitForFutureCompletion(banner->MoveToLastResult()); - - LogMessage("Moving the banner ad to bottom-left."); - banner->MoveTo(firebase::admob::BannerView::kPositionBottomLeft); - - WaitForFutureCompletion(banner->MoveToLastResult()); - - LogMessage("Moving the banner ad to bottom-right."); - banner->MoveTo(firebase::admob::BannerView::kPositionBottomRight); - - WaitForFutureCompletion(banner->MoveToLastResult()); - - // Try some coordinate moves. - LogMessage("Moving the banner ad to (100, 300)."); - banner->MoveTo(100, 300); - - WaitForFutureCompletion(banner->MoveToLastResult()); - - LogMessage("Moving the banner ad to (100, 400)."); - banner->MoveTo(100, 400); - - WaitForFutureCompletion(banner->MoveToLastResult()); - - // Try hiding and showing the BannerView. - LogMessage("Hiding the banner ad."); - banner->Hide(); - - WaitForFutureCompletion(banner->HideLastResult()); - - LogMessage("Showing the banner ad."); - banner->Show(); - - WaitForFutureCompletion(banner->ShowLastResult()); - - // A few last moves after showing it again. - LogMessage("Moving the banner ad to (100, 300)."); - banner->MoveTo(100, 300); - - WaitForFutureCompletion(banner->MoveToLastResult()); - - LogMessage("Moving the banner ad to (100, 400)."); - banner->MoveTo(100, 400); - - WaitForFutureCompletion(banner->MoveToLastResult()); - - LogMessage("Hiding the banner ad now that we're done with it."); - banner->Hide(); - - WaitForFutureCompletion(banner->HideLastResult()); - - // Create and test InterstitialAd. - LogMessage("Creating the InterstitialAd."); - firebase::admob::InterstitialAd* interstitial = - new firebase::admob::InterstitialAd(); - interstitial->Initialize(GetWindowContext(), kInterstitialAdUnit); - - WaitForFutureCompletion(interstitial->InitializeLastResult()); - - // Set the listener. - LoggingInterstitialAdListener interstitial_listener; - interstitial->SetListener(&interstitial_listener); - - // When the InterstitialAd is initialized, load an ad. - LogMessage("Loading an interstitial ad."); - interstitial->LoadAd(request); - - WaitForFutureCompletion(interstitial->LoadAdLastResult()); - - // When the InterstitialAd has loaded an ad, show it. - LogMessage("Showing the interstitial ad."); - interstitial->Show(); - - WaitForFutureCompletion(interstitial->ShowLastResult()); - - // Wait for the user to close the interstitial. - while (interstitial->presentation_state() != - firebase::admob::InterstitialAd::PresentationState:: - kPresentationStateHidden) { - ProcessEvents(1000); - } - - // Start up rewarded video ads and associated mediation adapters. - LogMessage("Initializing rewarded video."); - namespace rewarded_video = firebase::admob::rewarded_video; - rewarded_video::Initialize(); - - WaitForFutureCompletion(rewarded_video::InitializeLastResult()); - - LogMessage("Setting rewarded video listener."); - LoggingRewardedVideoListener rewarded_listener; - rewarded_video::SetListener(&rewarded_listener); - - LogMessage("Loading a rewarded video ad."); - rewarded_video::LoadAd(kRewardedVideoAdUnit, request); - - WaitForFutureCompletion(rewarded_video::LoadAdLastResult()); - - // If an ad has loaded, show it. If the user watches all the way through, the - // LoggingRewardedVideoListener will log a reward! - if (rewarded_video::LoadAdLastResult().error() == - firebase::admob::kAdMobErrorNone) { - LogMessage("Showing a rewarded video ad."); - rewarded_video::Show(GetWindowContext()); - - WaitForFutureCompletion(rewarded_video::ShowLastResult()); - - // Normally Pause and Resume would be called in response to the app pausing - // or losing focus. This is just a test. - LogMessage("Pausing."); - rewarded_video::Pause(); - - WaitForFutureCompletion(rewarded_video::PauseLastResult()); - - LogMessage("Resuming."); - rewarded_video::Resume(); - - WaitForFutureCompletion(rewarded_video::ResumeLastResult()); - } - - LogMessage("Done!"); - - // Wait until the user kills the app. - while (!ProcessEvents(1000)) { - } - - delete banner; - delete interstitial; - rewarded_video::Destroy(); - firebase::admob::Terminate(); - delete app; - - return 0; -} diff --git a/admob/testapp/src/desktop/desktop_main.cc b/admob/testapp/src/desktop/desktop_main.cc deleted file mode 100644 index 0220c688..00000000 --- a/admob/testapp/src/desktop/desktop_main.cc +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// -// 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 -#include -#include - -#ifdef _WIN32 -#include -#define chdir _chdir -#else -#include -#endif // _WIN32 - -#ifdef _WIN32 -#include -#endif // _WIN32 - -#include -#include - -#include "main.h" // NOLINT - -// The TO_STRING macro is useful for command line defined strings as the quotes -// get stripped. -#define TO_STRING_EXPAND(X) #X -#define TO_STRING(X) TO_STRING_EXPAND(X) - -// Path to the Firebase config file to load. -#ifdef FIREBASE_CONFIG -#define FIREBASE_CONFIG_STRING TO_STRING(FIREBASE_CONFIG) -#else -#define FIREBASE_CONFIG_STRING "" -#endif // FIREBASE_CONFIG - -extern "C" int common_main(int argc, const char* argv[]); - -static bool quit = false; - -#ifdef _WIN32 -static BOOL WINAPI SignalHandler(DWORD event) { - if (!(event == CTRL_C_EVENT || event == CTRL_BREAK_EVENT)) { - return FALSE; - } - quit = true; - return TRUE; -} -#else -static void SignalHandler(int /* ignored */) { quit = true; } -#endif // _WIN32 - -bool ProcessEvents(int msec) { -#ifdef _WIN32 - Sleep(msec); -#else - usleep(msec * 1000); -#endif // _WIN32 - return quit; -} - -std::string PathForResource() { - return std::string(); -} - -void LogMessage(const char* format, ...) { - va_list list; - va_start(list, format); - vprintf(format, list); - va_end(list); - printf("\n"); - fflush(stdout); -} - -WindowContext GetWindowContext() { return nullptr; } - -// Change the current working directory to the directory containing the -// specified file. -void ChangeToFileDirectory(const char* file_path) { - std::string path(file_path); - std::replace(path.begin(), path.end(), '\\', '/'); - auto slash = path.rfind('/'); - if (slash != std::string::npos) { - std::string directory = path.substr(0, slash); - if (!directory.empty()) chdir(directory.c_str()); - } -} - -int main(int argc, const char* argv[]) { - ChangeToFileDirectory( - FIREBASE_CONFIG_STRING[0] != '\0' ? - FIREBASE_CONFIG_STRING : argv[0]); // NOLINT -#ifdef _WIN32 - SetConsoleCtrlHandler((PHANDLER_ROUTINE)SignalHandler, TRUE); -#else - signal(SIGINT, SignalHandler); -#endif // _WIN32 - return common_main(argc, argv); -} - -#if defined(_WIN32) -// Returns the number of microseconds since the epoch. -int64_t WinGetCurrentTimeInMicroseconds() { - FILETIME file_time; - GetSystemTimeAsFileTime(&file_time); - - ULARGE_INTEGER now; - now.LowPart = file_time.dwLowDateTime; - now.HighPart = file_time.dwHighDateTime; - - // Windows file time is expressed in 100s of nanoseconds. - // To convert to microseconds, multiply x10. - return now.QuadPart * 10LL; -} -#endif diff --git a/admob/testapp/src/ios/ios_main.mm b/admob/testapp/src/ios/ios_main.mm deleted file mode 100644 index 6ccb2de5..00000000 --- a/admob/testapp/src/ios/ios_main.mm +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// -// 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 - -#include "main.h" - -extern "C" int common_main(int argc, const char* argv[]); - -@interface AppDelegate : UIResponder - -@property(nonatomic, strong) UIWindow *window; - -@end - -@interface FTAViewController : UIViewController - -@end - -static int g_exit_status = 0; -static bool g_shutdown = false; -static NSCondition *g_shutdown_complete; -static NSCondition *g_shutdown_signal; -static UITextView *g_text_view; -static UIView *g_parent_view; - -@implementation FTAViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - g_parent_view = self.view; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - const char *argv[] = {FIREBASE_TESTAPP_NAME}; - [g_shutdown_signal lock]; - g_exit_status = common_main(1, argv); - [g_shutdown_complete signal]; - }); -} - -@end - -bool ProcessEvents(int msec) { - [g_shutdown_signal - waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:static_cast(msec) / 1000.0f]]; - return g_shutdown; -} - -WindowContext GetWindowContext() { - return g_parent_view; -} - -// Log a message that can be viewed in the console. -void LogMessage(const char* format, ...) { - va_list args; - NSString *formatString = @(format); - - va_start(args, format); - NSString *message = [[NSString alloc] initWithFormat:formatString arguments:args]; - va_end(args); - - NSLog(@"%@", message); - message = [message stringByAppendingString:@"\n"]; - - dispatch_async(dispatch_get_main_queue(), ^{ - g_text_view.text = [g_text_view.text stringByAppendingString:message]; - }); -} - -int main(int argc, char* argv[]) { - @autoreleasepool { - UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } - return g_exit_status; -} - -@implementation AppDelegate - -- (BOOL)application:(UIApplication*)application - didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { - g_shutdown_complete = [[NSCondition alloc] init]; - g_shutdown_signal = [[NSCondition alloc] init]; - [g_shutdown_complete lock]; - - self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; - FTAViewController *viewController = [[FTAViewController alloc] init]; - self.window.rootViewController = viewController; - [self.window makeKeyAndVisible]; - - g_text_view = [[UITextView alloc] initWithFrame:viewController.view.bounds]; - - g_text_view.editable = NO; - g_text_view.scrollEnabled = YES; - g_text_view.userInteractionEnabled = YES; - - [viewController.view addSubview:g_text_view]; - - return YES; -} - -- (void)applicationWillTerminate:(UIApplication *)application { - g_shutdown = true; - [g_shutdown_signal signal]; - [g_shutdown_complete wait]; -} - -@end diff --git a/admob/testapp/src/main.h b/admob/testapp/src/main.h deleted file mode 100644 index 2eda2c10..00000000 --- a/admob/testapp/src/main.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// -// 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_TESTAPP_MAIN_H_ // NOLINT -#define FIREBASE_TESTAPP_MAIN_H_ // NOLINT - -#if defined(__ANDROID__) -#include -#include -#elif defined(__APPLE__) -extern "C" { -#include -} // extern "C" -#endif // __ANDROID__ - -// Defined using -DANDROID_MAIN_APP_NAME=some_app_name when compiling this -// file. -#ifndef FIREBASE_TESTAPP_NAME -#define FIREBASE_TESTAPP_NAME "android_main" -#endif // FIREBASE_TESTAPP_NAME - -// Cross platform logging method. -// Implemented by android/android_main.cc or ios/ios_main.mm. -extern "C" void LogMessage(const char* format, ...); - -// Platform-independent method to flush pending events for the main thread. -// Returns true when an event requesting program-exit is received. -bool ProcessEvents(int msec); - -// WindowContext represents the handle to the parent window. It's type -// (and usage) vary based on the OS. -#if defined(__ANDROID__) -typedef jobject WindowContext; // A jobject to the Java Activity. -#elif defined(__APPLE__) -typedef id WindowContext; // A pointer to an iOS UIView. -#else -typedef void* WindowContext; // A void* for any other environments. -#endif - -#if defined(__ANDROID__) -// Get the JNI environment. -JNIEnv* GetJniEnv(); -// Get the activity. -jobject GetActivity(); -#endif // defined(__ANDROID__) - -// Returns a variable that describes the window context for the app. On Android -// this will be a jobject pointing to the Activity. On iOS, it's an id pointing -// to the root view of the view controller. -WindowContext GetWindowContext(); - -#endif // FIREBASE_TESTAPP_MAIN_H_ // NOLINT diff --git a/admob/testapp/testapp.xcodeproj/project.pbxproj b/admob/testapp/testapp.xcodeproj/project.pbxproj deleted file mode 100644 index 3afd2dea..00000000 --- a/admob/testapp/testapp.xcodeproj/project.pbxproj +++ /dev/null @@ -1,312 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 4A7C015A1CEAA2480011C504 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4A7C01591CEAA2480011C504 /* Images.xcassets */; }; - 520BC0391C869159008CFBC3 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */; }; - 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D51C85F68000C89379 /* Foundation.framework */; }; - 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D71C85F68000C89379 /* CoreGraphics.framework */; }; - 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D91C85F68000C89379 /* UIKit.framework */; }; - 529227211C85FB6A00C89379 /* common_main.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5292271F1C85FB6A00C89379 /* common_main.cc */; }; - 529227241C85FB7600C89379 /* ios_main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 529227221C85FB7600C89379 /* ios_main.mm */; }; - D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 4A7C01591CEAA2480011C504 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = testapp/Images.xcassets; sourceTree = ""; }; - 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; - 529226D21C85F68000C89379 /* testapp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testapp.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 529226D51C85F68000C89379 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 529226D71C85F68000C89379 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 529226D91C85F68000C89379 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 529226EE1C85F68000C89379 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; - 5292271F1C85FB6A00C89379 /* common_main.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = common_main.cc; path = src/common_main.cc; sourceTree = ""; }; - 529227201C85FB6A00C89379 /* main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = main.h; path = src/main.h; sourceTree = ""; }; - 529227221C85FB7600C89379 /* ios_main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_main.mm; path = src/ios/ios_main.mm; sourceTree = ""; }; - 52FD1FF81C85FFA000BC68E3 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = testapp/Info.plist; sourceTree = ""; }; - D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 529226CF1C85F68000C89379 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */, - 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */, - 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 529226C91C85F68000C89379 = { - isa = PBXGroup; - children = ( - 4A7C01591CEAA2480011C504 /* Images.xcassets */, - D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */, - 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */, - 52FD1FF81C85FFA000BC68E3 /* Info.plist */, - 5292271D1C85FB5500C89379 /* src */, - 529226D41C85F68000C89379 /* Frameworks */, - 529226D31C85F68000C89379 /* Products */, - ); - sourceTree = ""; - }; - 529226D31C85F68000C89379 /* Products */ = { - isa = PBXGroup; - children = ( - 529226D21C85F68000C89379 /* testapp.app */, - ); - name = Products; - sourceTree = ""; - }; - 529226D41C85F68000C89379 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 529226D51C85F68000C89379 /* Foundation.framework */, - 529226D71C85F68000C89379 /* CoreGraphics.framework */, - 529226D91C85F68000C89379 /* UIKit.framework */, - 529226EE1C85F68000C89379 /* XCTest.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 5292271D1C85FB5500C89379 /* src */ = { - isa = PBXGroup; - children = ( - 5292271F1C85FB6A00C89379 /* common_main.cc */, - 529227201C85FB6A00C89379 /* main.h */, - 5292271E1C85FB5B00C89379 /* ios */, - ); - name = src; - sourceTree = ""; - }; - 5292271E1C85FB5B00C89379 /* ios */ = { - isa = PBXGroup; - children = ( - 529227221C85FB7600C89379 /* ios_main.mm */, - ); - name = ios; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 529226D11C85F68000C89379 /* testapp */ = { - isa = PBXNativeTarget; - buildConfigurationList = 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "testapp" */; - buildPhases = ( - 529226CE1C85F68000C89379 /* Sources */, - 529226CF1C85F68000C89379 /* Frameworks */, - 529226D01C85F68000C89379 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = testapp; - productName = testapp; - productReference = 529226D21C85F68000C89379 /* testapp.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 529226CA1C85F68000C89379 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0640; - ORGANIZATIONNAME = Google; - TargetAttributes = { - 529226D11C85F68000C89379 = { - CreatedOnToolsVersion = 6.4; - }; - }; - }; - buildConfigurationList = 529226CD1C85F68000C89379 /* Build configuration list for PBXProject "testapp" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 529226C91C85F68000C89379; - productRefGroup = 529226D31C85F68000C89379 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 529226D11C85F68000C89379 /* testapp */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 529226D01C85F68000C89379 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */, - 4A7C015A1CEAA2480011C504 /* Images.xcassets in Resources */, - 520BC0391C869159008CFBC3 /* GoogleService-Info.plist in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 529226CE1C85F68000C89379 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 529227241C85FB7600C89379 /* ios_main.mm in Sources */, - 529227211C85FB6A00C89379 /* common_main.cc in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 529226F71C85F68000C89379 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 529226F81C85F68000C89379 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 529226FA1C85F68000C89379 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "\"$(SRCROOT)/src\"", - ); - INFOPLIST_FILE = testapp/Info.plist; - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = app; - }; - name = Debug; - }; - 529226FB1C85F68000C89379 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "\"$(SRCROOT)/src\"", - ); - INFOPLIST_FILE = testapp/Info.plist; - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = app; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 529226CD1C85F68000C89379 /* Build configuration list for PBXProject "testapp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 529226F71C85F68000C89379 /* Debug */, - 529226F81C85F68000C89379 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "testapp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 529226FA1C85F68000C89379 /* Debug */, - 529226FB1C85F68000C89379 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 529226CA1C85F68000C89379 /* Project object */; -} diff --git a/admob/testapp/testapp/Images.xcassets/AppIcon.appiconset/Contents.json b/admob/testapp/testapp/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index eeea76c2..00000000 --- a/admob/testapp/testapp/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "83.5x83.5", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/admob/testapp/testapp/Images.xcassets/LaunchImage.launchimage/Contents.json b/admob/testapp/testapp/Images.xcassets/LaunchImage.launchimage/Contents.json deleted file mode 100644 index a0ad363c..00000000 --- a/admob/testapp/testapp/Images.xcassets/LaunchImage.launchimage/Contents.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "images" : [ - { - "orientation" : "portrait", - "idiom" : "ipad", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "1x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "1x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/admob/testapp/testapp/Info.plist b/admob/testapp/testapp/Info.plist deleted file mode 100644 index 3f0f944e..00000000 --- a/admob/testapp/testapp/Info.plist +++ /dev/null @@ -1,28 +0,0 @@ - - - - - GADApplicationIdentifier - YOUR_IOS_ADMOB_APP_ID - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - com.google.ios.admob.testapp - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - - diff --git a/scripts/build_scripts/build_testapps.json b/scripts/build_scripts/build_testapps.json index 7dc1d078..5b5ef2d1 100644 --- a/scripts/build_scripts/build_testapps.json +++ b/scripts/build_scripts/build_testapps.json @@ -1,18 +1,5 @@ { "apis": [ - { - "name": "admob", - "full_name": "FirebaseAdmob", - "bundle_id": "com.google.ios.admob.testapp", - "ios_target": "testapp", - "tvos_target": "", - "testapp_path": "admob/testapp", - "frameworks": [ - "firebase_admob.xcframework", - "firebase.xcframework" - ], - "provision": "Google_Development.mobileprovision" - }, { "name": "analytics", "full_name": "FirebaseAnalytics", diff --git a/scripts/gha-encrypted/admob/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/admob/GoogleService-Info.plist.gpg deleted file mode 100644 index 7a8dd56b43dacbfaf599257dc3c7228deffe524e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 671 zcmV;Q0$}}&4Fm}T0-Lp(S*XbSzyH$d0ccQ3S6V1c>`Vq{v@eT;(WXE&Mg7Sm$!4&< z@!pq8juOCk>c~ub=-BY`=|$N%sL8OnJhQx3;)u5G_mI7lb7x&|tZJ`xmU6Y|4}M`o-pzpt>cC;cW3n(fm#lMj0q5qrw#iXV@hH3!~0EURh?^Y}bnKHD}=G$)7BL6z=wX z61wI zU^IG4E^8z{RtfF8iGTe6w0ms+K{j{aCnwrF zQ(W`X)ryzv4IjF(R2}7emWWn?aS5FZaWa8+4BoL4^j}#qP{bD(UkyP^~9$knrMTAClQ`y;xhD(q}xeIq+JpqL8h^2E> zH%l>NZN>i!)bm8tWMoH+{9-#))^qYDF~q_RhG(d*n*RRsaoQ+$jVH Fi_{?GSk3?d diff --git a/scripts/gha-encrypted/admob/google-services.json.gpg b/scripts/gha-encrypted/admob/google-services.json.gpg deleted file mode 100644 index b62f63cbd715bac8245378fe906b83c40f168bbe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1002 zcmV|*kk0})|U8{>`vX{A^rB0mUfNRZ3b@0(nBs0uCLT5=f&CS7md#Vj&Q8(kxYI|_37n{ zJ}{jbQu@aHPH&_>z`JK!8@DwEYY^&yKTQ0dvkSeP*eUR(u1Uo5TYJf*^mDeGN9duk z8nii0zNRM>G4S=ub?k1o&K;x!!c%~Je;MAmq2m7_C;TP?FoA#-0aF-v#3`vetun(a%*PI# z-YEo)EDP?8qw7I;P;${whXK)^q5UYT`namLHDbE zv1#5*IDnu2pd4ACmBp^Av6(*@k|^+B^yML1DV_j+UAG*8?ovqQRQ{ z*{e3BDhx2%z*jOvllCRg!51fA0cDg$ymDS0b4BXgU#W)*kg69Ayb`d;C#Wt^5{Oxq z&LG)P>~?QI7BYDLKMlfL)Vfa5RqCvDdHuuNtN_H{y1h}xPGJ`#eM^_A@Ft#VHnP+m z+%l8o45e`Ql2}r~?NdQmIz2Cfvi(t9!^Ne-*o*|f*iIre@_eihE5slG-9_xHNlR54 zd|>Y0(rKpKTGZ%-lt}y({)arrs8Snc4GBf48&t1I`HN5o-?>I%-_i#MU@L9n$_}Lt z%>~;AA;Z13$f5C(fNXk8&Aox%LXL&b0Dp4Cm?d6wEb_1Q`}{2%m43+QSioY9j*9lx zfi&XaUSG~Qp_EOTU31bi0Z)!OzzJP4Qu|9Isy=iG>pi_|m;h2(U0A=U=Zs^MQ0Eig z@>P&AdHOoJG;=J0xZA>?(KL1xCX)wctgo1|yv@!RTFChPvNK(K!bUox+U6aQ5gAXd zipi1IvmVTR+>zj$82f9Y0>mLfFf5C1&+q|X!Fg%ST!JNNvbNXO*b-PoZ63MT5sxiV z&S&PyOhi6OBMXcedg~ut+-5@gSV|E4;bP8(z467TvcX;x`x0hYO{WmPoKO$Z_8Ey* Yboa4XrsEr5lqq?)xW4iT*rtkxy%%)*%m4rY From 233418b2f34111f1f08fc60ab153db7e894d3bd0 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 23 May 2024 16:41:59 -0700 Subject: [PATCH 47/57] Update Cocoapods to latest. --- analytics/testapp/Podfile | 4 ++-- auth/testapp/Podfile | 4 ++-- database/testapp/Podfile | 6 +++--- dynamic_links/testapp/Podfile | 4 ++-- firestore/testapp/Podfile | 6 +++--- functions/testapp/Podfile | 6 +++--- gma/testapp/Podfile | 6 +++--- messaging/testapp/Podfile | 4 ++-- remote_config/testapp/Podfile | 4 ++-- storage/testapp/Podfile | 6 +++--- 10 files changed, 25 insertions(+), 25 deletions(-) diff --git a/analytics/testapp/Podfile b/analytics/testapp/Podfile index f7888311..9428612e 100644 --- a/analytics/testapp/Podfile +++ b/analytics/testapp/Podfile @@ -1,6 +1,6 @@ source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' +platform :ios, '13.0' # Analytics test application. target 'testapp' do - pod 'Firebase/Analytics', '7.0.0' + pod 'Firebase/Analytics', '10.25.0' end diff --git a/auth/testapp/Podfile b/auth/testapp/Podfile index d2ddd900..a44a8d32 100644 --- a/auth/testapp/Podfile +++ b/auth/testapp/Podfile @@ -1,6 +1,6 @@ source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' +platform :ios, '13.0' # Auth test application. target 'testapp' do - pod 'Firebase/Auth', '7.0.0' + pod 'Firebase/Auth', '10.25.0' end diff --git a/database/testapp/Podfile b/database/testapp/Podfile index 966f7b10..f004f70a 100644 --- a/database/testapp/Podfile +++ b/database/testapp/Podfile @@ -1,7 +1,7 @@ source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' +platform :ios, '13.0' # Firebase Realtime Database test application. target 'testapp' do - pod 'Firebase/Database', '7.0.0' - pod 'Firebase/Auth', '7.0.0' + pod 'Firebase/Database', '10.25.0' + pod 'Firebase/Auth', '10.25.0' end diff --git a/dynamic_links/testapp/Podfile b/dynamic_links/testapp/Podfile index 8af0d756..af8f5566 100644 --- a/dynamic_links/testapp/Podfile +++ b/dynamic_links/testapp/Podfile @@ -1,6 +1,6 @@ source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' +platform :ios, '13.0' # Dynamic Links test application. target 'testapp' do - pod 'Firebase/DynamicLinks', '7.0.0' + pod 'Firebase/DynamicLinks', '10.25.0' end diff --git a/firestore/testapp/Podfile b/firestore/testapp/Podfile index 31e20c7c..2f14e9d3 100644 --- a/firestore/testapp/Podfile +++ b/firestore/testapp/Podfile @@ -1,7 +1,7 @@ source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '10.0' +platform :ios, '13.0' # Firebase Firestore test application. target 'testapp' do - pod 'Firebase/Firestore', '8.2.0' - pod 'Firebase/Auth', '8.2.0' + pod 'Firebase/Firestore', '10.25.0' + pod 'Firebase/Auth', '10.25.0' end diff --git a/functions/testapp/Podfile b/functions/testapp/Podfile index 51c5b50a..0a698245 100644 --- a/functions/testapp/Podfile +++ b/functions/testapp/Podfile @@ -1,7 +1,7 @@ source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' +platform :ios, '13.0' # Cloud Functions for Firebase test application. target 'testapp' do - pod 'Firebase/Functions', '7.0.0' - pod 'Firebase/Auth', '7.0.0' + pod 'Firebase/Functions', '10.25.0' + pod 'Firebase/Auth', '10.25.0' end diff --git a/gma/testapp/Podfile b/gma/testapp/Podfile index 51c73e38..aa47dcc4 100644 --- a/gma/testapp/Podfile +++ b/gma/testapp/Podfile @@ -1,7 +1,7 @@ source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '10.0' +platform :ios, '13.0' # GMA test application. target 'testapp' do - pod 'Google-Mobile-Ads-SDK', '8.13.0' - pod 'Firebase/Analytics', '8.10.0' + pod 'Google-Mobile-Ads-SDK', '11.2.0' + pod 'Firebase/Analytics', '10.25.0' end diff --git a/messaging/testapp/Podfile b/messaging/testapp/Podfile index e6ffc8dc..7aa873f4 100644 --- a/messaging/testapp/Podfile +++ b/messaging/testapp/Podfile @@ -1,6 +1,6 @@ source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' +platform :ios, '13.0' # FCM test application. target 'testapp' do - pod 'Firebase/Messaging', '7.0.0' + pod 'Firebase/Messaging', '10.25.0' end diff --git a/remote_config/testapp/Podfile b/remote_config/testapp/Podfile index 5ce98e6d..274d3540 100644 --- a/remote_config/testapp/Podfile +++ b/remote_config/testapp/Podfile @@ -1,6 +1,6 @@ source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' +platform :ios, '13.0' # Firebase Remote Config test application. target 'testapp' do - pod 'Firebase/RemoteConfig', '7.0.0' + pod 'Firebase/RemoteConfig', '10.25.0' end diff --git a/storage/testapp/Podfile b/storage/testapp/Podfile index f79f288b..8091b546 100644 --- a/storage/testapp/Podfile +++ b/storage/testapp/Podfile @@ -1,7 +1,7 @@ source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' +platform :ios, '13.0' # Cloud Storage for Firebase test application. target 'testapp' do - pod 'Firebase/Storage', '7.0.0' - pod 'Firebase/Auth', '7.0.0' + pod 'Firebase/Storage', '10.25.0' + pod 'Firebase/Auth', '10.25.0' end From 9e61685c85b5cbd56eaffcdf7ddd10166eca9560 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 23 May 2024 17:09:50 -0700 Subject: [PATCH 48/57] Added use_frameworks! flag needed for Swift compatibility. --- analytics/testapp/Podfile | 1 + auth/testapp/Podfile | 1 + .../testapp/testapp.xcodeproj/project.pbxproj | 78 +++++++++++++++++++ database/testapp/Podfile | 1 + dynamic_links/testapp/Podfile | 1 + firestore/testapp/Podfile | 1 + functions/testapp/Podfile | 1 + gma/testapp/Podfile | 1 + messaging/testapp/Podfile | 1 + remote_config/testapp/Podfile | 1 + storage/testapp/Podfile | 1 + 11 files changed, 88 insertions(+) diff --git a/analytics/testapp/Podfile b/analytics/testapp/Podfile index 9428612e..5895e3a3 100644 --- a/analytics/testapp/Podfile +++ b/analytics/testapp/Podfile @@ -1,5 +1,6 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '13.0' +use_frameworks! # Analytics test application. target 'testapp' do pod 'Firebase/Analytics', '10.25.0' diff --git a/auth/testapp/Podfile b/auth/testapp/Podfile index a44a8d32..825abee2 100644 --- a/auth/testapp/Podfile +++ b/auth/testapp/Podfile @@ -1,5 +1,6 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '13.0' +use_frameworks! # Auth test application. target 'testapp' do pod 'Firebase/Auth', '10.25.0' diff --git a/auth/testapp/testapp.xcodeproj/project.pbxproj b/auth/testapp/testapp.xcodeproj/project.pbxproj index 5769362c..65f4be31 100644 --- a/auth/testapp/testapp.xcodeproj/project.pbxproj +++ b/auth/testapp/testapp.xcodeproj/project.pbxproj @@ -15,9 +15,11 @@ 529227241C85FB7600C89379 /* ios_main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 529227221C85FB7600C89379 /* ios_main.mm */; }; 52B71EBB1C8600B600398745 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 52B71EBA1C8600B600398745 /* Images.xcassets */; }; D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */; }; + FA08030EA3D096D266A6DE7B /* Pods_testapp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46C2548FA84411C2A9D067CB /* Pods_testapp.framework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 46C2548FA84411C2A9D067CB /* Pods_testapp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_testapp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 529226D21C85F68000C89379 /* testapp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testapp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 529226D51C85F68000C89379 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; @@ -29,7 +31,9 @@ 529227221C85FB7600C89379 /* ios_main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_main.mm; path = src/ios/ios_main.mm; sourceTree = ""; }; 52B71EBA1C8600B600398745 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = testapp/Images.xcassets; sourceTree = ""; }; 52FD1FF81C85FFA000BC68E3 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = testapp/Info.plist; sourceTree = ""; }; + B1320FFA7E8D45124716A662 /* Pods-testapp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-testapp.release.xcconfig"; path = "Target Support Files/Pods-testapp/Pods-testapp.release.xcconfig"; sourceTree = ""; }; D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; + FC7EC0D42BD90C2E1CAB03EE /* Pods-testapp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-testapp.debug.xcconfig"; path = "Target Support Files/Pods-testapp/Pods-testapp.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -40,12 +44,23 @@ 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */, 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */, 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */, + FA08030EA3D096D266A6DE7B /* Pods_testapp.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 3E2FC86EB58D8B5977042124 /* Pods */ = { + isa = PBXGroup; + children = ( + FC7EC0D42BD90C2E1CAB03EE /* Pods-testapp.debug.xcconfig */, + B1320FFA7E8D45124716A662 /* Pods-testapp.release.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; 529226C91C85F68000C89379 = { isa = PBXGroup; children = ( @@ -56,6 +71,7 @@ 5292271D1C85FB5500C89379 /* src */, 529226D41C85F68000C89379 /* Frameworks */, 529226D31C85F68000C89379 /* Products */, + 3E2FC86EB58D8B5977042124 /* Pods */, ); sourceTree = ""; }; @@ -74,6 +90,7 @@ 529226D71C85F68000C89379 /* CoreGraphics.framework */, 529226D91C85F68000C89379 /* UIKit.framework */, 529226EE1C85F68000C89379 /* XCTest.framework */, + 46C2548FA84411C2A9D067CB /* Pods_testapp.framework */, ); name = Frameworks; sourceTree = ""; @@ -103,9 +120,11 @@ isa = PBXNativeTarget; buildConfigurationList = 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "testapp" */; buildPhases = ( + 17179573A7AC37A3937EFB3C /* [CP] Check Pods Manifest.lock */, 529226CE1C85F68000C89379 /* Sources */, 529226CF1C85F68000C89379 /* Frameworks */, 529226D01C85F68000C89379 /* Resources */, + D4E64C05496F0F15FA3C6510 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -160,6 +179,63 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 17179573A7AC37A3937EFB3C /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-testapp-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + D4E64C05496F0F15FA3C6510 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-testapp/Pods-testapp-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/FirebaseAppCheckInterop/FirebaseAppCheckInterop.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseAuth/FirebaseAuth.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework", + "${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework", + "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", + "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework", + "${BUILT_PRODUCTS_DIR}/RecaptchaInterop/RecaptchaInterop.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAppCheckInterop.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAuth.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMSessionFetcher.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RecaptchaInterop.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-testapp/Pods-testapp-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 529226CE1C85F68000C89379 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -255,6 +331,7 @@ }; 529226FA1C85F68000C89379 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = FC7EC0D42BD90C2E1CAB03EE /* Pods-testapp.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; @@ -271,6 +348,7 @@ }; 529226FB1C85F68000C89379 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = B1320FFA7E8D45124716A662 /* Pods-testapp.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; diff --git a/database/testapp/Podfile b/database/testapp/Podfile index f004f70a..5832b272 100644 --- a/database/testapp/Podfile +++ b/database/testapp/Podfile @@ -1,5 +1,6 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '13.0' +use_frameworks! # Firebase Realtime Database test application. target 'testapp' do pod 'Firebase/Database', '10.25.0' diff --git a/dynamic_links/testapp/Podfile b/dynamic_links/testapp/Podfile index af8f5566..e983680a 100644 --- a/dynamic_links/testapp/Podfile +++ b/dynamic_links/testapp/Podfile @@ -1,5 +1,6 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '13.0' +use_frameworks! # Dynamic Links test application. target 'testapp' do pod 'Firebase/DynamicLinks', '10.25.0' diff --git a/firestore/testapp/Podfile b/firestore/testapp/Podfile index 2f14e9d3..e0bca1be 100644 --- a/firestore/testapp/Podfile +++ b/firestore/testapp/Podfile @@ -1,5 +1,6 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '13.0' +use_frameworks! # Firebase Firestore test application. target 'testapp' do pod 'Firebase/Firestore', '10.25.0' diff --git a/functions/testapp/Podfile b/functions/testapp/Podfile index 0a698245..7197d817 100644 --- a/functions/testapp/Podfile +++ b/functions/testapp/Podfile @@ -1,5 +1,6 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '13.0' +use_frameworks! # Cloud Functions for Firebase test application. target 'testapp' do pod 'Firebase/Functions', '10.25.0' diff --git a/gma/testapp/Podfile b/gma/testapp/Podfile index aa47dcc4..4683028b 100644 --- a/gma/testapp/Podfile +++ b/gma/testapp/Podfile @@ -1,5 +1,6 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '13.0' +use_frameworks! # GMA test application. target 'testapp' do pod 'Google-Mobile-Ads-SDK', '11.2.0' diff --git a/messaging/testapp/Podfile b/messaging/testapp/Podfile index 7aa873f4..b022880f 100644 --- a/messaging/testapp/Podfile +++ b/messaging/testapp/Podfile @@ -1,5 +1,6 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '13.0' +use_frameworks! # FCM test application. target 'testapp' do pod 'Firebase/Messaging', '10.25.0' diff --git a/remote_config/testapp/Podfile b/remote_config/testapp/Podfile index 274d3540..14a96f7d 100644 --- a/remote_config/testapp/Podfile +++ b/remote_config/testapp/Podfile @@ -1,5 +1,6 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '13.0' +use_frameworks! # Firebase Remote Config test application. target 'testapp' do pod 'Firebase/RemoteConfig', '10.25.0' diff --git a/storage/testapp/Podfile b/storage/testapp/Podfile index 8091b546..7010e7c0 100644 --- a/storage/testapp/Podfile +++ b/storage/testapp/Podfile @@ -1,5 +1,6 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '13.0' +use_frameworks! # Cloud Storage for Firebase test application. target 'testapp' do pod 'Firebase/Storage', '10.25.0' From a1028f445901be3593784425eb78c0a69bc43020 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 28 May 2024 11:35:31 -0700 Subject: [PATCH 49/57] Remove extraneous pods. --- .../testapp/testapp.xcodeproj/project.pbxproj | 75 ++----------------- 1 file changed, 5 insertions(+), 70 deletions(-) diff --git a/auth/testapp/testapp.xcodeproj/project.pbxproj b/auth/testapp/testapp.xcodeproj/project.pbxproj index 65f4be31..dbad8094 100644 --- a/auth/testapp/testapp.xcodeproj/project.pbxproj +++ b/auth/testapp/testapp.xcodeproj/project.pbxproj @@ -15,11 +15,10 @@ 529227241C85FB7600C89379 /* ios_main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 529227221C85FB7600C89379 /* ios_main.mm */; }; 52B71EBB1C8600B600398745 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 52B71EBA1C8600B600398745 /* Images.xcassets */; }; D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */; }; - FA08030EA3D096D266A6DE7B /* Pods_testapp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46C2548FA84411C2A9D067CB /* Pods_testapp.framework */; }; + D6FC32B32C06595E00E3E028 /* GameKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6FC32B22C06595E00E3E028 /* GameKit.framework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 46C2548FA84411C2A9D067CB /* Pods_testapp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_testapp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 529226D21C85F68000C89379 /* testapp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testapp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 529226D51C85F68000C89379 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; @@ -31,9 +30,8 @@ 529227221C85FB7600C89379 /* ios_main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_main.mm; path = src/ios/ios_main.mm; sourceTree = ""; }; 52B71EBA1C8600B600398745 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = testapp/Images.xcassets; sourceTree = ""; }; 52FD1FF81C85FFA000BC68E3 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = testapp/Info.plist; sourceTree = ""; }; - B1320FFA7E8D45124716A662 /* Pods-testapp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-testapp.release.xcconfig"; path = "Target Support Files/Pods-testapp/Pods-testapp.release.xcconfig"; sourceTree = ""; }; D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; - FC7EC0D42BD90C2E1CAB03EE /* Pods-testapp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-testapp.debug.xcconfig"; path = "Target Support Files/Pods-testapp/Pods-testapp.debug.xcconfig"; sourceTree = ""; }; + D6FC32B22C06595E00E3E028 /* GameKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System/Library/Frameworks/GameKit.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -42,9 +40,9 @@ buildActionMask = 2147483647; files = ( 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */, + D6FC32B32C06595E00E3E028 /* GameKit.framework in Frameworks */, 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */, 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */, - FA08030EA3D096D266A6DE7B /* Pods_testapp.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -54,10 +52,7 @@ 3E2FC86EB58D8B5977042124 /* Pods */ = { isa = PBXGroup; children = ( - FC7EC0D42BD90C2E1CAB03EE /* Pods-testapp.debug.xcconfig */, - B1320FFA7E8D45124716A662 /* Pods-testapp.release.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -86,11 +81,11 @@ 529226D41C85F68000C89379 /* Frameworks */ = { isa = PBXGroup; children = ( + D6FC32B22C06595E00E3E028 /* GameKit.framework */, 529226D51C85F68000C89379 /* Foundation.framework */, 529226D71C85F68000C89379 /* CoreGraphics.framework */, 529226D91C85F68000C89379 /* UIKit.framework */, 529226EE1C85F68000C89379 /* XCTest.framework */, - 46C2548FA84411C2A9D067CB /* Pods_testapp.framework */, ); name = Frameworks; sourceTree = ""; @@ -120,11 +115,9 @@ isa = PBXNativeTarget; buildConfigurationList = 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "testapp" */; buildPhases = ( - 17179573A7AC37A3937EFB3C /* [CP] Check Pods Manifest.lock */, 529226CE1C85F68000C89379 /* Sources */, 529226CF1C85F68000C89379 /* Frameworks */, 529226D01C85F68000C89379 /* Resources */, - D4E64C05496F0F15FA3C6510 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -154,6 +147,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = 529226C91C85F68000C89379; @@ -179,63 +173,6 @@ }; /* End PBXResourcesBuildPhase section */ -/* Begin PBXShellScriptBuildPhase section */ - 17179573A7AC37A3937EFB3C /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-testapp-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - D4E64C05496F0F15FA3C6510 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-testapp/Pods-testapp-frameworks.sh", - "${BUILT_PRODUCTS_DIR}/FirebaseAppCheckInterop/FirebaseAppCheckInterop.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseAuth/FirebaseAuth.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework", - "${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework", - "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", - "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework", - "${BUILT_PRODUCTS_DIR}/RecaptchaInterop/RecaptchaInterop.framework", - ); - name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAppCheckInterop.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAuth.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMSessionFetcher.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RecaptchaInterop.framework", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-testapp/Pods-testapp-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - /* Begin PBXSourcesBuildPhase section */ 529226CE1C85F68000C89379 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -331,7 +268,6 @@ }; 529226FA1C85F68000C89379 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = FC7EC0D42BD90C2E1CAB03EE /* Pods-testapp.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; @@ -348,7 +284,6 @@ }; 529226FB1C85F68000C89379 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B1320FFA7E8D45124716A662 /* Pods-testapp.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; From ee5157fb350a6c916a8b6e6b64c2ddf2eb2dbc84 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Fri, 21 Jun 2024 13:11:01 -0700 Subject: [PATCH 50/57] Update secret files. --- scripts/gha-encrypted/README | 3 +-- .../analytics/GoogleService-Info.plist.gpg | Bin 683 -> 670 bytes .../analytics/google-services.json.gpg | Bin 958 -> 962 bytes .../auth/GoogleService-Info.plist.gpg | Bin 691 -> 681 bytes .../auth/google-services.json.gpg | Bin 1014 -> 1007 bytes .../database/GoogleService-Info.plist.gpg | Bin 711 -> 700 bytes .../database/google-services.json.gpg | Bin 719 -> 725 bytes .../GoogleService-Info.plist.gpg | Bin 736 -> 649 bytes .../dynamic_links/google-services.json.gpg | Bin 712 -> 711 bytes .../firestore/GoogleService-Info.plist.gpg | Bin 610 -> 597 bytes .../firestore/google-services.json.gpg | Bin 534 -> 523 bytes .../functions/GoogleService-Info.plist.gpg | Bin 688 -> 674 bytes .../functions/google-services.json.gpg | Bin 850 -> 525 bytes .../gma/GoogleService-Info.plist.gpg | Bin 672 -> 663 bytes .../gma/google-services.json.gpg | Bin 1002 -> 953 bytes .../messaging/GoogleService-Info.plist.gpg | Bin 692 -> 681 bytes .../messaging/google-services.json.gpg | Bin 911 -> 609 bytes .../GoogleService-Info.plist.gpg | Bin 720 -> 614 bytes .../remote_config/google-services.json.gpg | Bin 1013 -> 848 bytes .../storage/GoogleService-Info.plist.gpg | Bin 682 -> 641 bytes .../storage/google-services.json.gpg | Bin 816 -> 779 bytes 21 files changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/gha-encrypted/README b/scripts/gha-encrypted/README index eb31d713..e73cd287 100644 --- a/scripts/gha-encrypted/README +++ b/scripts/gha-encrypted/README @@ -1,4 +1,3 @@ See https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets -Googlers: code search firebase/cpp/Secrets/quickstart to find the sources. - +Googlers: code search firebase/cpp/Secrets to find the sources. \ No newline at end of file diff --git a/scripts/gha-encrypted/analytics/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/analytics/GoogleService-Info.plist.gpg index 094a665cff13969b6a82cb9a4ffc017316aae368..a7fad00c750ca5f5dbea9480b71f296ba5c91778 100644 GIT binary patch literal 670 zcmV;P0%84(4Fm}T0;WqzTw6|j&;Qct0i2^tOioR>@Kcp;1g1!uk_aZ3C^`hX5j}}E zKlP6GSt)+Z>(`Fq;Ctxq8p$Obk8d@b6xoPDGq2&ZxSH;?(t7zIp*GCg#AYQ(i}1yH zs+Hhhi9NitnlPzMP99N%+cB)XS`L(H1MYrp-~KV!iYYprqV1o^g@<7^;0i9_R9S0oaJH9VaiuIAN7?_z6gPk(fJONZ3?dY1 zjlR0$hMA!FTj{#6XdQ53vVcm0F&b1Pfx703y{k!N1^I;0tS9FNNVFbXC_5WqXi_wd z46o2Ee$M^i8S0-5opNgjHLtR+qw`}0UGhybjY>-gTm(Mu!kl^p765QDknVHiNE>J7 zfcJcSkyg8t_XR$recyAn68a;(+3NWRAyxr6fQawDB7~>U{E4tWtttdB{l**J=3Tv- z_~KO0(4^8-AZYNLU8dD|KwN&7!n56XzdXLJUH_%;qrcT7LYwX<2%O}pAr!GLovxrf zl!URHVp|eG-vUz>+{ZUx7j_Gm_ex;&V!a79XygiazNsSwbptDSp7TEdBW$dh8Aw=H zyhr_lUmzDvW5!TC@J7SJj3wO;bUzYFt>nSN-u;WNQotl(u|PXrzT`w#x0urz=PN53 zl$QW+EPKH?P9cQPR?Z^^cy7|MyO+mmv8GiYdb$kfjn}L##!+MiVCM(2yO|0i2OGg6KgFaNq@Qa0xP)ug||uQE}`=`2k86 zz`Ol|O@_9$cQym3YRKN#BX!RvOO_DMuG?3Z3GeV|BCO`>=2UkEU_MMw2%BivP=uiV zVm|E-o5EJH+F!8i+@yKeuq-3jP#Z?J_OcIriJ`|?j(M92cGr{iKX5XIThZ|?U`0)_M9FFE0)N13828W(5SyTxb;KeC=PI8jZ6avy? z8%tBEv8W99m)Fy;wNGjei88@E?p7Vx5dXSh7nDnt640O?PG4wy2&7r}=d)L7@d?); z+JHmXHFS<+K}$_SNEts5k(?}#MWu>{NdQpRmJUk?@x8zHpTfG~JLP@FtV<_M7iuon zS7Pw<+b?9!0mqll6c;D$MUl96OpKtPVd1pvSB$uwKK_u@8u&{qkX8gaP{{t6wqFW6 z{Qa#JYc#BT-UDlr`AZy}tBm{BxHANZ6%%eozM%NbU=GklVvM}CYs@vuKt)}940KPx zWuXnGzti=BXdHpj9iP%xvJHOG6!LlZ1efvOX7>qH(~{J9im(b1HZ|T1b-w1ye|5il zH|v5@00QR#0eukrPE9uTDL+S4O_y{GM+-@G-hHX#RX)xlDFR{a%FfYwYKX-pcOPsbPG{u!oPt_P(IcQOUB&{Ml$Hr1=~^m3-C1A z2+!JO<9GG(5BVP;_fvEQeO7H>+9)lpDp8{!_0 RUmC{{rNp@RriZN!T-3M=P}%?h diff --git a/scripts/gha-encrypted/analytics/google-services.json.gpg b/scripts/gha-encrypted/analytics/google-services.json.gpg index 58d461365e9d4a8c78e6ba066a36ddc91e212659..8e2a09d3632c44e795411a6282fe5d901f16d900 100644 GIT binary patch literal 962 zcmV;z13mnV4Fm}T0$!46MC_qDvH#NP0b@M-?2@P-`n)1YV4CrfAMDE)uLPjzzGWdT zw+iU_^=hkl+aFSzKetJrFx5X4K7QuthEGu_t64cD3ft-_3mZtrX5so!oF5CM z5V!WN@AEYeT={zmV>{BI1WSqbKM)aNM!BK5v6Yr!=pvS353fQHJEUSWh(cXF8 z{LI5aGknz#fHbmAN1_hslh<9yhsvGPUYoVVrgP2aK1L6E1E!p3;*=1Fm%He?KdC=n zAo9g(V%L(f2+tGQVSCn4U23x)9l$C5$e_0d0-GD6ts`YobTgGYj?kRb{JRaz>*yBW zV=+U792B(6IE{&wbWkZYYBc%a+F9~pB{^}^9&*v-7)1neHCy#Un{1>!>CBSAvn&{l z2Cw6Fas;OE6)3N!>+=wh6{FF9Kn(@!7e%{kpnyX52plUB-?hTEX(>wVgMI1nj!p;j zf;69TK&A^QkN@XCpQGe+6!$wcw5ld)3HJ&Afh198x%}Z#{|1k-!q(VzR@U&s_o}om zn%}Jo%-Xwq>moXY@3x;X+$-1d_?t-LS>2P?7gb{)vAE=(fTTi=9*;8f9)hu7V8Yl1StQ>U-ZUEduMpf@+UH(zYVJx^-@2j2EdVUQP)0QS3n42ikLtu>+LP-WBe@+k}}TVs~t{NDa2CLa(fs?$b+pVGEcQ9b8#qmb->%<`< ziVe8ihbJRK$;Kl_&w%86%mif#OG_Zp91HsV+_*r)$hFd$-c*N+-gFfR3Ws!iI&^bL z9>GMqL?U8Y)KGnx&baI%nX^}oZ~Rcp-g~ZG`K_O;uM7uGpo)}z5HR9E!GbGLW4VhY zsa^b{*f$%(Lo5CBg_H;3=gczcJYn2mJ8Bduo-jmKU(Y*W-yhZ0fH3|;-n=^TG)h^P zQGa-gWA8oHilnCpvZ-z@mZi=#(C%KBJ;Ofg(Em2B#+6Z|EeV)*!c-(1qZYw{rRk3g z0j92(JQ`$Or1#Wyb#=8Fa^dN1fAx5jRb|Rw%Vx9nen>8l@G}z78Tg-@TXO_Aw!xGe kpw7T=*H!qXWQ&~}5Ao)oW8Q4TJBC;?mCsfBqAi*#&qs^sV*mgE literal 958 zcmV;v13~T!1C6|W5>d-`i}bU6bA{|IG`5R zQK%DNYAwaq57z|kLC#*^RMa>!u&xPi+r9jLD<~bCqhQ^FE{Ese@uZPen3?v>*;>@< z-Ui5zxdFkXoEK`Aui(c47d#?&&E692D*xmcsT`6ddfh#x7A9U&bB!v6&Xv$aPYF!O zqn+K@wwH`7{w@|(*l>P-`+4@v>2|_FyazJ$y@Z?MW{h{dsZ$Jk# zIHn?v1D4efSn%9@xMVYYCugM%(qoutO{_21}S;!0QpC5-UJl2aeo0^?iwlL&f`|4Xi7zOc&Qrh<_vOA0(C_7s1DW zK`@GoM&l@(B6{xY$=Di$7W!7rcRH17{f3T{dlL98uIZaE;^6epw1O!5@kU_x2Ee?&ZA9pwH~v@DzjE{j2IM5M*vreO3))AeAax z&L>NtX;1M#WKBI8-}FywR%b-Y2&ogHBFSD=qg7mp(@d+)`bUzhJwmueo_^=+A zA;DO*eirh=OQ}pjI}8}Qvn>567FBtJH2JbDS@FWWA$Iu!YJ_gn=?i-}W)aJU^+`C{lh!8$qjHNuFGV4L~$9?sg-PKb=(_y7O^ diff --git a/scripts/gha-encrypted/auth/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/auth/GoogleService-Info.plist.gpg index 03490af4d0a7d8e6b73326e72709402670e41656..896aeabf097147db78a02c2621b253c3d4eed7d8 100644 GIT binary patch literal 681 zcmV;a0#^Nu4Fm}T0)^q1sm94UaR1Wj0WgL0MFx$_$<@G-EOi-&t#&2&e0#V7N9dL- zI+}-ZdwGi*In{=Gi6Ba_d;HD54xBEJ%+*j{{(`@Tja_i^Zp4{{U8D^y;^5WeGLTQ4 zgWCZE-|c1EJF6G{v@pfI6hjPVU1pQphbq4cf%*C12E3i$B8e({bU&N1hq`435Z7rM zsp8mYSA8;O1}T9tmuF@+o|6R}vN_j28gk>V(DNu~+1hXO_M=ZQA7s@n9HFw?*n0Du zIb%z-3)g>_4?w*WqA5#|xDN-oXMQPECzjD|e%?qgJ{DNE;~B=#HZ;3Wr`V=@HBPiG zh*qAhnJ;tbcjEryss18FW|NfQK8+`L-4;O6T&9qPm#{)2T&ocN z^F(m*zO*wn^0jH{?X6%Svr5t^g2s{*&(-sh3#Aw*^ILj^M~I& zHds!x@QSmEYRP;}+evop%(krSQZ+F`WHi+0?FsLnC&PHX#(&BvLCP_O5;aOlHm~h_ zNR9+R#V-lM4z}MLe5*-P)?Wur=p>wqTNSecX#yaD&VQi+4xKB4KZ5L>bI`{3=AhmN zUYe3lR0nx_>EB~raV{-eO?nN8|H8IU^ztSMWmDE1c5-Y%W3*B=^!Wva7=pj>fvj>9 zn@fK7f`RDT&WQ}6RPPE~m($`w*xh1UXJh%(w5E#gAJw{8lA^NIH9=E+rqR=l} z>x^Ydg~xpmLg5a3jk9S8RC3Ko$&DMaJ6rxm%>_YFi}Ax&Aw+8;`Ra_<*T%r9|=Pw*{dD9oenq%xPt}x zZohS$^X4lsLS}utirGsEzD{}&#g6scx4+nPx%H@~E(9+2{P+WO6@_*S<5>*)iEYBx zO5PA3mo?c!P5qM;4o6Oq+vAUr<+9V**PGTof#f6z>ydrZqK@rQr#kLfUCfA%Wp3d1P5>y+K?ntnpEzv|3NC~1F^^>%M<@0UXrW@qE*+M@iOP@mT|Gd1F@uR zmtxbpx}2aM7sj_~Q1<&I&`GoTa0e@Yykh7WQmk!U`1+UU#^dENB#Hj*efF|pQ0)Q3 za<0_gkOs+^1g%{!mNXF6h_`M$a(Trf7$c=(%20YmfDE}b#*Criw2=F(uVH|9Z_5Xy z3nMw8ScGIZ7X4YarR~a$O`}<^^36$2)dfZK3~V>FZt&7R2Ceg#d#7?J8?_d4s$<$+ zpg^q;YubOaxOJ)EiUZEQiK)bRAL>8^0{Vo$&&t1M3gsx%3!&4Onz}7GgP%^H$$L5+`QQp;Y4qR$6k)FDa*b1Kal-JuQ%;IOOS+5 ZL01p~douxq(TboFv_+~H0P(i1k1AEvVGRHP diff --git a/scripts/gha-encrypted/auth/google-services.json.gpg b/scripts/gha-encrypted/auth/google-services.json.gpg index dab68319270549a5feae30e2acbcb3299c7ded9c..9f86b0a3f0744d3414c5adb997de69569c43c655 100644 GIT binary patch literal 1007 zcmVM$j)HSj#JfyEq{6y@7%eWBzshrzeHbW(QPUh?1M%oN+ zl<#`oRRC)&L%l+yI5nrM(VO6&>7~!Gt*C_{*YPS$9&f$Au)UpZ8sY&(F@VmKT}mY& z#5C4Y@3zI`^>OS)5L+3UZj95$8X_6L$>?GoMe(2XG2OoLB+n`*0aV14*m|TXO%3vs z`#fR`)PVW-y<wD2UoZA5!4)tv-}w5O7GS@As$FYVSPE)Jy@f) zzgD2`C0KIc2N~IsAiBxlXeR66oCm;sw>(-%ZT6y-nJ&I2;{NXM%MuFqCXA{993tWg zJXMSsI6H}~gLpr59QJK%QjmeZ|I2b_GS7$L%6pJ`NgquEE>D6s2Q+^g>6sgk#{adh zamwNrSy-@NDnAc2umh$X4J%#vS{=W}mGoOJlRYgz`#T$Z?fG`jib)Ww!H(Ai+A|9( zCGD!5y)^2oOz1{DT18uC!5l&V2k3+ZIt^SVCDtNzn^fcR% zkR2H&^gUlwy%tbxBys(V%!sFdjcOsFNop zf}m7$cKvLevhAYfVDjuQ-tD(q8bKb47W{5(xY-&@b{r)RIL2WbXZRjo)d29MxnpSP zIN1VKmTH_zD~4*gDG|#;b9B{es}}-re5);FI5ymotn~{aG3+vxLEJ^C@|)JbgYC{n z&WV8T@)nMWydPPq-XvHsGz<>wG$x%K+zsFgNiCxGG(o6kv_j0$H6-HjK^7)xIS6Nr zwlIg-NLFM`T9I21@pqK`pDO3uyv6vrpI7z9&-HESydH}dUlCY-In(OK=4S%mMneLy deaS|)YNQ1sc8c)S(J0XeiL%r>S?SoKUA+l2_Kg4l literal 1014 zcmVL+WaXk?c zq*3kUynx<@M#=c@bk6dFVqn;6)ZBtB)Wwn5fcn1EvV-XPRFLVvqy4LGEuuYRa$lRv zyBsj80xKu49y!e9E+OW02mJ1BMTzC|*|XXG7v5>Bw`*yd6!(*$Hvf`8$_k4M;ev0- z7awGnaBFSRaVznrM}6yo_L<{-FL*wcOI!O0^Ata#RrFkB|?7LItTZv|eOY7wP+w>={~Jf%C(g21cPg zX|Mvab+=EgQBj+U#vETzaXZLXrr_P-UJJsZe7vBTAJO27 z-BteNGd+X?peYpy?U11xL)A5`LifKSDb@VK1TE;YkeI=2e=B^k2jiw69tbOX)?CAX z?AAp(G9!5}F5CK8Z6^6^Ap6^U;gtz~H?#ktH)!%2^~q+7%JL1^o9$={h@dkn+oV)= zEh6r-s#+gMQ8zXGQe@dE)IZbvVXVz8n zKC03CdF4!zxcskORJJQ!t7Qo{9fmJZmkwMN1kMAaHQD(-?(e)$olg1UB~Kx6<(1sJ kR+oCUDSlOJ$ZZ4zWZ!VAr$Sp_hSGH|$scxe{CmA+ApOk_b4Fm}T0(cJzehBA^?f=s00kcdA;5yS0EZ$;S0;$G?7>n8yJ(K!2&67ZF zWWR%SiD@5z=E^$ia~fPU{lSn$yiaAyWXYK2gUl2K#MZGBU;*&)j$R?VO`@K)^{c5D zDBzRFLGU>DK=rLle1% zQ&7ikKvoe{EWv0&<(fe)<|U`v?6b8WtmPa_Ob+?;0l-rI4Ucc3d&+6r-Ve`8=aO-^ zFaQF+Pp~yVNA&>RPg5W=!iW>Jt1y&Q%T!7+5Cimob<#=#!B2eLAfI}<%jXh4q((c) zC0?3|yN0x4>R@Fs!X)V!0{T%qu`ZyhO=HHQ1~w8~N<}TV9V8Zt^adEK=kT)vH`rKC zlWPa$GP!%l<`H#wt(5L%XJopqq49F3qxLr{ew?j2!J$)#0hJ&9w}KxIdovPA0M&QN zs1WNk(ucwAs5lM8B+3@shTTVdYOws$oGLI9>)!l4`%T!p+nO=L-}nGzH-$^D?ip!9 zhD8i8)crGxVk1ak@l>v9&=sWWh!|eQW(rrJu6332F^v4$pB8dptoVhgNxN#WqAdKm zMm5H@Dlb^_JNw5#O;)GyUA?@Scmo1GD9q??a(D;1Cf--Psmas`y_Cbo@XC(@le18v z@;9nvMxO-LPxF77j~wKAs=J#5O@nNV@-0Rnopzc1rg!fI_G4ARkw_PQ$#Um+vHV#M z@B$p9qJm>+CS~2{gjdU8@kJFV$#eR1z(T(=DS`0*Pl^?lpZnojFe%OMuO2yhGF;tu zh*tB@Fbhl*Blgw%MxDH6%#X<%$QL{?Qe?@S-Z;lt9u9H)K(guImHxx1573}Mhznfu i0ZCbQ9@F%tASpgo6Iv~MWx$&}Bm-LBzWPXW4=kaDAX+B? literal 711 zcmV;&0yzDQ4Fm}T0-KkN* z*AcJ9sh^H-4Y~JV3Ck26vB5BNaqheDd{-KqxxS9G?R<~O&vpSx>P1I(^nw;PczR!k zsFMY7EgTi|*GmA6EXrD)o>OwdCY@iY{h&>B1M^? z;T90c0fXV>`|TfoN)QWJNr+DsAWK8H7G0%&+2c@S5#OyeA>kmb9(alX8ONFnOc&+s z>1n%zgZ$`|4$$H-BQX@}vj*W>$zf~~?Mn7Q(_qE4@ZcL~EX?IzPHK@;Yv7f3(73Yf z3za5ER(%9uG&Va4bwRwIAqi%dBq8?M5+&?v6I@skmF*k*} z?rU{J>>BKpviowaGkUV`)<_S4q^8x^3pkQ+c6LVU7#~ZNF?I-lfLsH8=_HTq8H)TD z;Yr6hYz%`-)R%??jKCW$iMbm3aSM@YdXgqI(}lduq2GRB@Xy2NSk((zni8v$XykUb zw8JLO`AIA52|*#WU15yA+?L$F@bl8zyea!cN`LnHeaHanIDaQ8%mum`UsUx?Nx^sr zKDdv(_*56ScLp?@{(tQEh;J$DY~#4SR%@r z(hek?DkYFR;EPv69{Efcs~{pA#1`Pj%0(?6^g%^C@Fb21BnFF8BlK;}_0XBiO5((1Dx)2khkzu`aON|@;Vh{*jeNDD~ zi}#_Cy_i+!6lM+42$j{L4(c1^$%c?M6~#uzWZ_!((?{@NK%%cr*@Q(+pqJiz z(P-R8_|!Ks|{pQaQeY=ZcX#UL{QAEl+(sGUFi%s zW&WU*l)R6TsJta8Rg3fMG1;yH<%D|)syp+q^GYl|HQd`M`b8td^iMQt9qslQCT$bT zURH?DZj{ovE5Ai6k{V^TT?l+x*9%F;+l+7|O;rBPfMwjK7ea3mu^7~wIHbZw3aD(- zTz9q#dwdwBeETp2Hy4{01?J|LMAI zHp}cU5op)eQ0HlcfHoJG(nxd*imlmmah@FDqs`Nq8rHFEhL~`?FDH`4$@^9^{VN-R z?erSZ&AcyW$sh0{@iamdFaVac$G9H^u!nF-Hh3*fP)&(u)!^vHVzb#x8%hhR_TxmO z50buX>fQX11U1DptB38*Gc3b?Y#SV%_C4FE~&7O)zaVF@o7t@|;>?lb?5a zTVb)Gt&2?<>Q9HDQYX+CT$uBgdq?kkJCy366&N81OfWk3k60AAMQdlW-sC5Rx z_2lb2z&`)n??HLhp-HVDzygf7d9G@CBHD$D!~n~eu{3|CW37X z@)@nH#!9CCd3}X*zk~~4W;4Co=sP#wJ$8J>4zdrBHDDp3oGI&MVZS}eqt^n`hE+t@ z0-fhWA9GF#Pl3oZ3w^8Y!@8?4Nkb~u{zS2+j5x!zHd>Mhsr~#-Cb~tu@DuPr*k1=g zjq7y4sl2NZF{D|03)&1q*uk~;d1NRWLRBy({!v$15YY{jrvmszOdSft-XySWS8YuQ H8CqjunkZxu literal 719 zcmV;=0xqF(c=A$u&ooC)s zbjFHc`gAB*^gXRx9-$n#ZSN5C#eIlgVgwdLqcm*CT1>{H(~wM?-olk~90Sn5!dTho zeOTUEyNv;^raBh_XolvWN$(-yyBIG15u440aPXMWqC5|f9FCXVN|9(wS`hT|;Az>y zs@n;ad+ipmQpP0Gw6Y(Dt+uYwvhJBqQCSFcw4=IT*U7}&y1!$>0wOk?M>GF~kM+)u z@!ME-Kn}_k22-~n1;UrIq6hs`g)e}0p;GDl|1G0-X^Dr?2Pp)?yCiEbtl-0|TzTdk zkZ?b#95c;Hb{UO?Iq(@I{jb7IKvgkux1Q2Q1w7)0gFLHb63S*g&-BOW)4J#DGz1I{ z@4jpWTrg6;qo+7Cdqi@2>y-@^Ahq1_(|#)y-xqV&0p=@jpxcQ4QR+`a6nm`U^*y#L zx#RMkGKkt?aVK3^LqmCjr9Y=?JO%a06tygu@a9;lW}Nl!=1XEkD8KG@Xm>UqJ@&NZ zH1K56y}?TgW4FSK3eHG(y#=7iMyx?zyYB?sSxL%uAp7Q2RU}7H1gU3kn3_|*Jl-|z-TtiD)i~cf_QIF1;C`k6 zE{PCqjgsZ5n&EryV%QAvg37X;v5ektJ4DC%1hb~fnKmKVwXe`bGdw21y7YN)CRam1 z!EG{$hct?=x!w^6PIW%|zV)@!!$%njIkgzgW^%I-4kM=+tvZ(>P9(QA(IEEAQe>Zb BWBC98 diff --git a/scripts/gha-encrypted/dynamic_links/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/dynamic_links/GoogleService-Info.plist.gpg index 871ee6e1b6d0ffed52db74b79cc38f0bb04b760f..7d577bef1b38f967ce4e02edc3e611a517f52944 100644 GIT binary patch literal 649 zcmV;40(Sk34Fm}T0-Dh`Owg>JQ2)~D0aY1%yW!%9C4D+&6AtW4i+d0Z!YipN;u2b4 zGAfd*u_^DP&|{np4Gyof>Fm!*Aptt&AtnYaZ@nIY8OQ&Fljd>$hTeOWs`Q#6i`298 zx(P`77eg-Q8c{Hp!TZe-WnR`)=3;nav5~#l`R!%fT%_=#hP02bPMRkcZOSX`^yKv~ zymiROQy9=q(vPYJk~+9asS-1<#6ZHr-FcM%8Xf0`1(7F?@*&H703^>{>F-RH=G00s zB*sEexU{Y4d1M~yq6k|)VBe061ma4$`E|SQMe2rhMd;2VBV1BM+!?yUa_=5Qa%1M9 zU&DA%8o01d4V-&od>C)B5+juu9l&t1frY>{~?M&Fi1LP}IYsuaMzCKu`{>2vUbkAHFZ^@6mvTDEL`uR-O zCb)(iU7^*?K$@jKtNwusNDD|Djl3()*?V0=x9F8jf;9yn*YRGkz*HGED^XY}Yo_WT zpBy}$3-fV(XqKecyR_Gw;D?3rhzCd~fe;CDmfbOm)>oX}1EP z`3Xq6MEGe&iqFOj%&d>QVVZ@iai82pDti$c@1z_GVGvt(ANtQ&99jd|y!U)lA?)bZ zFHPk%V-U0sqqJ0gQULn-+z*r~OT~&p>@Ip;(%)zYa_Lj8#!a z*bw+An6v=*wjbxj@N0;LkhyiS=}>KZ1NIe(U~?HHQ5DzF@9lQe%zl9qB$q|_#*_CH z=Z(TytDjxU?w=KNC2V}W(9-18*R{~j%hA%7YuoUggxxIuIS3ZbpiieZ(2onuhM_G1KNZf}sb=#`e&piw;sU)05Bee-KkI(5v$+CPlrTt}^D(_dLpmlG+u zdV3^pNsrqQ&QrxwFfNrt-O3;xRyL4ap>#T-ifDIU3G5v$^8Jo;a3$3SlZ-bv4%jHi z*Ub^TE-?}#OHRgFGQNAZ=N%d^5($um1(+jAdpVK-tRUd_pWKcE3Q*FTnNJ85g-($7 zQcWF+C~C=JH_)6Ut6=T9tv7nTE)#`l;^vRbpc;Qnc)59+?lR%aMO%43X^>5m=j-I=QBP(Zg3DA_)3^+wZR#XHsbf% zSR#7b_?aIrl&N@`w=)&`;MwYB{7oPOz|OJ}e=NEQ{Q)ZZIu7y0tRO~Gp%WwTIlP77 z;I)RJ8Xcm0f@E)R;QqY0c$Q&VuU1UJtq<=f#k{O&PcBKtP>Ig)x{0A=?ILn z5R4Jgk$I`2m{oC>tuEukzzy;#*;gS)dqV9R(+;6pu0YlusFY$vXyh3v)xGjT zA^3$ZcQIM!H{W$Q%go9KAB81=8(ay)dsn;cEZ>v&<4&E{LVI3SQX=boIOd#*tMFG) SzZ_K7y2`7uphu8mqCB-8c5L1N diff --git a/scripts/gha-encrypted/dynamic_links/google-services.json.gpg b/scripts/gha-encrypted/dynamic_links/google-services.json.gpg index 846543f60e983f1a137e51e0507045d05d1283ce..0db36dbf672d1e8a0a826260209587442ca2955e 100644 GIT binary patch literal 711 zcmV;&0yzDQ4Fm}T0vVD9ATySnb^p@o0X^G}`r2?o2V$_+XNaYMGyUT(DGdX9b1&0C zT8whjlOBc=B;;vcs)hI@;pOM#F+Pjy`-51l)iY0lTEMRQha6~+zu-ZJRh_R#RR7rQTw4*-;gV#?u_*h=Yp|!UPpM z_Hy_ZMG{*Z1EtwL%j>4wg)WM2-)cR2RggY4gQcBlrYV-^T48dr3{dm<*>WP4{5Yth zajXTX{=PM&DC`uYb#DybKSRHj$^N2*X-;1{ zSj|5AfsJ-bu(-hsTPL({P z@}t;!3mKH-Wh%ZOFU%iYXCQA+O`Iop4BU!lSqTacXQm=cMskq_zhQ$m5Lgn|yo9JR zkmNW&*si=ujCB?KGD7WbwT7_w`JS2`=Xk|F*lk)nR#^!SR)4))}YPv{aV{{=)DLjeUF#+jC>>09SBzkk^)ALBo#EFP0)GObqCkRYE zSVnRoR`>BI4;$0_mU8)iH{{=k|~lmu8vN1O*D47 zgK@Mqx6E`%cBbZIYGaCsP!8q@dx*c@`ZovCtA7zf5j3LLrqJ~JAuoj4DOnF9 z17)4Ip7wJ3k^>@58&?OxBvku;%UfVO8}jI1G8~w<5Ky+a?9MlNf?2iCkr^Qv4~dv`c@hq4?aWM!-=pM`&=r=nQ?BG0_qZ|*1B^$5Fv#BvPoC}>#1}z`l^Ny z3xsc3>rVtnz%vK06b6icE(M$+ON^!nnWdlAD843Yo1o-hAa`4Oo$Oy3ZXeI42K^LF ubm?XGZzX5!($>B!R4x@>1V+ZJtXoIH$qYp!*P95aNyp?RgcLU{(Zi>x1zpJi diff --git a/scripts/gha-encrypted/firestore/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/firestore/GoogleService-Info.plist.gpg index 15ce08669627292013ee908e87fac31acaff9eef..4ae5fb4154aa88e5a0960c8a76b07b0ed930c12d 100644 GIT binary patch literal 597 zcmV-b0;>It4Fm}T0<3j;`}*~etpC#K0dM$E_Klms7qhh{e<*<_@<>z^i2PIsRL>`i-lu_e_^Hl7y4t zw~#KE-$j4xHTgQ5ARZr#QEL^J;NQR$87uzMN>@r;1IpcwSu7wgq`UG^k|AQT7v80}*a9QDczqwM8yOkz4d ze^PIUV{e-He8t$uRK_Y9HaqOH_p3%yQSqzd`{&jJ8Fp>y0??BqX#w~iX{K<)Pf;ww zaT~ika#*TZIiU@H_vl8unSHxBTl!baKuKv3MoAKs8G||*HR!A_f)5SzuL;@_?uoSN zR_GO3)P)zgYNzMC#_^G#LoaKzsdn@*N-O|WoKFt@Yb9a_N<Q!HM!sKL zcj=Ua)ec_!&!8yf4x#T^0@LcL|7Y^6d=5O*7wE8nn0`m-$0zS2n$GyuIr#buX(P56zqFy{+8cj-^nm z7Hr`-^1Ib|&hdg`jqOnMzS{wJLETZv)ILql7fJ4G8Y9sm3Kw#ZXk`z*0p=Gz{^_Q9 zD6XXqLvp3{QB#$}{p)qKRF5EGv)^rRw>Y3U!k43tVFI1<>U=FZ>ZIY#%VNTF)W6TA zMy&V^A7JF3Nt+PflxJa$K)p%xXxfM13>}@#tsyVPUmcW(m*5LBWH}HWK2wMoi~!i< zX%*|jXBuPpnwyYnEv{OZYt*7qD_o;^i+1o4(KPIl`@F!S_hoFWQ*$1>XACe|Q}8e+ zmtW@+Pbu$gS0F4zJi|Ft@1goj7YKAH>34mCp_YNpQ_Rwso$l$=fti$RO9exDwpXZ- zw+Z4>8m5|Kv#N45#nqmb(xNqQd=d-tj7nkf&BzrkB-3CID;WU-PLjstJGpfU5}SaV z;gxqdeulvxNduT_2~RMoEcXPVpu9Nt4t|QVPS?YVbKP9h!_G7~ev%)APM8n6o&Fd0 zfyrWrZYQl4kWTL|qoBhtQ0%<~HckpxK2&C}b?%>)!PE{X(xCeaGpz0V47jqZSlHYr w$ffhj1DuNqC%2YWTH+>#c<2nOvA-Bxn>ei(bn*{vGHYAZx-li$$u9-F3)^EXtpET3 diff --git a/scripts/gha-encrypted/firestore/google-services.json.gpg b/scripts/gha-encrypted/firestore/google-services.json.gpg index 9067b0d5720e88b7e5627be95bb7897e258cf234..9807334757f549f43b8e539c8e3f07272f57526f 100644 GIT binary patch literal 523 zcmV+m0`&ci4Fm}T0{pq`U*2ysTL03)IRW_&7 z*?~T&hUCDY5Zgl%eXy;Zv{&$f;FTYGPu(8%;i_)rSa<`{9@-y=OM06!dMSFZhj+fT z;C*YAzeny)arJMqI)D@$zO}JZJ2OIvte%buc$Gbzuhw4YOR|_jm-VcGX@d!nTS8ik z0Kf*J*DQWK*KkxJ{AV!Qp9K^$Q-z>0j+OWhdND5H8cJPW+E4x@i3mJ-DRHXTkuc4K z@a-^J@O5IwHp`Zu!{|cFLdCo3U8l1+daI`)cWj;iUQE@w{m>8gH3w;O)t4G$${WCA Nvp@Mw`)_THcA!*b0BryO literal 534 zcmV+x0_pvX4Fm}T0{*~q9{iWGv;WfR0s0HDOIVBGy4RwLz=KOkGZl<#eRes!xNxZH zEr9T5qJao+Z+qJD_H3R37DAFN~B8iJrg!)5d;nTvU>cz{{a0p>{2E*r1Ry~k8yXT?!E)gV`d1X za}VXAa$QY6m-fVmlmyK)k?2j_j2?KQH}#N-@~-=wNAMpM9GzBRoBg;PaoxaJG+u)MOH z!+mlgVZ7+2%gSzc?S?Ap%;AhZoP%EO9-8$w(|H~~ieCi2Kwdc~vPMKm({%&y6#3!q zL_g#P==9VHc5J6~FH1|Xu374+o7WTwz}lk~zFUF^yjjUDFz@JP2i6gQ5@7h{Vs&aiG8DBZ9d~uH=*;2YwLFc) zD(7rm1_}~6aooE{YAbeg9}f3A{<86qh*J3Wj4HS8TU>>V#tMAm8#2q|M=da)0dO6& zj?EBG&Y%gUA2%}A)75+h>5J>z?& zTgB+G+KJ@Fv|yeH0|d~rT4Oz=v`_TFm0bi(6*%1Wv9n3j;_|}PvBNU-_|=F~quo|P z!%(`KAZ`??1yTd-hScyLq@=jSg?wNtNScRh5?`R_hjf=1`CR?Scw_xQgRP%-$g0~%zPwCi&s1vG!Xi5;m(F?yjthQt+`-$56C^6zDx6U$Vlz;(n8R3MoPe zkPs$9{{)Q94|aZwwV7)rGhVCgf5oQjYw+%^qF8cq28a@puY52DT@jH%X?z2c*MkQ! z`KywMVlhSG-!3BaKXa0=kcRt`sVCIgmOCHFSfZ4D!B<4XYdzb??HR1lw^?dL7VsQ> zV+j#r{i9)Wim^LQ+arg&{3r_Y=oH+pa{l>qwFJ~8_aYMN@;zn=SaI^$V}0t8C~#z4 zIau9b?1w55xL0;4dvgfO<=GJ%zoc^#$vrpWJb+t(oZ&WP!c(FxdH8wRiyy I+!#PABySN)CGwSuv8y0yJg!xEF!H6d5b&yxvHMdm12%;^qJ?Ajpf+fxN2SCg zZ&-!)Z^`wH7+C@2MsFn#yLG``)2k1~e;V%pRh=dHai9KsMyXNhqZiFkm$-Q3lG+K2 z+^m;&ONh=g6DQ@3GQ{V6II|y)589iPvtn_D<3P1x->V=wPLyt=ALGGkur6H{HO=Ji6AzGA!@h|n;F7Sw&dU^R*x$Ll>dfA+*;))2Y)!E-z%sg$L?t{)enbUV?& z`hSA57Z@*U!wC{Y%%v3%h!zk>YxL7Z3w2-%5gEcEWTUFQh$Xw)VHuZ@6BjZDyyh&$;=UV%*9$kt6 diff --git a/scripts/gha-encrypted/functions/google-services.json.gpg b/scripts/gha-encrypted/functions/google-services.json.gpg index 41eed7b7e5c5ae888e7b53b148e46c2935ae3802..c9edac069d757c27369db388fb9c7c2fc48b1977 100644 GIT binary patch literal 525 zcmV+o0`mQg4Fm}T0pqeG z7XX_S2QE~FouFMOWTJcUPXB)JlC0^R60hrm6*Y_vxqw*D?7{vefHl!k4jl9kAIdfa z&^eWi)4);g{xX_)sIl6&^F`?Q?V~ls8SYT_mL;;&P+;@yw8~be6+IUMR+Y!>gESbu zrP+<0AZo+HIT3IPyj&;uLDTg|xhUX9i~Z(ya(VitBu{;Og^CYY=Ks~@M68xdL#56! zO|!TdV(<*&ynf^__C5-_lJE}^I~`vWZ*15@O(yYO3Mzq$Z2lFp16+aO?=CiD8~9%+ zm^k!ht*5(T@bN(1C-b{b5R&X^YRz4non5hdQLJ~OcNKNWIqo+tSWIFU#%(<1J`}=8 zbY%?n?*z*(aEBryXuzAVo(~kG$-kllOH2#+t8|!b^N!)7j4s!|wgtFu!8apX-Zlc(3_+p;YvBTU9F;X>FP?Z-0LyD#%yd P<^++o`2!*$pGGt{EocN) literal 850 zcmV-Y1Figw4Fm}T0<5<~zsUPs`Tx@C0g9{?M|q!2!(7*n{|}12)Isp^j$OFXkE4=I z5Sz>kwv`%#X)qzKTSVergpNoTNMu*U(|=K30aZ&T>+cv(q;@;8*>lyC=!3`cmuwN^u(~OVmAGK?y({HVgkh>ccYX(j{AShDmYSxu_R_OmaxO!U9=oDD9hf!~lU`^g4cfYn*WZ*k>s-@jTs;-<2e)0rQ6$*9EYj{}dg;ec8X5@t=6 z=r%5ID0`_n@XJTIcM1a*kWhQ=FBrhQHN1&0@<=o{vC5qI1~l_`+2=kGIMN)RS#R3z z$xTBx-~Qp}z<(JMTQl{QKzIWT(O`S2LJ(U^a z*Z$XxwsvZCBn=3%IPbatNFZVoWa^Qfp_b3Q7_Xm5c??~obpZUHoPRJ}ah<;WMDJqn z!x3q2rck+`M3Xiq_?C3~NJg-kAy9vsh8aVs?7}Slp~R(vh2ude;vHR3Dyg%PlxYyY zp@c=X~7{>A-v>tpsvfc(4}wdaA7;5IP)&gyl24ZypZ_f*w@{ zPG(Wdu5Vqm>_ZYJrkV}OPMCvOnM=az9CGeGv5GN-`z_0uhj&A9U0;f+gWxrt7>46p cn&8@9NHxUxA72=_ZY(Z2$lO diff --git a/scripts/gha-encrypted/gma/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/gma/GoogleService-Info.plist.gpg index 58896342a9fe3079458eb8aa63a9e806e139d62d..65b703ce7e8841cd231a8eeb0b355a6631c9f463 100644 GIT binary patch literal 663 zcmV;I0%-k=4Fm}T0-fzaCMf$rivQB-0p|fHWyO^&Ync6x>Efpw?qdT3?Bq zjPBP~k2>%=QT6e(ZG>MNm7#5O(Tt)6z3idw07jl=zmH+QdQwr!bWyx1XVPt(Y69$O zD4AO!?IvhRONC0FbWiJT`zhZmbn27_AYEmd>+nnOdpgf=n_!lIL zK)jN{X+d{4{S4FtlNI9nxr_#!x(Q%I``z*)J2;DCGM_|iX3|-W)CQ5^yN1O75hO)q zOAm}cNOC&k9UUh(06a3A3f}Rm%cuh@98<4}TzGKY(o zb$4E@E=$QI0G*5t)3w8Lpzo)!43vQH3lnr~U&CRUz|*s$yPy~p$lLU7|2?8b{0dPY xG>ERw<<0y28k literal 672 zcmV;R0$=@%4Fm}T0_%(Zwo`_NuK&{M0fc3b`Gu6#?+=rYlG&2v>SbN1s>zvyX}l#I z8j1Vm4I$k9@A8oRrn0q!CqDY?S1kilKw9M(bN+vFy@RA?O(K290W&ez+sgu$mdk=muyM$D6neiHbIBQkqmGzi(akogx z#+3L0oIAG3zErL(tN8;f(XbBq4Fw3zJRk>+BhhHuPFo8a|weImAK9D5a>qRDK!X`y_2xCziolhO?|G zP_C?h%S2(VBU7>ci6Q=!bZkjqQQ?CcVN)2cfWzeyv4!}PRO|>jkKhLu)>M&1cO1}> z9R+cbFf-W#wE!Gk-nheNj;Zb`h@jOLmT3@rTwdXI7~>!{){q+aofdyoKhAYJh7{)& zVa^db&^D=$E#%?8!Gg2a8m<_TM5ALeV>Y#JT4KCxRUCF{5F;%fy=fX>JKd6bwIB GtRThF2}+Rw diff --git a/scripts/gha-encrypted/gma/google-services.json.gpg b/scripts/gha-encrypted/gma/google-services.json.gpg index b118a4cb346e8149418cf8fa86ab5a616d648a3e..c46f596425a5955ec5b958766883ee90eb2ecf91 100644 GIT binary patch literal 953 zcmV;q14jIe4Fm}T0?5jj8X$yf(Erlu0o=SNVA9@O)Q#w6U2MVR(@sDoEKw4ruNO3O zPmJZ;D5%EpUdQb|p#VZcUSnlVF@HZ;Wo}Mq^r98p=hBMmONvOFn$0sn^L@iCqmP0F=UD9qsJblrIkqLol4tEpjp=eNY6-X z3b1{x7dV}KDG(ANS!?UAG=_uE%pR_G)fWWN=y3INqb`x*r;Qh`aW8c@%WR>J#-RSH z_yZ@%%_g%i!9NC5P8?4F*Q|}lID-2sQh`i3YbzJbE9Cv3R^QvR9b;>>avs%oXYmSZ z(s}B$Z%QQ#9*42A>|_%5lapchw(xLZ$O#HE7)Vtk;xn~`iH2pd{n2prmB}cn2+yHM z_KWm!Y7DPfg{`p<;raH;-q*N2tRG0zIdUPVn>knZifwyjUFtzxxP+pI2SIo$vq(7K zH(MHzZk5pMUByZtm?FxuJ5p@_pu|0(kvV5~7acIy|Ek-FrC2v9Xp<3(e<7|m<^>?% zg0PrAonln~Hd;|_%R*5#vo4#5d_|1?ZRSQzeZKDpUbZCyk|Y0PAtCl1xHz#^FFSZ^ z!1yU~KTei^?nVUonbM^qeEz;g^!3Dg#mNS;O`_ULM_J63hHe;7BL&mO>=K zwc<{Q4XsD%oc#^bfC`Biz~;ot-)Ku86zZ3) z-lCqPSZH;ue>aJDQ`eQ3FPi6QjYI@Rf&YQRqoCJu<<)m$PbpSakN-)z+b>_w;MdEA zM-w?Vvsh7EOK4T_iJEF2mPPu~{F~3me5AD}r)>`h)%;#B9;Mn=PX0M3s`>C?WSNK9vak2` zenu+TM-u+s2hgi?MXENJ{8#AIW@jq7BUic?=b7+v3gOs9KYZp literal 1002 zcmVFe&;$LD*U2V6jbw7A0UT^9NN8WQ= zL!01j1k_|^rv{=>;&kSH`%sP)Jy8+TO4R42x+jJ^{Q!FNY^pj@%BNQl3hSE>k?G?o zFuv2|$LYzUe{;GREk-smY>;EG@<+uV{)giF;8tP_h+-w#(wV8RWYhq3$M^RkS68PT zu$KB_Hrp&Y^TP3m+spKMuk_zU#q6_0KMP$R$o zwqE-{!H)SNDumqbBP1ngESQYS3Rgw9gE)*eLl2b~0l%50U*(83nS{7qXGe>Crz4w$ z@=i(ek~StY#h7hX?gL0)y{8=ZxXPflsJMJ&29Y-z7WG4&vI-R6l5n3E{~NaTEcdb! zs|*VCeRf#XKF_L@9B6As!50I`ahtj*yb8U7Ma3xl+gp_@7(NvTv)=~4YIVNnT@)&1 z)<5pNDkgT+yM69s*%Qg5SbcaSA!VWUuO2ZtFV75jjc~lKPM;)uRw|*%0L}5R5J@?%!9@* z{~04Fr5G@3^4mufbyGeaB>+-i@(KBkP*-S;oRSgJ9AijFhJ!$66D)<N6-G#<{<}U;MLm~VQ7gG2cXwSZ$Yc@%Ho6;OE*_DK+q4Xg{xmEBx`>Ug3!?V8 z_&qr0#OkxP4^l!&F*-MFswC*V#eDlIZAa2IpO>Awj&iYgt+K4j+BHKD@JFri)DtJj zcx-VH-Q|!NYo0ebe%T{?@QE>z*y4xFB@yCYQG`B=$8jixSNHWY(ng}IQF?K9K0ngd zW;_sIr8*^J&W|b8@Y`bjXTVS}+TPxGwOZXBMq;L|9qah*s>f(e>@k(+Cl;R;mpkM0 z{%YydGK@kl`8padeC6Ma`@0SG>Yp#+g-s6wp8J#2Y_sLBV;_Q@p4@bi?D{CW20|W$p^>asU7T diff --git a/scripts/gha-encrypted/messaging/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/messaging/GoogleService-Info.plist.gpg index f8581e8822441373c038c20ddd7ce20b58e81c76..cf95c652d8c3f4a8e1ced8e26ee693973b5d74f7 100644 GIT binary patch literal 681 zcmV;a0#^Nu4Fm}T0;FEs)peJ;@&D540h3?tHNL7~)BKD4v@4NWlr=pQilhSDjI(iF z1(VC?G|7B+^l)N*wBnzv=ff#48S7FhKjTGX6qJj#qbWpzs3X`M7jYiGa6YUW#qrs7 z$~{vT7&@}ERtlW)R~RBTQr_}>Fd3Za#vMrx_nM(ue3%zya0#Nue%6;3%2j6GNQE=V zHD4ThD>{GO+iJZ)1$%~CC4+{UT-Mx|Jsuzv^KhjdzCR?}3d+NbQiNe@Irgq6nh`VgjVY8XywJei9c?o_9aaV^(DPu% zS;tSQUS;lZFjZN)pq`-w1A?RUi`_b;FMN%^1&pYg!sZLxZ+9dv-YSA#OYh6vijEk z3E3-Ov+T4V!tI=hXAuO}LUZJcmlX=$oz=4$cL4|HL%Z?7wrgzfah%9k0N z4xJ)O^H!mk?{Mr1y~rnoFSt4b(e-G+rI@BwjhS0%K2IIQnWluOuA!08&@sQV14q?--w70#e3P*g0Fgn{F@t1QMLrUwdX9@RK%s*F<-PoM{#L!|q-MU$lj)v-t?i6NW z16$JzO$57WEn}f0tl2b|7fM!6G1w?4JtfM14uluB{JM`Gclo3CSgJ%`@(i3 z$3R3FD^_52ESBC6U58IY;8aALAu8M}MHdg94Ltq6KRosurqpqw!#B zaI6MxLL+j}M*;wg>+smq8b&YZCAk2Ks4Bx^EL4#A%@Px2l`AoQ;d!qy~V znsI<3LX_-OxBjoQs1j;NcOzFMEUvI172wL$4svH`;_T zC(C|(rC#WaZwHQubwrUw$Mn@ZXeXq<``kE=oAMgUIm9ij@&L;y?FePfLYm%I6u~ZcE9k$avopDHeC+k!Gf0{^@$L&F)@1*Gj2{gIZ{6E@N{={|fS^v`M0X;|)8~MWIq;;LywHFxnc6g{6OU$<8J3d(Z zDG_BIhEH?I&mMS4d8JPoN4MfS%^@c6db%X{O*6G54C(5)nG) z+T~qulRbQr^8EB({5m0xt3*KI+o{bm=+>spRyA1dL=`2Azpf71+M0sz_1zZ&;+2vB zS?s)I^+8WnSZ2OYB-q9;CrtNil=`o{{75)38dwMN%4Gvn2dNPf8b$C*X=2dU2GmHa zm&5MzqXebRAdUf$xLRgbT;@5WzA2JsW`2rX&v(KcD3{yo(77UYy4l9NUqaFX;TJ|9 za8H%NO!Yfl#PmbnufEnInb^7KpY`R)PT{$q0)kzrD#uztDx&@1j1Nef@6M{h5^FEu zL9@_G)ZdKY%Jhhc0~}_kK(`+}GR>1AH((#+?~ap@wt{NA`Q&CzoE?%KNJ=Y-@vbK% z)swGWEC{;@zbbO8Sqn5-Pq=UjaTB?ozA;r}n0pcKF2CU$+AqU0=0B*L46ptlCaBMg vPD~IzIRHz)j-tlSqT&%x5p2?6e(xKAWJfnzBs(C?QMLBN33UZmQW_K?5Pl{+ literal 911 zcmV;A191F|4Fm}T0`YxB4m(c}*8kG!0m7YmV&(C!pAo=|H-F$^7kIYfXLG&g?c~Z3 zEdgp3hDm6lBb71<;)#?`AOLY%9AS|v4v$YS;%Q!*MF@L*MN{$=c55>HY1-LER12MGAZ;_&6AouH}hQRXz(goDsP8S{33 z1BD}81eO)Daae5AmPRUy+6a0`hqO^c&Sif^&C9^-=m1UMfnZ0;=7=ME=SKzHE^&6- zwG~-V*d5_5Wv{PZ6zEvmkOtXsO-=hY1_qcFKt3SPs5>}XKUj@Jf^*d+)BYF8C@6UL+3Dg;j5V$fss|w2>}y@Ca3KIW#&Fi&N)c2UP+pSLc7f- zr;{M(n#C3Jzr1q#qn;a>_|P_6IKVT^y-5W;E9m&|w7Zf4BP*-(biYdQD=B?joPef& z@ItJN^I1Y*{!cMDlPBKSMRpwcn_|z>YaPa0E~Vedr4`cICx98(?Scayu{`(~G7=r=)+GI}i!`gNZiPViR7G0kb}UNA|MOx$QZ zeOnvxg-j(m$vUm(8pvR!YhzEvR2mvacg=XFb(U4sLs^Qe3M$KVR|a8LP+H#}!9SBi zQ0r8NC$8JPw3RIqnApv&r;QuhGP65x9R2dP;~V#G(b9ZZ>Y^8DTOYpadqW}@kOoh@ zA3x%P+4WlIAAqHI6z%#5odl#>Oh>h&cRMu#cDraU)7=hIUP2xG*oW{GQB2U`!=;&odZ=Bl62`TF)_{9k;n(cXE l?=3pxlZ=9HYOa1P=pe1Y+YnnzXD&){J}f3+zbi0-yi6L{yQ}~J diff --git a/scripts/gha-encrypted/remote_config/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/remote_config/GoogleService-Info.plist.gpg index 67535e90eb6aab32f1b9456bff223a7de20d5302..ea9dc946108db17d9abceca676221ca110659982 100644 GIT binary patch literal 614 zcmV-s0-61c4Fm}T0+!@LUVw)oga6X$0fm6UEhysKH8@d}V0ZtUPzYhNql4l=?%x}4 zZmy^lPM-hGQ^`3_SU5V}t?<$7wO#lRYbS#NJbKiC?$Om(>ySGh;2*mM`*0v6w{yfT zFVpiXcM&7eXSbsspzE%VSPYa^+6V~B9h8~|;s~X6i z3D;Fg9=y~7=|%nk81WNAj5>uFWF9~Wq#hWDw5T5(Xu*KJgjIPWU-xWxoaDH@AmeM9hU8mCRDr z$uy6Ya$`mTX;DyDaU1165bob?{>|t5z-v{b|K;zTNj+_GN+mRX1j|G`n`{68)cO0K za`4~>iOmCsTIK99CDNgX)`g*27>jnR8;V3(J@}4d=^OATG zyfY;(0ff)9RO16P==~yQ8CO#~gAgmt;Ej$_RgwxX@1S?5AwG^`7EJv0^?qCo=bSedPEu6uPY=pv zX8-ga0A`RM10x$iH4Fm}T0=^8^*~I=}N&nL60rw$}bMwNO=&7@TbiLg|!F%^?VFL9!Ij|Yv zlId#GD!R4GB(k9ZL087&vLAiP!4VzDRV18~b7ccc`es=y>ptcZeA0wNr*I@@j(?($ zB>qY{E*litsZJOk=saq-vTjjR;P^+1qA#zhAh(1QX56xThw>DKzn5#6q2;)!BQ7iN z8K#x*B>oTkvtes%mUp(L$N+R?%XH@?!r4$rlPdkXqiS+Xdb}vrs03LQp_3CRG^Ub9 z%4R4_v?sde90iAAVVKOSrRyJkACGRuasEoO7PzF?z~3-IGNdMtIXm)H+cg!}6$7vq zu#5J(6b}`D8v}*!`xI)_pf^5<6j1pGWz9yzw#J(P(om_g%`KhtS@{2!Dp7QI+DEIc6`TuCEL zFfcSd={;8v-+^wJ@0T$|Na|7`9j?gRa%!Gi1ey+mb-Yn$cLpHGUU9Q;+Zf}}iO;or z`Sudx@%P>LU8RJnbQ^V+hCFjRar?_G=d`9;CXM)4e-~-)F!U*k&K`73 z#i+^z{_resHsWoY1T6g^T+9x%Z*CnQC-KO3mw(tnk4#^wF;=Za5Vda#IYQ;4 z3IKSrMkKQe5VL%v#oJG7%TmMXfK3+rk^wqFZA(+@k2H2?;4!-u%LgaWE3ENhRc&y6 z+>QmjPCAF7A@s}0jw>%!aAU%ShZEOmQX$i;ESCa{w*~wTi5HpD{`+cA__c7Q>cX}R z6+93?dp#!gelrsBu_NOw=KI^DojPY4HU;yuIEcuf>h zWW{*LZQ6KL3?YM$XO*EC&9_}HOli>A=8fA|`?I{ITbn(r1l!n+K)O-{3IM8yYqHiD z`D3B(KX^u+uNaoBwokDam0Q*2lkgEB--!ov44iN7EytQ!yvlc_+JW6$pdfQ&TX~QY zF+#PhS@RDmKfJ#LW}$H92{NYja>N$oty;18BCSCxh~UuAij(!h?J7|dW)xXGW`&Kq a@DVqWc|5L*rEG4scQP@*HM&^F@@MEq9-0gQ literal 1013 zcmV7zLZ0{H_Y@4tTNp)K%Vi>#K#saZ`(5 zfG52v4akYo4e=E|q>atMcp^y+v09yf&{g8<8DSKx)>B3b4hlGH(dAUJ!?ze9TH*rO zq;J52BtOup$i$JVvw?c?)MST6igt!>A1bdU_F?aH+Rc>r_hezs4V+4=%et0kig@49 z)bjciZ(5@3#}*VA40yO;4$8+}2Z|8dA-P7+FIvz4xJfWco~B zn7;Q{wI2%&|5Vd1g7Q%_lQsYt0Q{uX55z1<7ptSDh*bsP7;5U+bCWN1kL>~Mb0nw2 zN+6oV+s zwCMVhU6tp5opfCTVZaEiR~AD~Z5SEAY?-@1(tgc3A}U@wduJxb`Ay3eg`ltGyu$nU zy`RHPqMm-Q&z$UvM(mW4!6M+=koY*J9)J6q{-!FddT+^ap{WaM$3*!mFi{jiY|#yg z^EUAJi|XE8wLx3-t4BoKBq6um;|aRgXUhs|nH}$nXorEcBF?W`HWtZ%;<7bmcsaT!$ek#vqx0` z|EM@zba;246$iSz3WlTtQ89EFozI+CQ4i7NQg00PZsAezumz~8oT$YHyVS#M+B;Zy zB$JL+ktITHorf|}GLKI&6 zuiZ*29RM;*19IiNE`eBJE@XyHv3y^6408JGL&J)kitFVGj$E-giszDeASqUmTMzFQ zh>&cDFiBj03LP!u$9G@^0#OW!ymA;nd$UNr8dqP5a=uC{VmXC8C7IIpg}nO$Ju=c{ zB~sfm^v)mya=8)D!to|y>^0zyUb-R}8JdBH>?kKWgpSQ<1ODF<2d|-_|9TEO1 diff --git a/scripts/gha-encrypted/storage/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/storage/GoogleService-Info.plist.gpg index de4c9c060ef900c64209cf477719da2b2b6e3847..01d28ec9c68dc2093039e5ef88d1b62e35c50863 100644 GIT binary patch literal 641 zcmV-{0)G9B4Fm}T0@BxCNCa2Mb^p@o0qtuiw?`tmd2RrUYRplF_cg~tu&`l%UZu36 zW0MRzaLxexhJhCfA|3TEiVMjoR0g|Ev<&_Vby6z0Esd`#5J`H{XGDoH?Th*BD?~wl z>&nNarqtokGHhG~MyqIYPd5@{=u^NAX%v;qpGq6@sI=4-~{0Nv73!Qd^ztPq)LTOE)Q+8 z+8rQw@R_hYkjkHRD{j;!jUVyU5~W!JF6xXofC?4?-5m&9adv!qB1 zG)WQ1&8goO)Ix|y2z3Q^8R|P&VCARg$3^&pOcXY{G+Ev6^+Wr7 zYn_il4A8BAPO3TpS-v?AGqn0=9&sg1fwHv3g@n=fL2ASJ$#uXTbB?Ck9Iw%~-Gbf= z{CuV)zbfK>m2pbZ5c=7UZ+uaBN8WID4!>K_X7Dv@ovP-*%J7VrJDQ|%v8D!iJ(H6y zowMHM(~G5nZYfLQ;hY4qMDEYch^&#t|5(0TMrK3;<|wn3kWMIuB9bE#?BN78xN|YY btXortgjczDJQD$D!1QIdm0!5@WZL-o7G^nu literal 682 zcmV;b0#*Ht4Fm}T0v!pkCXcJ+#sAXj0Z@8>?Hh4R@FkB5D3Uypi7`t7BSeCWHt?KO zg8Fy%ocVvr@D@~SMZLWa(L=^0g*WAmz3v$JWvi(defSRf7zRvQ+x;eBLu`JUOPSMw zn*TK-xVS+nChk}-XFq`yMa6?I@{k$$kq zza1!Pd~g&%NCJ-ze#J97&Eq2prlN)5-PT_yq0WO6HJW<-_3zlltL*I^x;?p^Fbv!K zG~Qno?;uL*Yc{`c{-)$ay}~6c4ty}{$kP3-i!2NkwD`~IW(XYILwijf5x9X8GO&$= zQ%&nV%m3c!?1>{`v7FyZ<#AW=DbxwgIUm1IAg|NdsTsih#F|x_jy0_C{TFM93r&mb zeg}TnkolFtEPvZvdPx5#D$qRGSU_5+S=yx$zsDwJ5`yW0lxk?mv(;$FsxsY(vTYR5 z7VPo5y&B%{tN_(W6=m{%xM$y-iE`=aCM5&*3PFm&+lR6K1io;UFD3Sy&V00Xu;M;M z650@GYf*prNbc3Ek1OcQm>(%l?rreoTwM_X0ICasoJUx;K6mf7qh@=Z|ACz`6(RC) z_p>Q-9LF*fV-?81bEkBMLFUX0@szZw)0a8};;D`;Q2|U!>X$$3wDJ?kUKDvumBDNX ze`2dhU6N3Mp9JX6339M;RO4Y?A#Waw6#GN%c5s@e+%O31FNCY8z$6_Va4>D@oBB^r Q@RD4!kXrp;=I5_ED>va;vj6}9 diff --git a/scripts/gha-encrypted/storage/google-services.json.gpg b/scripts/gha-encrypted/storage/google-services.json.gpg index 1393dce3671f22a200dcc706133d0b4f95f23b5a..57ba134aa519fd3e9fd4c6fe3e35bdfa7ab9f86c 100644 GIT binary patch literal 779 zcmV+m1N8ii4Fm}T0v}cjW*B7vvj5WQ0ddkb%Cwn*48_buW^@!uuT2?GV5}3TWRcaf z;2`T3gm||t~4(epM>5nKUnE1@cp zPB2p_6Sp_yGdE||m$yrkQC^U@B;`XBw4Cet#xE?0YMb#6G8d@)6V8x_sIk*A!hSxG zV{PUZD7#3x#tBKMIPUcS1L+?mTpz}NpgT?TVik0fopDg~XHo}Han$mf&N+!=2RR0gg4x(OqNwmUSzJr!dDiKul zx4T?gU)+wP%ZyMcWyP-F1mj{B_r+&$(3!qGN9*s%2Fpx>PdS+CD z9)wXN&TGX3ETIOI33%(0z&K5s*DR9}URZ%=kPuF(MhucM9GUcTZHp$xW)tyCW2|*q zo(#ZVKbkUg8s6MV zTFNY@&bsgi{{4(Hu5z^t51z8LB)Nkhez1gAY|&{QQ7p4;6-}>|E=j}bzt+9+2KA;_ z(?K^!D$*b~S80>8bJe}pa8wUq#4~28*g$H=Jv-D7>>I;SSk_fs;B zOiGw|(LyUVcd2k^$kRI{cifK?&2Cmvoph zVeX}Y2=EdIRM6+7s%-E;SPq~+L|oB#|GH6KI>Z+}JN#ayQovGuJg>igmM8$SD_rAj zy}5T+JM%kx4Ob`Cio}}uNR@u{>WS1rleQk_>GZuRp>2cXkr2#-h+O;E@QYwR5}81< zvfhaN$GE-*ATt67HE4i5L+8PImT7=M9~yX)Dyi}!t7(fumWFTDhJfvMdn;R{77Z3= z%sAFx`Qt zqW2YZ2jy7db)!C&hI3#aJ>%>>*-X~$YL9^fDFDYH^5?WQw#ON=5E=RW$>#XXL})YX z&SrDEOL}R;m0>YEC$iaM@EHt`O@3F|Y$Cp}t$jKtGu&^6Tm?ON%$~5)y;-MpXS~eX^3ptoq^@303CA))iMYnA2!@j`?`p=u#P8R0b)9@a9svQy`21NY6oNM+aUs)mO z{!$JyC$Ze9+$EJ From d099e4d8556b6b51564e604baba813221a252b7e Mon Sep 17 00:00:00 2001 From: a-maurice Date: Tue, 5 Nov 2024 15:51:26 -0800 Subject: [PATCH 51/57] Specify using v1 Cloud Functions --- functions/testapp/functions/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/functions/testapp/functions/index.js b/functions/testapp/functions/index.js index ebafe634..a8d1905d 100644 --- a/functions/testapp/functions/index.js +++ b/functions/testapp/functions/index.js @@ -15,9 +15,9 @@ */ 'use strict'; -const functions = require('firebase-functions'); +const functions = require('firebase-functions/v1'); const admin = require('firebase-admin'); -admin.initializeApp(functions.config().firebase); +admin.initializeApp(); // Adds two numbers to each other. exports.addNumbers = functions.https.onCall((data) => { From cf330de003168a0bb9892b93e6ca990f03433170 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 18 Dec 2024 17:04:19 +0000 Subject: [PATCH 52/57] firestore/CMakeLists.txt: add dbghelp and bcrypt libraries to ADDITIONAL_LIBS on windows --- firestore/testapp/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firestore/testapp/CMakeLists.txt b/firestore/testapp/CMakeLists.txt index a4dd2727..1a2c953f 100644 --- a/firestore/testapp/CMakeLists.txt +++ b/firestore/testapp/CMakeLists.txt @@ -106,7 +106,7 @@ else() "-framework SystemConfiguration" ) elseif(MSVC) - set(ADDITIONAL_LIBS advapi32 ws2_32 crypt32 iphlpapi psapi userenv) + set(ADDITIONAL_LIBS advapi32 ws2_32 crypt32 iphlpapi psapi userenv dbghelp bcrypt) else() set(ADDITIONAL_LIBS pthread) endif() From 8732ccf6e92831cffbe9dd8a16ebecc5d1e2873d Mon Sep 17 00:00:00 2001 From: joefspiro <97258781+joefspiro@users.noreply.github.com> Date: Fri, 22 Aug 2025 15:42:07 -0400 Subject: [PATCH 53/57] Alters FCM readme to refer directly to permanent docs. --- messaging/testapp/readme.md | 245 ++++-------------------------------- 1 file changed, 26 insertions(+), 219 deletions(-) diff --git a/messaging/testapp/readme.md b/messaging/testapp/readme.md index ea47af73..6bed21a3 100644 --- a/messaging/testapp/readme.md +++ b/messaging/testapp/readme.md @@ -1,241 +1,48 @@ Firebase Cloud Messaging Quickstart =================================== -The Firebase Cloud Messaging Test Application (testapp) demonstrates receiving -Firebase Cloud Messages using the Firebase Cloud Messaging C++ SDK. This +The Firebase Messaging C++ Sample (hereafter the 'test app') demonstrates receiving messages from [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/) +using the [Firebase C++ SDK](https://firebase.google.com/docs/cpp/setup). This application has no user interface and simply logs actions it's performing to the console. -Introduction ------------- +## Set up, build and run the test app -- [Read more about Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/) +> **_NOTE:_** Do not implement the code changes of the subsequent linked instructions as this codebase already has those functionalities. -Building and Running the testapp --------------------------------- -### iOS - - Link your iOS app to the Firebase libraries. - - Get CocoaPods version 1 or later by running, +1. Complete [Add Firebase to your C++ project](https://firebase.google.com/docs/cpp/setup) for your selected build platforms. +1. [Set up a Firebase Cloud Messaging client app with C++](https://firebase.google.com/docs/cloud-messaging/cpp/client). - ``` - sudo gem install cocoapods --pre - ``` - - From the testapp directory, install the CocoaPods listed in the Podfile by - running, - ``` - pod install - ``` - - Open the generated Xcode workspace (which now has the CocoaPods), - - ``` - open testapp.xcworkspace - ``` - - For further details please refer to the - [general instructions for setting up an iOS app with Firebase](https://firebase.google.com/docs/ios/setup). - - - Register your iOS app with Firebase. - - Create a new app on - [firebase.google.com/console](https://firebase.google.com/console/) - , and attach your iOS app to it. - - For Messaging, you will need an App Store ID. Use something random such - as 12345678." - - You can use "com.google.FirebaseCppMessagingTestApp.dev" as the iOS Bundle ID - while you're testing. - - Add the GoogleService-Info.plist that you downloaded from Firebase - console to the testapp root directory. This file identifies your iOS app - to the Firebase backend. - - Download the Firebase C++ SDK linked from - [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup) - and unzip it to a directory of your choice. - - Add the following frameworks from the Firebase C++ SDK to the project: - - frameworks/ios/universal/firebase.framework - - frameworks/ios/universal/firebase_messaging.framework - - You will need to either, - 1. Check "Copy items if needed" when adding the frameworks, or - 2. Add the framework path in "Framework Search Paths" - - e.g. If you downloaded the Firebase C++ SDK to - `/Users/me/firebase_cpp_sdk`, - then you would add the path - `/Users/me/firebase_cpp_sdk/frameworks/ios/universal`. - - To add the path, in XCode, select your project in the project - navigator, then select your target in the main window. - Select the "Build Settings" tab, and click "All" to see all - the build settings. Scroll down to "Search Paths", and add - your path to "Framework Search Paths". - - You need a valid - [APNs](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html) - certificate. If you don't already have one, see - [Provisioning APNs SSL Certificates.](https://firebase.google.com/docs/cloud-messaging/ios/certs) - - Configure the Xcode project for push messaging. - - Select the `testapp` project from the `Navigator area`. - - Select the `testapp` target from the `Editor area`. - - Select the `General` tab from the `Editor area`. - - Scroll down to `Linked Frameworks and Libraries` and click the `+` - button to add a framework. - - In the window that appears, scroll to `UserNotifications.framework` - and click on that entry, then click on `Add`. This framework will only - appear in Xcode version 8 and higher, required by this library. - - Select the `Capabilities` tab from the `Editor area`. - - Switch `Push Notifications` to `On`. - - Scroll down to `Background Modes` and switch it to `On`. - - Tick the `Remote notifications` box under `Background Modes`. - - In XCode, build & run the sample on an iOS device or simulator. - - The testapp has no user interface. The output of the app can be viewed - via the console. In Xcode, select - `View --> Debug Area --> Activate Console` from the menu. - -### Android -**Register your Android app with Firebase.** - -- Create a new app on -[firebase.google.com/console](https://firebase.google.com/console/) -, and attach your Android app to it. -- You can use "com.google.android.messaging.testapp" as the Package Name -while you're testing. -- To [generate a SHA1](https://developers.google.com/android/guides/client-auth) -run this command (_Note: the default password is 'android'_): - * Mac and Linux: - - ``` - keytool -exportcert -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore - ``` - * Windows: - - ``` - keytool -exportcert -list -v -alias androiddebugkey -keystore %USERPROFILE%\.android\debug.keystore - ``` -- If keytool reports that you do not have a debug.keystore, you can -[create one](http://developer.android.com/tools/publishing/app-signing.html#signing-manually) -with: - - ``` - keytool -genkey -v -keystore ~/.android/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US" - ``` -- Add the `google-services.json` file that you downloaded from Firebase - console to the root directory of testapp. This file identifies your - Android app to the Firebase backend. -- For further details please refer to the -[general instructions for setting up an Android app with Firebase](https://firebase.google.com/docs/android/setup). - -- Download the Firebase C++ SDK linked from - [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup) - and unzip it to a directory of your choice. - -**Configure your SDK paths** - -- Configure the location of the Firebase C++ SDK by setting the -`firebase_cpp_sdk.dir` Gradle property to the SDK install directory. - * Run this command in the project directory, and modify the path to match your - local installation path: - - ``` - echo "systemProp.firebase_cpp_sdk.dir=/User/$USER/firebase_cpp_sdk" >> gradle.properties - ``` -- Ensure the Android SDK and NDK locations are set in Android Studio. - * From the Android Studio launch menu, go to `File/Project Structure...` or - `Configure/Project Defaults/Project Structure...` - (Shortcut: Control + Alt + Shift + S on windows, Command + ";" on a mac) - and download the SDK and NDK if the locations are not yet set. - * Android Studio will write these paths to `local.properties`. - -**Optional: Configure your deep link URL** - -- To enable your app to receive deep links via FCM, you will need to add an - intent filter to your AndroidManifest.xml in the native activity that - associates your domain with your app. - -``` - - - - - - - -``` - -**Build & Run** - -- Open `build.gradle` in Android Studio. - - From the Android Studio launch menu, "Open an existing Android Studio - project", and select `build.gradle`. -- Install the SDK Platforms that Android Studio reports missing. -- Build the testapp and run it on an Android device or emulator. -- See [below](#using_the_test_app) for usage instructions. - -### Desktop - - Register your app with Firebase. - - Create a new app on the [Firebase console](https://firebase.google.com/console/), - following the above instructions for Android or iOS. - - If you have an Android project, add the `google-services.json` file that - you downloaded from the Firebase console to the root directory of the - testapp. - - If you have an iOS project, and don't wish to use an Android project, - you can use the Python script `generate_xml_from_google_services_json.py --plist`, - located in the Firebase C++ SDK, to convert your `GoogleService-Info.plist` - file into a `google-services-desktop.json` file, which can then be - placed in the root directory of the testapp. - - Download the Firebase C++ SDK linked from - [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup) - and unzip it to a directory of your choice. - - Configure the testapp with the location of the Firebase C++ SDK. - This can be done a couple different ways (in highest to lowest priority): - - When invoking cmake, pass in the location with - -DFIREBASE_CPP_SDK_DIR=/path/to/firebase_cpp_sdk. - - Set an environment variable for FIREBASE_CPP_SDK_DIR to the path to use. - - Edit the CMakeLists.txt file, changing the FIREBASE_CPP_SDK_DIR path - to the appropriate location. - - From the testapp directory, generate the build files by running, - ``` - cmake . - ``` - If you want to use XCode, you can use -G"Xcode" to generate the project. - Similarly, to use Visual Studio, -G"Visual Studio 15 2017". For more - information, see - [CMake generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html). - - Build the testapp, by either opening the generated project file based on - the platform, or running, - ``` - cmake --build . - ``` - - Execute the testapp by running, - ``` - ./desktop_testapp - ``` - Note that the executable might be under another directory, such as Debug. - - The testapp has no user interface, but the output can be viewed via the - console. Note that Messaging uses a stubbed implementation on desktop, - so functionality is not expected. - -Using the Test App ------------------- +### Running the test app +---------------------- - Install and run the test app on your iOS or Android device or emulator. - The application has minimal user interface. The output of the app can be viewed via the console: - * **iOS**: Open select "View --> Debug Area --> Activate Console" from the + * **iOS**: Open select "View -> Debug Area -> Activate Console" from the menu in Xcode. * **Android**: View the logcat output in Android studio or by running - "adb logcat" from the command line. + `adb logcat` from the command line. - When you first run the app, it will print: `Received Registration Token: `. Copy this code to a text editor. -- Copy the ServerKey from the firebase console: - - Open your project in the - [Firebase Console](https://firebase.google.com/console/). - - Click the gear icon then `Project settings` in the menu on the left - - Select the `Cloud Messaging` tab. - - Copy the `Server Key` -- Replace `` and `` in this command and run it -from the command line. -``` -curl --header "Authorization: key=" --header "Content-Type: application/json" https://android.googleapis.com/gcm/send -d '{"notification":{"title":"Hi","body":"Hello from the Cloud"},"data":{"score":"lots"},"to":""}' -``` -- Observe the command received in the app, via the console output. -Support -------- +### Send a message from your server environment +----------------------------------------------- + +1. Navigate to the FCM REST API Docs for [Method: projects.messages.send](https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages/send) +1. Look for the "Try this method" panel + 1. This might require you to expand your browser window. +1. Follow the API doc to understand what IDs and fields to fill in for your particular use case. + 1. Your project number is available from [Project settings](https://console.firebase.google.com/project/_/settings/general) +1. Fill in the `Request body` referencing the [FCM REST API docs](https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages). +1. Execute. +1. Observe the command received in the app, via the console output. + +Reminder, while this process is currently done from our website, it uses the FCM v1 Send API directly and provides the simplest starting point to switch to using the Send API or Admin SDKs in production. -[https://firebase.google.com/support/](https://firebase.google.com/support/) +## Troubleshooting and Support +- [Firebase Cloud Messaging troubleshooting & FAQ](https://firebase.google.com/docs/cloud-messaging/troubleshooting) +- [Firebase Support](https://firebase.google.com/support/) License ------- From 0618c447dd927c3faab803866af2b73080421244 Mon Sep 17 00:00:00 2001 From: joefspiro <97258781+joefspiro@users.noreply.github.com> Date: Fri, 22 Aug 2025 15:43:24 -0400 Subject: [PATCH 54/57] Fixes a style issue. --- messaging/testapp/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/messaging/testapp/readme.md b/messaging/testapp/readme.md index 6bed21a3..c5a59969 100644 --- a/messaging/testapp/readme.md +++ b/messaging/testapp/readme.md @@ -38,7 +38,7 @@ viewed via the console: 1. Execute. 1. Observe the command received in the app, via the console output. -Reminder, while this process is currently done from our website, it uses the FCM v1 Send API directly and provides the simplest starting point to switch to using the Send API or Admin SDKs in production. +Reminder, while this process is currently done from our website, it uses the FCM v1 Send API directly and provides the simplest starting point to switch to using the v1 Send API or the Firebase Admin SDK in production. ## Troubleshooting and Support - [Firebase Cloud Messaging troubleshooting & FAQ](https://firebase.google.com/docs/cloud-messaging/troubleshooting) From 2c8628995edccd2569e8ef6debeb96868f88f410 Mon Sep 17 00:00:00 2001 From: Ben Knutson Date: Wed, 18 Feb 2026 16:17:13 +0000 Subject: [PATCH 55/57] Refactor Github Action per b/485167538 --- .github/workflows/android.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index e086d3f9..5caea503 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -30,12 +30,14 @@ jobs: - id: set_outputs run: | if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - apis="${{ github.event.inputs.apis }}" + apis="${GITHUB_EVENT_INPUTS_APIS}" else apis="analytics,auth,database,dynamic_links,firestore,functions,gma,messaging,remote_config,storage" fi echo apis: ${apis} echo "::set-output name=apis::${apis}" + env: + GITHUB_EVENT_INPUTS_APIS: ${{ github.event.inputs.apis }} build: name: android-${{ matrix.os }}-${{ matrix.architecture }}-${{ matrix.python_version }} @@ -156,13 +158,15 @@ jobs: run: | set -x python scripts/build_scripts/build_testapps.py --p Android \ - --t ${{ needs.check_and_prepare.outputs.apis }} \ + --t ${NEEDS_CHECK_AND_PREPARE_OUTPUTS_APIS} \ --output_directory "${{ github.workspace }}" \ --artifact_name "android-${{ matrix.os }}" \ --noadd_timestamp \ --short_output_paths \ --gha_build \ --packaged_sdk /tmp/downloaded_sdk/firebase_cpp_sdk + env: + NEEDS_CHECK_AND_PREPARE_OUTPUTS_APIS: ${{ needs.check_and_prepare.outputs.apis }} - name: Stats for ccache (mac and linux) if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') @@ -204,6 +208,8 @@ jobs: shell: bash run: | cat build-results-android-${{ matrix.os }}.log - if [[ "${{ job.status }}" != "success" ]]; then + if [[ "${JOB_STATUS}" != "success" ]]; then exit 1 fi + env: + JOB_STATUS: ${{ job.status }} From fc0b9392d73a22eb5b27ba643ed4c83110dec6b8 Mon Sep 17 00:00:00 2001 From: a-maurice Date: Mon, 23 Feb 2026 14:32:56 -0800 Subject: [PATCH 56/57] Update android.yml --- .github/workflows/android.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 5caea503..9a597262 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -157,8 +157,9 @@ jobs: shell: bash run: | set -x + CLEAN_APIS=$(echo ${NEEDS_CHECK_AND_PREPARE_OUTPUTS_APIS} | tr -d "'" | tr -d "\"") python scripts/build_scripts/build_testapps.py --p Android \ - --t ${NEEDS_CHECK_AND_PREPARE_OUTPUTS_APIS} \ + --t ${CLEAN_APIS} \ --output_directory "${{ github.workspace }}" \ --artifact_name "android-${{ matrix.os }}" \ --noadd_timestamp \ From 6ec1960dbe47ef1067e3089156beb1541b2409da Mon Sep 17 00:00:00 2001 From: a-maurice Date: Tue, 24 Feb 2026 11:52:11 -0800 Subject: [PATCH 57/57] Remove unused workflows, and Dynamic Links (#167) --- .github/workflows/android.yml | 216 - .github/workflows/desktop.yml | 14 - .github/workflows/ios.yml | 14 - dynamic_links/testapp/AndroidManifest.xml | 23 - dynamic_links/testapp/CMakeLists.txt | 118 - dynamic_links/testapp/LICENSE | 202 - dynamic_links/testapp/LaunchScreen.storyboard | 7 - dynamic_links/testapp/Podfile | 7 - dynamic_links/testapp/build.gradle | 76 - dynamic_links/testapp/gradle.properties | 1 - .../testapp/gradle/wrapper/gradle-wrapper.jar | Bin 49896 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 - dynamic_links/testapp/gradlew | 164 - dynamic_links/testapp/gradlew.bat | 90 - dynamic_links/testapp/proguard.pro | 2 - dynamic_links/testapp/readme.md | 223 - dynamic_links/testapp/res/layout/main.xml | 12 - dynamic_links/testapp/res/values/strings.xml | 4 - dynamic_links/testapp/settings.gradle | 36 - .../testapp/src/android/android_main.cc | 255 - .../google/firebase/example/LoggingUtils.java | 55 - dynamic_links/testapp/src/common_main.cc | 203 - .../testapp/src/desktop/desktop_main.cc | 125 - dynamic_links/testapp/src/ios/ios_main.mm | 120 - dynamic_links/testapp/src/main.h | 63 - .../testapp/testapp.xcodeproj/project.pbxproj | 312 - .../AppIcon.appiconset/Contents.json | 58 - .../LaunchImage.launchimage/Contents.json | 51 - dynamic_links/testapp/testapp/Info.plist | 55 - functions/testapp/functions/package-lock.json | 8246 ----------------- .../build_scripts/android/install_prereqs.sh | 75 - scripts/build_scripts/build_testapps.json | 170 - scripts/build_scripts/build_testapps.py | 718 -- scripts/build_scripts/config_reader.py | 139 - scripts/build_scripts/python_requirements.txt | 2 - scripts/build_scripts/utils.py | 94 - scripts/build_scripts/xcodebuild.py | 119 - scripts/gha-encrypted/README | 3 - .../analytics/GoogleService-Info.plist.gpg | Bin 670 -> 0 bytes .../analytics/google-services.json.gpg | Bin 962 -> 0 bytes .../auth/GoogleService-Info.plist.gpg | 3 - .../auth/google-services.json.gpg | Bin 1007 -> 0 bytes .../database/GoogleService-Info.plist.gpg | Bin 700 -> 0 bytes .../database/google-services.json.gpg | Bin 725 -> 0 bytes .../GoogleService-Info.plist.gpg | Bin 649 -> 0 bytes .../dynamic_links/google-services.json.gpg | 3 - .../firestore/GoogleService-Info.plist.gpg | Bin 597 -> 0 bytes .../firestore/google-services.json.gpg | Bin 523 -> 0 bytes .../functions/GoogleService-Info.plist.gpg | Bin 674 -> 0 bytes .../functions/google-services.json.gpg | Bin 525 -> 0 bytes .../gma/GoogleService-Info.plist.gpg | Bin 663 -> 0 bytes .../gma/google-services.json.gpg | Bin 953 -> 0 bytes .../messaging/GoogleService-Info.plist.gpg | Bin 681 -> 0 bytes .../messaging/google-services.json.gpg | Bin 609 -> 0 bytes .../GoogleService-Info.plist.gpg | Bin 614 -> 0 bytes .../remote_config/google-services.json.gpg | Bin 848 -> 0 bytes .../storage/GoogleService-Info.plist.gpg | Bin 641 -> 0 bytes .../storage/google-services.json.gpg | Bin 779 -> 0 bytes scripts/restore_secrets.py | 186 - 59 files changed, 12271 deletions(-) delete mode 100644 .github/workflows/android.yml delete mode 100644 .github/workflows/desktop.yml delete mode 100644 .github/workflows/ios.yml delete mode 100644 dynamic_links/testapp/AndroidManifest.xml delete mode 100644 dynamic_links/testapp/CMakeLists.txt delete mode 100644 dynamic_links/testapp/LICENSE delete mode 100644 dynamic_links/testapp/LaunchScreen.storyboard delete mode 100644 dynamic_links/testapp/Podfile delete mode 100644 dynamic_links/testapp/build.gradle delete mode 100644 dynamic_links/testapp/gradle.properties delete mode 100644 dynamic_links/testapp/gradle/wrapper/gradle-wrapper.jar delete mode 100644 dynamic_links/testapp/gradle/wrapper/gradle-wrapper.properties delete mode 100755 dynamic_links/testapp/gradlew delete mode 100644 dynamic_links/testapp/gradlew.bat delete mode 100644 dynamic_links/testapp/proguard.pro delete mode 100644 dynamic_links/testapp/readme.md delete mode 100644 dynamic_links/testapp/res/layout/main.xml delete mode 100644 dynamic_links/testapp/res/values/strings.xml delete mode 100644 dynamic_links/testapp/settings.gradle delete mode 100644 dynamic_links/testapp/src/android/android_main.cc delete mode 100644 dynamic_links/testapp/src/android/java/com/google/firebase/example/LoggingUtils.java delete mode 100644 dynamic_links/testapp/src/common_main.cc delete mode 100644 dynamic_links/testapp/src/desktop/desktop_main.cc delete mode 100644 dynamic_links/testapp/src/ios/ios_main.mm delete mode 100644 dynamic_links/testapp/src/main.h delete mode 100644 dynamic_links/testapp/testapp.xcodeproj/project.pbxproj delete mode 100644 dynamic_links/testapp/testapp/Images.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 dynamic_links/testapp/testapp/Images.xcassets/LaunchImage.launchimage/Contents.json delete mode 100644 dynamic_links/testapp/testapp/Info.plist delete mode 100644 functions/testapp/functions/package-lock.json delete mode 100755 scripts/build_scripts/android/install_prereqs.sh delete mode 100644 scripts/build_scripts/build_testapps.json delete mode 100644 scripts/build_scripts/build_testapps.py delete mode 100644 scripts/build_scripts/config_reader.py delete mode 100644 scripts/build_scripts/python_requirements.txt delete mode 100644 scripts/build_scripts/utils.py delete mode 100644 scripts/build_scripts/xcodebuild.py delete mode 100644 scripts/gha-encrypted/README delete mode 100644 scripts/gha-encrypted/analytics/GoogleService-Info.plist.gpg delete mode 100644 scripts/gha-encrypted/analytics/google-services.json.gpg delete mode 100644 scripts/gha-encrypted/auth/GoogleService-Info.plist.gpg delete mode 100644 scripts/gha-encrypted/auth/google-services.json.gpg delete mode 100644 scripts/gha-encrypted/database/GoogleService-Info.plist.gpg delete mode 100644 scripts/gha-encrypted/database/google-services.json.gpg delete mode 100644 scripts/gha-encrypted/dynamic_links/GoogleService-Info.plist.gpg delete mode 100644 scripts/gha-encrypted/dynamic_links/google-services.json.gpg delete mode 100644 scripts/gha-encrypted/firestore/GoogleService-Info.plist.gpg delete mode 100644 scripts/gha-encrypted/firestore/google-services.json.gpg delete mode 100644 scripts/gha-encrypted/functions/GoogleService-Info.plist.gpg delete mode 100644 scripts/gha-encrypted/functions/google-services.json.gpg delete mode 100644 scripts/gha-encrypted/gma/GoogleService-Info.plist.gpg delete mode 100644 scripts/gha-encrypted/gma/google-services.json.gpg delete mode 100644 scripts/gha-encrypted/messaging/GoogleService-Info.plist.gpg delete mode 100644 scripts/gha-encrypted/messaging/google-services.json.gpg delete mode 100644 scripts/gha-encrypted/remote_config/GoogleService-Info.plist.gpg delete mode 100644 scripts/gha-encrypted/remote_config/google-services.json.gpg delete mode 100644 scripts/gha-encrypted/storage/GoogleService-Info.plist.gpg delete mode 100644 scripts/gha-encrypted/storage/google-services.json.gpg delete mode 100644 scripts/restore_secrets.py diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml deleted file mode 100644 index 9a597262..00000000 --- a/.github/workflows/android.yml +++ /dev/null @@ -1,216 +0,0 @@ -name: Android Builds - -on: - schedule: - - cron: "0 9 * * *" # 9am UTC = 1am PST / 2am PDT. for all testapps except firestore - pull_request: - types: [opened, reopened, synchronize] - workflow_dispatch: - inputs: - apis: - description: 'CSV of apis to build and test' - default: 'analytics,auth,database,dynamic_links,firestore,functions,gma,messaging,remote_config,storage' - required: true - -env: - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - GITHUB_TOKEN: ${{ github.token }} - xcodeVersion: "13.3.1" # Only affects Mac runners, and only for prerequisites. - -concurrency: - group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.head_ref || github.ref }} - cancel-in-progress: true - -jobs: - check_and_prepare: - runs-on: ubuntu-latest - outputs: - apis: ${{ steps.set_outputs.outputs.apis }} - steps: - - id: set_outputs - run: | - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - apis="${GITHUB_EVENT_INPUTS_APIS}" - else - apis="analytics,auth,database,dynamic_links,firestore,functions,gma,messaging,remote_config,storage" - fi - echo apis: ${apis} - echo "::set-output name=apis::${apis}" - env: - GITHUB_EVENT_INPUTS_APIS: ${{ github.event.inputs.apis }} - - build: - name: android-${{ matrix.os }}-${{ matrix.architecture }}-${{ matrix.python_version }} - runs-on: ${{ matrix.os }} - needs: [check_and_prepare] - strategy: - fail-fast: false - matrix: - os: [macos-12, ubuntu-latest, windows-latest] - architecture: [x64] - python_version: [3.7] - steps: - - name: setup Xcode version (macos) - if: runner.os == 'macOS' - run: sudo xcode-select -s /Applications/Xcode_${{ env.xcodeVersion }}.app/Contents/Developer - - - name: Store git credentials for all git commands - # Forces all git commands to use authenticated https, to prevent throttling. - shell: bash - run: | - git config --global credential.helper 'store --file /tmp/git-credentials' - echo 'https://${{ github.token }}@github.com' > /tmp/git-credentials - - - name: Enable Git Long-paths Support - if: runner.os == 'Windows' - run: git config --system core.longpaths true - - - uses: actions/checkout@v2 - with: - submodules: true - - - name: Set env variables for subsequent steps (all) - shell: bash - run: | - echo "MATRIX_UNIQUE_NAME=${{ matrix.os }}-${{ matrix.architecture }}" >> $GITHUB_ENV - echo "GHA_INSTALL_CCACHE=1" >> $GITHUB_ENV - - - name: Setup python - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python_version }} - architecture: ${{ matrix.architecture }} - - - name: Add msbuild to PATH - if: startsWith(matrix.os, 'windows') - uses: microsoft/setup-msbuild@v1.0.2 - - - name: Cache NDK - id: cache_ndk - uses: actions/cache@v2 - with: - path: /tmp/android-ndk-r21e - key: android-ndk-${{ matrix.os }}-r21e - - - name: Check cached NDK - shell: bash - if: steps.cache_ndk.outputs.cache-hit != 'true' - run: | - # If the NDK failed to download from the cache, but there is a - # /tmp/android-ndk-r21e directory, it's incomplete, so remove it. - if [[ -d "/tmp/android-ndk-r21e" ]]; then - echo "Removing incomplete download of NDK" - rm -rf /tmp/android-ndk-r21e - fi - - - name: Update homebrew (avoid bintray errors) - uses: nick-invision/retry@v2 - if: startsWith(matrix.os, 'macos') - with: - timeout_minutes: 10 - max_attempts: 3 - command: | - # Temporarily here until Github runners have updated their version of - # homebrew. This prevents errors arising from the shut down of - # binutils, used by older version of homebrew for hosting packages. - brew update - - - name: Install prerequisites - uses: nick-invision/retry@v2 - with: - timeout_minutes: 10 - max_attempts: 3 - shell: bash - command: | - scripts/build_scripts/android/install_prereqs.sh - echo "NDK_ROOT=/tmp/android-ndk-r21e" >> $GITHUB_ENV - echo "ANDROID_NDK_HOME=/tmp/android-ndk-r21e" >> $GITHUB_ENV - pip install -r scripts/build_scripts/python_requirements.txt - python scripts/restore_secrets.py --passphrase "${{ secrets.TEST_SECRET }}" - - - name: Download C++ SDK - shell: bash - run: | - set +e - # Retry up to 10 times because Curl has a tendency to timeout on - # Github runners. - for retry in {1..10} error; do - if [[ $retry == "error" ]]; then exit 5; fi - curl -LSs \ - "https://firebase.google.com/download/cpp" \ - --output firebase_cpp_sdk.zip && break - sleep 300 - done - set -e - mkdir /tmp/downloaded_sdk - unzip -q firebase_cpp_sdk.zip -d /tmp/downloaded_sdk/ - rm -f firebase_cpp_sdk.zip - - - name: Cache ccache files - id: cache_ccache - uses: actions/cache@v2 - with: - path: ccache_dir - key: dev-test-ccache-${{ env.MATRIX_UNIQUE_NAME }} - - - name: Build testapp - shell: bash - run: | - set -x - CLEAN_APIS=$(echo ${NEEDS_CHECK_AND_PREPARE_OUTPUTS_APIS} | tr -d "'" | tr -d "\"") - python scripts/build_scripts/build_testapps.py --p Android \ - --t ${CLEAN_APIS} \ - --output_directory "${{ github.workspace }}" \ - --artifact_name "android-${{ matrix.os }}" \ - --noadd_timestamp \ - --short_output_paths \ - --gha_build \ - --packaged_sdk /tmp/downloaded_sdk/firebase_cpp_sdk - env: - NEEDS_CHECK_AND_PREPARE_OUTPUTS_APIS: ${{ needs.check_and_prepare.outputs.apis }} - - - name: Stats for ccache (mac and linux) - if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') - run: ccache -s - - - name: Prepare results summary artifact - if: ${{ !cancelled() }} - shell: bash - run: | - if [ ! -f build-results-android-${{ matrix.os }}.log.json ]; then - echo "__SUMMARY_MISSING__" > build-results-android-${{ matrix.os }}.log.json - fi - - - name: Upload Android integration tests artifact - uses: actions/upload-artifact@v3 - if: ${{ !cancelled() }} - with: - name: testapps-android-${{ matrix.os }} - path: testapps-android-${{ matrix.os }} - retention-days: ${{ env.artifactRetentionDays }} - - - name: Upload Android build results artifact - uses: actions/upload-artifact@v3 - if: ${{ !cancelled() }} - with: - name: log-artifact - path: build-results-android-${{ matrix.os }}* - retention-days: ${{ env.artifactRetentionDays }} - - - name: Download log artifacts - if: ${{ needs.check_and_prepare.outputs.pr_number && failure() && !cancelled() }} - uses: actions/download-artifact@v3 - with: - path: test_results - name: log-artifact - - - name: Summarize build results - if: ${{ !cancelled() }} - shell: bash - run: | - cat build-results-android-${{ matrix.os }}.log - if [[ "${JOB_STATUS}" != "success" ]]; then - exit 1 - fi - env: - JOB_STATUS: ${{ job.status }} diff --git a/.github/workflows/desktop.yml b/.github/workflows/desktop.yml deleted file mode 100644 index b606cea0..00000000 --- a/.github/workflows/desktop.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: Desktop builds - -on: - workflow_dispatch: - inputs: - apis: - description: 'CSV of apis whose quickstart examples we should build' - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: noop - run: true diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml deleted file mode 100644 index 72c85f64..00000000 --- a/.github/workflows/ios.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: iOS builds - -on: - workflow_dispatch: - inputs: - apis: - description: 'CSV of apis whose quickstart examples we should build' - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: noop - run: true diff --git a/dynamic_links/testapp/AndroidManifest.xml b/dynamic_links/testapp/AndroidManifest.xml deleted file mode 100644 index 2aa60f2d..00000000 --- a/dynamic_links/testapp/AndroidManifest.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/dynamic_links/testapp/CMakeLists.txt b/dynamic_links/testapp/CMakeLists.txt deleted file mode 100644 index 5574b351..00000000 --- a/dynamic_links/testapp/CMakeLists.txt +++ /dev/null @@ -1,118 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -# User settings for Firebase samples. -# Path to Firebase SDK. -# Try to read the path to the Firebase C++ SDK from an environment variable. -if (NOT "$ENV{FIREBASE_CPP_SDK_DIR}" STREQUAL "") - set(DEFAULT_FIREBASE_CPP_SDK_DIR "$ENV{FIREBASE_CPP_SDK_DIR}") -else() - set(DEFAULT_FIREBASE_CPP_SDK_DIR "firebase_cpp_sdk") -endif() -if ("${FIREBASE_CPP_SDK_DIR}" STREQUAL "") - set(FIREBASE_CPP_SDK_DIR ${DEFAULT_FIREBASE_CPP_SDK_DIR}) -endif() -if(NOT EXISTS ${FIREBASE_CPP_SDK_DIR}) - message(FATAL_ERROR "The Firebase C++ SDK directory does not exist: ${FIREBASE_CPP_SDK_DIR}. See the readme.md for more information") -endif() - -# Windows runtime mode, either MD or MT depending on whether you are using -# /MD or /MT. For more information see: -# https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx -set(MSVC_RUNTIME_MODE MD) - -project(firebase_testapp) - -# Sample source files. -set(FIREBASE_SAMPLE_COMMON_SRCS - src/main.h - src/common_main.cc -) - -# The include directory for the testapp. -include_directories(src) - -# Sample uses some features that require C++ 11, such as lambdas. -set (CMAKE_CXX_STANDARD 11) - -if(ANDROID) - # Build an Android application. - - # Source files used for the Android build. - set(FIREBASE_SAMPLE_ANDROID_SRCS - src/android/android_main.cc - ) - - # Build native_app_glue as a static lib - add_library(native_app_glue STATIC - ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - - # Export ANativeActivity_onCreate(), - # Refer to: https://github.com/android-ndk/ndk/issues/381. - set(CMAKE_SHARED_LINKER_FLAGS - "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - - # Define the target as a shared library, as that is what gradle expects. - set(target_name "android_main") - add_library(${target_name} SHARED - ${FIREBASE_SAMPLE_ANDROID_SRCS} - ${FIREBASE_SAMPLE_COMMON_SRCS} - ) - - target_link_libraries(${target_name} - log android atomic native_app_glue - ) - - target_include_directories(${target_name} PRIVATE - ${ANDROID_NDK}/sources/android/native_app_glue) - - set(ADDITIONAL_LIBS) -else() - # Build a desktop application. - - # Windows runtime mode, either MD or MT depending on whether you are using - # /MD or /MT. For more information see: - # https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx - set(MSVC_RUNTIME_MODE MD) - - # Platform abstraction layer for the desktop sample. - set(FIREBASE_SAMPLE_DESKTOP_SRCS - src/desktop/desktop_main.cc - ) - - set(target_name "desktop_testapp") - add_executable(${target_name} - ${FIREBASE_SAMPLE_DESKTOP_SRCS} - ${FIREBASE_SAMPLE_COMMON_SRCS} - ) - - if(APPLE) - set(ADDITIONAL_LIBS pthread) - elseif(MSVC) - set(ADDITIONAL_LIBS) - else() - set(ADDITIONAL_LIBS pthread) - endif() - - # If a config file is present, copy it into the binary location so that it's - # possible to create the default Firebase app. - set(FOUND_JSON_FILE FALSE) - foreach(config "google-services-desktop.json" "google-services.json") - if (EXISTS ${config}) - add_custom_command( - TARGET ${target_name} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - ${config} $) - set(FOUND_JSON_FILE TRUE) - break() - endif() - endforeach() - if(NOT FOUND_JSON_FILE) - message(WARNING "Failed to find either google-services-desktop.json or google-services.json. See the readme.md for more information.") - endif() -endif() - -# Add the Firebase libraries to the target using the function from the SDK. -add_subdirectory(${FIREBASE_CPP_SDK_DIR} bin/ EXCLUDE_FROM_ALL) -# Note that firebase_app needs to be last in the list. -set(firebase_libs firebase_dynamic_links firebase_app) -target_link_libraries(${target_name} "${firebase_libs}" ${ADDITIONAL_LIBS}) diff --git a/dynamic_links/testapp/LICENSE b/dynamic_links/testapp/LICENSE deleted file mode 100644 index d6456956..00000000 --- a/dynamic_links/testapp/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - 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/dynamic_links/testapp/LaunchScreen.storyboard b/dynamic_links/testapp/LaunchScreen.storyboard deleted file mode 100644 index 673e0f7e..00000000 --- a/dynamic_links/testapp/LaunchScreen.storyboard +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/dynamic_links/testapp/Podfile b/dynamic_links/testapp/Podfile deleted file mode 100644 index e983680a..00000000 --- a/dynamic_links/testapp/Podfile +++ /dev/null @@ -1,7 +0,0 @@ -source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '13.0' -use_frameworks! -# Dynamic Links test application. -target 'testapp' do - pod 'Firebase/DynamicLinks', '10.25.0' -end diff --git a/dynamic_links/testapp/build.gradle b/dynamic_links/testapp/build.gradle deleted file mode 100644 index e7b828bb..00000000 --- a/dynamic_links/testapp/build.gradle +++ /dev/null @@ -1,76 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. -buildscript { - repositories { - mavenLocal() - maven { url 'https://maven.google.com' } - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:4.2.1' - classpath 'com.google.gms:google-services:4.0.1' - } -} - -allprojects { - repositories { - mavenLocal() - maven { url 'https://maven.google.com' } - jcenter() - } -} - -apply plugin: 'com.android.application' - -android { - compileOptions { - sourceCompatibility 1.8 - targetCompatibility 1.8 - } - compileSdkVersion 34 - ndkPath System.getenv('ANDROID_NDK_HOME') - buildToolsVersion '30.0.2' - - sourceSets { - main { - jniLibs.srcDirs = ['libs'] - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['src/android/java'] - res.srcDirs = ['res'] - } - } - - defaultConfig { - applicationId 'com.google.android.dynamiclinks.testapp' - minSdkVersion 23 - targetSdkVersion 28 - versionCode 1 - versionName '1.0' - externalNativeBuild.cmake { - arguments "-DFIREBASE_CPP_SDK_DIR=$gradle.firebase_cpp_sdk_dir" - } - } - externalNativeBuild.cmake { - path 'CMakeLists.txt' - } - buildTypes { - release { - minifyEnabled true - proguardFile getDefaultProguardFile('proguard-android.txt') - proguardFile file('proguard.pro') - } - } - packagingOptions { - pickFirst 'META-INF/**/coroutines.pro' - } - lintOptions { - abortOnError false - checkReleaseBuilds false - } -} - -apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle" -firebaseCpp.dependencies { - dynamicLinks -} - -apply plugin: 'com.google.gms.google-services' diff --git a/dynamic_links/testapp/gradle.properties b/dynamic_links/testapp/gradle.properties deleted file mode 100644 index d7ba8f42..00000000 --- a/dynamic_links/testapp/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -android.useAndroidX = true diff --git a/dynamic_links/testapp/gradle/wrapper/gradle-wrapper.jar b/dynamic_links/testapp/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 8c0fb64a8698b08ecc4158d828ca593c4928e9dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49896 zcmagFb986H(k`5d^NVfUwr$(C?M#x1ZQHiZiEVpg+jrjgoQrerx!>1o_ul)D>ebz~ zs=Mmxr&>W81QY-S1PKWQ%N-;H^tS;2*XwVA`dej1RRn1z<;3VgfE4~kaG`A%QSPsR z#ovnZe+tS9%1MfeDyz`RirvdjPRK~p(#^q2(^5@O&NM19EHdvN-A&StN>0g6QA^VN z0Gx%Gq#PD$QMRFzmK+utjS^Y1F0e8&u&^=w5K<;4Rz|i3A=o|IKLY+g`iK6vfr9?+ z-`>gmU&i?FGSL5&F?TXFu`&Js6h;15QFkXp2M1H9|Eq~bpov-GU(uz%mH0n55wUl- zv#~ccAz`F5wlQ>e_KlJS3@{)B?^v*EQM=IxLa&76^y51a((wq|2-`qON>+4dLc{Oo z51}}o^Zen(oAjxDK7b++9_Yg`67p$bPo3~BCpGM7uAWmvIhWc5Gi+gQZ|Pwa-Gll@<1xmcPy z|NZmu6m)g5Ftu~BG&Xdxclw7Cij{xbBMBn-LMII#Slp`AElb&2^Hw+w>(3crLH!;I zN+Vk$D+wP1#^!MDCiad@vM>H#6+`Ct#~6VHL4lzmy;lSdk>`z6)=>Wh15Q2)dQtGqvn0vJU@+(B5{MUc*qs4!T+V=q=wy)<6$~ z!G>e_4dN@lGeF_$q9`Ju6Ncb*x?O7=l{anm7Eahuj_6lA{*#Gv*TaJclevPVbbVYu z(NY?5q+xxbO6%g1xF0r@Ix8fJ~u)VRUp`S%&rN$&e!Od`~s+64J z5*)*WSi*i{k%JjMSIN#X;jC{HG$-^iX+5f5BGOIHWAl*%15Z#!xntpk($-EGKCzKa zT7{siZ9;4TICsWQ$pu&wKZQTCvpI$Xvzwxoi+XkkpeE&&kFb!B?h2hi%^YlXt|-@5 zHJ~%AN!g_^tmn1?HSm^|gCE#!GRtK2(L{9pL#hp0xh zME}|DB>(5)`iE7CM)&_+S}-Bslc#@B5W4_+k4Cp$l>iVyg$KP>CN?SVGZ(&02>iZK zB<^HP$g$Lq*L$BWd?2(F?-MUbNWTJVQdW7$#8a|k_30#vHAD1Z{c#p;bETk0VnU5A zBgLe2HFJ3032$G<`m*OB!KM$*sdM20jm)It5OSru@tXpK5LT>#8)N!*skNu1$TpIw zufjjdp#lyH5bZ%|Iuo|iu9vG1HrIVWLH>278xo>aVBkPN3V$~!=KnlXQ4eDqS7%E% zQ!z^$Q$b^6Q)g#cLpwur(|<0gWHo6A6jc;n`t(V9T;LzTAU{IAu*uEQ%Ort1k+Kn+f_N`9|bxYC+~Z1 zCC1UCWv*Orx$_@ydv9mIe(liLfOr7mhbV@tKw{6)q^1DH1nmvZ0cj215R<~&I<4S| zgnr;9Cdjqpz#o8i0CQjtl`}{c*P)aSdH|abxGdrR)-3z+02-eX(k*B)Uqv6~^nh** z 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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/dynamic_links/testapp/gradlew.bat b/dynamic_links/testapp/gradlew.bat deleted file mode 100644 index 8a0b282a..00000000 --- a/dynamic_links/testapp/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/dynamic_links/testapp/proguard.pro b/dynamic_links/testapp/proguard.pro deleted file mode 100644 index 54cd248b..00000000 --- a/dynamic_links/testapp/proguard.pro +++ /dev/null @@ -1,2 +0,0 @@ --ignorewarnings --keep,includedescriptorclasses public class com.google.firebase.example.LoggingUtils { *; } diff --git a/dynamic_links/testapp/readme.md b/dynamic_links/testapp/readme.md deleted file mode 100644 index 66190975..00000000 --- a/dynamic_links/testapp/readme.md +++ /dev/null @@ -1,223 +0,0 @@ -Firebase Dynamic Links Quickstart -================================= - -> [!IMPORTANT] -> Firebase Dynamic Links is **deprecated** and should not be used in new projects. The service will shut down on August 25, 2025. -> -> Please see our [Dynamic Links Deprecation FAQ documentation](https://firebase.google.com/support/dynamic-links-faq) for more guidance. - -The Firebase Dynamic Links Quickstart demonstrates logging a range -of different events using the Firebase Dynamic Links C++ SDK. The application -has no user interface and simply logs actions it's performing to the console. - -Introduction ------------- - -- [Read more about Firebase Dynamic Links](https://firebase.google.com/docs/dynamic-links/) - -Building and Running the testapp --------------------------------- - -### iOS - - Link your iOS app to the Firebase libraries. - - Get CocoaPods version 1 or later by running, - ``` - sudo gem install cocoapods --pre - ``` - - From the testapp directory, install the CocoaPods listed in the Podfile - by running, - ``` - pod install - ``` - - Open the generated Xcode workspace (which now has the CocoaPods), - ``` - open testapp.xcworkspace - ``` - - For further details please refer to the - [general instructions for setting up an iOS app with Firebase](https://firebase.google.com/docs/ios/setup). - - Register your iOS app with Firebase. - - Create a new app on the [Firebase console](https://firebase.google.com/console/), and attach - your iOS app to it. - - You can use "com.google.FirebaseCppDynamicLinksTestApp.dev" as the iOS Bundle ID - while you're testing. You can omit App Store ID while testing. - - Add the GoogleService-Info.plist that you downloaded from Firebase - console to the testapp root directory. This file identifies your iOS app - to the Firebase backend. - - Configure the app to handle dynamic links / app invites. - - In your project's Info tab, under the URL Types section, find the URL - Schemes box and add your app's bundle ID (the default scheme used - by dynamic links). - - Copy the dynamic links domain for your project under the Dynamic Links - tab of the [Firebase console](https://firebase.google.com/console/) - Then, in your project's Capabilities tab: - - Enable the Associated Domains capability. - - Add applinks:YOUR_DYNAMIC_LINKS_DOMAIN - For example "applinks:xyz.app.goo.gl". - - Copy the dynamic links domain for your project under the Dynamic Links - tab of the [Firebase console](https://firebase.google.com/console/) - e.g xyz.app.goo.gl and assign to the string kDomainUriPrefix in - src/common_main.cc . - - Optional: If you want to use a custom Dynamic Links domain, follow - [these instructions](https://firebase.google.com/docs/dynamic-links/custom-domains) - to set up the domain in Firebase console and in your project's Info.plist. - Be sure to assign that domain to the string kDomainUriPrefix in - src/common_main.cc. - - Download the Firebase C++ SDK linked from - [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup) - and unzip it to a directory of your choice. - - Add the following frameworks from the Firebase C++ SDK to the project: - - frameworks/ios/universal/firebase.framework - - frameworks/ios/universal/firebase\_dynamic_links.framework - - You will need to either, - 1. Check "Copy items if needed" when adding the frameworks, or - 2. Add the framework path in "Framework Search Paths" - - e.g. If you downloaded the Firebase C++ SDK to - `/Users/me/firebase_cpp_sdk`, - then you would add the path - `/Users/me/firebase_cpp_sdk/frameworks/ios/universal`. - - To add the path, in XCode, select your project in the project - navigator, then select your target in the main window. - Select the "Build Settings" tab, and click "All" to see all - the build settings. Scroll down to "Search Paths", and add - your path to "Framework Search Paths". - - In XCode, build & run the sample on an iOS device or simulator. - - The testapp has no user interface. The output of the app can be viewed - via the console. In Xcode, select - "View --> Debug Area --> Activate Console" from the menu. - - When running the application you should see: - - The dynamic link - if any - recevied by the application on startup. - - A dynamically generated long link. - - A dynamically generated short link. - - Leaving the application and opening a link (e.g via an email) for the app - should reopen the app and display the dynamic link. - -### Android - - Register your Android app with Firebase. - - Create a new app on the [Firebase console](https://firebase.google.com/console/), and attach - your Android app to it. - - You can use "com.google.android.dynamiclinks.testapp" as the Package Name - while you're testing. - - To [generate a SHA1](https://developers.google.com/android/guides/client-auth) - run this command on Mac and Linux, - ``` - keytool -exportcert -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore - ``` - or this command on Windows, - ``` - keytool -exportcert -list -v -alias androiddebugkey -keystore %USERPROFILE%\.android\debug.keystore - ``` - - If keytool reports that you do not have a debug.keystore, you can - [create one with](http://developer.android.com/tools/publishing/app-signing.html#signing-manually), - ``` - keytool -genkey -v -keystore ~/.android/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US" - ``` - - Add the `google-services.json` file that you downloaded from Firebase - console to the root directory of testapp. This file identifies your - Android app to the Firebase backend. - - For further details please refer to the - [general instructions for setting up an Android app with Firebase](https://firebase.google.com/docs/android/setup). - - Copy the dynamic links domain for your project under the Dynamic Links - tab of the [Firebase console](https://firebase.google.com/console/) - e.g xyz.app.goo.gl and assign to the string kDomainUriPrefix in - src/common_main.cc . - - Optional: If you want to use a custom Dynamic Links domain, follow - [these instructions](https://firebase.google.com/docs/dynamic-links/custom-domains) - to set up the domain in Firebase console. Be sure to assign that domain to - the string kDomainUriPrefix in src/common_main.cc. - - Download the Firebase C++ SDK linked from - [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup) - and unzip it to a directory of your choice. - - Configure the location of the Firebase C++ SDK by setting the - firebase\_cpp\_sdk.dir Gradle property to the SDK install directory. - For example, in the project directory: - ``` - echo "systemProp.firebase\_cpp\_sdk.dir=/User/$USER/firebase\_cpp\_sdk" >> gradle.properties - ``` - - Ensure the Android SDK and NDK locations are set in Android Studio. - - From the Android Studio launch menu, go to `File/Project Structure...` or - `Configure/Project Defaults/Project Structure...` - (Shortcut: Control + Alt + Shift + S on windows, Command + ";" on a mac) - and download the SDK and NDK if the locations are not yet set. - - Open *build.gradle* in Android Studio. - - From the Android Studio launch menu, "Open an existing Android Studio - project", and select `build.gradle`. - - Install the SDK Platforms that Android Studio reports missing. - - Build the testapp and run it on an Android device or emulator. - - The testapp has no user interface. The output of the app can be viewed - in the logcat output of Android studio or by running "adb logcat" from - the command line. - - When running the application you should see: - - The dynamic link - if any - recevied by the application on startup. - - A dynamically generated long link. - - A dynamically generated short link. - - Leaving the application and opening a link (e.g via an email) for the app - should reopen the app and display the dynamic link. - -### Desktop - - Register your app with Firebase. - - Create a new app on the [Firebase console](https://firebase.google.com/console/), - following the above instructions for Android or iOS. - - If you have an Android project, add the `google-services.json` file that - you downloaded from the Firebase console to the root directory of the - testapp. - - If you have an iOS project, and don't wish to use an Android project, - you can use the Python script `generate_xml_from_google_services_json.py --plist`, - located in the Firebase C++ SDK, to convert your `GoogleService-Info.plist` - file into a `google-services-desktop.json` file, which can then be - placed in the root directory of the testapp. - - Download the Firebase C++ SDK linked from - [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup) - and unzip it to a directory of your choice. - - Configure the testapp with the location of the Firebase C++ SDK. - This can be done a couple different ways (in highest to lowest priority): - - When invoking cmake, pass in the location with - -DFIREBASE_CPP_SDK_DIR=/path/to/firebase_cpp_sdk. - - Set an environment variable for FIREBASE_CPP_SDK_DIR to the path to use. - - Edit the CMakeLists.txt file, changing the FIREBASE_CPP_SDK_DIR path - to the appropriate location. - - From the testapp directory, generate the build files by running, - ``` - cmake . - ``` - If you want to use XCode, you can use -G"Xcode" to generate the project. - Similarly, to use Visual Studio, -G"Visual Studio 15 2017". For more - information, see - [CMake generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html). - - Build the testapp, by either opening the generated project file based on - the platform, or running, - ``` - cmake --build . - ``` - - Execute the testapp by running, - ``` - ./desktop_testapp - ``` - Note that the executable might be under another directory, such as Debug. - - The testapp has no user interface, but the output can be viewed via the - console. Note that Dynamic Links uses a stubbed implementation on desktop, - so functionality is not expected. - -Support -------- - -[https://firebase.google.com/support/](https://firebase.google.com/support/) - -License -------- - -Copyright 2017 Google, Inc. - -Licensed to the Apache Software Foundation (ASF) under one or more contributor -license agreements. See the NOTICE file distributed with this work for -additional information regarding copyright ownership. The ASF licenses this -file to you 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/dynamic_links/testapp/res/layout/main.xml b/dynamic_links/testapp/res/layout/main.xml deleted file mode 100644 index d3ffb630..00000000 --- a/dynamic_links/testapp/res/layout/main.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/dynamic_links/testapp/res/values/strings.xml b/dynamic_links/testapp/res/values/strings.xml deleted file mode 100644 index 33fe18b2..00000000 --- a/dynamic_links/testapp/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Firebase Dynamic Links Test - diff --git a/dynamic_links/testapp/settings.gradle b/dynamic_links/testapp/settings.gradle deleted file mode 100644 index 2a543b93..00000000 --- a/dynamic_links/testapp/settings.gradle +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2018 Google LLC -// -// 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. - -def firebase_cpp_sdk_dir = System.getProperty('firebase_cpp_sdk.dir') -if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) { - firebase_cpp_sdk_dir = System.getenv('FIREBASE_CPP_SDK_DIR') - if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) { - if ((new File('firebase_cpp_sdk')).exists()) { - firebase_cpp_sdk_dir = 'firebase_cpp_sdk' - } else { - throw new StopActionException( - 'firebase_cpp_sdk.dir property or the FIREBASE_CPP_SDK_DIR ' + - 'environment variable must be set to reference the Firebase C++ ' + - 'SDK install directory. This is used to configure static library ' + - 'and C/C++ include paths for the SDK.') - } - } -} -if (!(new File(firebase_cpp_sdk_dir)).exists()) { - throw new StopActionException( - sprintf('Firebase C++ SDK directory %s does not exist', - firebase_cpp_sdk_dir)) -} -gradle.ext.firebase_cpp_sdk_dir = "$firebase_cpp_sdk_dir" -includeBuild "$firebase_cpp_sdk_dir" \ No newline at end of file diff --git a/dynamic_links/testapp/src/android/android_main.cc b/dynamic_links/testapp/src/android/android_main.cc deleted file mode 100644 index 4e033e1c..00000000 --- a/dynamic_links/testapp/src/android/android_main.cc +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// -// 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 -#include - -#include -#include -#include -#include - -#include "main.h" // NOLINT - -// This implementation is derived from http://github.com/google/fplutil - -extern "C" int common_main(int argc, const char* argv[]); - -static struct android_app* g_app_state = nullptr; -static bool g_destroy_requested = false; -static bool g_started = false; -static bool g_restarted = false; -static pthread_mutex_t g_started_mutex; - -// Handle state changes from via native app glue. -static void OnAppCmd(struct android_app* app, int32_t cmd) { - g_destroy_requested |= cmd == APP_CMD_DESTROY; -} - -// Process events pending on the main thread. -// Returns true when the app receives an event requesting exit. -bool ProcessEvents(int msec) { - struct android_poll_source* source = nullptr; - int events; - int looperId = ALooper_pollAll(msec, nullptr, &events, - reinterpret_cast(&source)); - if (looperId >= 0 && source) { - source->process(g_app_state, source); - } - return g_destroy_requested | g_restarted; -} - -// Get the activity. -jobject GetActivity() { return g_app_state->activity->clazz; } - -// Get the window context. For Android, it's a jobject pointing to the Activity. -jobject GetWindowContext() { return g_app_state->activity->clazz; } - -// Find a class, attempting to load the class if it's not found. -jclass FindClass(JNIEnv* env, jobject activity_object, const char* class_name) { - jclass class_object = env->FindClass(class_name); - if (env->ExceptionCheck()) { - env->ExceptionClear(); - // If the class isn't found it's possible NativeActivity is being used by - // the application which means the class path is set to only load system - // classes. The following falls back to loading the class using the - // Activity before retrieving a reference to it. - jclass activity_class = env->FindClass("android/app/Activity"); - jmethodID activity_get_class_loader = env->GetMethodID( - activity_class, "getClassLoader", "()Ljava/lang/ClassLoader;"); - - jobject class_loader_object = - env->CallObjectMethod(activity_object, activity_get_class_loader); - - jclass class_loader_class = env->FindClass("java/lang/ClassLoader"); - jmethodID class_loader_load_class = - env->GetMethodID(class_loader_class, "loadClass", - "(Ljava/lang/String;)Ljava/lang/Class;"); - jstring class_name_object = env->NewStringUTF(class_name); - - class_object = static_cast(env->CallObjectMethod( - class_loader_object, class_loader_load_class, class_name_object)); - - if (env->ExceptionCheck()) { - env->ExceptionClear(); - class_object = nullptr; - } - env->DeleteLocalRef(class_name_object); - env->DeleteLocalRef(class_loader_object); - } - return class_object; -} - -// Vars that we need available for appending text to the log window: -class LoggingUtilsData { - public: - LoggingUtilsData() - : logging_utils_class_(nullptr), - logging_utils_add_log_text_(0), - logging_utils_init_log_window_(0) {} - - ~LoggingUtilsData() { - JNIEnv* env = GetJniEnv(); - assert(env); - if (logging_utils_class_) { - env->DeleteGlobalRef(logging_utils_class_); - } - } - - void Init() { - JNIEnv* env = GetJniEnv(); - assert(env); - - jclass logging_utils_class = FindClass( - env, GetActivity(), "com/google/firebase/example/LoggingUtils"); - assert(logging_utils_class != 0); - - // Need to store as global references so it don't get moved during garbage - // collection. - logging_utils_class_ = - static_cast(env->NewGlobalRef(logging_utils_class)); - env->DeleteLocalRef(logging_utils_class); - - logging_utils_init_log_window_ = env->GetStaticMethodID( - logging_utils_class_, "initLogWindow", "(Landroid/app/Activity;)V"); - logging_utils_add_log_text_ = env->GetStaticMethodID( - logging_utils_class_, "addLogText", "(Ljava/lang/String;)V"); - - env->CallStaticVoidMethod(logging_utils_class_, - logging_utils_init_log_window_, GetActivity()); - } - - void AppendText(const char* text) { - if (logging_utils_class_ == 0) return; // haven't been initted yet - JNIEnv* env = GetJniEnv(); - assert(env); - jstring text_string = env->NewStringUTF(text); - env->CallStaticVoidMethod(logging_utils_class_, logging_utils_add_log_text_, - text_string); - env->DeleteLocalRef(text_string); - } - - private: - jclass logging_utils_class_; - jmethodID logging_utils_add_log_text_; - jmethodID logging_utils_init_log_window_; -}; - -LoggingUtilsData* g_logging_utils_data; - -// Checks if a JNI exception has happened, and if so, logs it to the console. -void CheckJNIException() { - JNIEnv* env = GetJniEnv(); - if (env->ExceptionCheck()) { - // Get the exception text. - jthrowable exception = env->ExceptionOccurred(); - env->ExceptionClear(); - - // Convert the exception to a string. - jclass object_class = env->FindClass("java/lang/Object"); - jmethodID toString = - env->GetMethodID(object_class, "toString", "()Ljava/lang/String;"); - jstring s = (jstring)env->CallObjectMethod(exception, toString); - const char* exception_text = env->GetStringUTFChars(s, nullptr); - - // Log the exception text. - __android_log_print(ANDROID_LOG_INFO, FIREBASE_TESTAPP_NAME, - "-------------------JNI exception:"); - __android_log_print(ANDROID_LOG_INFO, FIREBASE_TESTAPP_NAME, "%s", - exception_text); - __android_log_print(ANDROID_LOG_INFO, FIREBASE_TESTAPP_NAME, - "-------------------"); - - // Also, assert fail. - assert(false); - - // In the event we didn't assert fail, clean up. - env->ReleaseStringUTFChars(s, exception_text); - env->DeleteLocalRef(s); - env->DeleteLocalRef(exception); - } -} - -// Log a message that can be viewed in "adb logcat". -void LogMessage(const char* format, ...) { - static const int kLineBufferSize = 1000; - char buffer[kLineBufferSize + 2]; - - va_list list; - va_start(list, format); - int string_len = vsnprintf(buffer, kLineBufferSize, format, list); - string_len = string_len < kLineBufferSize ? string_len : kLineBufferSize; - // append a linebreak to the buffer: - buffer[string_len] = '\n'; - buffer[string_len + 1] = '\0'; - - __android_log_vprint(ANDROID_LOG_INFO, FIREBASE_TESTAPP_NAME, format, list); - g_logging_utils_data->AppendText(buffer); - CheckJNIException(); - va_end(list); -} - -// Get the JNI environment. -JNIEnv* GetJniEnv() { - JavaVM* vm = g_app_state->activity->vm; - JNIEnv* env; - jint result = vm->AttachCurrentThread(&env, nullptr); - return result == JNI_OK ? env : nullptr; -} - -// Execute common_main(), flush pending events and finish the activity. -extern "C" void android_main(struct android_app* state) { - // native_app_glue spawns a new thread, calling android_main() when the - // activity onStart() or onRestart() methods are called. This code handles - // the case where we're re-entering this method on a different thread by - // signalling the existing thread to exit, waiting for it to complete before - // reinitializing the application. - if (g_started) { - g_restarted = true; - // Wait for the existing thread to exit. - pthread_mutex_lock(&g_started_mutex); - pthread_mutex_unlock(&g_started_mutex); - } else { - g_started_mutex = PTHREAD_MUTEX_INITIALIZER; - } - pthread_mutex_lock(&g_started_mutex); - g_started = true; - - // Save native app glue state and setup a callback to track the state. - g_destroy_requested = false; - g_app_state = state; - g_app_state->onAppCmd = OnAppCmd; - - // Create the logging display. - g_logging_utils_data = new LoggingUtilsData(); - g_logging_utils_data->Init(); - - // Execute cross platform entry point. - static const char* argv[] = {FIREBASE_TESTAPP_NAME}; - int return_value = common_main(1, argv); - (void)return_value; // Ignore the return value. - ProcessEvents(10); - - // Clean up logging display. - delete g_logging_utils_data; - g_logging_utils_data = nullptr; - - // Finish the activity. - if (!g_restarted) ANativeActivity_finish(state->activity); - - g_app_state->activity->vm->DetachCurrentThread(); - g_started = false; - g_restarted = false; - pthread_mutex_unlock(&g_started_mutex); -} diff --git a/dynamic_links/testapp/src/android/java/com/google/firebase/example/LoggingUtils.java b/dynamic_links/testapp/src/android/java/com/google/firebase/example/LoggingUtils.java deleted file mode 100644 index 11d67c5b..00000000 --- a/dynamic_links/testapp/src/android/java/com/google/firebase/example/LoggingUtils.java +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// -// 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. - -package com.google.firebase.example; - -import android.app.Activity; -import android.os.Handler; -import android.os.Looper; -import android.view.Window; -import android.widget.LinearLayout; -import android.widget.ScrollView; -import android.widget.TextView; - -/** - * A utility class, encapsulating the data and methods required to log arbitrary - * text to the screen, via a non-editable TextView. - */ -public class LoggingUtils { - public static TextView sTextView = null; - - public static void initLogWindow(Activity activity) { - LinearLayout linearLayout = new LinearLayout(activity); - ScrollView scrollView = new ScrollView(activity); - TextView textView = new TextView(activity); - textView.setTag("Logger"); - linearLayout.addView(scrollView); - scrollView.addView(textView); - Window window = activity.getWindow(); - window.takeSurface(null); - window.setContentView(linearLayout); - sTextView = textView; - } - - public static void addLogText(final String text) { - new Handler(Looper.getMainLooper()).post(new Runnable() { - @Override - public void run() { - if (sTextView != null) { - sTextView.append(text); - } - } - }); - } -} diff --git a/dynamic_links/testapp/src/common_main.cc b/dynamic_links/testapp/src/common_main.cc deleted file mode 100644 index 3201f859..00000000 --- a/dynamic_links/testapp/src/common_main.cc +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// -// 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 -#include - -#include "firebase/app.h" -#include "firebase/dynamic_links.h" -#include "firebase/dynamic_links/components.h" -#include "firebase/future.h" -#include "firebase/util.h" -// Thin OS abstraction layer. -#include "main.h" // NOLINT - -// Invalid domain, used to make sure the user sets a valid domain. -#define INVALID_DOMAIN_URI_PREFIX "THIS_IS_AN_INVALID_DOMAIN" - -static const char* kDomainUriPrefixInvalidError = - "kDomainUriPrefix is not valid, link shortening will fail.\n" - "To resolve this:\n" - "* Goto the Firebase console https://firebase.google.com/console/\n" - "* Click on the Dynamic Links tab\n" - "* Copy the URI prefix e.g https://x20yz.app.goo.gl\n" - "* Replace the value of kDomainUriPrefix with the copied URI prefix.\n"; - -// IMPORTANT: You need to set this to a valid URI prefix from the Firebase -// console (see kDomainUriPrefixInvalidError for the details). -static const char* kDomainUriPrefix = INVALID_DOMAIN_URI_PREFIX; - -// Displays a received dynamic link. -class Listener : public firebase::dynamic_links::Listener { - public: - // Called on the client when a dynamic link arrives. - void OnDynamicLinkReceived( - const firebase::dynamic_links::DynamicLink* dynamic_link) override { - LogMessage("Received link: %s", dynamic_link->url.c_str()); - } -}; - -void WaitForCompletion(const firebase::FutureBase& future, const char* name) { - while (future.status() == firebase::kFutureStatusPending) { - ProcessEvents(100); - } - if (future.status() != firebase::kFutureStatusComplete) { - LogMessage("ERROR: %s returned an invalid result.", name); - } else if (future.error() != 0) { - LogMessage("ERROR: %s returned error %d: %s", name, future.error(), - future.error_message()); - } -} - -// Show a generated link. -void ShowGeneratedLink( - const firebase::dynamic_links::GeneratedDynamicLink& generated_link, - const char* operation_description) { - if (!generated_link.warnings.empty()) { - LogMessage("%s generated warnings:", operation_description); - for (auto it = generated_link.warnings.begin(); - it != generated_link.warnings.end(); ++it) { - LogMessage(" %s", it->c_str()); - } - } - LogMessage("url: %s", generated_link.url.c_str()); -} - -// Wait for dynamic link generation to complete, logging the result. -void WaitForAndShowGeneratedLink( - const firebase::Future& - generated_dynamic_link_future, - const char* operation_description) { - LogMessage("%s...", operation_description); - WaitForCompletion(generated_dynamic_link_future, operation_description); - if (generated_dynamic_link_future.error() != 0) { - LogMessage("ERROR: %s failed with error %d: %s", operation_description, - generated_dynamic_link_future.error(), - generated_dynamic_link_future.error_message()); - return; - } - ShowGeneratedLink(*generated_dynamic_link_future.result(), - operation_description); -} - -// Execute all methods of the C++ Dynamic Links API. -extern "C" int common_main(int argc, const char* argv[]) { - namespace dynamic_links = ::firebase::dynamic_links; - ::firebase::App* app; - Listener* link_listener = new Listener; - - LogMessage("Initialize the Firebase Dynamic Links library"); -#if defined(__ANDROID__) - app = ::firebase::App::Create(GetJniEnv(), GetActivity()); -#else - app = ::firebase::App::Create(); -#endif // defined(__ANDROID__) - - LogMessage("Created the Firebase app %x", - static_cast(reinterpret_cast(app))); - - ::firebase::ModuleInitializer initializer; - initializer.Initialize(app, link_listener, - [](::firebase::App* app, void* listener) { - LogMessage("Try to initialize Dynamic Links"); - return ::firebase::dynamic_links::Initialize( - *app, reinterpret_cast(listener)); - }); - while (initializer.InitializeLastResult().status() != - firebase::kFutureStatusComplete) { - if (ProcessEvents(100)) return 1; // exit if requested - } - if (initializer.InitializeLastResult().error() != 0) { - LogMessage("Failed to initialize Firebase Dynamic Links: %s", - initializer.InitializeLastResult().error_message()); - ProcessEvents(2000); - return 1; - } - - LogMessage("Initialized the Firebase Dynamic Links API"); - - firebase::dynamic_links::GoogleAnalyticsParameters analytics_parameters; - analytics_parameters.source = "mysource"; - analytics_parameters.medium = "mymedium"; - analytics_parameters.campaign = "mycampaign"; - analytics_parameters.term = "myterm"; - analytics_parameters.content = "mycontent"; - - firebase::dynamic_links::IOSParameters ios_parameters("com.myapp.bundleid"); - ios_parameters.fallback_url = "https://mysite/fallback"; - ios_parameters.custom_scheme = "mycustomscheme"; - ios_parameters.minimum_version = "1.2.3"; - ios_parameters.ipad_bundle_id = "com.myapp.bundleid.ipad"; - ios_parameters.ipad_fallback_url = "https://mysite/fallbackipad"; - - firebase::dynamic_links::ITunesConnectAnalyticsParameters - app_store_parameters; - app_store_parameters.affiliate_token = "abcdefg"; - app_store_parameters.campaign_token = "hijklmno"; - app_store_parameters.provider_token = "pq-rstuv"; - - firebase::dynamic_links::AndroidParameters android_parameters( - "com.myapp.packageid"); - android_parameters.fallback_url = "https://mysite/fallback"; - android_parameters.minimum_version = 12; - - firebase::dynamic_links::SocialMetaTagParameters social_parameters; - social_parameters.title = "My App!"; - social_parameters.description = "My app is awesome!"; - social_parameters.image_url = "https://mysite.com/someimage.jpg"; - - firebase::dynamic_links::DynamicLinkComponents components( - "https://google.com/abc", kDomainUriPrefix); - components.google_analytics_parameters = &analytics_parameters; - components.ios_parameters = &ios_parameters; - components.itunes_connect_analytics_parameters = &app_store_parameters; - components.android_parameters = &android_parameters; - components.social_meta_tag_parameters = &social_parameters; - - dynamic_links::GeneratedDynamicLink long_link; - { - const char* description = "Generate long link from components"; - long_link = dynamic_links::GetLongLink(components); - LogMessage("%s...", description); - ShowGeneratedLink(long_link, description); - } - - if (strcmp(kDomainUriPrefix, INVALID_DOMAIN_URI_PREFIX) == 0) { - LogMessage(kDomainUriPrefixInvalidError); - } else { - { - firebase::Future link_future = - dynamic_links::GetShortLink(components); - WaitForAndShowGeneratedLink(link_future, - "Generate short link from components"); - } - if (!long_link.url.empty()) { - dynamic_links::DynamicLinkOptions options; - options.path_length = firebase::dynamic_links::kPathLengthShort; - firebase::Future link_future = - dynamic_links::GetShortLink(long_link.url.c_str(), options); - WaitForAndShowGeneratedLink(link_future, "Generate short from long link"); - } - } - - // Wait until the user wants to quit the app. - while (!ProcessEvents(1000)) { - } - - dynamic_links::Terminate(); - delete link_listener; - delete app; - - return 0; -} diff --git a/dynamic_links/testapp/src/desktop/desktop_main.cc b/dynamic_links/testapp/src/desktop/desktop_main.cc deleted file mode 100644 index 0220c688..00000000 --- a/dynamic_links/testapp/src/desktop/desktop_main.cc +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// -// 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 -#include -#include - -#ifdef _WIN32 -#include -#define chdir _chdir -#else -#include -#endif // _WIN32 - -#ifdef _WIN32 -#include -#endif // _WIN32 - -#include -#include - -#include "main.h" // NOLINT - -// The TO_STRING macro is useful for command line defined strings as the quotes -// get stripped. -#define TO_STRING_EXPAND(X) #X -#define TO_STRING(X) TO_STRING_EXPAND(X) - -// Path to the Firebase config file to load. -#ifdef FIREBASE_CONFIG -#define FIREBASE_CONFIG_STRING TO_STRING(FIREBASE_CONFIG) -#else -#define FIREBASE_CONFIG_STRING "" -#endif // FIREBASE_CONFIG - -extern "C" int common_main(int argc, const char* argv[]); - -static bool quit = false; - -#ifdef _WIN32 -static BOOL WINAPI SignalHandler(DWORD event) { - if (!(event == CTRL_C_EVENT || event == CTRL_BREAK_EVENT)) { - return FALSE; - } - quit = true; - return TRUE; -} -#else -static void SignalHandler(int /* ignored */) { quit = true; } -#endif // _WIN32 - -bool ProcessEvents(int msec) { -#ifdef _WIN32 - Sleep(msec); -#else - usleep(msec * 1000); -#endif // _WIN32 - return quit; -} - -std::string PathForResource() { - return std::string(); -} - -void LogMessage(const char* format, ...) { - va_list list; - va_start(list, format); - vprintf(format, list); - va_end(list); - printf("\n"); - fflush(stdout); -} - -WindowContext GetWindowContext() { return nullptr; } - -// Change the current working directory to the directory containing the -// specified file. -void ChangeToFileDirectory(const char* file_path) { - std::string path(file_path); - std::replace(path.begin(), path.end(), '\\', '/'); - auto slash = path.rfind('/'); - if (slash != std::string::npos) { - std::string directory = path.substr(0, slash); - if (!directory.empty()) chdir(directory.c_str()); - } -} - -int main(int argc, const char* argv[]) { - ChangeToFileDirectory( - FIREBASE_CONFIG_STRING[0] != '\0' ? - FIREBASE_CONFIG_STRING : argv[0]); // NOLINT -#ifdef _WIN32 - SetConsoleCtrlHandler((PHANDLER_ROUTINE)SignalHandler, TRUE); -#else - signal(SIGINT, SignalHandler); -#endif // _WIN32 - return common_main(argc, argv); -} - -#if defined(_WIN32) -// Returns the number of microseconds since the epoch. -int64_t WinGetCurrentTimeInMicroseconds() { - FILETIME file_time; - GetSystemTimeAsFileTime(&file_time); - - ULARGE_INTEGER now; - now.LowPart = file_time.dwLowDateTime; - now.HighPart = file_time.dwHighDateTime; - - // Windows file time is expressed in 100s of nanoseconds. - // To convert to microseconds, multiply x10. - return now.QuadPart * 10LL; -} -#endif diff --git a/dynamic_links/testapp/src/ios/ios_main.mm b/dynamic_links/testapp/src/ios/ios_main.mm deleted file mode 100644 index 2adcac9c..00000000 --- a/dynamic_links/testapp/src/ios/ios_main.mm +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// -// 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 - -#include "main.h" - -extern "C" int common_main(int argc, const char* argv[]); - -@interface AppDelegate : UIResponder - -@property(nonatomic, strong) UIWindow *window; - -@end - -@interface FTAViewController : UIViewController - -@end - -static int g_exit_status = 0; -static bool g_shutdown = false; -static NSCondition *g_shutdown_complete; -static NSCondition *g_shutdown_signal; -static UITextView *g_text_view; -static UIView *g_parent_view; - -@implementation FTAViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - g_parent_view = self.view; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - const char *argv[] = {FIREBASE_TESTAPP_NAME}; - [g_shutdown_signal lock]; - g_exit_status = common_main(1, argv); - [g_shutdown_complete signal]; - }); -} - -@end - -bool ProcessEvents(int msec) { - [g_shutdown_signal - waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:static_cast(msec) / 1000.0f]]; - return g_shutdown; -} - -WindowContext GetWindowContext() { - return g_parent_view; -} - -// Log a message that can be viewed in the console. -void LogMessage(const char* format, ...) { - va_list args; - NSString *formatString = @(format); - - va_start(args, format); - NSString *message = [[NSString alloc] initWithFormat:formatString arguments:args]; - va_end(args); - - NSLog(@"%@", message); - message = [message stringByAppendingString:@"\n"]; - - dispatch_async(dispatch_get_main_queue(), ^{ - g_text_view.text = [g_text_view.text stringByAppendingString:message]; - }); -} - -int main(int argc, char* argv[]) { - @autoreleasepool { - UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } - return g_exit_status; -} - -@implementation AppDelegate - -- (BOOL)application:(UIApplication*)application - didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { - g_shutdown_complete = [[NSCondition alloc] init]; - g_shutdown_signal = [[NSCondition alloc] init]; - [g_shutdown_complete lock]; - - self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; - FTAViewController *viewController = [[FTAViewController alloc] init]; - self.window.rootViewController = viewController; - [self.window makeKeyAndVisible]; - - g_text_view = [[UITextView alloc] initWithFrame:viewController.view.bounds]; - - g_text_view.accessibilityIdentifier = @"Logger"; - g_text_view.editable = NO; - g_text_view.scrollEnabled = YES; - g_text_view.userInteractionEnabled = YES; - - [viewController.view addSubview:g_text_view]; - - return YES; -} - -- (void)applicationWillTerminate:(UIApplication *)application { - g_shutdown = true; - [g_shutdown_signal signal]; - [g_shutdown_complete wait]; -} - -@end diff --git a/dynamic_links/testapp/src/main.h b/dynamic_links/testapp/src/main.h deleted file mode 100644 index 2eda2c10..00000000 --- a/dynamic_links/testapp/src/main.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// -// 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_TESTAPP_MAIN_H_ // NOLINT -#define FIREBASE_TESTAPP_MAIN_H_ // NOLINT - -#if defined(__ANDROID__) -#include -#include -#elif defined(__APPLE__) -extern "C" { -#include -} // extern "C" -#endif // __ANDROID__ - -// Defined using -DANDROID_MAIN_APP_NAME=some_app_name when compiling this -// file. -#ifndef FIREBASE_TESTAPP_NAME -#define FIREBASE_TESTAPP_NAME "android_main" -#endif // FIREBASE_TESTAPP_NAME - -// Cross platform logging method. -// Implemented by android/android_main.cc or ios/ios_main.mm. -extern "C" void LogMessage(const char* format, ...); - -// Platform-independent method to flush pending events for the main thread. -// Returns true when an event requesting program-exit is received. -bool ProcessEvents(int msec); - -// WindowContext represents the handle to the parent window. It's type -// (and usage) vary based on the OS. -#if defined(__ANDROID__) -typedef jobject WindowContext; // A jobject to the Java Activity. -#elif defined(__APPLE__) -typedef id WindowContext; // A pointer to an iOS UIView. -#else -typedef void* WindowContext; // A void* for any other environments. -#endif - -#if defined(__ANDROID__) -// Get the JNI environment. -JNIEnv* GetJniEnv(); -// Get the activity. -jobject GetActivity(); -#endif // defined(__ANDROID__) - -// Returns a variable that describes the window context for the app. On Android -// this will be a jobject pointing to the Activity. On iOS, it's an id pointing -// to the root view of the view controller. -WindowContext GetWindowContext(); - -#endif // FIREBASE_TESTAPP_MAIN_H_ // NOLINT diff --git a/dynamic_links/testapp/testapp.xcodeproj/project.pbxproj b/dynamic_links/testapp/testapp.xcodeproj/project.pbxproj deleted file mode 100644 index 5769362c..00000000 --- a/dynamic_links/testapp/testapp.xcodeproj/project.pbxproj +++ /dev/null @@ -1,312 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 520BC0391C869159008CFBC3 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */; }; - 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D51C85F68000C89379 /* Foundation.framework */; }; - 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D71C85F68000C89379 /* CoreGraphics.framework */; }; - 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D91C85F68000C89379 /* UIKit.framework */; }; - 529227211C85FB6A00C89379 /* common_main.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5292271F1C85FB6A00C89379 /* common_main.cc */; }; - 529227241C85FB7600C89379 /* ios_main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 529227221C85FB7600C89379 /* ios_main.mm */; }; - 52B71EBB1C8600B600398745 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 52B71EBA1C8600B600398745 /* Images.xcassets */; }; - D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; - 529226D21C85F68000C89379 /* testapp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testapp.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 529226D51C85F68000C89379 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 529226D71C85F68000C89379 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 529226D91C85F68000C89379 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 529226EE1C85F68000C89379 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; - 5292271F1C85FB6A00C89379 /* common_main.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = common_main.cc; path = src/common_main.cc; sourceTree = ""; }; - 529227201C85FB6A00C89379 /* main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = main.h; path = src/main.h; sourceTree = ""; }; - 529227221C85FB7600C89379 /* ios_main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_main.mm; path = src/ios/ios_main.mm; sourceTree = ""; }; - 52B71EBA1C8600B600398745 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = testapp/Images.xcassets; sourceTree = ""; }; - 52FD1FF81C85FFA000BC68E3 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = testapp/Info.plist; sourceTree = ""; }; - D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 529226CF1C85F68000C89379 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */, - 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */, - 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 529226C91C85F68000C89379 = { - isa = PBXGroup; - children = ( - D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */, - 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */, - 52B71EBA1C8600B600398745 /* Images.xcassets */, - 52FD1FF81C85FFA000BC68E3 /* Info.plist */, - 5292271D1C85FB5500C89379 /* src */, - 529226D41C85F68000C89379 /* Frameworks */, - 529226D31C85F68000C89379 /* Products */, - ); - sourceTree = ""; - }; - 529226D31C85F68000C89379 /* Products */ = { - isa = PBXGroup; - children = ( - 529226D21C85F68000C89379 /* testapp.app */, - ); - name = Products; - sourceTree = ""; - }; - 529226D41C85F68000C89379 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 529226D51C85F68000C89379 /* Foundation.framework */, - 529226D71C85F68000C89379 /* CoreGraphics.framework */, - 529226D91C85F68000C89379 /* UIKit.framework */, - 529226EE1C85F68000C89379 /* XCTest.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 5292271D1C85FB5500C89379 /* src */ = { - isa = PBXGroup; - children = ( - 5292271F1C85FB6A00C89379 /* common_main.cc */, - 529227201C85FB6A00C89379 /* main.h */, - 5292271E1C85FB5B00C89379 /* ios */, - ); - name = src; - sourceTree = ""; - }; - 5292271E1C85FB5B00C89379 /* ios */ = { - isa = PBXGroup; - children = ( - 529227221C85FB7600C89379 /* ios_main.mm */, - ); - name = ios; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 529226D11C85F68000C89379 /* testapp */ = { - isa = PBXNativeTarget; - buildConfigurationList = 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "testapp" */; - buildPhases = ( - 529226CE1C85F68000C89379 /* Sources */, - 529226CF1C85F68000C89379 /* Frameworks */, - 529226D01C85F68000C89379 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = testapp; - productName = testapp; - productReference = 529226D21C85F68000C89379 /* testapp.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 529226CA1C85F68000C89379 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0640; - ORGANIZATIONNAME = Google; - TargetAttributes = { - 529226D11C85F68000C89379 = { - CreatedOnToolsVersion = 6.4; - }; - }; - }; - buildConfigurationList = 529226CD1C85F68000C89379 /* Build configuration list for PBXProject "testapp" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 529226C91C85F68000C89379; - productRefGroup = 529226D31C85F68000C89379 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 529226D11C85F68000C89379 /* testapp */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 529226D01C85F68000C89379 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */, - 52B71EBB1C8600B600398745 /* Images.xcassets in Resources */, - 520BC0391C869159008CFBC3 /* GoogleService-Info.plist in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 529226CE1C85F68000C89379 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 529227241C85FB7600C89379 /* ios_main.mm in Sources */, - 529227211C85FB6A00C89379 /* common_main.cc in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 529226F71C85F68000C89379 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 529226F81C85F68000C89379 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 529226FA1C85F68000C89379 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "\"$(SRCROOT)/src\"", - ); - INFOPLIST_FILE = testapp/Info.plist; - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = app; - }; - name = Debug; - }; - 529226FB1C85F68000C89379 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "\"$(SRCROOT)/src\"", - ); - INFOPLIST_FILE = testapp/Info.plist; - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = app; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 529226CD1C85F68000C89379 /* Build configuration list for PBXProject "testapp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 529226F71C85F68000C89379 /* Debug */, - 529226F81C85F68000C89379 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "testapp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 529226FA1C85F68000C89379 /* Debug */, - 529226FB1C85F68000C89379 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 529226CA1C85F68000C89379 /* Project object */; -} diff --git a/dynamic_links/testapp/testapp/Images.xcassets/AppIcon.appiconset/Contents.json b/dynamic_links/testapp/testapp/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index b7f3352e..00000000 --- a/dynamic_links/testapp/testapp/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/dynamic_links/testapp/testapp/Images.xcassets/LaunchImage.launchimage/Contents.json b/dynamic_links/testapp/testapp/Images.xcassets/LaunchImage.launchimage/Contents.json deleted file mode 100644 index 6f870a46..00000000 --- a/dynamic_links/testapp/testapp/Images.xcassets/LaunchImage.launchimage/Contents.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "images" : [ - { - "orientation" : "portrait", - "idiom" : "iphone", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "iphone", - "subtype" : "retina4", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "1x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "1x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/dynamic_links/testapp/testapp/Info.plist b/dynamic_links/testapp/testapp/Info.plist deleted file mode 100644 index c9ef93fc..00000000 --- a/dynamic_links/testapp/testapp/Info.plist +++ /dev/null @@ -1,55 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - com.google.FirebaseCppDynamicLinksTestApp.dev - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleURLSchemes - - com.google.FirebaseCppDynamicLinksTestApp.dev - - CFBundleURLTypes - - - CFBundleTypeRole - Editor - CFBundleURLName - com.google.FirebaseCppDynamicLinksTestApp.dev - CFBundleURLSchemes - - com.google.FirebaseCppDynamicLinksTestApp.dev - - - - CFBundleTypeRole - Editor - CFBundleURLName - google - CFBundleURLSchemes - - YOUR_REVERSED_CLIENT_ID - - - - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - NSContactsUsageDescription - Invite others to use the app. - - diff --git a/functions/testapp/functions/package-lock.json b/functions/testapp/functions/package-lock.json deleted file mode 100644 index 988b0b35..00000000 --- a/functions/testapp/functions/package-lock.json +++ /dev/null @@ -1,8246 +0,0 @@ -{ - "name": "functions", - "requires": true, - "lockfileVersion": 1, - "dependencies": { - "@firebase/app": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.1.10.tgz", - "integrity": "sha512-2GTXt3b2QZXkmx6/5nNJq+pEN/VTjAG55MFJS1WMoLVZkwKuNpWNk65QVyPaoL88x1iHtuLqAMFgJUOnhOg+Pw==", - "requires": { - "@firebase/app-types": "0.1.2", - "@firebase/util": "0.1.10", - "tslib": "1.9.0" - } - }, - "@firebase/app-types": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.1.2.tgz", - "integrity": "sha512-bCIZGeMtP0ibrXNNaU214/1tRNw0jHnir/cfiAao1gjUyIS7RzOTQoH+zbwPJNEwUqJ0T3ykw/Tv4/khGqbVBg==" - }, - "@firebase/database": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.2.1.tgz", - "integrity": "sha512-IxONy7MM+Vmnx7bupBujmUyaTqE0n9Jt5xW/2gyLRc9i2wOxNR0XDlJ3Oc12+bksW/zMXHJU1hNO1jxRmIKmsw==", - "requires": { - "@firebase/database-types": "0.2.0", - "@firebase/logger": "0.1.0", - "@firebase/util": "0.1.10", - "faye-websocket": "0.11.1", - "tslib": "1.9.0" - }, - "dependencies": { - "faye-websocket": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", - "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", - "requires": { - "websocket-driver": "0.7.0" - } - } - } - }, - "@firebase/database-types": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.2.0.tgz", - "integrity": "sha512-QFrxlLABVbZAVJqw1XNkSYZK22qPjpE3U5eM1SO7Htx69TrIgX7tb1/+BJnFkb3AKUD33tAr22Z4XVth5Ys46A==" - }, - "@firebase/logger": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.1.0.tgz", - "integrity": "sha512-/abxM9/l0V9WzNXvSonI2imVqORVhyCVS8yJ1O2rsRmNzw3FIPPIt0BuTvmCBH1oh1uDtZIn2Aar1p7zF69KWg==" - }, - "@firebase/util": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.1.10.tgz", - "integrity": "sha512-XEogRfUQBZ4T37TMq/3ZbuiTdRAKX8hF3TgJglUZNCJf/6QnQ+jlupCuMAXBqCGfw2Mw0m2matoCUBWpsyevOA==", - "requires": { - "tslib": "1.9.0" - } - }, - "@google-cloud/common": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-0.16.2.tgz", - "integrity": "sha512-GrkaFoj0/oO36pNs4yLmaYhTujuA3i21FdQik99Fd/APix1uhf01VlpJY4lAteTDFLRNkRx6ydEh7OVvmeUHng==", - "requires": { - "array-uniq": "1.0.3", - "arrify": "1.0.1", - "concat-stream": "1.6.2", - "create-error-class": "3.0.2", - "duplexify": "3.5.4", - "ent": "2.2.0", - "extend": "3.0.1", - "google-auto-auth": "0.9.7", - "is": "3.2.1", - "log-driver": "1.2.7", - "methmeth": "1.1.0", - "modelo": "4.2.3", - "request": "2.85.0", - "retry-request": "3.3.1", - "split-array-stream": "1.0.3", - "stream-events": "1.0.2", - "string-format-obj": "1.1.1", - "through2": "2.0.3" - } - }, - "@google-cloud/common-grpc": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@google-cloud/common-grpc/-/common-grpc-0.6.0.tgz", - "integrity": "sha512-b5i2auMeP+kPPPpWtZVgjbbbIB+3uDGw+Vww1QjG0SEQlahcGrwkCEaNLQit1R77m8ibxs+sTVa+AH/FNILAdQ==", - "requires": { - "@google-cloud/common": "0.16.2", - "dot-prop": "4.2.0", - "duplexify": "3.5.4", - "extend": "3.0.1", - "grpc": "1.9.1", - "is": "3.2.1", - "modelo": "4.2.3", - "retry-request": "3.3.1", - "through2": "2.0.3" - } - }, - "@google-cloud/firestore": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-0.13.0.tgz", - "integrity": "sha512-9Aak9O/NBwdhAJWn2ooaHJT0uyU6IN6oHegW4GcAzLwJKwx8nw+c/GwFufSS6PRMLTiXdpV0I/rvdz4nSgO1HA==", - "requires": { - "@google-cloud/common": "0.16.2", - "@google-cloud/common-grpc": "0.6.0", - "bun": "0.0.12", - "deep-equal": "1.0.1", - "extend": "3.0.1", - "functional-red-black-tree": "1.0.1", - "google-gax": "0.15.0", - "is": "3.2.1", - "safe-buffer": "5.1.1", - "through2": "2.0.3" - } - }, - "@google-cloud/storage": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-1.6.0.tgz", - "integrity": "sha512-yQ63bJYoiwY220gn/KdTLPoHppAPwFHfG7VFLPwJ+1R5U1eqUN5XV2a7uPj1szGF8/gxlKm2UbE8DgoJJ76DFw==", - "requires": { - "@google-cloud/common": "0.16.2", - "arrify": "1.0.1", - "async": "2.6.0", - "compressible": "2.0.13", - "concat-stream": "1.6.2", - "create-error-class": "3.0.2", - "duplexify": "3.5.4", - "extend": "3.0.1", - "gcs-resumable-upload": "0.9.0", - "hash-stream-validation": "0.2.1", - "is": "3.2.1", - "mime": "2.2.0", - "mime-types": "2.1.18", - "once": "1.4.0", - "pumpify": "1.4.0", - "request": "2.85.0", - "safe-buffer": "5.1.1", - "snakeize": "0.1.0", - "stream-events": "1.0.2", - "string-format-obj": "1.1.1", - "through2": "2.0.3" - } - }, - "@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", - "requires": { - "call-me-maybe": "1.0.1", - "glob-to-regexp": "0.3.0" - } - }, - "@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" - }, - "@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" - }, - "@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", - "requires": { - "@protobufjs/aspromise": "1.1.2", - "@protobufjs/inquire": "1.1.0" - } - }, - "@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" - }, - "@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" - }, - "@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" - }, - "@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" - }, - "@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" - }, - "@types/body-parser": { - "version": "1.16.8", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.16.8.tgz", - "integrity": "sha512-BdN2PXxOFnTXFcyONPW6t0fHjz2fvRZHVMFpaS0wYr+Y8fWEaNOs4V8LEu/fpzQlMx+ahdndgTaGTwPC+J/EeA==", - "requires": { - "@types/express": "4.11.1", - "@types/node": "8.9.5" - } - }, - "@types/cors": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.3.tgz", - "integrity": "sha512-wiZ7yYSIKZ005QJeyoUk5OHHEamNHTxaYwaFQWfTPohBjyhgIDHTgV8oGn+zBYTWQCb9WQYg54PhtntFTD7GVg==", - "requires": { - "@types/express": "4.11.1" - } - }, - "@types/events": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", - "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==" - }, - "@types/express": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.11.1.tgz", - "integrity": "sha512-ttWle8cnPA5rAelauSWeWJimtY2RsUf2aspYZs7xPHiWgOlPn6nnUfBMtrkcnjFJuIHJF4gNOdVvpLK2Zmvh6g==", - "requires": { - "@types/body-parser": "1.16.8", - "@types/express-serve-static-core": "4.11.1", - "@types/serve-static": "1.13.1" - } - }, - "@types/express-serve-static-core": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.11.1.tgz", - "integrity": "sha512-EehCl3tpuqiM8RUb+0255M8PhhSwTtLfmO7zBBdv0ay/VTd/zmrqDfQdZFsa5z/PVMbH2yCMZPXsnrImpATyIw==", - "requires": { - "@types/events": "1.2.0", - "@types/node": "8.9.5" - } - }, - "@types/google-cloud__storage": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@types/google-cloud__storage/-/google-cloud__storage-1.1.7.tgz", - "integrity": "sha512-010Llp+5ze+XWWmZuLDxs0pZgFjOgtJQVt9icJ0Ed67ZFLq7PnXkYx8x/k9nwDojR5/X4XoLPNqB1F627TScdQ==", - "requires": { - "@types/node": "8.9.5" - } - }, - "@types/jsonwebtoken": { - "version": "7.2.6", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-7.2.6.tgz", - "integrity": "sha512-SuCA16HtLqPy0yerKEvMdaEAeLRgm6zPUJE1sF7bwGq0hAO4xW9UJZxTcDBaBwr5rcz1HST5QC1+1qXQ1+R9yw==", - "requires": { - "@types/node": "8.9.5" - } - }, - "@types/lodash": { - "version": "4.14.105", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.105.tgz", - "integrity": "sha512-LB5PKR4QNoDrgcl4H8JdhBMp9wHWp0OATkU9EHzuXKiutRwbvsyYmqPUaMSWmdCycJoKHtdAWh47/zSe/GZ1yA==" - }, - "@types/long": { - "version": "3.0.32", - "resolved": "https://registry.npmjs.org/@types/long/-/long-3.0.32.tgz", - "integrity": "sha512-ZXyOOm83p7X8p3s0IYM3VeueNmHpkk/yMlP8CLeOnEcu6hIwPH7YjZBvhQkR0ZFS2DqZAxKtJ/M5fcuv3OU5BA==" - }, - "@types/mime": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.0.tgz", - "integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==" - }, - "@types/node": { - "version": "8.9.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.9.5.tgz", - "integrity": "sha512-jRHfWsvyMtXdbhnz5CVHxaBgnV6duZnPlQuRSo/dm/GnmikNcmZhxIES4E9OZjUmQ8C+HCl4KJux+cXN/ErGDQ==" - }, - "@types/serve-static": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.1.tgz", - "integrity": "sha512-jDMH+3BQPtvqZVIcsH700Dfi8Q3MIcEx16g/VdxjoqiGR/NntekB10xdBpirMKnPe9z2C5cBmL0vte0YttOr3Q==", - "requires": { - "@types/express-serve-static-core": "4.11.1", - "@types/mime": "2.0.0" - } - }, - "@types/sha1": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/sha1/-/sha1-1.1.1.tgz", - "integrity": "sha512-Yrz4TPsm/xaw7c39aTISskNirnRJj2W9OVeHv8ooOR9SG8NHEfh4lwvGeN9euzxDyPfBdFkvL/VHIY3kM45OpQ==", - "requires": { - "@types/node": "8.9.5" - } - }, - "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "requires": { - "mime-types": "2.1.18", - "negotiator": "0.6.1" - } - }, - "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" - }, - "acorn-es7-plugin": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz", - "integrity": "sha1-8u4fMiipDurRJF+asZIusucdM2s=" - }, - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" - }, - "array-filter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", - "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=" - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "requires": { - "array-uniq": "1.0.3" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" - }, - "ascli": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz", - "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", - "requires": { - "colour": "0.7.1", - "optjs": "3.2.2" - } - }, - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" - }, - "async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", - "requires": { - "lodash": "4.17.5" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "atob": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", - "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" - }, - "axios": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", - "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", - "requires": { - "follow-redirects": "1.4.1", - "is-buffer": "1.1.6" - } - }, - "bad-words": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/bad-words/-/bad-words-1.6.1.tgz", - "integrity": "sha1-BkgwIZUanYD7X8qi8Nmh51p0W1A=", - "requires": { - "badwords-list": "1.0.0" - } - }, - "badwords-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/badwords-list/-/badwords-list-1.0.0.tgz", - "integrity": "sha1-XphW2/E0gqKVw7CzBK+51M/FxXk=" - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "requires": { - "cache-base": "1.0.1", - "class-utils": "0.3.6", - "component-emitter": "1.2.1", - "define-property": "1.0.0", - "isobject": "3.0.1", - "mixin-deep": "1.3.1", - "pascalcase": "0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "1.0.2" - } - } - } - }, - "base64url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", - "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs=" - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "body-parser": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", - "requires": { - "bytes": "3.0.0", - "content-type": "1.0.4", - "debug": "2.6.9", - "depd": "1.1.2", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "on-finished": "2.3.0", - "qs": "6.5.1", - "raw-body": "2.3.2", - "type-is": "1.6.16" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "boom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "requires": { - "hoek": "4.2.1" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.1.tgz", - "integrity": "sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==", - "requires": { - "arr-flatten": "1.1.0", - "array-unique": "0.3.2", - "define-property": "1.0.0", - "extend-shallow": "2.0.1", - "fill-range": "4.0.0", - "isobject": "3.0.1", - "kind-of": "6.0.2", - "repeat-element": "1.1.2", - "snapdragon": "0.8.2", - "snapdragon-node": "2.1.1", - "split-string": "3.1.0", - "to-regex": "3.0.2" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "1.0.2" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=" - }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" - }, - "buffer-from": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", - "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==" - }, - "bun": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/bun/-/bun-0.0.12.tgz", - "integrity": "sha512-Toms18J9DqnT+IfWkwxVTB2EaBprHvjlMWrTIsfX4xbu3ZBqVBwrERU0em1IgtRe04wT+wJxMlKHZok24hrcSQ==", - "requires": { - "readable-stream": "1.0.34" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } - } - }, - "bytebuffer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", - "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=", - "requires": { - "long": "3.2.0" - } - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "requires": { - "collection-visit": "1.0.0", - "component-emitter": "1.2.1", - "get-value": "2.0.6", - "has-value": "1.0.0", - "isobject": "3.0.1", - "set-value": "2.0.0", - "to-object-path": "0.3.0", - "union-value": "1.0.0", - "unset-value": "1.0.0" - } - }, - "call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" - }, - "call-signature": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/call-signature/-/call-signature-0.0.2.tgz", - "integrity": "sha1-qEq8glpV70yysCi9dOIFpluaSZY=" - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" - }, - "capitalize-sentence": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/capitalize-sentence/-/capitalize-sentence-0.1.5.tgz", - "integrity": "sha1-e/LtUdyKoqY8lPgkA55KphS3HeY=" - }, - "capture-stack-trace": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", - "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "requires": { - "arr-union": "3.1.0", - "define-property": "0.2.5", - "isobject": "3.0.1", - "static-extend": "0.1.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "requires": { - "map-visit": "1.0.0", - "object-visit": "1.0.1" - } - }, - "colour": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz", - "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=" - }, - "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "requires": { - "delayed-stream": "1.0.0" - } - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" - }, - "compressible": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.13.tgz", - "integrity": "sha1-DRAgq5JLL9tNYnmHXH1tq6a6p6k=", - "requires": { - "mime-db": "1.33.0" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "requires": { - "buffer-from": "1.0.0", - "inherits": "2.0.3", - "readable-stream": "2.3.5", - "typedarray": "0.0.6" - } - }, - "configstore": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.1.tgz", - "integrity": "sha512-5oNkD/L++l0O6xGXxb1EWS7SivtjfGQlRyxJsYgE0Z495/L81e2h4/d3r969hoPXuFItzNOKMtsXgYG4c7dYvw==", - "requires": { - "dot-prop": "4.2.0", - "graceful-fs": "4.1.11", - "make-dir": "1.2.0", - "unique-string": "1.0.0", - "write-file-atomic": "2.3.0", - "xdg-basedir": "3.0.0" - } - }, - "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" - }, - "core-js": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", - "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cors": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", - "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", - "requires": { - "object-assign": "4.1.1", - "vary": "1.1.2" - } - }, - "create-error-class": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", - "requires": { - "capture-stack-trace": "1.0.0" - } - }, - "crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" - }, - "cryptiles": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", - "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "requires": { - "boom": "5.2.0" - }, - "dependencies": { - "boom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "requires": { - "hoek": "4.2.1" - } - } - } - }, - "crypto-random-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "1.0.0" - } - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, - "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" - }, - "define-properties": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", - "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", - "requires": { - "foreach": "2.0.5", - "object-keys": "1.0.11" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "requires": { - "is-descriptor": "1.0.2", - "isobject": "3.0.1" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "diff-match-patch": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.0.tgz", - "integrity": "sha1-HMPIOkkNZ/ldkeOfatHy4Ia2MEg=" - }, - "dir-glob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", - "requires": { - "arrify": "1.0.1", - "path-type": "3.0.0" - } - }, - "dot-prop": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", - "requires": { - "is-obj": "1.0.1" - } - }, - "duplexify": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.4.tgz", - "integrity": "sha512-JzYSLYMhoVVBe8+mbHQ4KgpvHpm0DZpJuL8PY93Vyv1fW7jYJ90LoXa1di/CVbJM+TgMs91rbDapE/RNIfnJsA==", - "requires": { - "end-of-stream": "1.4.1", - "inherits": "2.0.3", - "readable-stream": "2.3.5", - "stream-shift": "1.0.0" - } - }, - "eastasianwidth": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.1.1.tgz", - "integrity": "sha1-RNZW3p2kFWlEZzNTZfsxR7hXK3w=" - }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "ecdsa-sig-formatter": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz", - "integrity": "sha1-S8kmJ07Dtau1AW5+HWCSGsJisqE=", - "requires": { - "base64url": "2.0.0", - "safe-buffer": "5.1.1" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "empower": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/empower/-/empower-1.2.3.tgz", - "integrity": "sha1-bw2nNEf07dg4/sXGAxOoi6XLhSs=", - "requires": { - "core-js": "2.5.3", - "empower-core": "0.6.2" - } - }, - "empower-core": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/empower-core/-/empower-core-0.6.2.tgz", - "integrity": "sha1-Wt71ZgiOMfuoC6CjbfR9cJQWkUQ=", - "requires": { - "call-signature": "0.0.2", - "core-js": "2.5.3" - } - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "requires": { - "once": "1.4.0" - } - }, - "ent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "espurify": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/espurify/-/espurify-1.7.0.tgz", - "integrity": "sha1-HFz2y8zDLm9jk4C9T5kfq5up0iY=", - "requires": { - "core-js": "2.5.3" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "requires": { - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "posix-character-classes": "0.1.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "0.1.6" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "0.1.1" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "express": { - "version": "4.16.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", - "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", - "requires": { - "accepts": "1.3.5", - "array-flatten": "1.1.1", - "body-parser": "1.18.2", - "content-disposition": "0.5.2", - "content-type": "1.0.4", - "cookie": "0.3.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "1.1.2", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", - "finalhandler": "1.1.1", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "1.1.2", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.3", - "qs": "6.5.1", - "range-parser": "1.2.0", - "safe-buffer": "5.1.1", - "send": "0.16.2", - "serve-static": "1.13.2", - "setprototypeof": "1.1.0", - "statuses": "1.4.0", - "type-is": "1.6.16", - "utils-merge": "1.0.1", - "vary": "1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "requires": { - "array-unique": "0.3.2", - "define-property": "1.0.0", - "expand-brackets": "2.1.4", - "extend-shallow": "2.0.1", - "fragment-cache": "0.2.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "1.0.2" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" - }, - "fast-glob": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.0.tgz", - "integrity": "sha512-4F75PTznkNtSKs2pbhtBwRkw8sRwa7LfXx5XaQJOe4IQ6yTjceLDTwM5gj1s80R2t/5WeDC1gVfm3jLE+l39Tw==", - "requires": { - "@mrmlnc/readdir-enhanced": "2.2.1", - "glob-parent": "3.1.0", - "is-glob": "4.0.0", - "merge2": "1.2.1", - "micromatch": "3.1.9" - } - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" - }, - "faye-websocket": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.9.3.tgz", - "integrity": "sha1-SCpQWw3wrmJrlphm0710DNuWLoM=", - "requires": { - "websocket-driver": "0.7.0" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "2.0.1", - "is-number": "3.0.0", - "repeat-string": "1.6.1", - "to-regex-range": "2.1.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "finalhandler": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", - "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", - "requires": { - "debug": "2.6.9", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.4.0", - "unpipe": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "firebase-admin": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-5.10.0.tgz", - "integrity": "sha1-dtj85rsdvSwF7HbL+1ncGtOXflY=", - "requires": { - "@firebase/app": "0.1.10", - "@firebase/database": "0.2.1", - "@google-cloud/firestore": "0.13.0", - "@google-cloud/storage": "1.6.0", - "@types/google-cloud__storage": "1.1.7", - "@types/node": "8.9.5", - "faye-websocket": "0.9.3", - "jsonwebtoken": "8.1.0", - "node-forge": "0.7.1" - } - }, - "firebase-functions": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-0.9.0.tgz", - "integrity": "sha1-X6FXJb25z8UbpxbppXpVR1PQwHM=", - "requires": { - "@types/cors": "2.8.3", - "@types/express": "4.11.1", - "@types/jsonwebtoken": "7.2.6", - "@types/lodash": "4.14.105", - "@types/sha1": "1.1.1", - "cors": "2.8.4", - "express": "4.16.3", - "jsonwebtoken": "7.4.3", - "lodash": "4.17.5", - "sha1": "1.1.1" - }, - "dependencies": { - "jsonwebtoken": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz", - "integrity": "sha1-d/UCHeBYtgWheD+hKD6ZgS5kVjg=", - "requires": { - "joi": "6.10.1", - "jws": "3.1.4", - "lodash.once": "4.1.1", - "ms": "2.0.0", - "xtend": "4.0.1" - } - } - } - }, - "follow-redirects": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz", - "integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==", - "requires": { - "debug": "3.1.0" - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.6", - "mime-types": "2.1.18" - } - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "requires": { - "map-cache": "0.2.2" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" - }, - "gcp-metadata": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-0.6.3.tgz", - "integrity": "sha512-MSmczZctbz91AxCvqp9GHBoZOSbJKAICV7Ow/AIWSJZRrRchUd5NL1b2P4OfP+4m490BEUPhhARfpHdqCxuCvg==", - "requires": { - "axios": "0.18.0", - "extend": "3.0.1", - "retry-axios": "0.3.2" - } - }, - "gcs-resumable-upload": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-0.9.0.tgz", - "integrity": "sha512-+Zrmr0JKO2y/2mg953TW6JLu+NAMHqQsKzqCm7CIT24gMQakolPJCMzDleVpVjXAqB7ZCD276tcUq2ebOfqTug==", - "requires": { - "buffer-equal": "1.0.0", - "configstore": "3.1.1", - "google-auto-auth": "0.9.7", - "pumpify": "1.4.0", - "request": "2.85.0", - "stream-events": "1.0.2", - "through2": "2.0.3" - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "1.0.0" - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "2.1.1" - } - } - } - }, - "glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=" - }, - "globby": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.1.tgz", - "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", - "requires": { - "array-union": "1.0.2", - "dir-glob": "2.0.0", - "fast-glob": "2.2.0", - "glob": "7.1.2", - "ignore": "3.3.7", - "pify": "3.0.0", - "slash": "1.0.0" - } - }, - "google-auth-library": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-1.3.2.tgz", - "integrity": "sha512-aRz0om4Bs85uyR2Ousk3Gb8Nffx2Sr2RoKts1smg1MhRwrehE1aD1HC4RmprNt1HVJ88IDnQ8biJQ/aXjiIxlQ==", - "requires": { - "axios": "0.18.0", - "gcp-metadata": "0.6.3", - "gtoken": "2.2.0", - "jws": "3.1.4", - "lodash.isstring": "4.0.1", - "lru-cache": "4.1.2", - "retry-axios": "0.3.2" - } - }, - "google-auto-auth": { - "version": "0.9.7", - "resolved": "https://registry.npmjs.org/google-auto-auth/-/google-auto-auth-0.9.7.tgz", - "integrity": "sha512-Nro7aIFrL2NP0G7PoGrJqXGMZj8AjdBOcbZXRRm/8T3w08NUHIiNN3dxpuUYzDsZizslH+c8e+7HXL8vh3JXTQ==", - "requires": { - "async": "2.6.0", - "gcp-metadata": "0.6.3", - "google-auth-library": "1.3.2", - "request": "2.85.0" - } - }, - "google-gax": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-0.15.0.tgz", - "integrity": "sha512-a+WBi3oiV3jQ0eLCIM0GAFe8vYQ10yYuXRnjhEEXFKSNd8nW6XSQ7YWqMLIod2Xnyu6JiSSymMBwCr5YSwQyRQ==", - "requires": { - "extend": "3.0.1", - "globby": "8.0.1", - "google-auto-auth": "0.9.7", - "google-proto-files": "0.15.1", - "grpc": "1.9.1", - "is-stream-ended": "0.1.3", - "lodash": "4.17.5", - "protobufjs": "6.8.6", - "readable-stream": "2.3.5", - "through2": "2.0.3" - }, - "dependencies": { - "long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "protobufjs": { - "version": "6.8.6", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.6.tgz", - "integrity": "sha512-eH2OTP9s55vojr3b7NBaF9i4WhWPkv/nq55nznWNp/FomKrLViprUcqnBjHph2tFQ+7KciGPTPsVWGz0SOhL0Q==", - "requires": { - "@protobufjs/aspromise": "1.1.2", - "@protobufjs/base64": "1.1.2", - "@protobufjs/codegen": "2.0.4", - "@protobufjs/eventemitter": "1.1.0", - "@protobufjs/fetch": "1.1.0", - "@protobufjs/float": "1.0.2", - "@protobufjs/inquire": "1.1.0", - "@protobufjs/path": "1.1.2", - "@protobufjs/pool": "1.1.0", - "@protobufjs/utf8": "1.1.0", - "@types/long": "3.0.32", - "@types/node": "8.9.5", - "long": "4.0.0" - } - } - } - }, - "google-p12-pem": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-1.0.2.tgz", - "integrity": "sha512-+EuKr4CLlGsnXx4XIJIVkcKYrsa2xkAmCvxRhX2HsazJzUBAJ35wARGeApHUn4nNfPD03Vl057FskNr20VaCyg==", - "requires": { - "node-forge": "0.7.4", - "pify": "3.0.0" - }, - "dependencies": { - "node-forge": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.4.tgz", - "integrity": "sha512-8Df0906+tq/omxuCZD6PqhPaQDYuyJ1d+VITgxoIA8zvQd1ru+nMJcDChHH324MWitIgbVkAkQoGEEVJNpn/PA==" - } - } - }, - "google-proto-files": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/google-proto-files/-/google-proto-files-0.15.1.tgz", - "integrity": "sha512-ebtmWgi/ooR5Nl63qRVZZ6VLM6JOb5zTNxTT/ZAU8yfMOdcauoOZNNMOVg0pCmTjqWXeuuVbgPP0CwO5UHHzBQ==", - "requires": { - "globby": "7.1.1", - "power-assert": "1.4.4", - "protobufjs": "6.8.6" - }, - "dependencies": { - "globby": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", - "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", - "requires": { - "array-union": "1.0.2", - "dir-glob": "2.0.0", - "glob": "7.1.2", - "ignore": "3.3.7", - "pify": "3.0.0", - "slash": "1.0.0" - } - }, - "long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "protobufjs": { - "version": "6.8.6", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.6.tgz", - "integrity": "sha512-eH2OTP9s55vojr3b7NBaF9i4WhWPkv/nq55nznWNp/FomKrLViprUcqnBjHph2tFQ+7KciGPTPsVWGz0SOhL0Q==", - "requires": { - "@protobufjs/aspromise": "1.1.2", - "@protobufjs/base64": "1.1.2", - "@protobufjs/codegen": "2.0.4", - "@protobufjs/eventemitter": "1.1.0", - "@protobufjs/fetch": "1.1.0", - "@protobufjs/float": "1.0.2", - "@protobufjs/inquire": "1.1.0", - "@protobufjs/path": "1.1.2", - "@protobufjs/pool": "1.1.0", - "@protobufjs/utf8": "1.1.0", - "@types/long": "3.0.32", - "@types/node": "8.9.5", - "long": "4.0.0" - } - } - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" - }, - "grpc": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/grpc/-/grpc-1.9.1.tgz", - "integrity": "sha512-WNW3MWMuAoo63AwIlzFE3T0KzzvNBSvOkg67Hm8WhvHNkXFBlIk1QyJRE3Ocm0O5eIwS7JU8Ssota53QR1zllg==", - "requires": { - "lodash": "4.17.5", - "nan": "2.10.0", - "node-pre-gyp": "0.6.39", - "protobufjs": "5.0.2" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, - "are-we-there-yet": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.3" - } - }, - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" - }, - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" - }, - "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "requires": { - "inherits": "2.0.3" - } - }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "requires": { - "hoek": "2.16.3" - } - }, - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", - "requires": { - "delayed-stream": "1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "requires": { - "boom": "2.10.1" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - } - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" - }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" - } - }, - "fstream-ignore": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", - "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", - "requires": { - "fstream": "1.0.11", - "inherits": "2.0.3", - "minimatch": "3.0.4" - } - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - } - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" - }, - "har-schema": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=" - }, - "har-validator": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", - "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" - } - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "requires": { - "jsonify": "0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - } - } - }, - "mime-db": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" - }, - "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", - "requires": { - "mime-db": "1.30.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "1.1.8" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node-pre-gyp": { - "version": "0.6.39", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz", - "integrity": "sha512-OsJV74qxnvz/AMGgcfZoDaeDXKD3oY3QVIbBmwszTFkRisTSXbMQyn4UWzUMOtA5SVhrBZOTp0wcoSBgfMfMmQ==", - "requires": { - "detect-libc": "1.0.3", - "hawk": "3.1.3", - "mkdirp": "0.5.1", - "nopt": "4.0.1", - "npmlog": "4.1.2", - "rc": "1.2.4", - "request": "2.81.0", - "rimraf": "2.6.2", - "semver": "5.5.0", - "tar": "2.2.1", - "tar-pack": "3.4.1" - } - }, - "nopt": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", - "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.4" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1.0.2" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "osenv": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", - "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "performance-now": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=" - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" - }, - "rc": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.4.tgz", - "integrity": "sha1-oPYGyq4qO4YrvQ74VILAElsxX6M=", - "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" - } - } - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "request": { - "version": "2.81.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.3", - "tunnel-agent": "0.6.0", - "uuid": "3.2.1" - } - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "requires": { - "glob": "7.1.2" - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" - }, - "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" - }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "requires": { - "hoek": "2.16.3" - } - }, - "sshpk": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - } - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "5.1.1" - } - }, - "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, - "tar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - } - }, - "tar-pack": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.1.tgz", - "integrity": "sha512-PPRybI9+jM5tjtCbN2cxmmRU7YmqT3Zv/UDy48tAh2XRkLa9bAORtSWLkVc13+GJF+cdTh1yEnHEk3cpTaL5Kg==", - "requires": { - "debug": "2.6.9", - "fstream": "1.0.11", - "fstream-ignore": "1.0.5", - "once": "1.4.0", - "readable-stream": "2.3.3", - "rimraf": "2.6.2", - "tar": "2.2.1", - "uid-number": "0.0.6" - } - }, - "tough-cookie": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", - "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", - "requires": { - "punycode": "1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "5.1.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "optional": true - }, - "uid-number": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", - "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=" - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "1.3.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - } - } - }, - "wide-align": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", - "requires": { - "string-width": "1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - } - } - }, - "gtoken": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-2.2.0.tgz", - "integrity": "sha512-tvQs8B1z5+I1FzMPZnq/OCuxTWFOkvy7cUJcpNdBOK2L7yEtPZTVCPtZU181sSDF+isUPebSqFTNTkIejFASAQ==", - "requires": { - "axios": "0.18.0", - "google-p12-pem": "1.0.2", - "jws": "3.1.4", - "mime": "2.2.0", - "pify": "3.0.0" - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" - } - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "requires": { - "get-value": "2.0.6", - "has-values": "1.0.0", - "isobject": "3.0.1" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "hash-stream-validation": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.1.tgz", - "integrity": "sha1-7Mm5l7IYvluzEphii7gHhptz3NE=", - "requires": { - "through2": "2.0.3" - } - }, - "hawk": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "requires": { - "boom": "4.3.1", - "cryptiles": "3.1.2", - "hoek": "4.2.1", - "sntp": "2.1.0" - } - }, - "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" - }, - "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "requires": { - "depd": "1.1.1", - "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": "1.4.0" - }, - "dependencies": { - "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" - }, - "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" - } - } - }, - "http-parser-js": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.11.tgz", - "integrity": "sha512-QCR5O2AjjMW8Mo4HyI1ctFcv+O99j/0g367V3YoVnrNw5hkDvAWZD0lWGcc+F4yN3V55USPCVix4efb75HxFfA==" - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.14.1" - } - }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" - }, - "ignore": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", - "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==" - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" - }, - "ipaddr.js": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", - "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" - }, - "is": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", - "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=" - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "6.0.2" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "6.0.2" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "requires": { - "is-extglob": "2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" - }, - "is-odd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", - "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", - "requires": { - "is-number": "4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" - } - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "requires": { - "isobject": "3.0.1" - } - }, - "is-stream-ended": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.3.tgz", - "integrity": "sha1-oEc7Jnx1ZjVIa+7cfjNE5UnRUqw=" - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isemail": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", - "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo=" - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "joi": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", - "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", - "requires": { - "hoek": "2.16.3", - "isemail": "1.2.0", - "moment": "2.21.0", - "topo": "1.1.0" - }, - "dependencies": { - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" - } - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "jsonwebtoken": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.1.0.tgz", - "integrity": "sha1-xjl80uX9WD1lwAeoPce7eOaYK4M=", - "requires": { - "jws": "3.1.4", - "lodash.includes": "4.3.0", - "lodash.isboolean": "3.0.3", - "lodash.isinteger": "4.0.4", - "lodash.isnumber": "3.0.3", - "lodash.isplainobject": "4.0.6", - "lodash.isstring": "4.0.1", - "lodash.once": "4.1.1", - "ms": "2.0.0", - "xtend": "4.0.1" - } - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "jwa": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz", - "integrity": "sha1-oFUs4CIHQs1S4VN3SjKQXDDnVuU=", - "requires": { - "base64url": "2.0.0", - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.9", - "safe-buffer": "5.1.1" - } - }, - "jws": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz", - "integrity": "sha1-+ei5M46KhHJ31kRLFGT2GIDgUKI=", - "requires": { - "base64url": "2.0.0", - "jwa": "1.1.5", - "safe-buffer": "5.1.1" - } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "requires": { - "invert-kv": "1.0.0" - } - }, - "lodash": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" - }, - "lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" - }, - "lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" - }, - "lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" - }, - "lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" - }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" - }, - "log-driver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", - "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==" - }, - "long": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", - "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" - }, - "lru-cache": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", - "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - }, - "make-dir": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", - "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", - "requires": { - "pify": "3.0.0" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "requires": { - "object-visit": "1.0.1" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "merge2": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.1.tgz", - "integrity": "sha512-wUqcG5pxrAcaFI1lkqkMnk3Q7nUxV/NWfpAFSeWUwG9TRODnBDCUHa75mi3o3vLWQ5N4CQERWCauSlP0I3ZqUg==" - }, - "methmeth": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/methmeth/-/methmeth-1.1.0.tgz", - "integrity": "sha1-6AomYY5S9cQiKGG7dIUQvRDikIk=" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "micromatch": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.9.tgz", - "integrity": "sha512-SlIz6sv5UPaAVVFRKodKjCg48EbNoIhgetzfK/Cy0v5U52Z6zB136M8tp0UC9jM53LYbmIRihJszvvqpKkfm9g==", - "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "braces": "2.3.1", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "extglob": "2.0.4", - "fragment-cache": "0.2.1", - "kind-of": "6.0.2", - "nanomatch": "1.2.9", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" - } - }, - "mime": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.2.0.tgz", - "integrity": "sha512-0Qz9uF1ATtl8RKJG4VRfOymh7PyEor6NbrI/61lRfuRe4vx9SNATrvAeTj2EWVRKjEQGskrzWkJBBY5NbaVHIA==" - }, - "mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" - }, - "mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", - "requires": { - "mime-db": "1.33.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "1.1.11" - } - }, - "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", - "requires": { - "for-in": "1.0.2", - "is-extendable": "1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "2.0.4" - } - } - } - }, - "modelo": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/modelo/-/modelo-4.2.3.tgz", - "integrity": "sha512-9DITV2YEMcw7XojdfvGl3gDD8J9QjZTJ7ZOUuSAkP+F3T6rDbzMJuPktxptsdHYEvZcmXrCD3LMOhdSAEq6zKA==" - }, - "moment": { - "version": "2.21.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.21.0.tgz", - "integrity": "sha512-TCZ36BjURTeFTM/CwRcViQlfkMvL1/vFISuNLO5GkcVm1+QHfbSiNqZuWeMFjj1/3+uAjXswgRk30j1kkLYJBQ==" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "nan": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" - }, - "nanomatch": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", - "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", - "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "fragment-cache": "0.2.1", - "is-odd": "2.0.0", - "is-windows": "1.0.2", - "kind-of": "6.0.2", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" - } - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" - }, - "node-forge": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.1.tgz", - "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA=" - }, - "npm": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/npm/-/npm-5.8.0.tgz", - "integrity": "sha512-DowXzQwtSWDtbAjuWecuEiismR0VdNEYaL3VxNTYTdW6AGkYxfGk9LUZ/rt6etEyiH4IEk95HkJeGfXE5Rz9xQ==", - "requires": { - "JSONStream": "1.3.2", - "abbrev": "1.1.1", - "ansi-regex": "3.0.0", - "ansicolors": "0.3.2", - "ansistyles": "0.1.3", - "aproba": "1.2.0", - "archy": "1.0.0", - "bin-links": "1.1.0", - "bluebird": "3.5.1", - "cacache": "10.0.4", - "call-limit": "1.1.0", - "chownr": "1.0.1", - "cli-table2": "0.2.0", - "cmd-shim": "2.0.2", - "columnify": "1.5.4", - "config-chain": "1.1.11", - "debuglog": "1.0.1", - "detect-indent": "5.0.0", - "detect-newline": "2.1.0", - "dezalgo": "1.0.3", - "editor": "1.0.0", - "find-npm-prefix": "1.0.2", - "fs-vacuum": "1.2.10", - "fs-write-stream-atomic": "1.0.10", - "gentle-fs": "2.0.1", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "has-unicode": "2.0.1", - "hosted-git-info": "2.6.0", - "iferr": "0.1.5", - "imurmurhash": "0.1.4", - "inflight": "1.0.6", - "inherits": "2.0.3", - "ini": "1.3.5", - "init-package-json": "1.10.3", - "is-cidr": "1.0.0", - "json-parse-better-errors": "1.0.1", - "lazy-property": "1.0.0", - "libcipm": "1.6.0", - "libnpx": "10.0.1", - "lockfile": "1.0.3", - "lodash._baseindexof": "3.1.0", - "lodash._baseuniq": "4.6.0", - "lodash._bindcallback": "3.0.1", - "lodash._cacheindexof": "3.0.2", - "lodash._createcache": "3.1.2", - "lodash._getnative": "3.9.1", - "lodash.clonedeep": "4.5.0", - "lodash.restparam": "3.6.1", - "lodash.union": "4.6.0", - "lodash.uniq": "4.5.0", - "lodash.without": "4.4.0", - "lru-cache": "4.1.1", - "meant": "1.0.1", - "mississippi": "3.0.0", - "mkdirp": "0.5.1", - "move-concurrently": "1.0.1", - "nopt": "4.0.1", - "normalize-package-data": "2.4.0", - "npm-cache-filename": "1.0.2", - "npm-install-checks": "3.0.0", - "npm-lifecycle": "2.0.1", - "npm-package-arg": "6.0.0", - "npm-packlist": "1.1.10", - "npm-profile": "3.0.1", - "npm-registry-client": "8.5.1", - "npm-user-validate": "1.0.0", - "npmlog": "4.1.2", - "once": "1.4.0", - "opener": "1.4.3", - "osenv": "0.1.5", - "pacote": "7.6.1", - "path-is-inside": "1.0.2", - "promise-inflight": "1.0.1", - "qrcode-terminal": "0.11.0", - "query-string": "5.1.0", - "qw": "1.0.1", - "read": "1.0.7", - "read-cmd-shim": "1.0.1", - "read-installed": "4.0.3", - "read-package-json": "2.0.13", - "read-package-tree": "5.1.6", - "readable-stream": "2.3.5", - "readdir-scoped-modules": "1.0.2", - "request": "2.83.0", - "retry": "0.10.1", - "rimraf": "2.6.2", - "safe-buffer": "5.1.1", - "semver": "5.5.0", - "sha": "2.0.1", - "slide": "1.1.6", - "sorted-object": "2.0.1", - "sorted-union-stream": "2.1.3", - "ssri": "5.2.4", - "strip-ansi": "4.0.0", - "tar": "4.4.0", - "text-table": "0.2.0", - "uid-number": "0.0.6", - "umask": "1.1.0", - "unique-filename": "1.1.0", - "unpipe": "1.0.0", - "update-notifier": "2.3.0", - "uuid": "3.2.1", - "validate-npm-package-license": "3.0.1", - "validate-npm-package-name": "3.0.0", - "which": "1.3.0", - "worker-farm": "1.5.4", - "wrappy": "1.0.2", - "write-file-atomic": "2.3.0" - }, - "dependencies": { - "JSONStream": { - "version": "1.3.2", - "bundled": true, - "requires": { - "jsonparse": "1.3.1", - "through": "2.3.8" - }, - "dependencies": { - "jsonparse": { - "version": "1.3.1", - "bundled": true - }, - "through": { - "version": "2.3.8", - "bundled": true - } - } - }, - "abbrev": { - "version": "1.1.1", - "bundled": true - }, - "ansi-regex": { - "version": "3.0.0", - "bundled": true - }, - "ansicolors": { - "version": "0.3.2", - "bundled": true - }, - "ansistyles": { - "version": "0.1.3", - "bundled": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true - }, - "archy": { - "version": "1.0.0", - "bundled": true - }, - "bin-links": { - "version": "1.1.0", - "bundled": true, - "requires": { - "bluebird": "3.5.1", - "cmd-shim": "2.0.2", - "fs-write-stream-atomic": "1.0.10", - "gentle-fs": "2.0.1", - "graceful-fs": "4.1.11", - "slide": "1.1.6" - } - }, - "bluebird": { - "version": "3.5.1", - "bundled": true - }, - "cacache": { - "version": "10.0.4", - "bundled": true, - "requires": { - "bluebird": "3.5.1", - "chownr": "1.0.1", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "lru-cache": "4.1.1", - "mississippi": "2.0.0", - "mkdirp": "0.5.1", - "move-concurrently": "1.0.1", - "promise-inflight": "1.0.1", - "rimraf": "2.6.2", - "ssri": "5.2.4", - "unique-filename": "1.1.0", - "y18n": "4.0.0" - }, - "dependencies": { - "mississippi": { - "version": "2.0.0", - "bundled": true, - "requires": { - "concat-stream": "1.6.1", - "duplexify": "3.5.4", - "end-of-stream": "1.4.1", - "flush-write-stream": "1.0.2", - "from2": "2.3.0", - "parallel-transform": "1.1.0", - "pump": "2.0.1", - "pumpify": "1.4.0", - "stream-each": "1.2.2", - "through2": "2.0.3" - }, - "dependencies": { - "concat-stream": { - "version": "1.6.1", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.5", - "typedarray": "0.0.6" - }, - "dependencies": { - "typedarray": { - "version": "0.0.6", - "bundled": true - } - } - }, - "duplexify": { - "version": "3.5.4", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "inherits": "2.0.3", - "readable-stream": "2.3.5", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "end-of-stream": { - "version": "1.4.1", - "bundled": true, - "requires": { - "once": "1.4.0" - } - }, - "flush-write-stream": { - "version": "1.0.2", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.5" - } - }, - "from2": { - "version": "2.3.0", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.5" - } - }, - "parallel-transform": { - "version": "1.1.0", - "bundled": true, - "requires": { - "cyclist": "0.2.2", - "inherits": "2.0.3", - "readable-stream": "2.3.5" - }, - "dependencies": { - "cyclist": { - "version": "0.2.2", - "bundled": true - } - } - }, - "pump": { - "version": "2.0.1", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - }, - "pumpify": { - "version": "1.4.0", - "bundled": true, - "requires": { - "duplexify": "3.5.4", - "inherits": "2.0.3", - "pump": "2.0.1" - } - }, - "stream-each": { - "version": "1.2.2", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "through2": { - "version": "2.0.3", - "bundled": true, - "requires": { - "readable-stream": "2.3.5", - "xtend": "4.0.1" - }, - "dependencies": { - "xtend": { - "version": "4.0.1", - "bundled": true - } - } - } - } - }, - "y18n": { - "version": "4.0.0", - "bundled": true - } - } - }, - "call-limit": { - "version": "1.1.0", - "bundled": true - }, - "chownr": { - "version": "1.0.1", - "bundled": true - }, - "cli-table2": { - "version": "0.2.0", - "bundled": true, - "requires": { - "colors": "1.1.2", - "lodash": "3.10.1", - "string-width": "1.0.2" - }, - "dependencies": { - "colors": { - "version": "1.1.2", - "bundled": true, - "optional": true - }, - "lodash": { - "version": "3.10.1", - "bundled": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "1.0.1" - }, - "dependencies": { - "number-is-nan": { - "version": "1.0.1", - "bundled": true - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true - } - } - } - } - } - } - }, - "cmd-shim": { - "version": "2.0.2", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11", - "mkdirp": "0.5.1" - } - }, - "columnify": { - "version": "1.5.4", - "bundled": true, - "requires": { - "strip-ansi": "3.0.1", - "wcwidth": "1.0.1" - }, - "dependencies": { - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true - } - } - }, - "wcwidth": { - "version": "1.0.1", - "bundled": true, - "requires": { - "defaults": "1.0.3" - }, - "dependencies": { - "defaults": { - "version": "1.0.3", - "bundled": true, - "requires": { - "clone": "1.0.2" - }, - "dependencies": { - "clone": { - "version": "1.0.2", - "bundled": true - } - } - } - } - } - } - }, - "config-chain": { - "version": "1.1.11", - "bundled": true, - "requires": { - "ini": "1.3.5", - "proto-list": "1.2.4" - }, - "dependencies": { - "proto-list": { - "version": "1.2.4", - "bundled": true - } - } - }, - "debuglog": { - "version": "1.0.1", - "bundled": true - }, - "detect-indent": { - "version": "5.0.0", - "bundled": true - }, - "detect-newline": { - "version": "2.1.0", - "bundled": true - }, - "dezalgo": { - "version": "1.0.3", - "bundled": true, - "requires": { - "asap": "2.0.5", - "wrappy": "1.0.2" - }, - "dependencies": { - "asap": { - "version": "2.0.5", - "bundled": true - } - } - }, - "editor": { - "version": "1.0.0", - "bundled": true - }, - "find-npm-prefix": { - "version": "1.0.2", - "bundled": true - }, - "fs-vacuum": { - "version": "1.2.10", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11", - "path-is-inside": "1.0.2", - "rimraf": "2.6.2" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11", - "iferr": "0.1.5", - "imurmurhash": "0.1.4", - "readable-stream": "2.3.5" - } - }, - "gentle-fs": { - "version": "2.0.1", - "bundled": true, - "requires": { - "aproba": "1.2.0", - "fs-vacuum": "1.2.10", - "graceful-fs": "4.1.11", - "iferr": "0.1.5", - "mkdirp": "0.5.1", - "path-is-inside": "1.0.2", - "read-cmd-shim": "1.0.1", - "slide": "1.1.6" - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - }, - "dependencies": { - "fs.realpath": { - "version": "1.0.0", - "bundled": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "1.1.8" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.8", - "bundled": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - } - } - } - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true - } - } - }, - "graceful-fs": { - "version": "4.1.11", - "bundled": true - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true - }, - "hosted-git-info": { - "version": "2.6.0", - "bundled": true - }, - "iferr": { - "version": "0.1.5", - "bundled": true - }, - "imurmurhash": { - "version": "0.1.4", - "bundled": true - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true - }, - "ini": { - "version": "1.3.5", - "bundled": true - }, - "init-package-json": { - "version": "1.10.3", - "bundled": true, - "requires": { - "glob": "7.1.2", - "npm-package-arg": "6.0.0", - "promzard": "0.3.0", - "read": "1.0.7", - "read-package-json": "2.0.13", - "semver": "5.5.0", - "validate-npm-package-license": "3.0.1", - "validate-npm-package-name": "3.0.0" - }, - "dependencies": { - "promzard": { - "version": "0.3.0", - "bundled": true, - "requires": { - "read": "1.0.7" - } - } - } - }, - "is-cidr": { - "version": "1.0.0", - "bundled": true, - "requires": { - "cidr-regex": "1.0.6" - }, - "dependencies": { - "cidr-regex": { - "version": "1.0.6", - "bundled": true - } - } - }, - "json-parse-better-errors": { - "version": "1.0.1", - "bundled": true - }, - "lazy-property": { - "version": "1.0.0", - "bundled": true - }, - "libcipm": { - "version": "1.6.0", - "bundled": true, - "requires": { - "bin-links": "1.1.0", - "bluebird": "3.5.1", - "find-npm-prefix": "1.0.2", - "graceful-fs": "4.1.11", - "lock-verify": "2.0.0", - "npm-lifecycle": "2.0.1", - "npm-logical-tree": "1.2.1", - "npm-package-arg": "6.0.0", - "pacote": "7.6.1", - "protoduck": "5.0.0", - "read-package-json": "2.0.13", - "rimraf": "2.6.2", - "worker-farm": "1.5.4" - }, - "dependencies": { - "lock-verify": { - "version": "2.0.0", - "bundled": true, - "requires": { - "npm-package-arg": "5.1.2", - "semver": "5.5.0" - }, - "dependencies": { - "npm-package-arg": { - "version": "5.1.2", - "bundled": true, - "requires": { - "hosted-git-info": "2.6.0", - "osenv": "0.1.5", - "semver": "5.5.0", - "validate-npm-package-name": "3.0.0" - } - } - } - }, - "npm-logical-tree": { - "version": "1.2.1", - "bundled": true - }, - "protoduck": { - "version": "5.0.0", - "bundled": true, - "requires": { - "genfun": "4.0.1" - }, - "dependencies": { - "genfun": { - "version": "4.0.1", - "bundled": true - } - } - }, - "worker-farm": { - "version": "1.5.4", - "bundled": true, - "requires": { - "errno": "0.1.7", - "xtend": "4.0.1" - }, - "dependencies": { - "errno": { - "version": "0.1.7", - "bundled": true, - "requires": { - "prr": "1.0.1" - }, - "dependencies": { - "prr": { - "version": "1.0.1", - "bundled": true - } - } - }, - "xtend": { - "version": "4.0.1", - "bundled": true - } - } - } - } - }, - "libnpx": { - "version": "10.0.1", - "bundled": true, - "requires": { - "dotenv": "5.0.1", - "npm-package-arg": "6.0.0", - "rimraf": "2.6.2", - "safe-buffer": "5.1.1", - "update-notifier": "2.3.0", - "which": "1.3.0", - "y18n": "4.0.0", - "yargs": "11.0.0" - }, - "dependencies": { - "dotenv": { - "version": "5.0.1", - "bundled": true - }, - "y18n": { - "version": "4.0.0", - "bundled": true - }, - "yargs": { - "version": "11.0.0", - "bundled": true, - "requires": { - "cliui": "4.0.0", - "decamelize": "1.2.0", - "find-up": "2.1.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "9.0.2" - }, - "dependencies": { - "cliui": { - "version": "4.0.0", - "bundled": true, - "requires": { - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "wrap-ansi": "2.1.0" - }, - "dependencies": { - "wrap-ansi": { - "version": "2.1.0", - "bundled": true, - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "1.0.1" - }, - "dependencies": { - "number-is-nan": { - "version": "1.0.1", - "bundled": true - } - } - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true - } - } - } - } - } - } - }, - "decamelize": { - "version": "1.2.0", - "bundled": true - }, - "find-up": { - "version": "2.1.0", - "bundled": true, - "requires": { - "locate-path": "2.0.0" - }, - "dependencies": { - "locate-path": { - "version": "2.0.0", - "bundled": true, - "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" - }, - "dependencies": { - "p-locate": { - "version": "2.0.0", - "bundled": true, - "requires": { - "p-limit": "1.2.0" - }, - "dependencies": { - "p-limit": { - "version": "1.2.0", - "bundled": true, - "requires": { - "p-try": "1.0.0" - }, - "dependencies": { - "p-try": { - "version": "1.0.0", - "bundled": true - } - } - } - } - }, - "path-exists": { - "version": "3.0.0", - "bundled": true - } - } - } - } - }, - "get-caller-file": { - "version": "1.0.2", - "bundled": true - }, - "os-locale": { - "version": "2.1.0", - "bundled": true, - "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" - }, - "dependencies": { - "execa": { - "version": "0.7.0", - "bundled": true, - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "bundled": true, - "requires": { - "lru-cache": "4.1.1", - "shebang-command": "1.2.0", - "which": "1.3.0" - }, - "dependencies": { - "shebang-command": { - "version": "1.2.0", - "bundled": true, - "requires": { - "shebang-regex": "1.0.0" - }, - "dependencies": { - "shebang-regex": { - "version": "1.0.0", - "bundled": true - } - } - } - } - }, - "get-stream": { - "version": "3.0.0", - "bundled": true - }, - "is-stream": { - "version": "1.1.0", - "bundled": true - }, - "npm-run-path": { - "version": "2.0.2", - "bundled": true, - "requires": { - "path-key": "2.0.1" - }, - "dependencies": { - "path-key": { - "version": "2.0.1", - "bundled": true - } - } - }, - "p-finally": { - "version": "1.0.0", - "bundled": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true - }, - "strip-eof": { - "version": "1.0.0", - "bundled": true - } - } - }, - "lcid": { - "version": "1.0.0", - "bundled": true, - "requires": { - "invert-kv": "1.0.0" - }, - "dependencies": { - "invert-kv": { - "version": "1.0.0", - "bundled": true - } - } - }, - "mem": { - "version": "1.1.0", - "bundled": true, - "requires": { - "mimic-fn": "1.2.0" - }, - "dependencies": { - "mimic-fn": { - "version": "1.2.0", - "bundled": true - } - } - } - } - }, - "require-directory": { - "version": "2.1.1", - "bundled": true - }, - "require-main-filename": { - "version": "1.0.1", - "bundled": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true - }, - "string-width": { - "version": "2.1.1", - "bundled": true, - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true - } - } - }, - "which-module": { - "version": "2.0.0", - "bundled": true - }, - "y18n": { - "version": "3.2.1", - "bundled": true - }, - "yargs-parser": { - "version": "9.0.2", - "bundled": true, - "requires": { - "camelcase": "4.1.0" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "bundled": true - } - } - } - } - } - } - }, - "lockfile": { - "version": "1.0.3", - "bundled": true - }, - "lodash._baseindexof": { - "version": "3.1.0", - "bundled": true - }, - "lodash._baseuniq": { - "version": "4.6.0", - "bundled": true, - "requires": { - "lodash._createset": "4.0.3", - "lodash._root": "3.0.1" - }, - "dependencies": { - "lodash._createset": { - "version": "4.0.3", - "bundled": true - }, - "lodash._root": { - "version": "3.0.1", - "bundled": true - } - } - }, - "lodash._bindcallback": { - "version": "3.0.1", - "bundled": true - }, - "lodash._cacheindexof": { - "version": "3.0.2", - "bundled": true - }, - "lodash._createcache": { - "version": "3.1.2", - "bundled": true, - "requires": { - "lodash._getnative": "3.9.1" - } - }, - "lodash._getnative": { - "version": "3.9.1", - "bundled": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "bundled": true - }, - "lodash.restparam": { - "version": "3.6.1", - "bundled": true - }, - "lodash.union": { - "version": "4.6.0", - "bundled": true - }, - "lodash.uniq": { - "version": "4.5.0", - "bundled": true - }, - "lodash.without": { - "version": "4.4.0", - "bundled": true - }, - "lru-cache": { - "version": "4.1.1", - "bundled": true, - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - }, - "dependencies": { - "pseudomap": { - "version": "1.0.2", - "bundled": true - }, - "yallist": { - "version": "2.1.2", - "bundled": true - } - } - }, - "meant": { - "version": "1.0.1", - "bundled": true - }, - "mississippi": { - "version": "3.0.0", - "bundled": true, - "requires": { - "concat-stream": "1.6.1", - "duplexify": "3.5.4", - "end-of-stream": "1.4.1", - "flush-write-stream": "1.0.2", - "from2": "2.3.0", - "parallel-transform": "1.1.0", - "pump": "3.0.0", - "pumpify": "1.4.0", - "stream-each": "1.2.2", - "through2": "2.0.3" - }, - "dependencies": { - "concat-stream": { - "version": "1.6.1", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.5", - "typedarray": "0.0.6" - }, - "dependencies": { - "typedarray": { - "version": "0.0.6", - "bundled": true - } - } - }, - "duplexify": { - "version": "3.5.4", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "inherits": "2.0.3", - "readable-stream": "2.3.5", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "end-of-stream": { - "version": "1.4.1", - "bundled": true, - "requires": { - "once": "1.4.0" - } - }, - "flush-write-stream": { - "version": "1.0.2", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.5" - } - }, - "from2": { - "version": "2.3.0", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.5" - } - }, - "parallel-transform": { - "version": "1.1.0", - "bundled": true, - "requires": { - "cyclist": "0.2.2", - "inherits": "2.0.3", - "readable-stream": "2.3.5" - }, - "dependencies": { - "cyclist": { - "version": "0.2.2", - "bundled": true - } - } - }, - "pump": { - "version": "3.0.0", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - }, - "pumpify": { - "version": "1.4.0", - "bundled": true, - "requires": { - "duplexify": "3.5.4", - "inherits": "2.0.3", - "pump": "2.0.1" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - } - } - }, - "stream-each": { - "version": "1.2.2", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "through2": { - "version": "2.0.3", - "bundled": true, - "requires": { - "readable-stream": "2.3.5", - "xtend": "4.0.1" - }, - "dependencies": { - "xtend": { - "version": "4.0.1", - "bundled": true - } - } - } - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "bundled": true - } - } - }, - "move-concurrently": { - "version": "1.0.1", - "bundled": true, - "requires": { - "aproba": "1.2.0", - "copy-concurrently": "1.0.5", - "fs-write-stream-atomic": "1.0.10", - "mkdirp": "0.5.1", - "rimraf": "2.6.2", - "run-queue": "1.0.3" - }, - "dependencies": { - "copy-concurrently": { - "version": "1.0.5", - "bundled": true, - "requires": { - "aproba": "1.2.0", - "fs-write-stream-atomic": "1.0.10", - "iferr": "0.1.5", - "mkdirp": "0.5.1", - "rimraf": "2.6.2", - "run-queue": "1.0.3" - } - }, - "run-queue": { - "version": "1.0.3", - "bundled": true, - "requires": { - "aproba": "1.2.0" - } - } - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.5" - } - }, - "normalize-package-data": { - "version": "2.4.0", - "bundled": true, - "requires": { - "hosted-git-info": "2.6.0", - "is-builtin-module": "1.0.0", - "semver": "5.5.0", - "validate-npm-package-license": "3.0.1" - }, - "dependencies": { - "is-builtin-module": { - "version": "1.0.0", - "bundled": true, - "requires": { - "builtin-modules": "1.1.1" - }, - "dependencies": { - "builtin-modules": { - "version": "1.1.1", - "bundled": true - } - } - } - } - }, - "npm-cache-filename": { - "version": "1.0.2", - "bundled": true - }, - "npm-install-checks": { - "version": "3.0.0", - "bundled": true, - "requires": { - "semver": "5.5.0" - } - }, - "npm-lifecycle": { - "version": "2.0.1", - "bundled": true, - "requires": { - "byline": "5.0.0", - "graceful-fs": "4.1.11", - "node-gyp": "3.6.2", - "resolve-from": "4.0.0", - "slide": "1.1.6", - "uid-number": "0.0.6", - "umask": "1.1.0", - "which": "1.3.0" - }, - "dependencies": { - "byline": { - "version": "5.0.0", - "bundled": true - }, - "node-gyp": { - "version": "3.6.2", - "bundled": true, - "requires": { - "fstream": "1.0.11", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "npmlog": "4.1.2", - "osenv": "0.1.5", - "request": "2.83.0", - "rimraf": "2.6.2", - "semver": "5.3.0", - "tar": "2.2.1", - "which": "1.3.0" - }, - "dependencies": { - "fstream": { - "version": "1.0.11", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" - } - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "1.1.11" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - } - } - } - } - }, - "nopt": { - "version": "3.0.6", - "bundled": true, - "requires": { - "abbrev": "1.1.1" - } - }, - "semver": { - "version": "5.3.0", - "bundled": true - }, - "tar": { - "version": "2.2.1", - "bundled": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - }, - "dependencies": { - "block-stream": { - "version": "0.0.9", - "bundled": true, - "requires": { - "inherits": "2.0.3" - } - } - } - } - } - }, - "resolve-from": { - "version": "4.0.0", - "bundled": true - } - } - }, - "npm-package-arg": { - "version": "6.0.0", - "bundled": true, - "requires": { - "hosted-git-info": "2.6.0", - "osenv": "0.1.5", - "semver": "5.5.0", - "validate-npm-package-name": "3.0.0" - } - }, - "npm-packlist": { - "version": "1.1.10", - "bundled": true, - "requires": { - "ignore-walk": "3.0.1", - "npm-bundled": "1.0.3" - }, - "dependencies": { - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "requires": { - "minimatch": "3.0.4" - }, - "dependencies": { - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "1.1.8" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.8", - "bundled": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - } - } - } - } - } - } - }, - "npm-bundled": { - "version": "1.0.3", - "bundled": true - } - } - }, - "npm-profile": { - "version": "3.0.1", - "bundled": true, - "requires": { - "aproba": "1.2.0", - "make-fetch-happen": "2.6.0" - }, - "dependencies": { - "make-fetch-happen": { - "version": "2.6.0", - "bundled": true, - "requires": { - "agentkeepalive": "3.3.0", - "cacache": "10.0.4", - "http-cache-semantics": "3.8.1", - "http-proxy-agent": "2.0.0", - "https-proxy-agent": "2.1.1", - "lru-cache": "4.1.1", - "mississippi": "1.3.1", - "node-fetch-npm": "2.0.2", - "promise-retry": "1.1.1", - "socks-proxy-agent": "3.0.1", - "ssri": "5.2.4" - }, - "dependencies": { - "agentkeepalive": { - "version": "3.3.0", - "bundled": true, - "requires": { - "humanize-ms": "1.2.1" - }, - "dependencies": { - "humanize-ms": { - "version": "1.2.1", - "bundled": true, - "requires": { - "ms": "2.1.1" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "bundled": true - } - } - } - } - }, - "http-cache-semantics": { - "version": "3.8.1", - "bundled": true - }, - "http-proxy-agent": { - "version": "2.0.0", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "debug": "2.6.9" - }, - "dependencies": { - "agent-base": { - "version": "4.2.0", - "bundled": true, - "requires": { - "es6-promisify": "5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "4.2.4" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.4", - "bundled": true - } - } - } - } - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true - } - } - } - } - }, - "https-proxy-agent": { - "version": "2.1.1", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "debug": "3.1.0" - }, - "dependencies": { - "agent-base": { - "version": "4.2.0", - "bundled": true, - "requires": { - "es6-promisify": "5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "4.2.4" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.4", - "bundled": true - } - } - } - } - }, - "debug": { - "version": "3.1.0", - "bundled": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true - } - } - } - } - }, - "mississippi": { - "version": "1.3.1", - "bundled": true, - "requires": { - "concat-stream": "1.6.0", - "duplexify": "3.5.3", - "end-of-stream": "1.4.1", - "flush-write-stream": "1.0.2", - "from2": "2.3.0", - "parallel-transform": "1.1.0", - "pump": "1.0.3", - "pumpify": "1.4.0", - "stream-each": "1.2.2", - "through2": "2.0.3" - }, - "dependencies": { - "concat-stream": { - "version": "1.6.0", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.5", - "typedarray": "0.0.6" - }, - "dependencies": { - "typedarray": { - "version": "0.0.6", - "bundled": true - } - } - }, - "duplexify": { - "version": "3.5.3", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "inherits": "2.0.3", - "readable-stream": "2.3.5", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "end-of-stream": { - "version": "1.4.1", - "bundled": true, - "requires": { - "once": "1.4.0" - } - }, - "flush-write-stream": { - "version": "1.0.2", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.5" - } - }, - "from2": { - "version": "2.3.0", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.5" - } - }, - "parallel-transform": { - "version": "1.1.0", - "bundled": true, - "requires": { - "cyclist": "0.2.2", - "inherits": "2.0.3", - "readable-stream": "2.3.5" - }, - "dependencies": { - "cyclist": { - "version": "0.2.2", - "bundled": true - } - } - }, - "pump": { - "version": "1.0.3", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - }, - "pumpify": { - "version": "1.4.0", - "bundled": true, - "requires": { - "duplexify": "3.5.3", - "inherits": "2.0.3", - "pump": "2.0.1" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - } - } - }, - "stream-each": { - "version": "1.2.2", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "through2": { - "version": "2.0.3", - "bundled": true, - "requires": { - "readable-stream": "2.3.5", - "xtend": "4.0.1" - }, - "dependencies": { - "xtend": { - "version": "4.0.1", - "bundled": true - } - } - } - } - }, - "node-fetch-npm": { - "version": "2.0.2", - "bundled": true, - "requires": { - "encoding": "0.1.12", - "json-parse-better-errors": "1.0.1", - "safe-buffer": "5.1.1" - }, - "dependencies": { - "encoding": { - "version": "0.1.12", - "bundled": true, - "requires": { - "iconv-lite": "0.4.19" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.19", - "bundled": true - } - } - }, - "json-parse-better-errors": { - "version": "1.0.1", - "bundled": true - } - } - }, - "promise-retry": { - "version": "1.1.1", - "bundled": true, - "requires": { - "err-code": "1.1.2", - "retry": "0.10.1" - }, - "dependencies": { - "err-code": { - "version": "1.1.2", - "bundled": true - } - } - }, - "socks-proxy-agent": { - "version": "3.0.1", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "socks": "1.1.10" - }, - "dependencies": { - "agent-base": { - "version": "4.2.0", - "bundled": true, - "requires": { - "es6-promisify": "5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "4.2.4" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.4", - "bundled": true - } - } - } - } - }, - "socks": { - "version": "1.1.10", - "bundled": true, - "requires": { - "ip": "1.1.5", - "smart-buffer": "1.1.15" - }, - "dependencies": { - "ip": { - "version": "1.1.5", - "bundled": true - }, - "smart-buffer": { - "version": "1.1.15", - "bundled": true - } - } - } - } - } - } - } - } - }, - "npm-registry-client": { - "version": "8.5.1", - "bundled": true, - "requires": { - "concat-stream": "1.6.1", - "graceful-fs": "4.1.11", - "normalize-package-data": "2.4.0", - "npm-package-arg": "6.0.0", - "npmlog": "4.1.2", - "once": "1.4.0", - "request": "2.83.0", - "retry": "0.10.1", - "safe-buffer": "5.1.1", - "semver": "5.5.0", - "slide": "1.1.6", - "ssri": "5.2.4" - }, - "dependencies": { - "concat-stream": { - "version": "1.6.1", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.5", - "typedarray": "0.0.6" - }, - "dependencies": { - "typedarray": { - "version": "0.0.6", - "bundled": true - } - } - } - } - }, - "npm-user-validate": { - "version": "1.0.0", - "bundled": true - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - }, - "dependencies": { - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.5" - }, - "dependencies": { - "delegates": { - "version": "1.0.0", - "bundled": true - } - } - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - }, - "dependencies": { - "object-assign": { - "version": "4.1.1", - "bundled": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "1.0.1" - }, - "dependencies": { - "number-is-nan": { - "version": "1.0.1", - "bundled": true - } - } - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true - } - } - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "requires": { - "string-width": "1.0.2" - } - } - } - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true - } - } - }, - "once": { - "version": "1.4.0", - "bundled": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "opener": { - "version": "1.4.3", - "bundled": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - }, - "dependencies": { - "os-homedir": { - "version": "1.0.2", - "bundled": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true - } - } - }, - "pacote": { - "version": "7.6.1", - "bundled": true, - "requires": { - "bluebird": "3.5.1", - "cacache": "10.0.4", - "get-stream": "3.0.0", - "glob": "7.1.2", - "lru-cache": "4.1.1", - "make-fetch-happen": "2.6.0", - "minimatch": "3.0.4", - "mississippi": "3.0.0", - "mkdirp": "0.5.1", - "normalize-package-data": "2.4.0", - "npm-package-arg": "6.0.0", - "npm-packlist": "1.1.10", - "npm-pick-manifest": "2.1.0", - "osenv": "0.1.5", - "promise-inflight": "1.0.1", - "promise-retry": "1.1.1", - "protoduck": "5.0.0", - "rimraf": "2.6.2", - "safe-buffer": "5.1.1", - "semver": "5.5.0", - "ssri": "5.2.4", - "tar": "4.4.0", - "unique-filename": "1.1.0", - "which": "1.3.0" - }, - "dependencies": { - "get-stream": { - "version": "3.0.0", - "bundled": true - }, - "make-fetch-happen": { - "version": "2.6.0", - "bundled": true, - "requires": { - "agentkeepalive": "3.4.0", - "cacache": "10.0.4", - "http-cache-semantics": "3.8.1", - "http-proxy-agent": "2.1.0", - "https-proxy-agent": "2.2.0", - "lru-cache": "4.1.1", - "mississippi": "1.3.1", - "node-fetch-npm": "2.0.2", - "promise-retry": "1.1.1", - "socks-proxy-agent": "3.0.1", - "ssri": "5.2.4" - }, - "dependencies": { - "agentkeepalive": { - "version": "3.4.0", - "bundled": true, - "requires": { - "humanize-ms": "1.2.1" - }, - "dependencies": { - "humanize-ms": { - "version": "1.2.1", - "bundled": true, - "requires": { - "ms": "2.1.1" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "bundled": true - } - } - } - } - }, - "http-cache-semantics": { - "version": "3.8.1", - "bundled": true - }, - "http-proxy-agent": { - "version": "2.1.0", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "debug": "3.1.0" - }, - "dependencies": { - "agent-base": { - "version": "4.2.0", - "bundled": true, - "requires": { - "es6-promisify": "5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "4.2.4" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.4", - "bundled": true - } - } - } - } - }, - "debug": { - "version": "3.1.0", - "bundled": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true - } - } - } - } - }, - "https-proxy-agent": { - "version": "2.2.0", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "debug": "3.1.0" - }, - "dependencies": { - "agent-base": { - "version": "4.2.0", - "bundled": true, - "requires": { - "es6-promisify": "5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "4.2.4" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.4", - "bundled": true - } - } - } - } - }, - "debug": { - "version": "3.1.0", - "bundled": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true - } - } - } - } - }, - "mississippi": { - "version": "1.3.1", - "bundled": true, - "requires": { - "concat-stream": "1.6.1", - "duplexify": "3.5.4", - "end-of-stream": "1.4.1", - "flush-write-stream": "1.0.2", - "from2": "2.3.0", - "parallel-transform": "1.1.0", - "pump": "1.0.3", - "pumpify": "1.4.0", - "stream-each": "1.2.2", - "through2": "2.0.3" - }, - "dependencies": { - "concat-stream": { - "version": "1.6.1", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.5", - "typedarray": "0.0.6" - }, - "dependencies": { - "typedarray": { - "version": "0.0.6", - "bundled": true - } - } - }, - "duplexify": { - "version": "3.5.4", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "inherits": "2.0.3", - "readable-stream": "2.3.5", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "end-of-stream": { - "version": "1.4.1", - "bundled": true, - "requires": { - "once": "1.4.0" - } - }, - "flush-write-stream": { - "version": "1.0.2", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.5" - } - }, - "from2": { - "version": "2.3.0", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.5" - } - }, - "parallel-transform": { - "version": "1.1.0", - "bundled": true, - "requires": { - "cyclist": "0.2.2", - "inherits": "2.0.3", - "readable-stream": "2.3.5" - }, - "dependencies": { - "cyclist": { - "version": "0.2.2", - "bundled": true - } - } - }, - "pump": { - "version": "1.0.3", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - }, - "pumpify": { - "version": "1.4.0", - "bundled": true, - "requires": { - "duplexify": "3.5.4", - "inherits": "2.0.3", - "pump": "2.0.1" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - } - } - }, - "stream-each": { - "version": "1.2.2", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "through2": { - "version": "2.0.3", - "bundled": true, - "requires": { - "readable-stream": "2.3.5", - "xtend": "4.0.1" - }, - "dependencies": { - "xtend": { - "version": "4.0.1", - "bundled": true - } - } - } - } - }, - "node-fetch-npm": { - "version": "2.0.2", - "bundled": true, - "requires": { - "encoding": "0.1.12", - "json-parse-better-errors": "1.0.1", - "safe-buffer": "5.1.1" - }, - "dependencies": { - "encoding": { - "version": "0.1.12", - "bundled": true, - "requires": { - "iconv-lite": "0.4.19" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.19", - "bundled": true - } - } - }, - "json-parse-better-errors": { - "version": "1.0.1", - "bundled": true - } - } - }, - "socks-proxy-agent": { - "version": "3.0.1", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "socks": "1.1.10" - }, - "dependencies": { - "agent-base": { - "version": "4.2.0", - "bundled": true, - "requires": { - "es6-promisify": "5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "4.2.4" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.4", - "bundled": true - } - } - } - } - }, - "socks": { - "version": "1.1.10", - "bundled": true, - "requires": { - "ip": "1.1.5", - "smart-buffer": "1.1.15" - }, - "dependencies": { - "ip": { - "version": "1.1.5", - "bundled": true - }, - "smart-buffer": { - "version": "1.1.15", - "bundled": true - } - } - } - } - } - } - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "1.1.11" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - } - } - } - } - }, - "npm-pick-manifest": { - "version": "2.1.0", - "bundled": true, - "requires": { - "npm-package-arg": "6.0.0", - "semver": "5.5.0" - } - }, - "promise-retry": { - "version": "1.1.1", - "bundled": true, - "requires": { - "err-code": "1.1.2", - "retry": "0.10.1" - }, - "dependencies": { - "err-code": { - "version": "1.1.2", - "bundled": true - } - } - }, - "protoduck": { - "version": "5.0.0", - "bundled": true, - "requires": { - "genfun": "4.0.1" - }, - "dependencies": { - "genfun": { - "version": "4.0.1", - "bundled": true - } - } - } - } - }, - "path-is-inside": { - "version": "1.0.2", - "bundled": true - }, - "promise-inflight": { - "version": "1.0.1", - "bundled": true - }, - "qrcode-terminal": { - "version": "0.11.0", - "bundled": true - }, - "query-string": { - "version": "5.1.0", - "bundled": true, - "requires": { - "decode-uri-component": "0.2.0", - "object-assign": "4.1.1", - "strict-uri-encode": "1.1.0" - }, - "dependencies": { - "decode-uri-component": { - "version": "0.2.0", - "bundled": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true - }, - "strict-uri-encode": { - "version": "1.1.0", - "bundled": true - } - } - }, - "qw": { - "version": "1.0.1", - "bundled": true - }, - "read": { - "version": "1.0.7", - "bundled": true, - "requires": { - "mute-stream": "0.0.7" - }, - "dependencies": { - "mute-stream": { - "version": "0.0.7", - "bundled": true - } - } - }, - "read-cmd-shim": { - "version": "1.0.1", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11" - } - }, - "read-installed": { - "version": "4.0.3", - "bundled": true, - "requires": { - "debuglog": "1.0.1", - "graceful-fs": "4.1.11", - "read-package-json": "2.0.13", - "readdir-scoped-modules": "1.0.2", - "semver": "5.5.0", - "slide": "1.1.6", - "util-extend": "1.0.3" - }, - "dependencies": { - "util-extend": { - "version": "1.0.3", - "bundled": true - } - } - }, - "read-package-json": { - "version": "2.0.13", - "bundled": true, - "requires": { - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "json-parse-better-errors": "1.0.1", - "normalize-package-data": "2.4.0", - "slash": "1.0.0" - }, - "dependencies": { - "json-parse-better-errors": { - "version": "1.0.1", - "bundled": true - }, - "slash": { - "version": "1.0.0", - "bundled": true - } - } - }, - "read-package-tree": { - "version": "5.1.6", - "bundled": true, - "requires": { - "debuglog": "1.0.1", - "dezalgo": "1.0.3", - "once": "1.4.0", - "read-package-json": "2.0.13", - "readdir-scoped-modules": "1.0.2" - } - }, - "readable-stream": { - "version": "2.3.5", - "bundled": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true - }, - "string_decoder": { - "version": "1.0.3", - "bundled": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true - } - } - }, - "readdir-scoped-modules": { - "version": "1.0.2", - "bundled": true, - "requires": { - "debuglog": "1.0.1", - "dezalgo": "1.0.3", - "graceful-fs": "4.1.11", - "once": "1.4.0" - } - }, - "request": { - "version": "2.83.0", - "bundled": true, - "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.3.1", - "har-validator": "5.0.3", - "hawk": "6.0.2", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "performance-now": "2.1.0", - "qs": "6.5.1", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.3", - "tunnel-agent": "0.6.0", - "uuid": "3.2.1" - }, - "dependencies": { - "aws-sign2": { - "version": "0.7.0", - "bundled": true - }, - "aws4": { - "version": "1.6.0", - "bundled": true - }, - "caseless": { - "version": "0.12.0", - "bundled": true - }, - "combined-stream": { - "version": "1.0.5", - "bundled": true, - "requires": { - "delayed-stream": "1.0.0" - }, - "dependencies": { - "delayed-stream": { - "version": "1.0.0", - "bundled": true - } - } - }, - "extend": { - "version": "3.0.1", - "bundled": true - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true - }, - "form-data": { - "version": "2.3.1", - "bundled": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" - }, - "dependencies": { - "asynckit": { - "version": "0.4.0", - "bundled": true - } - } - }, - "har-validator": { - "version": "5.0.3", - "bundled": true, - "requires": { - "ajv": "5.2.3", - "har-schema": "2.0.0" - }, - "dependencies": { - "ajv": { - "version": "5.2.3", - "bundled": true, - "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.0.0", - "json-schema-traverse": "0.3.1", - "json-stable-stringify": "1.0.1" - }, - "dependencies": { - "co": { - "version": "4.6.0", - "bundled": true - }, - "fast-deep-equal": { - "version": "1.0.0", - "bundled": true - }, - "json-schema-traverse": { - "version": "0.3.1", - "bundled": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "bundled": true, - "requires": { - "jsonify": "0.0.0" - }, - "dependencies": { - "jsonify": { - "version": "0.0.0", - "bundled": true - } - } - } - } - }, - "har-schema": { - "version": "2.0.0", - "bundled": true - } - } - }, - "hawk": { - "version": "6.0.2", - "bundled": true, - "requires": { - "boom": "4.3.1", - "cryptiles": "3.1.2", - "hoek": "4.2.0", - "sntp": "2.0.2" - }, - "dependencies": { - "boom": { - "version": "4.3.1", - "bundled": true, - "requires": { - "hoek": "4.2.0" - } - }, - "cryptiles": { - "version": "3.1.2", - "bundled": true, - "requires": { - "boom": "5.2.0" - }, - "dependencies": { - "boom": { - "version": "5.2.0", - "bundled": true, - "requires": { - "hoek": "4.2.0" - } - } - } - }, - "hoek": { - "version": "4.2.0", - "bundled": true - }, - "sntp": { - "version": "2.0.2", - "bundled": true, - "requires": { - "hoek": "4.2.0" - } - } - } - }, - "http-signature": { - "version": "1.2.0", - "bundled": true, - "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true - }, - "jsprim": { - "version": "1.4.1", - "bundled": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - }, - "dependencies": { - "extsprintf": { - "version": "1.3.0", - "bundled": true - }, - "json-schema": { - "version": "0.2.3", - "bundled": true - }, - "verror": { - "version": "1.10.0", - "bundled": true, - "requires": { - "assert-plus": "1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "1.3.0" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "bundled": true - } - } - } - } - }, - "sshpk": { - "version": "1.13.1", - "bundled": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "asn1": { - "version": "0.2.3", - "bundled": true - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "bundled": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "dashdash": { - "version": "1.14.1", - "bundled": true, - "requires": { - "assert-plus": "1.0.0" - } - }, - "ecc-jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "getpass": { - "version": "0.1.7", - "bundled": true, - "requires": { - "assert-plus": "1.0.0" - } - }, - "jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true - }, - "tweetnacl": { - "version": "0.14.5", - "bundled": true, - "optional": true - } - } - } - } - }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true - }, - "mime-types": { - "version": "2.1.17", - "bundled": true, - "requires": { - "mime-db": "1.30.0" - }, - "dependencies": { - "mime-db": { - "version": "1.30.0", - "bundled": true - } - } - }, - "oauth-sign": { - "version": "0.8.2", - "bundled": true - }, - "performance-now": { - "version": "2.1.0", - "bundled": true - }, - "qs": { - "version": "6.5.1", - "bundled": true - }, - "stringstream": { - "version": "0.0.5", - "bundled": true - }, - "tough-cookie": { - "version": "2.3.3", - "bundled": true, - "requires": { - "punycode": "1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "bundled": true - } - } - }, - "tunnel-agent": { - "version": "0.6.0", - "bundled": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "retry": { - "version": "0.10.1", - "bundled": true - }, - "rimraf": { - "version": "2.6.2", - "bundled": true, - "requires": { - "glob": "7.1.2" - } - }, - "safe-buffer": { - "version": "5.1.1", - "bundled": true - }, - "semver": { - "version": "5.5.0", - "bundled": true - }, - "sha": { - "version": "2.0.1", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11", - "readable-stream": "2.3.5" - } - }, - "slide": { - "version": "1.1.6", - "bundled": true - }, - "sorted-object": { - "version": "2.0.1", - "bundled": true - }, - "sorted-union-stream": { - "version": "2.1.3", - "bundled": true, - "requires": { - "from2": "1.3.0", - "stream-iterate": "1.2.0" - }, - "dependencies": { - "from2": { - "version": "1.3.0", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "1.1.14" - }, - "dependencies": { - "readable-stream": { - "version": "1.1.14", - "bundled": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "isarray": { - "version": "0.0.1", - "bundled": true - }, - "string_decoder": { - "version": "0.10.31", - "bundled": true - } - } - } - } - }, - "stream-iterate": { - "version": "1.2.0", - "bundled": true, - "requires": { - "readable-stream": "2.3.5", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - } - } - }, - "ssri": { - "version": "5.2.4", - "bundled": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "strip-ansi": { - "version": "4.0.0", - "bundled": true, - "requires": { - "ansi-regex": "3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "bundled": true - } - } - }, - "tar": { - "version": "4.4.0", - "bundled": true, - "requires": { - "chownr": "1.0.1", - "fs-minipass": "1.2.5", - "minipass": "2.2.1", - "minizlib": "1.1.0", - "mkdirp": "0.5.1", - "yallist": "3.0.2" - }, - "dependencies": { - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "requires": { - "minipass": "2.2.1" - } - }, - "minipass": { - "version": "2.2.1", - "bundled": true, - "requires": { - "yallist": "3.0.2" - } - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "requires": { - "minipass": "2.2.1" - } - }, - "yallist": { - "version": "3.0.2", - "bundled": true - } - } - }, - "text-table": { - "version": "0.2.0", - "bundled": true - }, - "uid-number": { - "version": "0.0.6", - "bundled": true - }, - "umask": { - "version": "1.1.0", - "bundled": true - }, - "unique-filename": { - "version": "1.1.0", - "bundled": true, - "requires": { - "unique-slug": "2.0.0" - }, - "dependencies": { - "unique-slug": { - "version": "2.0.0", - "bundled": true, - "requires": { - "imurmurhash": "0.1.4" - } - } - } - }, - "unpipe": { - "version": "1.0.0", - "bundled": true - }, - "update-notifier": { - "version": "2.3.0", - "bundled": true, - "requires": { - "boxen": "1.2.1", - "chalk": "2.1.0", - "configstore": "3.1.1", - "import-lazy": "2.1.0", - "is-installed-globally": "0.1.0", - "is-npm": "1.0.0", - "latest-version": "3.1.0", - "semver-diff": "2.1.0", - "xdg-basedir": "3.0.0" - }, - "dependencies": { - "boxen": { - "version": "1.2.1", - "bundled": true, - "requires": { - "ansi-align": "2.0.0", - "camelcase": "4.1.0", - "chalk": "2.1.0", - "cli-boxes": "1.0.0", - "string-width": "2.1.1", - "term-size": "1.2.0", - "widest-line": "1.0.0" - }, - "dependencies": { - "ansi-align": { - "version": "2.0.0", - "bundled": true, - "requires": { - "string-width": "2.1.1" - } - }, - "camelcase": { - "version": "4.1.0", - "bundled": true - }, - "cli-boxes": { - "version": "1.0.0", - "bundled": true - }, - "string-width": { - "version": "2.1.1", - "bundled": true, - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true - } - } - }, - "term-size": { - "version": "1.2.0", - "bundled": true, - "requires": { - "execa": "0.7.0" - }, - "dependencies": { - "execa": { - "version": "0.7.0", - "bundled": true, - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "bundled": true, - "requires": { - "lru-cache": "4.1.1", - "shebang-command": "1.2.0", - "which": "1.3.0" - }, - "dependencies": { - "shebang-command": { - "version": "1.2.0", - "bundled": true, - "requires": { - "shebang-regex": "1.0.0" - }, - "dependencies": { - "shebang-regex": { - "version": "1.0.0", - "bundled": true - } - } - } - } - }, - "get-stream": { - "version": "3.0.0", - "bundled": true - }, - "is-stream": { - "version": "1.1.0", - "bundled": true - }, - "npm-run-path": { - "version": "2.0.2", - "bundled": true, - "requires": { - "path-key": "2.0.1" - }, - "dependencies": { - "path-key": { - "version": "2.0.1", - "bundled": true - } - } - }, - "p-finally": { - "version": "1.0.0", - "bundled": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true - }, - "strip-eof": { - "version": "1.0.0", - "bundled": true - } - } - } - } - }, - "widest-line": { - "version": "1.0.0", - "bundled": true, - "requires": { - "string-width": "1.0.2" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "1.0.1" - }, - "dependencies": { - "number-is-nan": { - "version": "1.0.1", - "bundled": true - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true - } - } - } - } - } - } - } - } - }, - "chalk": { - "version": "2.1.0", - "bundled": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.4.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "bundled": true, - "requires": { - "color-convert": "1.9.0" - }, - "dependencies": { - "color-convert": { - "version": "1.9.0", - "bundled": true, - "requires": { - "color-name": "1.1.3" - }, - "dependencies": { - "color-name": { - "version": "1.1.3", - "bundled": true - } - } - } - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "bundled": true - }, - "supports-color": { - "version": "4.4.0", - "bundled": true, - "requires": { - "has-flag": "2.0.0" - }, - "dependencies": { - "has-flag": { - "version": "2.0.0", - "bundled": true - } - } - } - } - }, - "configstore": { - "version": "3.1.1", - "bundled": true, - "requires": { - "dot-prop": "4.2.0", - "graceful-fs": "4.1.11", - "make-dir": "1.0.0", - "unique-string": "1.0.0", - "write-file-atomic": "2.3.0", - "xdg-basedir": "3.0.0" - }, - "dependencies": { - "dot-prop": { - "version": "4.2.0", - "bundled": true, - "requires": { - "is-obj": "1.0.1" - }, - "dependencies": { - "is-obj": { - "version": "1.0.1", - "bundled": true - } - } - }, - "make-dir": { - "version": "1.0.0", - "bundled": true, - "requires": { - "pify": "2.3.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "bundled": true - } - } - }, - "unique-string": { - "version": "1.0.0", - "bundled": true, - "requires": { - "crypto-random-string": "1.0.0" - }, - "dependencies": { - "crypto-random-string": { - "version": "1.0.0", - "bundled": true - } - } - } - } - }, - "import-lazy": { - "version": "2.1.0", - "bundled": true - }, - "is-installed-globally": { - "version": "0.1.0", - "bundled": true, - "requires": { - "global-dirs": "0.1.0", - "is-path-inside": "1.0.0" - }, - "dependencies": { - "global-dirs": { - "version": "0.1.0", - "bundled": true, - "requires": { - "ini": "1.3.5" - } - }, - "is-path-inside": { - "version": "1.0.0", - "bundled": true, - "requires": { - "path-is-inside": "1.0.2" - } - } - } - }, - "is-npm": { - "version": "1.0.0", - "bundled": true - }, - "latest-version": { - "version": "3.1.0", - "bundled": true, - "requires": { - "package-json": "4.0.1" - }, - "dependencies": { - "package-json": { - "version": "4.0.1", - "bundled": true, - "requires": { - "got": "6.7.1", - "registry-auth-token": "3.3.1", - "registry-url": "3.1.0", - "semver": "5.5.0" - }, - "dependencies": { - "got": { - "version": "6.7.1", - "bundled": true, - "requires": { - "create-error-class": "3.0.2", - "duplexer3": "0.1.4", - "get-stream": "3.0.0", - "is-redirect": "1.0.0", - "is-retry-allowed": "1.1.0", - "is-stream": "1.1.0", - "lowercase-keys": "1.0.0", - "safe-buffer": "5.1.1", - "timed-out": "4.0.1", - "unzip-response": "2.0.1", - "url-parse-lax": "1.0.0" - }, - "dependencies": { - "create-error-class": { - "version": "3.0.2", - "bundled": true, - "requires": { - "capture-stack-trace": "1.0.0" - }, - "dependencies": { - "capture-stack-trace": { - "version": "1.0.0", - "bundled": true - } - } - }, - "duplexer3": { - "version": "0.1.4", - "bundled": true - }, - "get-stream": { - "version": "3.0.0", - "bundled": true - }, - "is-redirect": { - "version": "1.0.0", - "bundled": true - }, - "is-retry-allowed": { - "version": "1.1.0", - "bundled": true - }, - "is-stream": { - "version": "1.1.0", - "bundled": true - }, - "lowercase-keys": { - "version": "1.0.0", - "bundled": true - }, - "timed-out": { - "version": "4.0.1", - "bundled": true - }, - "unzip-response": { - "version": "2.0.1", - "bundled": true - }, - "url-parse-lax": { - "version": "1.0.0", - "bundled": true, - "requires": { - "prepend-http": "1.0.4" - }, - "dependencies": { - "prepend-http": { - "version": "1.0.4", - "bundled": true - } - } - } - } - }, - "registry-auth-token": { - "version": "3.3.1", - "bundled": true, - "requires": { - "rc": "1.2.1", - "safe-buffer": "5.1.1" - }, - "dependencies": { - "rc": { - "version": "1.2.1", - "bundled": true, - "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "deep-extend": { - "version": "0.4.2", - "bundled": true - }, - "minimist": { - "version": "1.2.0", - "bundled": true - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true - } - } - } - } - }, - "registry-url": { - "version": "3.1.0", - "bundled": true, - "requires": { - "rc": "1.2.1" - }, - "dependencies": { - "rc": { - "version": "1.2.1", - "bundled": true, - "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "deep-extend": { - "version": "0.4.2", - "bundled": true - }, - "minimist": { - "version": "1.2.0", - "bundled": true - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true - } - } - } - } - } - } - } - } - }, - "semver-diff": { - "version": "2.1.0", - "bundled": true, - "requires": { - "semver": "5.5.0" - } - }, - "xdg-basedir": { - "version": "3.0.0", - "bundled": true - } - } - }, - "uuid": { - "version": "3.2.1", - "bundled": true - }, - "validate-npm-package-license": { - "version": "3.0.1", - "bundled": true, - "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.4" - }, - "dependencies": { - "spdx-correct": { - "version": "1.0.2", - "bundled": true, - "requires": { - "spdx-license-ids": "1.2.2" - }, - "dependencies": { - "spdx-license-ids": { - "version": "1.2.2", - "bundled": true - } - } - }, - "spdx-expression-parse": { - "version": "1.0.4", - "bundled": true - } - } - }, - "validate-npm-package-name": { - "version": "3.0.0", - "bundled": true, - "requires": { - "builtins": "1.0.3" - }, - "dependencies": { - "builtins": { - "version": "1.0.3", - "bundled": true - } - } - }, - "which": { - "version": "1.3.0", - "bundled": true, - "requires": { - "isexe": "2.0.0" - }, - "dependencies": { - "isexe": { - "version": "2.0.0", - "bundled": true - } - } - }, - "worker-farm": { - "version": "1.5.4", - "bundled": true, - "requires": { - "errno": "0.1.7", - "xtend": "4.0.1" - }, - "dependencies": { - "errno": { - "version": "0.1.7", - "bundled": true, - "requires": { - "prr": "1.0.1" - }, - "dependencies": { - "prr": { - "version": "1.0.1", - "bundled": true - } - } - }, - "xtend": { - "version": "4.0.1", - "bundled": true - } - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true - }, - "write-file-atomic": { - "version": "2.3.0", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11", - "imurmurhash": "0.1.4", - "signal-exit": "3.0.2" - }, - "dependencies": { - "signal-exit": { - "version": "3.0.2", - "bundled": true - } - } - } - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "requires": { - "copy-descriptor": "0.1.1", - "define-property": "0.2.5", - "kind-of": "3.2.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "3.2.2" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "3.2.2" - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "object-keys": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "requires": { - "isobject": "3.0.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "requires": { - "isobject": "3.0.1" - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1.0.2" - } - }, - "optjs": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", - "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "requires": { - "lcid": "1.0.0" - } - }, - "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "requires": { - "pify": "3.0.0" - } - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" - }, - "power-assert": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/power-assert/-/power-assert-1.4.4.tgz", - "integrity": "sha1-kpXqdDcZb1pgH95CDwQmMRhtdRc=", - "requires": { - "define-properties": "1.1.2", - "empower": "1.2.3", - "power-assert-formatter": "1.4.1", - "universal-deep-strict-equal": "1.2.2", - "xtend": "4.0.1" - } - }, - "power-assert-context-formatter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/power-assert-context-formatter/-/power-assert-context-formatter-1.1.1.tgz", - "integrity": "sha1-7bo1LT7YpgMRTWZyZazOYNaJzN8=", - "requires": { - "core-js": "2.5.3", - "power-assert-context-traversal": "1.1.1" - } - }, - "power-assert-context-reducer-ast": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/power-assert-context-reducer-ast/-/power-assert-context-reducer-ast-1.1.2.tgz", - "integrity": "sha1-SEqZ4m9Jc/+IMuXFzHVnAuYJQXQ=", - "requires": { - "acorn": "4.0.13", - "acorn-es7-plugin": "1.1.7", - "core-js": "2.5.3", - "espurify": "1.7.0", - "estraverse": "4.2.0" - } - }, - "power-assert-context-traversal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/power-assert-context-traversal/-/power-assert-context-traversal-1.1.1.tgz", - "integrity": "sha1-iMq8oNE7Y1nwfT0+ivppkmRXftk=", - "requires": { - "core-js": "2.5.3", - "estraverse": "4.2.0" - } - }, - "power-assert-formatter": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/power-assert-formatter/-/power-assert-formatter-1.4.1.tgz", - "integrity": "sha1-XcEl7VCj37HdomwZNH879Y7CiEo=", - "requires": { - "core-js": "2.5.3", - "power-assert-context-formatter": "1.1.1", - "power-assert-context-reducer-ast": "1.1.2", - "power-assert-renderer-assertion": "1.1.1", - "power-assert-renderer-comparison": "1.1.1", - "power-assert-renderer-diagram": "1.1.2", - "power-assert-renderer-file": "1.1.1" - } - }, - "power-assert-renderer-assertion": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/power-assert-renderer-assertion/-/power-assert-renderer-assertion-1.1.1.tgz", - "integrity": "sha1-y/wOd+AIao+Wrz8djme57n4ozpg=", - "requires": { - "power-assert-renderer-base": "1.1.1", - "power-assert-util-string-width": "1.1.1" - } - }, - "power-assert-renderer-base": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/power-assert-renderer-base/-/power-assert-renderer-base-1.1.1.tgz", - "integrity": "sha1-lqZQxv0F7hvB9mtUrWFELIs/Y+s=" - }, - "power-assert-renderer-comparison": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/power-assert-renderer-comparison/-/power-assert-renderer-comparison-1.1.1.tgz", - "integrity": "sha1-10Odl9hRVr5OMKAPL7WnJRTOPAg=", - "requires": { - "core-js": "2.5.3", - "diff-match-patch": "1.0.0", - "power-assert-renderer-base": "1.1.1", - "stringifier": "1.3.0", - "type-name": "2.0.2" - } - }, - "power-assert-renderer-diagram": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/power-assert-renderer-diagram/-/power-assert-renderer-diagram-1.1.2.tgz", - "integrity": "sha1-ZV+PcRk1qbbVQbhjJ2VHF8Y3qYY=", - "requires": { - "core-js": "2.5.3", - "power-assert-renderer-base": "1.1.1", - "power-assert-util-string-width": "1.1.1", - "stringifier": "1.3.0" - } - }, - "power-assert-renderer-file": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/power-assert-renderer-file/-/power-assert-renderer-file-1.1.1.tgz", - "integrity": "sha1-o34rvReMys0E5427eckv40kzxec=", - "requires": { - "power-assert-renderer-base": "1.1.1" - } - }, - "power-assert-util-string-width": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/power-assert-util-string-width/-/power-assert-util-string-width-1.1.1.tgz", - "integrity": "sha1-vmWet5N/3S5smncmjar2S9W3xZI=", - "requires": { - "eastasianwidth": "0.1.1" - } - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" - }, - "protobufjs": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.2.tgz", - "integrity": "sha1-WXSNfc8D0tsiwT2p/rAk4Wq4DJE=", - "requires": { - "ascli": "1.0.1", - "bytebuffer": "5.0.1", - "glob": "7.1.2", - "yargs": "3.32.0" - } - }, - "proxy-addr": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", - "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", - "requires": { - "forwarded": "0.1.2", - "ipaddr.js": "1.6.0" - } - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - }, - "pumpify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", - "integrity": "sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==", - "requires": { - "duplexify": "3.5.4", - "inherits": "2.0.3", - "pump": "2.0.1" - } - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" - }, - "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "unpipe": "1.0.0" - } - }, - "readable-stream": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", - "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "requires": { - "extend-shallow": "3.0.2", - "safe-regex": "1.1.0" - } - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" - }, - "request": { - "version": "2.85.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", - "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", - "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.3.2", - "har-validator": "5.0.3", - "hawk": "6.0.2", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "oauth-sign": "0.8.2", - "performance-now": "2.1.0", - "qs": "6.5.1", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.4", - "tunnel-agent": "0.6.0", - "uuid": "3.2.1" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" - }, - "retry-axios": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/retry-axios/-/retry-axios-0.3.2.tgz", - "integrity": "sha512-jp4YlI0qyDFfXiXGhkCOliBN1G7fRH03Nqy8YdShzGqbY5/9S2x/IR6C88ls2DFkbWuL3ASkP7QD3pVrNpPgwQ==" - }, - "retry-request": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-3.3.1.tgz", - "integrity": "sha512-PjAmtWIxjNj4Co/6FRtBl8afRP3CxrrIAnUzb1dzydfROd+6xt7xAebFeskgQgkfFf8NmzrXIoaB3HxmswXyxw==", - "requires": { - "request": "2.85.0", - "through2": "2.0.3" - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "requires": { - "ret": "0.1.15" - } - }, - "send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "requires": { - "debug": "2.6.9", - "depd": "1.1.2", - "destroy": "1.0.4", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", - "fresh": "0.5.2", - "http-errors": "1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "2.3.0", - "range-parser": "1.2.0", - "statuses": "1.4.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" - } - } - }, - "serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", - "requires": { - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "parseurl": "1.3.2", - "send": "0.16.2" - } - }, - "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "split-string": "3.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - }, - "sha1": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", - "integrity": "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg=", - "requires": { - "charenc": "0.0.2", - "crypt": "0.0.2" - } - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" - }, - "snakeize": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/snakeize/-/snakeize-0.1.0.tgz", - "integrity": "sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0=" - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "requires": { - "base": "0.11.2", - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "map-cache": "0.2.2", - "source-map": "0.5.7", - "source-map-resolve": "0.5.1", - "use": "3.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "0.1.6" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "0.1.1" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "requires": { - "define-property": "1.0.0", - "isobject": "3.0.1", - "snapdragon-util": "3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "1.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "sntp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "requires": { - "hoek": "4.2.1" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - }, - "source-map-resolve": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", - "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", - "requires": { - "atob": "2.0.3", - "decode-uri-component": "0.2.0", - "resolve-url": "0.2.1", - "source-map-url": "0.4.0", - "urix": "0.1.0" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" - }, - "split-array-stream": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/split-array-stream/-/split-array-stream-1.0.3.tgz", - "integrity": "sha1-0rdajl4Ngk1S/eyLgiWDncLjXfo=", - "requires": { - "async": "2.6.0", - "is-stream-ended": "0.1.3" - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "requires": { - "extend-shallow": "3.0.2" - } - }, - "sshpk": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", - "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - } - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "requires": { - "define-property": "0.2.5", - "object-copy": "0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" - }, - "stream-events": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.2.tgz", - "integrity": "sha1-q/OfZsCJCk63lbyNXoWbJhW1kLI=", - "requires": { - "stubs": "3.0.0" - } - }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" - }, - "string-format-obj": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string-format-obj/-/string-format-obj-1.1.1.tgz", - "integrity": "sha512-Mm+sROy+pHJmx0P/0Bs1uxIX6UhGJGj6xDGQZ5zh9v/SZRmLGevp+p0VJxV7lirrkAmQ2mvva/gHKpnF/pTb+Q==" - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "5.1.1" - } - }, - "stringifier": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/stringifier/-/stringifier-1.3.0.tgz", - "integrity": "sha1-3vGDQvaTPbDy2/yaoCF1tEjBeVk=", - "requires": { - "core-js": "2.5.3", - "traverse": "0.6.6", - "type-name": "2.0.2" - } - }, - "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "stubs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", - "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=" - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "requires": { - "readable-stream": "2.3.5", - "xtend": "4.0.1" - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "requires": { - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "regex-not": "1.0.2", - "safe-regex": "1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "requires": { - "is-number": "3.0.0", - "repeat-string": "1.6.1" - } - }, - "topo": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", - "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=", - "requires": { - "hoek": "2.16.3" - }, - "dependencies": { - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" - } - } - }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "requires": { - "punycode": "1.4.1" - } - }, - "traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=" - }, - "tslib": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", - "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==" - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "5.1.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "optional": true - }, - "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "2.1.18" - } - }, - "type-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/type-name/-/type-name-2.0.2.tgz", - "integrity": "sha1-7+fUEj2KxSr/9/QMfk3sUmYAj7Q=" - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" - }, - "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "requires": { - "arr-union": "3.1.0", - "get-value": "2.0.6", - "is-extendable": "0.1.1", - "set-value": "0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "0.1.1" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "to-object-path": "0.3.0" - } - } - } - }, - "unique-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", - "requires": { - "crypto-random-string": "1.0.0" - } - }, - "universal-deep-strict-equal": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/universal-deep-strict-equal/-/universal-deep-strict-equal-1.2.2.tgz", - "integrity": "sha1-DaSsL3PP95JMgfpN4BjKViyisKc=", - "requires": { - "array-filter": "1.0.0", - "indexof": "0.0.1", - "object-keys": "1.0.11" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "requires": { - "has-value": "0.3.1", - "isobject": "3.0.1" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "requires": { - "get-value": "2.0.6", - "has-values": "0.1.4", - "isobject": "2.1.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" - } - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" - }, - "use": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", - "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", - "requires": { - "kind-of": "6.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "1.3.0" - } - }, - "websocket-driver": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", - "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", - "requires": { - "http-parser-js": "0.4.11", - "websocket-extensions": "0.1.3" - } - }, - "websocket-extensions": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" - }, - "window-size": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", - "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write-file-atomic": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", - "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", - "requires": { - "graceful-fs": "4.1.11", - "imurmurhash": "0.1.4", - "signal-exit": "3.0.2" - } - }, - "xdg-basedir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - }, - "yargs": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", - "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", - "requires": { - "camelcase": "2.1.1", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "os-locale": "1.4.0", - "string-width": "1.0.2", - "window-size": "0.1.4", - "y18n": "3.2.1" - } - } - } -} diff --git a/scripts/build_scripts/android/install_prereqs.sh b/scripts/build_scripts/android/install_prereqs.sh deleted file mode 100755 index f5d6efe9..00000000 --- a/scripts/build_scripts/android/install_prereqs.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/bash -e - -# Copyright 2022 Google LLC - -if [[ $(uname) == "Darwin" ]]; then - platform=darwin - if [[ ! -z "${GHA_INSTALL_CCACHE}" ]]; then - brew install ccache - echo "CCACHE_INSTALLED=1" >> $GITHUB_ENV - fi -elif [[ $(uname) == "Linux" ]]; then - platform=linux - if [[ ! -z "${GHA_INSTALL_CCACHE}" ]]; then - sudo apt install ccache - echo "CCACHE_INSTALLED=1" >> $GITHUB_ENV - fi -else - platform=windows -fi - -if [[ -z $(which cmake) ]]; then - echo "Error, cmake is not installed or is not in the PATH." - exit 1 -fi - -if [[ -z $(which python) ]]; then - echo "Error, python is not installed or is not in the PATH." - exit 1 -else - updated_pip=0 - if ! $(echo "import absl"$'\n' | python - 2> /dev/null); then - echo "Installing python packages." - set -x - # On Windows bash shell, sudo doesn't exist - if [[ $(uname) == "Linux" ]] || [[ $(uname) == "Darwin" ]]; then - sudo python -m pip install --upgrade pip - else - python -m pip install --upgrade pip - fi - pip install absl-py - set +x - fi -fi - -if [[ -z "${ANDROID_HOME}" ]]; then - echo "Error, ANDROID_HOME environment variable is not set." - exit 1 -fi - -if [[ -z "${NDK_ROOT}" || -z $(grep "Pkg\.Revision = 21\." "${NDK_ROOT}/source.properties") ]]; then - if [[ -d /tmp/android-ndk-r21e && \ - -n $(grep "Pkg\.Revision = 21\." "/tmp/android-ndk-r21e/source.properties") ]]; then - echo "Using NDK r21e in /tmp/android-ndk-r21e". - else - echo "NDK_ROOT environment variable is not set, or NDK version is incorrect." - echo "This build recommends NDK r21e, downloading..." - if [[ -z $(which curl) ]]; then - echo "Error, could not run 'curl' to download NDK. Is it in your PATH?" - exit 1 - fi - set +e - # Retry up to 10 times because Curl has a tendency to timeout on - # Github runners. - for retry in {1..10} error; do - if [[ $retry == "error" ]]; then exit 5; fi - curl --http1.1 -LSs \ - "https://dl.google.com/android/repository/android-ndk-r21e-${platform}-x86_64.zip" \ - --output /tmp/android-ndk-r21e.zip && break - sleep 300 - done - set -e - (cd /tmp && unzip -oq android-ndk-r21e.zip && rm -f android-ndk-r21e.zip) - echo "NDK r21e has been downloaded into /tmp/android-ndk-r21e" - fi -fi diff --git a/scripts/build_scripts/build_testapps.json b/scripts/build_scripts/build_testapps.json deleted file mode 100644 index 5b5ef2d1..00000000 --- a/scripts/build_scripts/build_testapps.json +++ /dev/null @@ -1,170 +0,0 @@ -{ - "apis": [ - { - "name": "analytics", - "full_name": "FirebaseAnalytics", - "bundle_id": "com.google.ios.analytics.testapp", - "ios_target": "testapp", - "tvos_target": "", - "testapp_path": "analytics/testapp", - "frameworks": [ - "firebase_analytics.xcframework", - "firebase.xcframework" - ], - "provision": "Google_Development.mobileprovision" - }, - { - "name": "auth", - "full_name": "FirebaseAuth", - "bundle_id": "com.google.FirebaseCppAuthTestApp.dev", - "ios_target": "testapp", - "tvos_target": "", - "testapp_path": "auth/testapp", - "frameworks": [ - "firebase_auth.xcframework", - "firebase.xcframework" - ], - "provision": "Firebase_Cpp_Auth_Test_App_Dev.mobileprovision" - }, - { - "name": "database", - "full_name": "FirebaseDatabase", - "bundle_id": "com.google.firebase.cpp.database.testapp", - "ios_target": "testapp", - "tvos_target": "", - "testapp_path": "database/testapp", - "frameworks": [ - "firebase_auth.xcframework", - "firebase_database.xcframework", - "firebase.xcframework" - ], - "provision": "Firebase_Dev_Wildcard.mobileprovision" - }, - { - "name": "dynamic_links", - "full_name": "FirebaseDynamicLinks", - "bundle_id": "com.google.FirebaseCppDynamicLinksTestApp.dev", - "ios_target": "testapp", - "tvos_target": "", - "testapp_path": "dynamic_links/testapp", - "frameworks": [ - "firebase_dynamic_links.xcframework", - "firebase.xcframework" - ], - "provision": "Firebase_Cpp_Dynamic_Links_Test_App_Dev.mobileprovision" - }, - { - "name": "functions", - "full_name": "FirebaseFunctions", - "bundle_id": "com.google.firebase.cpp.functions.testapp", - "ios_target": "testapp", - "tvos_target": "", - "testapp_path": "functions/testapp", - "frameworks": [ - "firebase_auth.xcframework", - "firebase_functions.xcframework", - "firebase.xcframework" - ], - "provision": "Firebase_Dev_Wildcard.mobileprovision" - }, - { - "name": "gma", - "full_name": "FirebaseGma", - "bundle_id": "com.google.ios.admob.testapp", - "ios_target": "testapp", - "tvos_target": "", - "testapp_path": "gma/testapp", - "frameworks": [ - "firebase_gma.xcframework", - "firebase.xcframework" - ], - "provision": "Google_Development.mobileprovision" - }, - { - "name": "messaging", - "full_name": "FirebaseMessaging", - "bundle_id": "com.google.FirebaseCppMessagingTestApp.dev", - "ios_target": "testapp", - "tvos_target": "", - "testapp_path": "messaging/testapp", - "frameworks": [ - "firebase_messaging.xcframework", - "firebase.xcframework" - ], - "provision": "Firebase_Cpp_Messaging_Test_App_Dev.mobileprovision" - }, - { - "name": "remote_config", - "full_name": "FirebaseRemoteConfig", - "bundle_id": "com.google.ios.remoteconfig.testapp", - "ios_target": "testapp", - "tvos_target": "", - "testapp_path": "remote_config/testapp", - "frameworks": [ - "firebase_remote_config.xcframework", - "firebase.xcframework" - ], - "provision": "Google_Development.mobileprovision" - }, - { - "name": "storage", - "full_name": "FirebaseStorage", - "bundle_id": "com.google.firebase.cpp.storage.testapp", - "ios_target": "testapp", - "tvos_target": "", - "testapp_path": "storage/testapp", - "frameworks": [ - "firebase_storage.xcframework", - "firebase_auth.xcframework", - "firebase.xcframework" - ], - "provision": "Firebase_Dev_Wildcard.mobileprovision" - }, - { - "name": "firestore", - "full_name": "FirebaseFirestore", - "bundle_id": "com.google.firebase.cpp.firestore.testapp", - "ios_target": "testapp", - "tvos_target": "", - "testapp_path": "firestore/testapp", - "frameworks": [ - "firebase_firestore.xcframework", - "firebase_auth.xcframework", - "firebase.xcframework" - ], - "provision": "Firebase_Dev_Wildcard.mobileprovision", - "minify": "proguard" - } - ], - "apple_team_id": "REPLACE_ME_TEMP_INVALID_ID", - "compiler_dict": { - "gcc-4.8": [ - "-DCMAKE_C_COMPILER=gcc-4.8", - "-DCMAKE_CXX_COMPILER=g++-4.8" - ], - "gcc-7": [ - "-DCMAKE_C_COMPILER=gcc-7", - "-DCMAKE_CXX_COMPILER=g++-7" - ], - "gcc-9": [ - "-DCMAKE_C_COMPILER=gcc-9", - "-DCMAKE_CXX_COMPILER=g++-9" - ], - "clang-5.0": [ - "-DCMAKE_C_COMPILER=clang-5.0", - "-DCMAKE_CXX_COMPILER=clang++-5.0" - ], - "VisualStudio2015": [ - "-G", - "Visual Studio 14 2015 Win64" - ], - "VisualStudio2017": [ - "-G", - "Visual Studio 15 2017 Win64" - ], - "VisualStudio2019": [ - "-G", - "Visual Studio 16 2019" - ] - } - } diff --git a/scripts/build_scripts/build_testapps.py b/scripts/build_scripts/build_testapps.py deleted file mode 100644 index 3caf85f0..00000000 --- a/scripts/build_scripts/build_testapps.py +++ /dev/null @@ -1,718 +0,0 @@ -# Copyright 2022 Google LLC -# -# 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. - -r"""Build automation tool for Firebase C++ testapps for desktop and mobile. - -USAGE: - -This tool has a number of dependencies (listed below). Once those are taken -care of, here is an example of an execution of the tool (on MacOS): - -python build_testapps.py --t auth,messaging --p iOS --s /tmp/firebase-cpp-sdk - -Critical flags: ---t (full name: testapps, default: None) ---p (full name: platforms, default: None) ---s (full name: packaged_sdk, default: None) - -By default, this tool will build integration tests from source, which involves - -Under most circumstances the other flags don't need to be set, but can be -seen by running --help. Note that all path flags will forcefully expand -the user ~. - - -DEPENDENCIES: - -----Firebase Repo---- -The Firebase C++ Quickstart repo must be locally present. -Path specified by the flag: - - --repo_dir (default: current working directory) - -----Python Dependencies---- -The requirements.txt file has the required dependencies for this Python tool. - - pip install -r requirements.txt - -----CMake (Desktop only)---- -CMake must be installed and on the system path. - -----Environment Variables (Android only)---- -If building for Android, gradle requires several environment variables. -The following lists expected variables, and examples of what -a configured value may look like on MacOS: - - JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-8-latest/Contents/Home - ANDROID_HOME=/Users/user_name/Library/Android/sdk - ANDROID_SDK_HOME=/Users/user_name/Library/Android/sdk - ANDROID_NDK_HOME=/Users/user_name/Library/Android/sdk/ndk-bundle - -Or on Linux: - JAVA_HOME=/usr/local/buildtools/java/jdk/ - ANDROID_HOME=~/Android/Sdk - ANDROID_SDK_HOME=~/Android/Sdk - ANDROID_NDK_HOME=~/Android/Sdk/ndk - -If using this tool frequently, you will likely find it convenient to -modify your bashrc file to automatically set these variables. - -""" - -import attr -import datetime -import json -import os -import platform -import shutil -import stat -import subprocess -import sys -import tempfile - -from absl import app -from absl import flags -from absl import logging -from distutils import dir_util - -import utils -import config_reader -import xcodebuild - -# Environment variables -_JAVA_HOME = "JAVA_HOME" -_ANDROID_HOME = "ANDROID_HOME" -_ANDROID_SDK_HOME = "ANDROID_SDK_HOME" -_NDK_ROOT = "NDK_ROOT" -_ANDROID_NDK_HOME = "ANDROID_NDK_HOME" - -# Platforms -_ANDROID = "Android" -_IOS = "iOS" -_TVOS = "tvOS" -_DESKTOP = "Desktop" -_SUPPORTED_PLATFORMS = (_ANDROID, _IOS, _TVOS, _DESKTOP) - -# Architecture -_SUPPORTED_ARCHITECTURES = ("x64", "x86", "arm64") - -# Values for iOS SDK flag (where the iOS app will run) -_APPLE_SDK_DEVICE = "real" -_APPLE_SDK_SIMULATOR = "virtual" -_SUPPORTED_APPLE_SDK = (_APPLE_SDK_DEVICE, _APPLE_SDK_SIMULATOR) - -_DEFAULT_RUN_TIMEOUT_SECONDS = 4800 # 1 hour 20 min - -FLAGS = flags.FLAGS - -flags.DEFINE_string( - "packaged_sdk", None, "Firebase SDK directory.") - -flags.DEFINE_string( - "output_directory", "~", - "Build output will be placed in this directory.") - -flags.DEFINE_string( - "artifact_name", "local-build", - "artifacts will be created and placed in output_directory." - " testapps artifact is testapps-$artifact_name;" - " build log artifact is build-results-$artifact_name.log.") - -flags.DEFINE_string( - "repo_dir", os.getcwd(), - "Firebase C++ Quickstart Git repository. Current directory by default.") - -flags.DEFINE_list( - "testapps", None, "Which testapps (Firebase APIs) to build, e.g." - " 'analytics,auth'.", - short_name="t") - -flags.DEFINE_list( - "platforms", None, "Which platforms to build. Can be Android, iOS and/or" - " Desktop", short_name="p") - -flags.DEFINE_bool( - "add_timestamp", True, - "Add a timestamp to the output directory for disambiguation." - " Recommended when running locally, so each execution gets its own " - " directory.") - -flags.DEFINE_list( - "ios_sdk", _APPLE_SDK_DEVICE, - "(iOS only) Build for real device (.ipa), virtual device / simulator (.app), " - "or both. Building for both will produce both an .app and an .ipa.") - -flags.DEFINE_list( - "tvos_sdk", _APPLE_SDK_SIMULATOR, - "(tvOS only) Build for real device (.ipa), virtual device / simulator (.app), " - "or both. Building for both will produce both an .app and an .ipa.") - -flags.DEFINE_bool( - "update_pod_repo", True, - "(iOS/tvOS only) Will run 'pod repo update' before building for iOS/tvOS to update" - " the local spec repos available on this machine. Must also include iOS/tvOS" - " in platforms flag.") - -flags.DEFINE_string( - "compiler", None, - "(Desktop only) Specify the compiler with CMake during the testapps build." - " Check the config file to see valid choices for this flag." - " If none, will invoke cmake without specifying a compiler.") - -flags.DEFINE_string( - "arch", "x64", - "(Desktop only) Which architecture to build: x64 (all), x86 (Windows/Linux), " - "or arm64 (Mac only).") - -# Get the number of CPUs for the default value of FLAGS.jobs -CPU_COUNT = os.cpu_count(); -# If CPU count couldn't be determined, default to 2. -DEFAULT_CPU_COUNT = 2 -if CPU_COUNT is None: CPU_COUNT = DEFAULT_CPU_COUNT -# Cap at 4 CPUs. -MAX_CPU_COUNT = 4 -if CPU_COUNT > MAX_CPU_COUNT: CPU_COUNT = MAX_CPU_COUNT - -flags.DEFINE_integer( - "jobs", CPU_COUNT, - "(Desktop only) If > 0, pass in -j to make CMake parallelize the" - " build. Defaults to the system's CPU count (max %s)." % MAX_CPU_COUNT) - -flags.DEFINE_multi_string( - "cmake_flag", None, - "Pass an additional flag to the CMake configure step." - " This option can be specified multiple times.") - -flags.register_validator( - "platforms", - lambda p: all(platform in _SUPPORTED_PLATFORMS for platform in p), - message="Valid platforms: " + ",".join(_SUPPORTED_PLATFORMS), - flag_values=FLAGS) - -flags.register_validator( - "ios_sdk", - lambda s: all(ios_sdk in _SUPPORTED_APPLE_SDK for ios_sdk in s), - message="Valid platforms: " + ",".join(_SUPPORTED_APPLE_SDK), - flag_values=FLAGS) - -flags.register_validator( - "tvos_sdk", - lambda s: all(tvos_sdk in _SUPPORTED_APPLE_SDK for tvos_sdk in s), - message="Valid platforms: " + ",".join(_SUPPORTED_APPLE_SDK), - flag_values=FLAGS) - -flags.DEFINE_bool( - "short_output_paths", False, - "Use short directory names for output paths. Useful to avoid hitting file " - "path limits on Windows.") - -flags.DEFINE_bool( - "gha_build", False, - "Set to true if this is a GitHub Actions build.") - -def main(argv): - if len(argv) > 1: - raise app.UsageError("Too many command-line arguments.") - - platforms = FLAGS.platforms - testapps = FLAGS.testapps - - sdk_dir = _fix_path(FLAGS.packaged_sdk) - root_output_dir = _fix_path(FLAGS.output_directory) - repo_dir = _fix_path(FLAGS.repo_dir) - - update_pod_repo = FLAGS.update_pod_repo - if FLAGS.add_timestamp: - timestamp = datetime.datetime.now().strftime("%Y_%m_%d-%H_%M_%S") - else: - timestamp = "" - - if FLAGS.short_output_paths: - output_dir = os.path.join(root_output_dir, "ta") - else: - output_dir = os.path.join(root_output_dir, "testapps" + timestamp) - - config = config_reader.read_config() - - xcframework_dir = os.path.join(sdk_dir, "xcframeworks") - xcframework_exist = os.path.isdir(xcframework_dir) - if not xcframework_exist: - if _IOS in platforms: - _build_xcframework_from_repo(repo_dir, "ios", testapps, config) - if _TVOS in platforms: - _build_xcframework_from_repo(repo_dir, "tvos", testapps, config) - - if update_pod_repo and (_IOS in platforms or _TVOS in platforms): - _run(["pod", "repo", "update"]) - - cmake_flags = _get_desktop_compiler_flags(FLAGS.compiler, config.compilers) - - if (_DESKTOP in platforms and utils.is_linux_os() and FLAGS.arch == "x86"): - # Write out a temporary toolchain file to force 32-bit Linux builds, as - # the SDK-included toolchain file may not be present when building against - # the packaged SDK. - temp_toolchain_file = tempfile.NamedTemporaryFile("w+", suffix=".cmake") - temp_toolchain_file.writelines([ - 'set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")\n', - 'set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")\n', - 'set(CMAKE_LIBRARY_PATH "/usr/lib/i386-linux-gnu")\n', - 'set(INCLUDE_DIRECTORIES ${INCLUDE_DIRECTORIES} "/usr/include/i386-linux-gnu")\n']) - temp_toolchain_file.flush() - # Leave the file open, as it will be deleted on close, i.e. when this script exits. - # (On Linux, the file can be opened a second time by cmake while still open by - # this script) - cmake_flags.extend(["-DCMAKE_TOOLCHAIN_FILE=%s" % temp_toolchain_file.name]) - - if FLAGS.cmake_flag: - cmake_flags.extend(FLAGS.cmake_flag) - - failures = [] - for testapp in testapps: - api_config = config.get_api(testapp) - testapp_dirs = [api_config.testapp_path] - for testapp_dir in testapp_dirs: - logging.info("BEGIN building for %s: %s", testapp, testapp_dir) - failures += _build( - testapp=testapp, - platforms=platforms, - api_config=config.get_api(testapp), - testapp_dir=testapp_dir, - output_dir=output_dir, - sdk_dir=sdk_dir, - xcframework_exist=xcframework_exist, - repo_dir=repo_dir, - ios_sdk=FLAGS.ios_sdk, - tvos_sdk=FLAGS.tvos_sdk, - cmake_flags=cmake_flags, - short_output_paths=FLAGS.short_output_paths) - logging.info("END building for %s", testapp) - - _collect_integration_tests(testapps, root_output_dir, output_dir, FLAGS.artifact_name) - - _summarize_results(testapps, platforms, failures, root_output_dir, FLAGS.artifact_name) - return 1 if failures else 0 - - -def _build( - testapp, platforms, api_config, testapp_dir, output_dir, sdk_dir, xcframework_exist, - repo_dir, ios_sdk, tvos_sdk, cmake_flags, short_output_paths): - """Builds one testapp on each of the specified platforms.""" - os.chdir(repo_dir) - project_dir = os.path.join(output_dir, api_config.name) - if short_output_paths: - # Combining the first letter of every part separated by underscore for - # testapp paths. This is a trick to reduce file path length as we were - # exceeding the limit on Windows. - testapp_dir_parts = os.path.basename(testapp_dir).split('_') - output_testapp_dir = ''.join([x[0] for x in testapp_dir_parts]) - else: - output_testapp_dir = os.path.basename(testapp_dir) - - project_dir = os.path.join(project_dir, output_testapp_dir) - - logging.info("Copying testapp project to %s", project_dir) - os.makedirs(project_dir) - dir_util.copy_tree(testapp_dir, project_dir) - - logging.info("Changing directory to %s", project_dir) - os.chdir(project_dir) - - # TODO(DDB): remove - # _run_setup_script(repo_dir, project_dir) - - failures = [] - - if _DESKTOP in platforms: - logging.info("BEGIN %s, %s", testapp, _DESKTOP) - try: - _build_desktop(sdk_dir, cmake_flags) - except subprocess.SubprocessError as e: - failures.append( - Failure(testapp=testapp, platform=_DESKTOP, error_message=str(e))) - _rm_dir_safe(os.path.join(project_dir, "bin")) - logging.info("END %s, %s", testapp, _DESKTOP) - - if _ANDROID in platforms: - logging.info("BEGIN %s, %s", testapp, _ANDROID) - try: - _validate_android_environment_variables() - _build_android(project_dir, sdk_dir) - except subprocess.SubprocessError as e: - failures.append( - Failure(testapp=testapp, platform=_ANDROID, error_message=str(e))) - _rm_dir_safe(os.path.join(project_dir, "build", "intermediates")) - _rm_dir_safe(os.path.join(project_dir, ".externalNativeBuild")) - logging.info("END %s, %s", testapp, _ANDROID) - - if _IOS in platforms: - logging.info("BEGIN %s, %s", testapp, _IOS) - try: - _build_apple( - sdk_dir=sdk_dir, - xcframework_exist=xcframework_exist, - project_dir=project_dir, - repo_dir=repo_dir, - api_config=api_config, - target=api_config.ios_target, - scheme=api_config.ios_scheme, - apple_platfrom=_IOS, - apple_sdk=ios_sdk) - - except subprocess.SubprocessError as e: - failures.append( - Failure(testapp=testapp, platform=_IOS, error_message=str(e))) - logging.info("END %s, %s", testapp, _IOS) - - if _TVOS in platforms and api_config.tvos_target: - logging.info("BEGIN %s, %s", testapp, _TVOS) - try: - _build_apple( - sdk_dir=sdk_dir, - xcframework_exist=xcframework_exist, - project_dir=project_dir, - repo_dir=repo_dir, - api_config=api_config, - target=api_config.tvos_target, - scheme=api_config.tvos_scheme, - apple_platfrom=_TVOS, - apple_sdk=tvos_sdk) - except subprocess.SubprocessError as e: - failures.append( - Failure(testapp=testapp, platform=_TVOS, error_message=str(e))) - logging.info("END %s, %s", testapp, _TVOS) - - return failures - - -def _collect_integration_tests(testapps, root_output_dir, output_dir, artifact_name): - testapps_artifact_dir = "testapps-" + artifact_name - android_testapp_extension = ".apk" - ios_testapp_extension = ".ipa" - ios_simualtor_testapp_extension = ".app" - desktop_testapp_name = "testapp" - if platform.system() == "Windows": - desktop_testapp_name += ".exe" - - testapp_paths = [] - testapp_google_services = {} - for file_dir, directories, file_names in os.walk(output_dir): - for directory in directories: - if directory.endswith(ios_simualtor_testapp_extension): - testapp_paths.append(os.path.join(file_dir, directory)) - for file_name in file_names: - if ((file_name == desktop_testapp_name and "ios_build" not in file_dir) - or file_name.endswith(android_testapp_extension) - or file_name.endswith(ios_testapp_extension)): - testapp_paths.append(os.path.join(file_dir, file_name)) - if (file_name == "google-services.json"): - testapp_google_services[file_dir.split(os.path.sep)[-2]] = os.path.join(file_dir, file_name) - - artifact_path = os.path.join(root_output_dir, testapps_artifact_dir) - _rm_dir_safe(artifact_path) - for testapp in testapps: - os.makedirs(os.path.join(artifact_path, testapp)) - for path in testapp_paths: - for testapp in testapps: - if testapp in path: - if os.path.isfile(path): - shutil.copy(path, os.path.join(artifact_path, testapp)) - if path.endswith(desktop_testapp_name) and testapp_google_services.get(testapp): - shutil.copy(testapp_google_services[testapp], os.path.join(artifact_path, testapp)) - else: - dir_util.copy_tree(path, os.path.join(artifact_path, testapp, os.path.basename(path))) - break - - -def _write_summary(testapp_dir, summary, file_name="summary.log"): - with open(os.path.join(testapp_dir, file_name), "a") as f: - timestamp = datetime.datetime.now().strftime("%Y_%m_%d-%H_%M_%S") - f.write("\n%s\n%s\n" % (timestamp, summary)) - - -def _summarize_results(testapps, platforms, failures, root_output_dir, artifact_name): - """Logs a readable summary of the results of the build.""" - file_name = "build-results-" + artifact_name + ".log" - - summary = [] - summary.append("BUILD SUMMARY:") - summary.append("TRIED TO BUILD: " + ",".join(testapps)) - summary.append("ON PLATFORMS: " + ",".join(platforms)) - - if not failures: - summary.append("ALL BUILDS SUCCEEDED") - else: - summary.append("SOME ERRORS OCCURRED:") - for i, failure in enumerate(failures, start=1): - summary.append("%d: %s" % (i, failure.describe())) - summary = "\n".join(summary) - - logging.info(summary) - _write_summary(root_output_dir, summary, file_name=file_name) - - summary_json = {} - summary_json["type"] = "build" - summary_json["testapps"] = testapps - summary_json["errors"] = {failure.testapp:failure.error_message for failure in failures} - with open(os.path.join(root_output_dir, file_name+".json"), "a") as f: - f.write(json.dumps(summary_json, indent=2)) - - -def _build_desktop(sdk_dir, cmake_flags): - cmake_configure_cmd = ["cmake", ".", "-DCMAKE_BUILD_TYPE=Debug", - "-DFIREBASE_CPP_SDK_DIR=" + sdk_dir] - if utils.is_windows_os(): - cmake_configure_cmd += ["-A", - "Win32" if FLAGS.arch == "x86" else FLAGS.arch] - elif utils.is_mac_os(): - # Ensure that correct Mac architecture is built. - cmake_configure_cmd += ["-DCMAKE_OSX_ARCHITECTURES=%s" % - ("arm64" if FLAGS.arch == "arm64" else "x86_64")] - - _run(cmake_configure_cmd + cmake_flags) - _run(["cmake", "--build", ".", "--config", "Debug"] + - ["-j", str(FLAGS.jobs)] if FLAGS.jobs > 0 else []) - - -def _get_desktop_compiler_flags(compiler, compiler_table): - """Returns the command line flags for this compiler.""" - if not compiler: # None is an acceptable default value - return [] - try: - return compiler_table[compiler] - except KeyError: - valid_keys = ", ".join(compiler_table.keys()) - raise ValueError( - "Given compiler: %s. Valid compilers: %s" % (compiler, valid_keys)) - - -def _build_android(project_dir, sdk_dir): - """Builds an Android binary (apk).""" - if platform.system() == "Windows": - gradlew = "gradlew.bat" - sdk_dir = sdk_dir.replace("\\", "/") # Gradle misinterprets backslashes. - else: - gradlew = "./gradlew" - logging.info("Patching gradle properties with path to SDK") - gradle_properties = os.path.join(project_dir, "gradle.properties") - with open(gradle_properties, "a+") as f: - f.write("systemProp.firebase_cpp_sdk.dir=" + sdk_dir + "\n") - f.write("http.keepAlive=false\n") - f.write("maven.wagon.http.pool=false\n") - f.write("maven.wagon.httpconnectionManager.ttlSeconds=120") - # This will log the versions of dependencies for debugging purposes. - _run([gradlew, "dependencies", "--configuration", "debugCompileClasspath",]) - _run([gradlew, "assembleDebug", "--stacktrace"]) - - -def _validate_android_environment_variables(): - """Checks environment variables that may be required for Android.""" - # Ultimately we let the gradle build be the source of truth on what env vars - # are required, but try to repair holes and log warnings if we can't. - android_home = os.environ.get(_ANDROID_HOME) - if not os.environ.get(_JAVA_HOME): - logging.warning("%s not set", _JAVA_HOME) - if not os.environ.get(_ANDROID_SDK_HOME): - if android_home: # Use ANDROID_HOME as backup for ANDROID_SDK_HOME - os.environ[_ANDROID_SDK_HOME] = android_home - logging.info("%s not found, using %s", _ANDROID_SDK_HOME, _ANDROID_HOME) - else: - logging.warning("Missing: %s and %s", _ANDROID_SDK_HOME, _ANDROID_HOME) - # Different environments may have different NDK env vars specified. We look - # for these, in this order, and set the others to the first found. - # If none are set, we check the default location for the ndk. - ndk_path = None - ndk_vars = [_NDK_ROOT, _ANDROID_NDK_HOME] - for env_var in ndk_vars: - val = os.environ.get(env_var) - if val: - ndk_path = val - break - if not ndk_path: - if android_home: - default_ndk_path = os.path.join(android_home, "ndk-bundle") - if os.path.isdir(default_ndk_path): - ndk_path = default_ndk_path - if ndk_path: - logging.info("Found ndk: %s", ndk_path) - for env_var in ndk_vars: - if os.environ.get(env_var) != ndk_path: - logging.info("Setting %s to %s", env_var, ndk_path) - os.environ[env_var] = ndk_path - else: - logging.warning("No NDK env var set. Set one of %s", ", ".join(ndk_vars)) - -# build required ios xcframeworks based on makefiles -# the xcframeworks locates at repo_dir/ios_build -def _build_xcframework_from_repo(repo_dir, apple_platform, testapps, config): - """Builds xcframework from SDK source.""" - output_path = os.path.join(repo_dir, apple_platform + "_build") - _rm_dir_safe(output_path) - xcframework_builder = os.path.join( - repo_dir, "scripts", "gha", "build_ios_tvos.py") - - # build only required targets to save time - target = set() - for testapp in testapps: - api_config = config.get_api(testapp) - if apple_platform == "ios" or (apple_platform == "tvos" and api_config.tvos_target): - for framework in api_config.frameworks: - # firebase_analytics.framework -> firebase_analytics - target.add(os.path.splitext(framework)[0]) - - # firebase is not a target in CMake, firebase_app is the target - # firebase_app will be built by other target as well - target.remove("firebase") - - framework_builder_args = [ - sys.executable, xcframework_builder, - "-b", output_path, - "-s", repo_dir, - "-o", apple_platform, - "-t" - ] - framework_builder_args.extend(target) - _run(framework_builder_args) - - -def _build_apple( - sdk_dir, xcframework_exist, project_dir, repo_dir, api_config, - target, scheme, apple_platfrom, apple_sdk): - """Builds an iOS application (.app, .ipa or both).""" - build_dir = apple_platfrom.lower() + "_build" - if not xcframework_exist: - sdk_dir = os.path.join(repo_dir, build_dir) - - build_dir = os.path.join(project_dir, build_dir) - os.makedirs(build_dir) - - logging.info("Copying XCFrameworks") - framework_src_dir = os.path.join(sdk_dir, "xcframeworks") - framework_paths = [] # Paths to the copied frameworks. - for framework in api_config.frameworks: - framework_src_path = os.path.join(framework_src_dir, framework) - framework_dest_path = os.path.join(project_dir, "Frameworks", framework) - dir_util.copy_tree(framework_src_path, framework_dest_path) - framework_paths.append(framework_dest_path) - - _run(["pod", "install"]) - - entitlements_path = os.path.join( - project_dir, api_config.ios_target + ".entitlements") - xcode_tool_path = os.path.join( - repo_dir, "scripts", "gha", "integration_testing", "xcode_tool.rb") - xcode_patcher_args = [ - "ruby", xcode_tool_path, - "--XCodeCPP.xcodeProjectDir", project_dir, - "--XCodeCPP.target", target, - "--XCodeCPP.frameworks", ",".join(framework_paths) - ] - # Internal integration tests require the SDK root as an include path. - if repo_dir and api_config.internal_testapp_path: - xcode_patcher_args.extend(("--XCodeCPP.include", repo_dir)) - if os.path.isfile(entitlements_path): # Not all testapps require entitlements - logging.info("Entitlements file detected.") - xcode_patcher_args.extend(("--XCodeCPP.entitlement", entitlements_path)) - else: - logging.info("No entitlements found at %s.", entitlements_path) - _run(xcode_patcher_args) - - xcode_path = os.path.join(project_dir, "integration_test.xcworkspace") - if _APPLE_SDK_SIMULATOR in apple_sdk: - _run( - xcodebuild.get_args_for_build( - path=xcode_path, - scheme=scheme, - output_dir=build_dir, - apple_platfrom=apple_platfrom, - apple_sdk=_APPLE_SDK_SIMULATOR, - configuration="Debug")) - - if _APPLE_SDK_DEVICE in apple_sdk: - _run( - xcodebuild.get_args_for_build( - path=xcode_path, - scheme=scheme, - output_dir=build_dir, - apple_platfrom=apple_platfrom, - apple_sdk=_APPLE_SDK_DEVICE, - configuration="Debug")) - - xcodebuild.generate_unsigned_ipa( - output_dir=build_dir, configuration="Debug") - - -# This should be executed before performing any builds. -def _run_setup_script(root_dir, testapp_dir): - """Runs the setup_integration_tests.py script.""" - # This script will download gtest to its own directory. - # The CMake projects were configured to download gtest, but this was - # found to be flaky and errors didn't propagate up the build system - # layers. The workaround is to download gtest with this script and copy it. - downloader_dir = os.path.join(root_dir, "testing", "test_framework") - _run([sys.executable, os.path.join(downloader_dir, "download_googletest.py")]) - # Copies shared test framework files into the project, including gtest. - script_path = os.path.join(root_dir, "setup_integration_tests.py") - _run([sys.executable, script_path, testapp_dir]) - - -def _run(args, timeout=_DEFAULT_RUN_TIMEOUT_SECONDS, capture_output=False, text=None, check=True): - """Executes a command in a subprocess.""" - logging.info("Running in subprocess: %s", " ".join(args)) - return subprocess.run( - args=args, - timeout=timeout, - capture_output=capture_output, - text=text, - check=check) - - -def _handle_readonly_file(func, path, excinfo): - """Function passed into shutil.rmtree to handle Access Denied error""" - os.chmod(path, stat.S_IWRITE) - func(path) # will re-throw if a different error occurrs - - -def _rm_dir_safe(directory_path): - """Removes directory at given path. No error if dir doesn't exist.""" - logging.info("Deleting %s...", directory_path) - try: - shutil.rmtree(directory_path, onerror=_handle_readonly_file) - except OSError as e: - # There are two known cases where this can happen: - # The directory doesn't exist (FileNotFoundError) - # A file in the directory is open in another process (PermissionError) - logging.warning("Failed to remove directory:\n%s", e.strerror) - - -def _fix_path(path): - """Expands ~, normalizes slashes, and converts relative paths to absolute.""" - return os.path.abspath(os.path.expanduser(path)) - - -@attr.s(frozen=True, eq=False) -class Failure(object): - """Holds context for the failure of a testapp to build/run.""" - testapp = attr.ib() - platform = attr.ib() - error_message = attr.ib() - - def describe(self): - return "%s, %s: %s" % (self.testapp, self.platform, self.error_message) - - -if __name__ == "__main__": - flags.mark_flag_as_required("testapps") - flags.mark_flag_as_required("platforms") - flags.mark_flag_as_required("packaged_sdk") - app.run(main) diff --git a/scripts/build_scripts/config_reader.py b/scripts/build_scripts/config_reader.py deleted file mode 100644 index a24f5d7a..00000000 --- a/scripts/build_scripts/config_reader.py +++ /dev/null @@ -1,139 +0,0 @@ -# Copyright 2022 Google LLC -# -# 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. - -"""A utility for working with testapp builder JSON files. - -This module handles loading the central configuration file for a testapp -builder, returning a 'Config' object that exposes all the data. - -The motivation for loading the config into a class as opposed to returning -the loaded JSON directly is to validate the data upfront, to fail fast if -anything is missing or formatted incorrectly. - -Example of such a configuration file: - -{ - "apis": [ - { - "name": "analytics", - "full_name": "FirebaseAnalytics", - "bundle_id": "com.google.ios.analytics.testapp", - "ios_target": "testapp", - "tvos_target": "", - "testapp_path": "analytics/testapp", - "frameworks": [ - "firebase_analytics.framework", - "firebase.framework" - ], - "provision": "Google_Development.mobileprovision" - }, - { - "name": "admob", - "full_name": "FirebaseAdmob", - "bundle_id": "com.google.ios.admob.testapp", - "ios_target": "testapp", - "tvos_target": "", - "testapp_path": "admob/testapp", - "frameworks": [ - "firebase_admob.framework", - "firebase.framework" - ], - "provision": "Google_Development.mobileprovision" - } - ], - "dev_team": "ABCDEFGHIJK" -} - -""" - -import json -import os -import pathlib - -import attr - -_DEFAULT_CONFIG_NAME = "build_testapps.json" - - -def read_config(path=None): - """Creates an in-memory 'Config' object out of a testapp config file. - - Args: - path (str): Path to a testapp builder config file. If not specified, will - look for 'build_testapps.json' in the same directory as this file. - - Returns: - Config: All of the testapp builder's configuration. - - """ - if not path: - directory = pathlib.Path(__file__).parent.absolute() - path = os.path.join(directory, _DEFAULT_CONFIG_NAME) - with open(path, "r") as config: - config = json.load(config) - api_configs = dict() - try: - for api in config["apis"]: - api_name = api["name"] - api_configs[api_name] = APIConfig( - name=api_name, - full_name=api["full_name"], - bundle_id=api["bundle_id"], - ios_target=api["ios_target"], - tvos_target=api["tvos_target"], - ios_scheme=api["ios_target"], # Scheme assumed to be same as target. - tvos_scheme=api["tvos_target"], - testapp_path=api["testapp_path"], - internal_testapp_path=api.get("internal_testapp_path", None), - frameworks=api["frameworks"], - provision=api["provision"], - minify=api.get("minify", None)) - return Config( - apis=api_configs, - compilers=config["compiler_dict"]) - except (KeyError, TypeError, IndexError): - # The error will be cryptic on its own, so we dump the JSON to - # offer context, then reraise the error. - print( - "Error occurred while parsing config. Full config dump:\n" - + json.dumps(config, sort_keys=True, indent=4, separators=(",", ":"))) - raise - - -@attr.s(frozen=True, eq=False) -class Config(object): - apis = attr.ib() # Mapping of str: APIConfig - compilers = attr.ib() - - def get_api(self, api): - """Returns the APIConfig object for the given api, e.g. 'analytics'.""" - return self.apis[api] - - -@attr.s(frozen=True, eq=False) -class APIConfig(object): - """Holds all the configuration for a single testapp project.""" - name = attr.ib() - full_name = attr.ib() - bundle_id = attr.ib() - ios_target = attr.ib() - tvos_target = attr.ib() - ios_scheme = attr.ib() - tvos_scheme = attr.ib() - testapp_path = attr.ib() # testapp dir relative to sdk root - internal_testapp_path = attr.ib() # Internal testdir dir relative to sdk root - frameworks = attr.ib() # Required custom xcode frameworks - provision = attr.ib() # Path to the local mobile provision - minify = attr.ib() # (Optional) Android minification. - diff --git a/scripts/build_scripts/python_requirements.txt b/scripts/build_scripts/python_requirements.txt deleted file mode 100644 index 214a8aac..00000000 --- a/scripts/build_scripts/python_requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -attrs -absl-py diff --git a/scripts/build_scripts/utils.py b/scripts/build_scripts/utils.py deleted file mode 100644 index 631dc8df..00000000 --- a/scripts/build_scripts/utils.py +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2022 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. - -""" -Helper functions that are shared amongst prereqs and build scripts across various -platforms. -""" - -import distutils.spawn -import platform -import shutil -import subprocess -import os -import urllib.request - -def run_command(cmd, capture_output=False, cwd=None, check=False, as_root=False, - print_cmd=True): - """Run a command. - - Args: - cmd (list(str)): Command to run as a list object. - Eg: ['ls', '-l']. - capture_output (bool): Capture the output of this command. - Output can be accessed as .stdout - cwd (str): Directory to execute the command from. - check (bool): Raises a CalledProcessError if True and the command errored out - as_root (bool): Run command as root user with admin priveleges (supported on mac and linux). - print_cmd (bool): Print the command we are running to stdout. - - Raises: - (subprocess.CalledProcessError): If command errored out and `text=True` - - Returns: - (`subprocess.CompletedProcess`): object containing information from - command execution - """ - - if as_root and (is_mac_os() or is_linux_os()): - cmd.insert(0, 'sudo') - - cmd_string = ' '.join(cmd) - if print_cmd: - print('Running cmd: {0}\n'.format(cmd_string)) - # If capture_output is requested, we also set text=True to store the returned value of the - # command as a string instead of bytes object - return subprocess.run(cmd, capture_output=capture_output, cwd=cwd, - check=check, text=capture_output) - - -def is_command_installed(tool): - """Check if a command is installed on the system.""" - return distutils.spawn.find_executable(tool) - - -def delete_directory(dir_path): - """Recursively delete a valid directory""" - if os.path.exists(dir_path): - shutil.rmtree(dir_path) - - -def download_file(url, file_path): - """Download from url and save to specified file path.""" - with urllib.request.urlopen(url) as response, open(file_path, 'wb') as out_file: - shutil.copyfileobj(response, out_file) - - -def unpack_files(archive_file_path, output_dir=None): - """Unpack/extract an archive to specified output_directory""" - shutil.unpack_archive(archive_file_path, output_dir) - - -def is_windows_os(): - return platform.system() == 'Windows' - - -def is_mac_os(): - return platform.system() == 'Darwin' - - -def is_linux_os(): - return platform.system() == 'Linux' diff --git a/scripts/build_scripts/xcodebuild.py b/scripts/build_scripts/xcodebuild.py deleted file mode 100644 index b60c70dc..00000000 --- a/scripts/build_scripts/xcodebuild.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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. - -"""Helper module for working with xcode projects. - -The tool xcodebuild provides support to build xcode projects from the command -line. The motivation was to simplify usage of xcodebuild, since it was non-trivial -to figure out which flags were needed to get it working in a CI environment. -The options required by the methods in this module were found to work both -locally and on CI, with both the Unity and C++ projects. - -get_args_for_build() method doesn't performing operations with xcodebuild directly, -this module returns arg sequences. These sequences can be passed to e.g. -subprocess.run to execute the operations. - -get_args_for_build() support either device or simulator builds. For simulator -builds, it suffices to use get_args_for_build() to create a .app that can be -used with simulators. For unsigned device builds, generate .app via -get_args_for_build() step and then use generate_unsigned_ipa() to package -the .app to .ipa. - -""" - -import os -import shutil - -def get_args_for_build( - path, scheme, output_dir, apple_platfrom, apple_sdk, configuration): - """Constructs subprocess args for an unsigned xcode build. - - Args: - path (str): Full path to the project or workspace to build. Must end in - either .xcodeproj or .xcworkspace. - scheme (str): Name of the scheme to build. - output_dir (str): Directory for the resulting build artifacts. Will be - created if it doesn't already exist. - apple_platfrom (str): iOS or tvOS. - apple_sdk (str): Where this build will be run: real device or virtual device (simulator). - configuration (str): Value for the -configuration flag. - - Returns: - Sequence of strings, corresponding to valid args for a subprocess call. - - """ - args = [ - "xcodebuild", - "-sdk", _get_apple_env_from_target(apple_platfrom, apple_sdk), - "-scheme", scheme, - "-configuration", configuration, - "-quiet", - "BUILD_DIR=" + output_dir - ] - - if apple_sdk == "real": - args.extend(['CODE_SIGN_IDENTITY=""', - "CODE_SIGNING_REQUIRED=NO", - "CODE_SIGNING_ALLOWED=NO"]) - elif apple_sdk == "virtual" and apple_platfrom == "tvOS": - args.extend(['-arch', "x86_64"]) - - if not path: - raise ValueError("Must supply a path.") - if path.endswith(".xcworkspace"): - args.extend(("-workspace", path)) - elif path.endswith(".xcodeproj"): - args.extend(("-project", path)) - else: - raise ValueError("Path must end with .xcworkspace or .xcodeproj: %s" % path) - return args - - -def _get_apple_env_from_target(apple_platfrom, apple_sdk): - """Return a value for the -sdk flag based on the target (device/simulator).""" - if apple_platfrom == "iOS": - if apple_sdk == "real": - return "iphoneos" - elif apple_sdk == "virtual": - return "iphonesimulator" - else: - raise ValueError("Unrecognized apple_sdk: %s" % apple_sdk) - elif apple_platfrom == "tvOS": - if apple_sdk == "real": - return "appletvos" - elif apple_sdk == "virtual": - return "appletvsimulator" - else: - raise ValueError("Unrecognized apple_sdk: %s" % apple_sdk) - else: - raise ValueError("Unrecognized apple_sdk: %s" % apple_sdk) - - -def generate_unsigned_ipa(output_dir, configuration): - """create unsigned .ipa from .app, then remove .app afterwards - - Args: - output_dir (str): Same value as get_args_for_build. generated unsigned .ipa - will be placed within the subdirectory "Debug-iphoneos" or "Release-iphoneos". - configuration (str): Same value as get_args_for_build. - """ - iphone_build_dir = os.path.join(output_dir, configuration + "-iphoneos") - payload_path = os.path.join(iphone_build_dir, "Payload") - app_path = os.path.join(iphone_build_dir, "integration_test.app") - ipa_path = os.path.join(iphone_build_dir, "integration_test.ipa") - os.mkdir(payload_path) - shutil.move(app_path, payload_path) - shutil.make_archive(payload_path, 'zip', root_dir=iphone_build_dir, base_dir='Payload') - shutil.move('%s.%s'%(payload_path, 'zip'), ipa_path) - shutil.rmtree(payload_path) diff --git a/scripts/gha-encrypted/README b/scripts/gha-encrypted/README deleted file mode 100644 index e73cd287..00000000 --- a/scripts/gha-encrypted/README +++ /dev/null @@ -1,3 +0,0 @@ -See https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets - -Googlers: code search firebase/cpp/Secrets to find the sources. \ No newline at end of file diff --git a/scripts/gha-encrypted/analytics/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/analytics/GoogleService-Info.plist.gpg deleted file mode 100644 index a7fad00c750ca5f5dbea9480b71f296ba5c91778..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 670 zcmV;P0%84(4Fm}T0;WqzTw6|j&;Qct0i2^tOioR>@Kcp;1g1!uk_aZ3C^`hX5j}}E zKlP6GSt)+Z>(`Fq;Ctxq8p$Obk8d@b6xoPDGq2&ZxSH;?(t7zIp*GCg#AYQ(i}1yH zs+Hhhi9NitnlPzMP99N%+cB)XS`L(H1MYrp-~KV!iYYprqV1o^g@<7^;0i9_R9S0oaJH9VaiuIAN7?_z6gPk(fJONZ3?dY1 zjlR0$hMA!FTj{#6XdQ53vVcm0F&b1Pfx703y{k!N1^I;0tS9FNNVFbXC_5WqXi_wd z46o2Ee$M^i8S0-5opNgjHLtR+qw`}0UGhybjY>-gTm(Mu!kl^p765QDknVHiNE>J7 zfcJcSkyg8t_XR$recyAn68a;(+3NWRAyxr6fQawDB7~>U{E4tWtttdB{l**J=3Tv- z_~KO0(4^8-AZYNLU8dD|KwN&7!n56XzdXLJUH_%;qrcT7LYwX<2%O}pAr!GLovxrf zl!URHVp|eG-vUz>+{ZUx7j_Gm_ex;&V!a79XygiazNsSwbptDSp7TEdBW$dh8Aw=H zyhr_lUmzDvW5!TC@J7SJj3wO;bUzYFt>nSN-u;WNQotl(u|PXrzT`w#x0urz=PN53 zl$QW+EPKH?P9cQPR?Z^^cy7|MyO+mmv8GiYdb$kfjn}L##!+MiVCM(2o!oF5CM z5V!WN@AEYeT={zmV>{BI1WSqbKM)aNM!BK5v6Yr!=pvS353fQHJEUSWh(cXF8 z{LI5aGknz#fHbmAN1_hslh<9yhsvGPUYoVVrgP2aK1L6E1E!p3;*=1Fm%He?KdC=n zAo9g(V%L(f2+tGQVSCn4U23x)9l$C5$e_0d0-GD6ts`YobTgGYj?kRb{JRaz>*yBW zV=+U792B(6IE{&wbWkZYYBc%a+F9~pB{^}^9&*v-7)1neHCy#Un{1>!>CBSAvn&{l z2Cw6Fas;OE6)3N!>+=wh6{FF9Kn(@!7e%{kpnyX52plUB-?hTEX(>wVgMI1nj!p;j zf;69TK&A^QkN@XCpQGe+6!$wcw5ld)3HJ&Afh198x%}Z#{|1k-!q(VzR@U&s_o}om zn%}Jo%-Xwq>moXY@3x;X+$-1d_?t-LS>2P?7gb{)vAE=(fTTi=9*;8f9)hu7V8Yl1StQ>U-ZUEduMpf@+UH(zYVJx^-@2j2EdVUQP)0QS3n42ikLtu>+LP-WBe@+k}}TVs~t{NDa2CLa(fs?$b+pVGEcQ9b8#qmb->%<`< ziVe8ihbJRK$;Kl_&w%86%mif#OG_Zp91HsV+_*r)$hFd$-c*N+-gFfR3Ws!iI&^bL z9>GMqL?U8Y)KGnx&baI%nX^}oZ~Rcp-g~ZG`K_O;uM7uGpo)}z5HR9E!GbGLW4VhY zsa^b{*f$%(Lo5CBg_H;3=gczcJYn2mJ8Bduo-jmKU(Y*W-yhZ0fH3|;-n=^TG)h^P zQGa-gWA8oHilnCpvZ-z@mZi=#(C%KBJ;Ofg(Em2B#+6Z|EeV)*!c-(1qZYw{rRk3g z0j92(JQ`$Or1#Wyb#=8Fa^dN1fAx5jRb|Rw%Vx9nen>8l@G}z78Tg-@TXO_Aw!xGe kpw7T=*H!qXWQ&~}5Ao)oW8Q4TJBC;?mCsfBqAi*#&qs^sV*mgE diff --git a/scripts/gha-encrypted/auth/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/auth/GoogleService-Info.plist.gpg deleted file mode 100644 index 896aeabf..00000000 --- a/scripts/gha-encrypted/auth/GoogleService-Info.plist.gpg +++ /dev/null @@ -1,3 +0,0 @@ -  ᗩ9p0E,uv%|{G+:q{y9Նz J{;.P^]pnę] -2Oe;0żC f]fۇ* -"*{t?eigW}2f)1gf69>r(goO0d-z9cK @)Kg~)T'm~H/>X64Oئ{5N-V/sw"Df>%>wNAǽ@\B"\Dp35i` ܨ̺哐ʡvM:K!\ٌ<6XNj|MIv̶R51Bd4 'x(A15JH6{H@/ |IR_M$[i +?s^NTyzc]q.-[Mz ¶O&eSvrlAcR5rK~Ή T -[AbZgcӴպX5AS|ӧm7l{~*K& ) ?8tR狮UL衧q,!7eI}B{iTrHɍ;[EAPV!Dk" 陑dyb"kJՖ \ No newline at end of file diff --git a/scripts/gha-encrypted/auth/google-services.json.gpg b/scripts/gha-encrypted/auth/google-services.json.gpg deleted file mode 100644 index 9f86b0a3f0744d3414c5adb997de69569c43c655..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1007 zcmVM$j)HSj#JfyEq{6y@7%eWBzshrzeHbW(QPUh?1M%oN+ zl<#`oRRC)&L%l+yI5nrM(VO6&>7~!Gt*C_{*YPS$9&f$Au)UpZ8sY&(F@VmKT}mY& z#5C4Y@3zI`^>OS)5L+3UZj95$8X_6L$>?GoMe(2XG2OoLB+n`*0aV14*m|TXO%3vs z`#fR`)PVW-y<wD2UoZA5!4)tv-}w5O7GS@As$FYVSPE)Jy@f) zzgD2`C0KIc2N~IsAiBxlXeR66oCm;sw>(-%ZT6y-nJ&I2;{NXM%MuFqCXA{993tWg zJXMSsI6H}~gLpr59QJK%QjmeZ|I2b_GS7$L%6pJ`NgquEE>D6s2Q+^g>6sgk#{adh zamwNrSy-@NDnAc2umh$X4J%#vS{=W}mGoOJlRYgz`#T$Z?fG`jib)Ww!H(Ai+A|9( zCGD!5y)^2oOz1{DT18uC!5l&V2k3+ZIt^SVCDtNzn^fcR% zkR2H&^gUlwy%tbxBys(V%!sFdjcOsFNop zf}m7$cKvLevhAYfVDjuQ-tD(q8bKb47W{5(xY-&@b{r)RIL2WbXZRjo)d29MxnpSP zIN1VKmTH_zD~4*gDG|#;b9B{es}}-re5);FI5ymotn~{aG3+vxLEJ^C@|)JbgYC{n z&WV8T@)nMWydPPq-XvHsGz<>wG$x%K+zsFgNiCxGG(o6kv_j0$H6-HjK^7)xIS6Nr zwlIg-NLFM`T9I21@pqK`pDO3uyv6vrpI7z9&-HESydH}dUlCY-In(OK=4S%mMneLy deaS|)YNQ1sc8c)S(J0XeiL%r>S?SoKUA+l2_Kg4l diff --git a/scripts/gha-encrypted/database/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/database/GoogleService-Info.plist.gpg deleted file mode 100644 index 9d7f62a886aa814bead25a93c9436bd3659940f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 700 zcmV;t0z>_b4Fm}T0(cJzehBA^?f=s00kcdA;5yS0EZ$;S0;$G?7>n8yJ(K!2&67ZF zWWR%SiD@5z=E^$ia~fPU{lSn$yiaAyWXYK2gUl2K#MZGBU;*&)j$R?VO`@K)^{c5D zDBzRFLGU>DK=rLle1% zQ&7ikKvoe{EWv0&<(fe)<|U`v?6b8WtmPa_Ob+?;0l-rI4Ucc3d&+6r-Ve`8=aO-^ zFaQF+Pp~yVNA&>RPg5W=!iW>Jt1y&Q%T!7+5Cimob<#=#!B2eLAfI}<%jXh4q((c) zC0?3|yN0x4>R@Fs!X)V!0{T%qu`ZyhO=HHQ1~w8~N<}TV9V8Zt^adEK=kT)vH`rKC zlWPa$GP!%l<`H#wt(5L%XJopqq49F3qxLr{ew?j2!J$)#0hJ&9w}KxIdovPA0M&QN zs1WNk(ucwAs5lM8B+3@shTTVdYOws$oGLI9>)!l4`%T!p+nO=L-}nGzH-$^D?ip!9 zhD8i8)crGxVk1ak@l>v9&=sWWh!|eQW(rrJu6332F^v4$pB8dptoVhgNxN#WqAdKm zMm5H@Dlb^_JNw5#O;)GyUA?@Scmo1GD9q??a(D;1Cf--Psmas`y_Cbo@XC(@le18v z@;9nvMxO-LPxF77j~wKAs=J#5O@nNV@-0Rnopzc1rg!fI_G4ARkw_PQ$#Um+vHV#M z@B$p9qJm>+CS~2{gjdU8@kJFV$#eR1z(T(=DS`0*Pl^?lpZnojFe%OMuO2yhGF;tu zh*tB@Fbhl*Blgw%MxDH6%#X<%$QL{?Qe?@S-Z;lt9u9H)K(guImHxx1573}Mhznfu i0ZCbQ9@F%tASpgo6Iv~MWx$&}Bm-LBzWPXW4=kaDAX+B? diff --git a/scripts/gha-encrypted/database/google-services.json.gpg b/scripts/gha-encrypted/database/google-services.json.gpg deleted file mode 100644 index a9421faae4990e4cbac78dde074564a183198e5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 725 zcmV;`0xJEC4Fm}T0z{6KDZ~|>lK;}_0XBiO5((1Dx)2khkzu`aON|@;Vh{*jeNDD~ zi}#_Cy_i+!6lM+42$j{L4(c1^$%c?M6~#uzWZ_!((?{@NK%%cr*@Q(+pqJiz z(P-R8_|!Ks|{pQaQeY=ZcX#UL{QAEl+(sGUFi%s zW&WU*l)R6TsJta8Rg3fMG1;yH<%D|)syp+q^GYl|HQd`M`b8td^iMQt9qslQCT$bT zURH?DZj{ovE5Ai6k{V^TT?l+x*9%F;+l+7|O;rBPfMwjK7ea3mu^7~wIHbZw3aD(- zTz9q#dwdwBeETp2Hy4{01?J|LMAI zHp}cU5op)eQ0HlcfHoJG(nxd*imlmmah@FDqs`Nq8rHFEhL~`?FDH`4$@^9^{VN-R z?erSZ&AcyW$sh0{@iamdFaVac$G9H^u!nF-Hh3*fP)&(u)!^vHVzb#x8%hhR_TxmO z50buX>fQX11U1DptB38*Gc3b?Y#SV%_C4FE~&7O)zaVF@o7t@|;>?lb?5a zTVb)Gt&2?<>Q9HDQYX+CT$uBgdq?kkJCy366&N81OfWk3k60AAMQdlW-sC5Rx z_2lb2z&`)n??HLhp-HVDzygf7d9G@CBHD$D!~n~eu{3|CW37X z@)@nH#!9CCd3}X*zk~~4W;4Co=sP#wJ$8J>4zdrBHDDp3oGI&MVZS}eqt^n`hE+t@ z0-fhWA9GF#Pl3oZ3w^8Y!@8?4Nkb~u{zS2+j5x!zHd>Mhsr~#-Cb~tu@DuPr*k1=g zjq7y4sl2NZF{D|03)&1q*uk~;d1NRWLRBy({!v$15YY{jrvmszOdSft-XySWS8YuQ H8CqjunkZxu diff --git a/scripts/gha-encrypted/dynamic_links/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/dynamic_links/GoogleService-Info.plist.gpg deleted file mode 100644 index 7d577bef1b38f967ce4e02edc3e611a517f52944..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 649 zcmV;40(Sk34Fm}T0-Dh`Owg>JQ2)~D0aY1%yW!%9C4D+&6AtW4i+d0Z!YipN;u2b4 zGAfd*u_^DP&|{np4Gyof>Fm!*Aptt&AtnYaZ@nIY8OQ&Fljd>$hTeOWs`Q#6i`298 zx(P`77eg-Q8c{Hp!TZe-WnR`)=3;nav5~#l`R!%fT%_=#hP02bPMRkcZOSX`^yKv~ zymiROQy9=q(vPYJk~+9asS-1<#6ZHr-FcM%8Xf0`1(7F?@*&H703^>{>F-RH=G00s zB*sEexU{Y4d1M~yq6k|)VBe061ma4$`E|SQMe2rhMd;2VBV1BM+!?yUa_=5Qa%1M9 zU&DA%8o01d4V-&od>C)B5+juu9l&t1frY>{~?M&Fi1LP}IYsuaMzCKu`{>2vUbkAHFZ^@6mvTDEL`uR-O zCb)(iU7^*?K$@jKtNwusNDD|Djl3()*?V0=x9F8jf;9yn*YRGkz*HGED^XY}Yo_WT zpBy}$3-fV(XqKecyR_Gw;D?3rhzCd~fe;CDmfbOm)>oX}1EP z`3Xq6MEGe&iqFOj%&d>QVVZ@iai82pDti$c@1z_GVGvt(ANtQ&99jd|y!U)lA?)bZ zFHX3OZh%YM t?_C:AiclƎ \񏔸m.IMi?9 {S~ZUXt⾘=}ݔV||1M-u_m8cVS]brQ㈃:rE[=ۅ.nj=zU>5h)Zar Pr"8qбo>E 3|nF(KUe5(uo ?CiN_:X>vJ ['g_okL\ IZJٕ'@ȲN? k$-SaCSRqv7 -rlYyRQEx%L蔘%p8y e*/\g oOM'w ܊fY -g"KFra6X׼18?خIu2Bmx>mZ;V2zy4LuiД;T]̄SI brZ*R|*'6ȑ~XSMG| !ˇ2֠Butq!3nr@lVu H &P5KO y}e;eUa">g \ No newline at end of file diff --git a/scripts/gha-encrypted/firestore/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/firestore/GoogleService-Info.plist.gpg deleted file mode 100644 index 4ae5fb4154aa88e5a0960c8a76b07b0ed930c12d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 597 zcmV-b0;>It4Fm}T0<3j;`}*~etpC#K0dM$E_Klms7qhh{e<*<_@<>z^i2PIsRL>`i-lu_e_^Hl7y4t zw~#KE-$j4xHTgQ5ARZr#QEL^J;NQR$87uzMN>@r;1IpcwSu7wgq`UG^k|AQT7v80}*a9QDczqwM8yOkz4d ze^PIUV{e-He8t$uRK_Y9HaqOH_p3%yQSqzd`{&jJ8Fp>y0??BqX#w~iX{K<)Pf;ww zaT~ika#*TZIiU@H_vl8unSHxBTl!baKuKv3MoAKs8G||*HR!A_f)5SzuL;@_?uoSN zR_GO3)P)zgYNzMC#_^G#LoaKzsdn@*N-O|WoKFt@Yb9a_N<7 z*?~T&hUCDY5Zgl%eXy;Zv{&$f;FTYGPu(8%;i_)rSa<`{9@-y=OM06!dMSFZhj+fT z;C*YAzeny)arJMqI)D@$zO}JZJ2OIvte%buc$Gbzuhw4YOR|_jm-VcGX@d!nTS8ik z0Kf*J*DQWK*KkxJ{AV!Qp9K^$Q-z>0j+OWhdND5H8cJPW+E4x@i3mJ-DRHXTkuc4K z@a-^J@O5IwHp`Zu!{|cFLdCo3U8l1+daI`)cWj;iUQE@w{m>8gH3w;O)t4G$${WCA Nvp@Mw`)_THcA!*b0BryO diff --git a/scripts/gha-encrypted/functions/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/functions/GoogleService-Info.plist.gpg deleted file mode 100644 index 6ed5b9d8f0a81ecf7159779b063d5761e8b8a91e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 674 zcmV;T0$u%#4Fm}T0{+I-3o$$IIRDb=0X=l4a@*bqyT-s#vf6D=ZjQVLrtngcdl3@X zc%26e$Bjijl3_LnV2<9#tiKqzPNofg#DPN`#&aiG8DBZ9d~uH=*;2YwLFc) zD(7rm1_}~6aooE{YAbeg9}f3A{<86qh*J3Wj4HS8TU>>V#tMAm8#2q|M=da)0dO6& zj?EBG&Y%gUA2%}A)75+h>5J>z?& zTgB+G+KJ@Fv|yeH0|d~rT4Oz=v`_TFm0bi(6*%1Wv9n3j;_|}PvBNU-_|=F~quo|P z!%(`KAZ`??1yTd-hScyLq@=jSg?wNtNScRh5?`R_hjf=1`CR?Scw_xQgRP%-$g0~%zPwCi&s1vG!Xi5;m(F?yjthQt+`-$56C^6zDx6U$Vlz;(n8R3MoPe zkPs$9{{)Q94|aZwwV7)rGhVCgf5oQjYw+%^qF8cq28a@puY52DT@jH%X?z2c*MkQ! z`KywMVlhSG-!3BaKXa0=kcRt`sVCIgmOCHFSfZ4D!B<4XYdzb??HR1lw^?dL7VsQ> zV+j#r{i9)Wim^LQ+arg&{3r_Y=oH+pa{l>qwFJ~8_aYMN@;zn=SaI^$V}0t8C~#z4 zIau9b?1w55xL0;4dvgfO<=GJ%zoc^#$vrpWJb+t(oZ&WP!c(FxdH8wRiyy I+!#PABySNpqeG z7XX_S2QE~FouFMOWTJcUPXB)JlC0^R60hrm6*Y_vxqw*D?7{vefHl!k4jl9kAIdfa z&^eWi)4);g{xX_)sIl6&^F`?Q?V~ls8SYT_mL;;&P+;@yw8~be6+IUMR+Y!>gESbu zrP+<0AZo+HIT3IPyj&;uLDTg|xhUX9i~Z(ya(VitBu{;Og^CYY=Ks~@M68xdL#56! zO|!TdV(<*&ynf^__C5-_lJE}^I~`vWZ*15@O(yYO3Mzq$Z2lFp16+aO?=CiD8~9%+ zm^k!ht*5(T@bN(1C-b{b5R&X^YRz4non5hdQLJ~OcNKNWIqo+tSWIFU#%(<1J`}=8 zbY%?n?*z*(aEBryXuzAVo(~kG$-kllOH2#+t8|!b^N!)7j4s!|wgtFu!8apX-Zlc(3_+p;YvBTU9F;X>FP?Z-0LyD#%yd P<^++o`2!*$pGGt{EocN) diff --git a/scripts/gha-encrypted/gma/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/gma/GoogleService-Info.plist.gpg deleted file mode 100644 index 65b703ce7e8841cd231a8eeb0b355a6631c9f463..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 663 zcmV;I0%-k=4Fm}T0-fzaCMf$rivQB-0p|fHWyO^&Ync6x>Efpw?qdT3?Bq zjPBP~k2>%=QT6e(ZG>MNm7#5O(Tt)6z3idw07jl=zmH+QdQwr!bWyx1XVPt(Y69$O zD4AO!?IvhRONC0FbWiJT`zhZmbn27_AYEmd>+nnOdpgf=n_!lIL zK)jN{X+d{4{S4FtlNI9nxr_#!x(Q%I``z*)J2;DCGM_|iX3|-W)CQ5^yN1O75hO)q zOAm}cNOC&k9UUh(06a3A3f}Rm%cuh@98<4}TzGKY(o zb$4E@E=$QI0G*5t)3w8Lpzo)!43vQH3lnr~U&CRUz|*s$yPy~p$lLU7|2?8b{0dPY xG>ERw<<0y28k diff --git a/scripts/gha-encrypted/gma/google-services.json.gpg b/scripts/gha-encrypted/gma/google-services.json.gpg deleted file mode 100644 index c46f596425a5955ec5b958766883ee90eb2ecf91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 953 zcmV;q14jIe4Fm}T0?5jj8X$yf(Erlu0o=SNVA9@O)Q#w6U2MVR(@sDoEKw4ruNO3O zPmJZ;D5%EpUdQb|p#VZcUSnlVF@HZ;Wo}Mq^r98p=hBMmONvOFn$0sn^L@iCqmP0F=UD9qsJblrIkqLol4tEpjp=eNY6-X z3b1{x7dV}KDG(ANS!?UAG=_uE%pR_G)fWWN=y3INqb`x*r;Qh`aW8c@%WR>J#-RSH z_yZ@%%_g%i!9NC5P8?4F*Q|}lID-2sQh`i3YbzJbE9Cv3R^QvR9b;>>avs%oXYmSZ z(s}B$Z%QQ#9*42A>|_%5lapchw(xLZ$O#HE7)Vtk;xn~`iH2pd{n2prmB}cn2+yHM z_KWm!Y7DPfg{`p<;raH;-q*N2tRG0zIdUPVn>knZifwyjUFtzxxP+pI2SIo$vq(7K zH(MHzZk5pMUByZtm?FxuJ5p@_pu|0(kvV5~7acIy|Ek-FrC2v9Xp<3(e<7|m<^>?% zg0PrAonln~Hd;|_%R*5#vo4#5d_|1?ZRSQzeZKDpUbZCyk|Y0PAtCl1xHz#^FFSZ^ z!1yU~KTei^?nVUonbM^qeEz;g^!3Dg#mNS;O`_ULM_J63hHe;7BL&mO>=K zwc<{Q4XsD%oc#^bfC`Biz~;ot-)Ku86zZ3) z-lCqPSZH;ue>aJDQ`eQ3FPi6QjYI@Rf&YQRqoCJu<<)m$PbpSakN-)z+b>_w;MdEA zM-w?Vvsh7EOK4T_iJEF2mPPu~{F~3me5AD}r)>`h)%;#B9;Mn=PX0M3s`>C?WSNK9vak2` zenu+TM-u+s2hgi?MXENJ{8#AIW@jq7BUic?=b7+v3gOs9KYZp diff --git a/scripts/gha-encrypted/messaging/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/messaging/GoogleService-Info.plist.gpg deleted file mode 100644 index cf95c652d8c3f4a8e1ced8e26ee693973b5d74f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 681 zcmV;a0#^Nu4Fm}T0;FEs)peJ;@&D540h3?tHNL7~)BKD4v@4NWlr=pQilhSDjI(iF z1(VC?G|7B+^l)N*wBnzv=ff#48S7FhKjTGX6qJj#qbWpzs3X`M7jYiGa6YUW#qrs7 z$~{vT7&@}ERtlW)R~RBTQr_}>Fd3Za#vMrx_nM(ue3%zya0#Nue%6;3%2j6GNQE=V zHD4ThD>{GO+iJZ)1$%~CC4+{UT-Mx|Jsuzv^KhjdzCR?}3d+NbQiNe@Irgq6nh`VgjVY8XywJei9c?o_9aaV^(DPu% zS;tSQUS;lZFjZN)pq`-w1A?RUi`_b;FMN%^1&pYg!sZLxZ+9dv-YSA#OYh6vijEk z3E3-Ov+T4V!tI=hXAuO}LUZJcmlX=$oz=4$cL4|HL%Z?7wrgzfah%9k0N z4xJ)O^H!mk?{Mr1y~rnoFSt4b(e-G+rI@BwjhS0%K2IIQnWluOuA={|fS^v`M0X;|)8~MWIq;;LywHFxnc6g{6OU$<8J3d(Z zDG_BIhEH?I&mMS4d8JPoN4MfS%^@c6db%X{O*6G54C(5)nG) z+T~qulRbQr^8EB({5m0xt3*KI+o{bm=+>spRyA1dL=`2Azpf71+M0sz_1zZ&;+2vB zS?s)I^+8WnSZ2OYB-q9;CrtNil=`o{{75)38dwMN%4Gvn2dNPf8b$C*X=2dU2GmHa zm&5MzqXebRAdUf$xLRgbT;@5WzA2JsW`2rX&v(KcD3{yo(77UYy4l9NUqaFX;TJ|9 za8H%NO!Yfl#PmbnufEnInb^7KpY`R)PT{$q0)kzrD#uztDx&@1j1Nef@6M{h5^FEu zL9@_G)ZdKY%Jhhc0~}_kK(`+}GR>1AH((#+?~ap@wt{NA`Q&CzoE?%KNJ=Y-@vbK% z)swGWEC{;@zbbO8Sqn5-Pq=UjaTB?ozA;r}n0pcKF2CU$+AqU0=0B*L46ptlCaBMg vPD~IzIRHz)j-tlSqT&%x5p2?6e(xKAWJfnzBs(C?QMLBN33UZmQW_K?5Pl{+ diff --git a/scripts/gha-encrypted/remote_config/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/remote_config/GoogleService-Info.plist.gpg deleted file mode 100644 index ea9dc946108db17d9abceca676221ca110659982..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 614 zcmV-s0-61c4Fm}T0+!@LUVw)oga6X$0fm6UEhysKH8@d}V0ZtUPzYhNql4l=?%x}4 zZmy^lPM-hGQ^`3_SU5V}t?<$7wO#lRYbS#NJbKiC?$Om(>ySGh;2*mM`*0v6w{yfT zFVpiXcM&7eXSbsspzE%VSPYa^+6V~B9h8~|;s~X6i z3D;Fg9=y~7=|%nk81WNAj5>uFWF9~Wq#hWDw5T5(Xu*KJgjIPWU-xWxoaDH@AmeM9hU8mCRDr z$uy6Ya$`mTX;DyDaU1165bob?{>|t5z-v{b|K;zTNj+_GN+mRX1j|G`n`{68)cO0K za`4~>iOmCsTIK99CDNgX)`g*27>jnR8;V3(J@}4d=^OATG zyfY;(0ff)9RO16P==~yQ8CO#~gAgmt;Ej$_RgwxX@1S?5AwG^`7EJv0^?qCo=bSedPEu6uPY=pv zX8-ga0A`RM1tnk4#^wF;=Za5Vda#IYQ;4 z3IKSrMkKQe5VL%v#oJG7%TmMXfK3+rk^wqFZA(+@k2H2?;4!-u%LgaWE3ENhRc&y6 z+>QmjPCAF7A@s}0jw>%!aAU%ShZEOmQX$i;ESCa{w*~wTi5HpD{`+cA__c7Q>cX}R z6+93?dp#!gelrsBu_NOw=KI^DojPY4HU;yuIEcuf>h zWW{*LZQ6KL3?YM$XO*EC&9_}HOli>A=8fA|`?I{ITbn(r1l!n+K)O-{3IM8yYqHiD z`D3B(KX^u+uNaoBwokDam0Q*2lkgEB--!ov44iN7EytQ!yvlc_+JW6$pdfQ&TX~QY zF+#PhS@RDmKfJ#LW}$H92{NYja>N$oty;18BCSCxh~UuAij(!h?J7|dW)xXGW`&Kq a@DVqWc|5L*rEG4scQP@*HM&^F@@MEq9-0gQ diff --git a/scripts/gha-encrypted/storage/GoogleService-Info.plist.gpg b/scripts/gha-encrypted/storage/GoogleService-Info.plist.gpg deleted file mode 100644 index 01d28ec9c68dc2093039e5ef88d1b62e35c50863..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 641 zcmV-{0)G9B4Fm}T0@BxCNCa2Mb^p@o0qtuiw?`tmd2RrUYRplF_cg~tu&`l%UZu36 zW0MRzaLxexhJhCfA|3TEiVMjoR0g|Ev<&_Vby6z0Esd`#5J`H{XGDoH?Th*BD?~wl z>&nNarqtokGHhG~MyqIYPd5@{=u^NAX%v;qpGq6@sI=4-~{0Nv73!Qd^ztPq)LTOE)Q+8 z+8rQw@R_hYkjkHRD{j;!jUVyU5~W!JF6xXofC?4?-5m&9adv!qB1 zG)WQ1&8goO)Ix|y2z3Q^8R|P&VCARg$3^&pOcXY{G+Ev6^+Wr7 zYn_il4A8BAPO3TpS-v?AGqn0=9&sg1fwHv3g@n=fL2ASJ$#uXTbB?Ck9Iw%~-Gbf= z{CuV)zbfK>m2pbZ5c=7UZ+uaBN8WID4!>K_X7Dv@ovP-*%J7VrJDQ|%v8D!iJ(H6y zowMHM(~G5nZYfLQ;hY4qMDEYch^&#t|5(0TMrK3;<|wn3kWMIuB9bE#?BN78xN|YY btXortgjczDJQD$D!1QIdm0!5@WZL-o7G^nu diff --git a/scripts/gha-encrypted/storage/google-services.json.gpg b/scripts/gha-encrypted/storage/google-services.json.gpg deleted file mode 100644 index 57ba134aa519fd3e9fd4c6fe3e35bdfa7ab9f86c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 779 zcmV+m1N8ii4Fm}T0v}cjW*B7vvj5WQ0ddkb%Cwn*48_buW^@!uuT2?GV5}3TWRcaf z;2`T3gm||t~4(epM>5nKUnE1@cp zPB2p_6Sp_yGdE||m$yrkQC^U@B;`XBw4Cet#xE?0YMb#6G8d@)6V8x_sIk*A!hSxG zV{PUZD7#3x#tBKMIPUcS1L+?mTpz}NpgT?TVik0fopDg~XHo}Han$mf&N+!=2RR0gg4x(OqNwmUSzJr!dDiKul zx4T?gU)+wP%ZyMcWyP-F1mj{B_r+&$(3!qGN9*s%2Fpx>PdS+CD z9)wXN&TGX3ETIOI33%(0z&K5s*DR9}URZ%=kPuF(MhucM9GUcTZHp$xW)tyCW2|*q zo(#ZVKbkUg8s6MV zTFNY@&bsgi{{4(Hu5z^t51z8LB)Nkhez1gAY|&{QQ7p4;6-}>|E=j}bzt+9+2KA;_ z(?K^!D$*b~S80>8bJe}pa8wUq#4~28*g$H=Jv-D7>>I;SSk_fs;B zOiGw|(LyUVcd2k^$kR] -python restore_secrets.py --passphrase_file [--repo_dir ] - ---passphrase: Passphrase to decrypt the files. This option is insecure on a - multi-user machine; use the --passphrase_file option instead. ---passphrase_file: Specify a file to read the passphrase from (only reads the - first line). Use "-" (without quotes) for stdin. ---repo_dir: Path to C++ Quickstart Github repository. Defaults to current - directory. ---apis: Specify a list of particular product APIs and retrieve only their - secrets. - -This script will perform the following: - -- Google Service files (plist and json) will be restored into the - testapp directories. -- The reverse id will be patched into all Info.plist files, using the value from - the decrypted Google Service plist files as the source of truth. - -""" - -import os -import plistlib -import subprocess - -from absl import app -from absl import flags - - -FLAGS = flags.FLAGS - -flags.DEFINE_string("repo_dir", os.getcwd(), "Path to C++ SDK Github repo.") -flags.DEFINE_string("passphrase", None, "The passphrase itself.") -flags.DEFINE_string("passphrase_file", None, - "Path to file with passphrase. Use \"-\" (without quotes) for stdin.") -flags.DEFINE_string("artifact", None, "Artifact Path, google-services.json will be placed here.") -flags.DEFINE_list("apis",[], "Optional comma-separated list of APIs for which to retreive " - " secrets. All secrets will be fetched if this is flag is not defined.") - - -def main(argv): - if len(argv) > 1: - raise app.UsageError("Too many command-line arguments.") - - repo_dir = FLAGS.repo_dir - # The passphrase is sensitive, do not log. - if FLAGS.passphrase: - passphrase = FLAGS.passphrase - elif FLAGS.passphrase_file == "-": - passphrase = input() - elif FLAGS.passphrase_file: - with open(FLAGS.passphrase_file, "r") as f: - passphrase = f.readline().strip() - else: - raise ValueError("Must supply passphrase or passphrase_file arg.") - - if FLAGS.apis: - print("Retrieving secrets for product APIs: ", FLAGS.apis) - - secrets_dir = os.path.join(repo_dir, "scripts", "gha-encrypted") - encrypted_files = _find_encrypted_files(secrets_dir) - print("Found these encrypted files:\n%s" % "\n".join(encrypted_files)) - - for path in encrypted_files: - if "google-services" in path or "GoogleService" in path: - # We infer the destination from the file's directory, example: - # /scripts/gha-encrypted/auth/google-services.json.gpg turns into - # //auth/testapp/google-services.json - api = os.path.basename(os.path.dirname(path)) - if FLAGS.apis and api not in FLAGS.apis: - print("Skipping secret found in product api", api) - continue - print("Encrypted Google Service file found: %s" % path) - file_name = os.path.basename(path).replace(".gpg", "") - dest_paths = [os.path.join(repo_dir, api, "testapp", file_name)] - if FLAGS.artifact: - # ///auth/google-services.json - if "google-services" in path and os.path.isdir(os.path.join(repo_dir, FLAGS.artifact, api)): - dest_paths = [os.path.join(repo_dir, FLAGS.artifact, api, file_name)] - else: - continue - - decrypted_text = _decrypt(path, passphrase) - for dest_path in dest_paths: - with open(dest_path, "w") as f: - f.write(decrypted_text) - print("Copied decrypted google service file to %s" % dest_path) - # We use a Google Service file as the source of truth for the reverse id - # that needs to be patched into the Info.plist files. - if dest_path.endswith(".plist"): - _patch_reverse_id(dest_path) - _patch_bundle_id(dest_path) - - if FLAGS.artifact: - return - -def _find_encrypted_files(directory_to_search): - """Returns a list of full paths to all files encrypted with gpg.""" - encrypted_files = [] - for prefix, _, files in os.walk(directory_to_search): - for relative_path in files: - if relative_path.endswith(".gpg"): - encrypted_files.append(os.path.join(prefix, relative_path)) - return encrypted_files - - -def _decrypt(encrypted_file, passphrase): - """Returns the decrypted contents of the given .gpg file.""" - print("Decrypting %s" % encrypted_file) - # Note: if setting check=True, be sure to catch the error and not rethrow it - # or print a traceback, as the message will include the passphrase. - result = subprocess.run( - args=[ - "gpg", - "--passphrase", passphrase, - "--quiet", - "--batch", - "--yes", - "--decrypt", - encrypted_file], - check=False, - text=True, - capture_output=True) - if result.returncode: - # Remove any instances of the passphrase from error before logging it. - raise RuntimeError(result.stderr.replace(passphrase, "****")) - print("Decryption successful") - # rstrip to eliminate a linebreak that GPG may introduce. - return result.stdout.rstrip() - - -def _patch_reverse_id(service_plist_path): - """Patches the Info.plist file with the reverse id from the Service plist.""" - print("Attempting to patch reverse id in Info.plist") - with open(service_plist_path, "rb") as f: - service_plist = plistlib.load(f) - _patch_file( - path=os.path.join(os.path.dirname(service_plist_path), "testapp", "Info.plist"), - placeholder="REPLACE_WITH_REVERSED_CLIENT_ID", - value=service_plist["REVERSED_CLIENT_ID"]) - - -def _patch_bundle_id(service_plist_path): - """Patches the Info.plist file with the bundle id from the Service plist.""" - print("Attempting to patch bundle id in Info.plist") - with open(service_plist_path, "rb") as f: - service_plist = plistlib.load(f) - _patch_file( - path=os.path.join(os.path.dirname(service_plist_path), "testapp", "Info.plist"), - placeholder="$(PRODUCT_BUNDLE_IDENTIFIER)", - value=service_plist["BUNDLE_ID"]) - - -def _patch_file(path, placeholder, value): - """Patches instances of the placeholder with the given value.""" - # Note: value may be sensitive, so do not log. - with open(path, "r") as f_read: - text = f_read.read() - # Count number of times placeholder appears for debugging purposes. - replacements = text.count(placeholder) - patched_text = text.replace(placeholder, value) - with open(path, "w") as f_write: - f_write.write(patched_text) - print("Patched %d instances of %s in %s" % (replacements, placeholder, path)) - - -if __name__ == "__main__": - app.run(main)