From 0f837893610c712d3f94fe30a50be5f20c781372 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 14:58:21 -0700 Subject: [PATCH 01/50] Added initial header and empty stub for UMP ConsentInfo. --- gma/CMakeLists.txt | 4 + gma/src/common/ump/consent_info_internal.cc | 33 ++++ gma/src/common/ump/consent_info_internal.h | 38 +++++ gma/src/include/firebase/gma/ump.h | 39 +++++ .../include/firebase/gma/ump/consent_info.h | 118 ++++++++++++++ gma/src/include/firebase/gma/ump/types.h | 152 ++++++++++++++++++ .../stub/ump/consent_info_internal_stub.cc | 31 ++++ gma/src/stub/ump/consent_info_internal_stub.h | 39 +++++ 8 files changed, 454 insertions(+) create mode 100644 gma/src/common/ump/consent_info_internal.cc create mode 100644 gma/src/common/ump/consent_info_internal.h create mode 100644 gma/src/include/firebase/gma/ump.h create mode 100644 gma/src/include/firebase/gma/ump/consent_info.h create mode 100644 gma/src/include/firebase/gma/ump/types.h create mode 100644 gma/src/stub/ump/consent_info_internal_stub.cc create mode 100644 gma/src/stub/ump/consent_info_internal_stub.h diff --git a/gma/CMakeLists.txt b/gma/CMakeLists.txt index caf0a32508..9e57c0c7eb 100644 --- a/gma/CMakeLists.txt +++ b/gma/CMakeLists.txt @@ -16,6 +16,7 @@ # Common source files used by all platforms set(common_SRCS + src/common/ump/consent_info.cc src/common/gma_common.cc src/common/ad_view.cc src/common/ad_view_internal.cc @@ -38,6 +39,7 @@ binary_to_array("gma_resources" # Source files used by the Android implementation. set(android_SRCS ${gma_resources_source} + src/stub/ump/consent_info_internal_stub.cc src/android/ad_request_converter.cc src/android/ad_error_android.cc src/android/adapter_response_info_android.cc @@ -51,6 +53,7 @@ set(android_SRCS # Source files used by the iOS implementation. set(ios_SRCS + src/stub/ump/consent_info_internal_stub.cc src/ios/FADAdSize.mm src/ios/FADAdView.mm src/ios/FADInterstitialDelegate.mm @@ -69,6 +72,7 @@ set(ios_SRCS # Source files used by the stub implementation. set(stub_SRCS + src/stub/ump/consent_info_internal_stub.cc src/stub/ad_error_stub.cc src/stub/adapter_response_info_stub.cc src/stub/gma_stub.cc diff --git a/gma/src/common/ump/consent_info_internal.cc b/gma/src/common/ump/consent_info_internal.cc new file mode 100644 index 0000000000..e82dd58823 --- /dev/null +++ b/gma/src/common/ump/consent_info_internal.cc @@ -0,0 +1,33 @@ +/* + * Copyright 2023 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. + */ + +#include "gma/src/common/ump/consent_info_internal.h" + +namespace firebase { +namespace gma { +namespace ump { +namespace internal { + +virtual ConsentInfoInternal::~ConsentInfoInternal() { + +} + +} // namespace internal +} // namespace ump +} // namespace gma +} // namespace firebase + + diff --git a/gma/src/common/ump/consent_info_internal.h b/gma/src/common/ump/consent_info_internal.h new file mode 100644 index 0000000000..c3d261b892 --- /dev/null +++ b/gma/src/common/ump/consent_info_internal.h @@ -0,0 +1,38 @@ +/* + * Copyright 2023 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. + */ + +#ifndef FIREBASE_GMA_SRC_COMMON_UMP_CONSENT_INFO_INTERNAL_H_ +#define FIREBASE_GMA_SRC_COMMON_UMP_CONSENT_INFO_INTERNAL_H_ + +#include "firebase/gma/ump.h" + +namespace firebase { +namespace gma { +namespace ump { +namespace internal { + +class ConsentInfoInternal { +public: + ConsentInfoInternal() {} + virtual ~ConsentInfoInternal(); +}; + +} // namespace internal +} // namespace ump +} // namespace gma +} // namespace firebase + +#endif // FIREBASE_GMA_SRC_COMMON_UMP_CONSENT_INFO_INTERNAL_H_ diff --git a/gma/src/include/firebase/gma/ump.h b/gma/src/include/firebase/gma/ump.h new file mode 100644 index 0000000000..4a6ed9f775 --- /dev/null +++ b/gma/src/include/firebase/gma/ump.h @@ -0,0 +1,39 @@ +/* + * Copyright 2023 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. + */ + +#ifndef FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_UMP_H_ +#define FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_UMP_H_ + +#include "firebase/gma/ump/types.h" +#include "firebase/gma/ump/consent_info.h" + +namespace firebase { +namespace gma { +/// @brief API for User Messaging Platform. +/// +/// The User Messaging Platform (UMP) SDK is Google’s option to handle user +/// privacy and consent in mobile apps. +/// +/// See the ConsentInfo class for details. +namespace ump { + +// More information is available in ump/consent_info.h. + +} // namespace ump +} // namespace gma +} // namespace firebase + +#endif // FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_UMP_H_ diff --git a/gma/src/include/firebase/gma/ump/consent_info.h b/gma/src/include/firebase/gma/ump/consent_info.h new file mode 100644 index 0000000000..54d3f0aaca --- /dev/null +++ b/gma/src/include/firebase/gma/ump/consent_info.h @@ -0,0 +1,118 @@ +/* + * Copyright 2023 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. + */ + +#ifndef FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_UMP_CONSENT_INFO_H_ +#define FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_UMP_CONSENT_INFO_H_ + +#include "firebase/gma/ump/types.h" +#include "firebase/internal/platform.h" + +#if FIREBASE_PLATFORM_ANDROID +#include +#endif // FIREBASE_PLATFORM_ANDROID + +#include + +#include "firebase/app.h" +#include "firebase/internal/common.h" + +namespace firebase { +namespace gma { +/// @brief API for User Messaging Platform. +/// +/// The User Messaging Platform (UMP) SDK is Google’s option to handle user +/// privacy and consent in mobile apps. +namespace ump { + +namespace internal { +// Forward declaration for platform-specific data, implemented in each library. +class ConsentInfoInternal; +} // namespace internal + + +class ConsentInfo { + public: + /// Initializes the User Messaging Platform Consent API. + /// + /// @param[in] app Any Firebase App instance. + /// + /// @param[out] init_result_out Optional: If provided, write the basic init + /// result here. kInitResultSuccess if initialization succeeded, or + /// kInitResultFailedMissingDependency on Android if there are Android + /// dependencies missing. + /// + /// @return A pointer to the ConsentInfo instance if UMP was successfully + /// initialized, nullptr otherwise. Each call to GetInstance() will return the + /// same pointer; when you are finished using the SDK, you can delete the + /// pointer and the UMP SDK will shut down. + static ConsentInfo* GetInstance(const ::firebase::App& app, + InitResult* init_result_out = nullptr); + +#if FIREBASE_PLATFORM_ANDROID || defined(DOXYGEN) + /// Initializes the User Messaging Platform Consent API without Firebase for + /// Android. + /// + /// The arguments to @ref Initialize are platform-specific so the caller must do + /// something like this: + /// @code + /// #if defined(__ANDROID__) + /// consent_info = firebase::gma::ump::ConsentInfo::GetInstance(jni_env, activity); + /// #else + /// consent_info = firebase::gma::ump::GetInstance(); + /// #endif + /// @endcode + /// + /// @param[in] jni_env JNIEnv pointer. + /// @param[in] activity Activity used to start the application. + /// @param[out] init_result_out Optional: If provided, write the basic init + /// result here. kInitResultSuccess if initialization succeeded, or + /// kInitResultFailedMissingDependency on Android if there are Android + /// dependencies missing. + /// + /// @return A pointer to the ConsentInfo instance if UMP was successfully + /// initialized, nullptr otherwise. Each call to GetInstance() will return the + /// same pointer; when you are finished using the SDK, you can delete the + /// pointer and the UMP SDK will shut down. + static ConsentInfo* GetInstance(JNIEnv* jni_env, jobject activity, + InitResult* init_result_out = nullptr); +#endif // FIREBASE_PLATFORM_ANDROID || defined(DOXYGEN) + +#if !FIREBASE_PLATFORM_ANDROID || defined(DOXYGEN) + /// Initializes Google Mobile Ads (GMA) without Firebase for iOS. + /// + /// @param[out] init_result_out Optional: If provided, write the basic init + /// result here. kInitResultSuccess if initialization succeeded, or + /// kInitResultFailedMissingDependency if a dependency is missing. On iOS, this + /// will always return kInitResultSuccess, as missing dependencies would have + /// caused a linker error at build time. + /// + /// @return A pointer to the ConsentInfo instance. Each call to GetInstance() + /// will return the same pointer; when you are finished using the SDK, you can + /// delete the pointer, and the UMP SDK will shut down. + static ConsentInfo* GetInstance(InitResult* init_result_out = nullptr); +#endif // !defined(__ANDROID__) || defined(DOXYGEN) + + private: + // An internal, platform-specific implementation object that this class uses + // to interact with the User Messaging Platform SDKs for iOS and Android. + internal::ConsentInfoInternal* internal_; +}; + +} // namespace ump +} // namespace gma +} // namespace firebase + +#endif // FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_CONSENT_INFO_H_ diff --git a/gma/src/include/firebase/gma/ump/types.h b/gma/src/include/firebase/gma/ump/types.h new file mode 100644 index 0000000000..3399597852 --- /dev/null +++ b/gma/src/include/firebase/gma/ump/types.h @@ -0,0 +1,152 @@ +/* + * Copyright 2023 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. + */ + +#ifndef FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_UMP_TYPES_H_ +#define FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_UMP_TYPES_H_ + +#include +#include +#include + +#include "firebase/internal/platform.h" + +namespace firebase { +namespace gma { +namespace ump { + +enum ConsentDebugGeography { + kConsentDebugGeographyDisabled = 0, + kConsentDebugGeographyEEA, + kConsentDebugGeographyNonEEA +}; + +struct ConsentDebugSettings { + ConsentDebugSettings() : debug_geography(kConsentDebugGeographyDisabled) {} + + ConsentDebugGeography debug_geography; + std::vector debug_device_ids; +}; + +// Parameters for the consent info request operation. +class ConsentRequestParameters { +public: + ConsentRequestParameters() : has_debug_settings_(false), + tag_for_under_age_of_consent_(false), + has_tag_for_under_age_of_consent_(false) + {} + // Set the age of consent tag. + void set_tag_for_under_age_of_consent(bool tag) { + tag_for_under_age_of_consent_ = tag; + has_tag_for_under_age_of_consent_ = true; + } + // Get the age of consent tag. + bool tag_for_under_age_of_consent() { + return tag_for_under_age_of_consent_; + } + // Get whether the age of consent tag was previously set. + bool has_tag_for_under_age_of_consent() { + return has_tag_for_under_age_of_consent_; + } + + // Set the debug settings. + void set_debug_settings(const ConsentDebugSettings& settings) { + debug_settings_ = settings; + has_debug_settings_ = true; + } + // Set the debug settings without copying data, useful if you have a large + // list of debug device IDs. + void set_debug_settings(const ConsentDebugSettings&& settings) { + debug_settings_ = std::move(settings); + has_debug_settings_ = true; + } + // Get the debug settings. + ConsentDebugSettings debug_settings() { + return debug_settings_; + } + // Get whether debug settings were set. + bool has_debug_settings() { + return has_debug_settings_; + } +private: + ConsentDebugSettings debug_settings_; + bool tag_for_under_age_of_consent_; + bool has_debug_settings_; + bool has_tag_for_under_age_of_consent_; +}; + +/// This is a platform specific datatype that is required to show a consent form +/// on screen. +/// +/// The following defines the datatype on each platform: +///
    +///
  • Android: A `jobject` which references an Android Activity.
  • +///
  • iOS: An `id` which references an iOS UIViewController.
  • +///
+#if FIREBASE_PLATFORM_ANDROID +/// An Android Activity from Java. +typedef jobject FormParent; +#elif FIREBASE_PLATFORM_IOS || FIREBASE_PLATFORM_TVOS +/// A pointer to an iOS UIViewController. +typedef id FormParent; +#else +/// A void pointer for stub classes. +typedef void* FormParent; +#endif // FIREBASE_PLATFORM_ANDROID, FIREBASE_PLATFORM_IOS, + // FIREBASE_PLATFORM_TVOS + +enum ConsentStatus { + // Unknown status, e.g. prior to calling Request, or if the request fails. + kConsentStatusUnknown = 0, + // Consent is required, but not obtained + kConsentStatusRequired, + // Consent is not required + kConsentStatusNotRequired, + // Consent was required, and has been obtained + kConsentStatusObtained +}; + +enum ConsentRequestError { + kConsentRequestSuccess = 0, + kConsentRequestErrorInvalidAppId, + kConsentRequestErrorNetwork, + kConsentRequestErrorTagForAgeOfConsentNotSet, + kConsentRequestErrorInternal, + kConsentRequestErrorCodeMisconfiguration, + kConsentRequestErrorUnknown, +}; + +enum ConsentFormStatus { + kConsentFormStatusUnknown=0, + kConsentFormStatusUnavailable, + kConsentFormStatusAvailable, +}; + +enum ConsentFormError { + kConsentFormSuccess = 0, + kConsentFormErrorTimeout, + kConsentFormErrorNotLoaded, + kConsentFormErrorInternal, + kConsentFormErrorUnknown, + kConsentFormErrorCodeAlreadyUsed, + kConsentFormErrorInvalidOperation, + kConsentFormErrorNetwork +}; + +} // namespace ump +} // namespace gma +} // namespace firebase + +#endif // FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_UMP_TYPES_H_ diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc new file mode 100644 index 0000000000..53e07c2f66 --- /dev/null +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -0,0 +1,31 @@ +/* + * Copyright 2023 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. + */ + +#include "gma/src/stub/ump/consent_info_internal_stub.h" + +namespace firebase { +namespace gma { +namespace ump { +namespace internal { + +ConsentInfoInternalStub::~ConsentInfoInternalStub() { + +} + +} // namespace internal +} // namespace ump +} // namespace gma +} // namespace firebase diff --git a/gma/src/stub/ump/consent_info_internal_stub.h b/gma/src/stub/ump/consent_info_internal_stub.h new file mode 100644 index 0000000000..06cafa0026 --- /dev/null +++ b/gma/src/stub/ump/consent_info_internal_stub.h @@ -0,0 +1,39 @@ +/* + * Copyright 2023 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. + */ + +#ifndef FIREBASE_GMA_SRC_STUB_UMP_CONSENT_INFO_INTERNAL_STUB_H_ +#define FIREBASE_GMA_SRC_STUB_UMP_CONSENT_INFO_INTERNAL_STUB_H_ + +#include "gma/src/common/ump/consent_info_internal.h" + +namespace firebase { +namespace gma { +namespace ump { +namespace internal { + +class ConsentInfoInternalStub : ConsentInfoInternal { + public: + ConsentInfoInternalStub() {} + ~ConsentInfoInternalStub() override; + +}; + +} // namespace internal +} // namespace ump +} // namespace gma +} // namespace firebase + +#endif // FIREBASE_GMA_SRC_STUB_UMP_CONSENT_INFO_INTERNAL_STUB_H_ From 61b9efe5d505a4653fde9fa0efef5a4a1dd8883d Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 15:03:41 -0700 Subject: [PATCH 02/50] Added error message getters. --- gma/src/include/firebase/gma/ump.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gma/src/include/firebase/gma/ump.h b/gma/src/include/firebase/gma/ump.h index 4a6ed9f775..6e0f50b23d 100644 --- a/gma/src/include/firebase/gma/ump.h +++ b/gma/src/include/firebase/gma/ump.h @@ -30,7 +30,11 @@ namespace gma { /// See the ConsentInfo class for details. namespace ump { -// More information is available in ump/consent_info.h. +/// Returns a static string describing the given error code. +const char* GetConsentRequestErrorMessage(ConsentRequestError code); + +/// Returns a static string describing the given error code. +const char* GetConsentFormErrorMessage(ConsentFormError code); } // namespace ump } // namespace gma From 092f76e0af67a01ad56efa54ed453d37cd3aec6b Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 15:12:33 -0700 Subject: [PATCH 03/50] Add ConsentInfo methods. --- gma/src/include/firebase/gma/ump.h | 6 ++-- .../include/firebase/gma/ump/consent_info.h | 28 +++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/gma/src/include/firebase/gma/ump.h b/gma/src/include/firebase/gma/ump.h index 6e0f50b23d..3468ba6156 100644 --- a/gma/src/include/firebase/gma/ump.h +++ b/gma/src/include/firebase/gma/ump.h @@ -17,8 +17,8 @@ #ifndef FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_UMP_H_ #define FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_UMP_H_ -#include "firebase/gma/ump/types.h" #include "firebase/gma/ump/consent_info.h" +#include "firebase/gma/ump/types.h" namespace firebase { namespace gma { @@ -31,10 +31,10 @@ namespace gma { namespace ump { /// Returns a static string describing the given error code. -const char* GetConsentRequestErrorMessage(ConsentRequestError code); +const char* GetConsentRequestErrorMessage(ConsentRequestError error_code); /// Returns a static string describing the given error code. -const char* GetConsentFormErrorMessage(ConsentFormError code); +const char* GetConsentFormErrorMessage(ConsentFormError error_code); } // namespace ump } // namespace gma diff --git a/gma/src/include/firebase/gma/ump/consent_info.h b/gma/src/include/firebase/gma/ump/consent_info.h index 54d3f0aaca..404657564b 100644 --- a/gma/src/include/firebase/gma/ump/consent_info.h +++ b/gma/src/include/firebase/gma/ump/consent_info.h @@ -27,6 +27,7 @@ #include #include "firebase/app.h" +#include "firebase/future.h" #include "firebase/internal/common.h" namespace firebase { @@ -105,6 +106,33 @@ class ConsentInfo { static ConsentInfo* GetInstance(InitResult* init_result_out = nullptr); #endif // !defined(__ANDROID__) || defined(DOXYGEN) + + /// Requests consent information update. Must be called before loading a + /// consent form. + Future RequestConsentStatus(const ConsentRequestParameters& params); + + /// The user’s consent status. This value is cached between app sessions and + /// can be read before requesting updated parameters. + ConsentStatus GetConsentStatus(); + + /// Consent form status. This value defaults to kConsentFormStatusUnknown and + /// requires a call to RequestConsentStatus() to update. + ConsentFormStatus GetConsentFormStatus(); + + /// Loads a consent form. + Future LoadConsentForm(); + + /// Presents the full screen consent form using the given FormParent, which is + /// defined as an Activity on Android and a UIViewController on iOS. The form + /// will be dismissed and the Future will be completed after the user selects + /// an option. GetConsentStatus() is updated prior to the Future being + /// completed. + Future ShowConsentForm(FormParent parent); + + /// Clears all consent state from persistent storage. This can be used in + /// development to simulate a new installation. + void Reset(); + private: // An internal, platform-specific implementation object that this class uses // to interact with the User Messaging Platform SDKs for iOS and Android. From 1de4ac66c0f5169b4560872b1c0a1429b8c99877 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 15:13:08 -0700 Subject: [PATCH 04/50] Format code. --- gma/src/common/ump/consent_info_internal.cc | 6 +--- gma/src/common/ump/consent_info_internal.h | 2 +- .../include/firebase/gma/ump/consent_info.h | 25 +++++++------- gma/src/include/firebase/gma/ump/types.h | 33 ++++++++----------- .../stub/ump/consent_info_internal_stub.cc | 4 +-- gma/src/stub/ump/consent_info_internal_stub.h | 1 - 6 files changed, 28 insertions(+), 43 deletions(-) diff --git a/gma/src/common/ump/consent_info_internal.cc b/gma/src/common/ump/consent_info_internal.cc index e82dd58823..f58f892c7a 100644 --- a/gma/src/common/ump/consent_info_internal.cc +++ b/gma/src/common/ump/consent_info_internal.cc @@ -21,13 +21,9 @@ namespace gma { namespace ump { namespace internal { -virtual ConsentInfoInternal::~ConsentInfoInternal() { - -} +virtual ConsentInfoInternal::~ConsentInfoInternal() {} } // namespace internal } // namespace ump } // namespace gma } // namespace firebase - - diff --git a/gma/src/common/ump/consent_info_internal.h b/gma/src/common/ump/consent_info_internal.h index c3d261b892..080fb35326 100644 --- a/gma/src/common/ump/consent_info_internal.h +++ b/gma/src/common/ump/consent_info_internal.h @@ -25,7 +25,7 @@ namespace ump { namespace internal { class ConsentInfoInternal { -public: + public: ConsentInfoInternal() {} virtual ~ConsentInfoInternal(); }; diff --git a/gma/src/include/firebase/gma/ump/consent_info.h b/gma/src/include/firebase/gma/ump/consent_info.h index 404657564b..3e696f3fbf 100644 --- a/gma/src/include/firebase/gma/ump/consent_info.h +++ b/gma/src/include/firebase/gma/ump/consent_info.h @@ -43,7 +43,6 @@ namespace internal { class ConsentInfoInternal; } // namespace internal - class ConsentInfo { public: /// Initializes the User Messaging Platform Consent API. @@ -60,20 +59,18 @@ class ConsentInfo { /// same pointer; when you are finished using the SDK, you can delete the /// pointer and the UMP SDK will shut down. static ConsentInfo* GetInstance(const ::firebase::App& app, - InitResult* init_result_out = nullptr); + InitResult* init_result_out = nullptr); #if FIREBASE_PLATFORM_ANDROID || defined(DOXYGEN) /// Initializes the User Messaging Platform Consent API without Firebase for /// Android. /// - /// The arguments to @ref Initialize are platform-specific so the caller must do - /// something like this: + /// The arguments to @ref Initialize are platform-specific so the caller must + /// do something like this: /// @code /// #if defined(__ANDROID__) - /// consent_info = firebase::gma::ump::ConsentInfo::GetInstance(jni_env, activity); - /// #else - /// consent_info = firebase::gma::ump::GetInstance(); - /// #endif + /// consent_info = firebase::gma::ump::ConsentInfo::GetInstance(jni_env, + /// activity); #else consent_info = firebase::gma::ump::GetInstance(); #endif /// @endcode /// /// @param[in] jni_env JNIEnv pointer. @@ -88,7 +85,7 @@ class ConsentInfo { /// same pointer; when you are finished using the SDK, you can delete the /// pointer and the UMP SDK will shut down. static ConsentInfo* GetInstance(JNIEnv* jni_env, jobject activity, - InitResult* init_result_out = nullptr); + InitResult* init_result_out = nullptr); #endif // FIREBASE_PLATFORM_ANDROID || defined(DOXYGEN) #if !FIREBASE_PLATFORM_ANDROID || defined(DOXYGEN) @@ -96,9 +93,9 @@ class ConsentInfo { /// /// @param[out] init_result_out Optional: If provided, write the basic init /// result here. kInitResultSuccess if initialization succeeded, or - /// kInitResultFailedMissingDependency if a dependency is missing. On iOS, this - /// will always return kInitResultSuccess, as missing dependencies would have - /// caused a linker error at build time. + /// kInitResultFailedMissingDependency if a dependency is missing. On iOS, + /// this will always return kInitResultSuccess, as missing dependencies would + /// have caused a linker error at build time. /// /// @return A pointer to the ConsentInfo instance. Each call to GetInstance() /// will return the same pointer; when you are finished using the SDK, you can @@ -106,10 +103,10 @@ class ConsentInfo { static ConsentInfo* GetInstance(InitResult* init_result_out = nullptr); #endif // !defined(__ANDROID__) || defined(DOXYGEN) - /// Requests consent information update. Must be called before loading a /// consent form. - Future RequestConsentStatus(const ConsentRequestParameters& params); + Future RequestConsentStatus( + const ConsentRequestParameters& params); /// The user’s consent status. This value is cached between app sessions and /// can be read before requesting updated parameters. diff --git a/gma/src/include/firebase/gma/ump/types.h b/gma/src/include/firebase/gma/ump/types.h index 3399597852..2127137314 100644 --- a/gma/src/include/firebase/gma/ump/types.h +++ b/gma/src/include/firebase/gma/ump/types.h @@ -42,20 +42,18 @@ struct ConsentDebugSettings { // Parameters for the consent info request operation. class ConsentRequestParameters { -public: - ConsentRequestParameters() : has_debug_settings_(false), - tag_for_under_age_of_consent_(false), - has_tag_for_under_age_of_consent_(false) - {} + public: + ConsentRequestParameters() + : has_debug_settings_(false), + tag_for_under_age_of_consent_(false), + has_tag_for_under_age_of_consent_(false) {} // Set the age of consent tag. void set_tag_for_under_age_of_consent(bool tag) { tag_for_under_age_of_consent_ = tag; has_tag_for_under_age_of_consent_ = true; } // Get the age of consent tag. - bool tag_for_under_age_of_consent() { - return tag_for_under_age_of_consent_; - } + bool tag_for_under_age_of_consent() { return tag_for_under_age_of_consent_; } // Get whether the age of consent tag was previously set. bool has_tag_for_under_age_of_consent() { return has_tag_for_under_age_of_consent_; @@ -73,20 +71,17 @@ class ConsentRequestParameters { has_debug_settings_ = true; } // Get the debug settings. - ConsentDebugSettings debug_settings() { - return debug_settings_; - } + ConsentDebugSettings debug_settings() { return debug_settings_; } // Get whether debug settings were set. - bool has_debug_settings() { - return has_debug_settings_; - } -private: + bool has_debug_settings() { return has_debug_settings_; } + + private: ConsentDebugSettings debug_settings_; bool tag_for_under_age_of_consent_; bool has_debug_settings_; bool has_tag_for_under_age_of_consent_; }; - + /// This is a platform specific datatype that is required to show a consent form /// on screen. /// @@ -129,17 +124,17 @@ enum ConsentRequestError { }; enum ConsentFormStatus { - kConsentFormStatusUnknown=0, + kConsentFormStatusUnknown = 0, kConsentFormStatusUnavailable, kConsentFormStatusAvailable, }; - + enum ConsentFormError { kConsentFormSuccess = 0, kConsentFormErrorTimeout, kConsentFormErrorNotLoaded, kConsentFormErrorInternal, - kConsentFormErrorUnknown, + kConsentFormErrorUnknown, kConsentFormErrorCodeAlreadyUsed, kConsentFormErrorInvalidOperation, kConsentFormErrorNetwork diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index 53e07c2f66..70ad10a735 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -21,9 +21,7 @@ namespace gma { namespace ump { namespace internal { -ConsentInfoInternalStub::~ConsentInfoInternalStub() { - -} +ConsentInfoInternalStub::~ConsentInfoInternalStub() {} } // namespace internal } // namespace ump diff --git a/gma/src/stub/ump/consent_info_internal_stub.h b/gma/src/stub/ump/consent_info_internal_stub.h index 06cafa0026..f215fc15fb 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.h +++ b/gma/src/stub/ump/consent_info_internal_stub.h @@ -28,7 +28,6 @@ class ConsentInfoInternalStub : ConsentInfoInternal { public: ConsentInfoInternalStub() {} ~ConsentInfoInternalStub() override; - }; } // namespace internal From 1074858320a17b510726e6f5924381f0c6ea9d34 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 15:14:21 -0700 Subject: [PATCH 05/50] Comment tweak. --- gma/src/include/firebase/gma/ump/consent_info.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gma/src/include/firebase/gma/ump/consent_info.h b/gma/src/include/firebase/gma/ump/consent_info.h index 3e696f3fbf..6618daab38 100644 --- a/gma/src/include/firebase/gma/ump/consent_info.h +++ b/gma/src/include/firebase/gma/ump/consent_info.h @@ -109,7 +109,7 @@ class ConsentInfo { const ConsentRequestParameters& params); /// The user’s consent status. This value is cached between app sessions and - /// can be read before requesting updated parameters. + /// can be read before calling RequestConsentStatus(). ConsentStatus GetConsentStatus(); /// Consent form status. This value defaults to kConsentFormStatusUnknown and @@ -122,7 +122,7 @@ class ConsentInfo { /// Presents the full screen consent form using the given FormParent, which is /// defined as an Activity on Android and a UIViewController on iOS. The form /// will be dismissed and the Future will be completed after the user selects - /// an option. GetConsentStatus() is updated prior to the Future being + /// an option. GetConsentStatus() is updated prior to the Future being /// completed. Future ShowConsentForm(FormParent parent); From 4c8ff0bb7d60da36c30d3d497af4c565a4070276 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 15:14:51 -0700 Subject: [PATCH 06/50] Fix lint error. --- gma/src/include/firebase/gma/ump/consent_info.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gma/src/include/firebase/gma/ump/consent_info.h b/gma/src/include/firebase/gma/ump/consent_info.h index 6618daab38..cf0d11dc59 100644 --- a/gma/src/include/firebase/gma/ump/consent_info.h +++ b/gma/src/include/firebase/gma/ump/consent_info.h @@ -140,4 +140,4 @@ class ConsentInfo { } // namespace gma } // namespace firebase -#endif // FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_CONSENT_INFO_H_ +#endif // FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_UMP_CONSENT_INFO_H_ From 06540704c4a5c68e3babb0b3ec94319c136cb089 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 15:15:55 -0700 Subject: [PATCH 07/50] Add LastResult methods. --- gma/src/include/firebase/gma/ump/consent_info.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gma/src/include/firebase/gma/ump/consent_info.h b/gma/src/include/firebase/gma/ump/consent_info.h index cf0d11dc59..5c0ce5b5ad 100644 --- a/gma/src/include/firebase/gma/ump/consent_info.h +++ b/gma/src/include/firebase/gma/ump/consent_info.h @@ -108,6 +108,9 @@ class ConsentInfo { Future RequestConsentStatus( const ConsentRequestParameters& params); + /// Get the Future from the most recent call to RequestConsentStatus(). + Future RequestConsentStatusLastResult(); + /// The user’s consent status. This value is cached between app sessions and /// can be read before calling RequestConsentStatus(). ConsentStatus GetConsentStatus(); @@ -119,6 +122,9 @@ class ConsentInfo { /// Loads a consent form. Future LoadConsentForm(); + /// Get the Future from the most recent call to LoadConsentForm(). + Future LoadConsentFormLastResult(); + /// Presents the full screen consent form using the given FormParent, which is /// defined as an Activity on Android and a UIViewController on iOS. The form /// will be dismissed and the Future will be completed after the user selects From f6399cedcdd103da361836d35076a62aae9929b5 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 15:58:09 -0700 Subject: [PATCH 08/50] Additional implementation. --- gma/src/common/ump/consent_info_internal.h | 6 +++- .../include/firebase/gma/ump/consent_info.h | 34 ++++++++++++++----- .../stub/ump/consent_info_internal_stub.cc | 5 +++ gma/src/stub/ump/consent_info_internal_stub.h | 2 +- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/gma/src/common/ump/consent_info_internal.h b/gma/src/common/ump/consent_info_internal.h index 080fb35326..58a5dbef00 100644 --- a/gma/src/common/ump/consent_info_internal.h +++ b/gma/src/common/ump/consent_info_internal.h @@ -26,8 +26,12 @@ namespace internal { class ConsentInfoInternal { public: - ConsentInfoInternal() {} virtual ~ConsentInfoInternal(); + + static ConsentInfoInternal* CreateInstance(); + + protected: + ConsentInfoInternal() {} }; } // namespace internal diff --git a/gma/src/include/firebase/gma/ump/consent_info.h b/gma/src/include/firebase/gma/ump/consent_info.h index 5c0ce5b5ad..ad830bb34d 100644 --- a/gma/src/include/firebase/gma/ump/consent_info.h +++ b/gma/src/include/firebase/gma/ump/consent_info.h @@ -17,19 +17,17 @@ #ifndef FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_UMP_CONSENT_INFO_H_ #define FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_UMP_CONSENT_INFO_H_ +#include "app/src/assert.h" +#include "firebase/app.h" +#include "firebase/future.h" #include "firebase/gma/ump/types.h" +#include "firebase/internal/common.h" #include "firebase/internal/platform.h" #if FIREBASE_PLATFORM_ANDROID #include #endif // FIREBASE_PLATFORM_ANDROID -#include - -#include "firebase/app.h" -#include "firebase/future.h" -#include "firebase/internal/common.h" - namespace firebase { namespace gma { /// @brief API for User Messaging Platform. @@ -45,7 +43,10 @@ class ConsentInfoInternal; class ConsentInfo { public: - /// Initializes the User Messaging Platform Consent API. + /// Shut down the User Messaging Platform Consent SDK + ~ConsentInfo(); + + /// Initializes the User Messaging Platform Consent SDK. /// /// @param[in] app Any Firebase App instance. /// @@ -62,7 +63,7 @@ class ConsentInfo { InitResult* init_result_out = nullptr); #if FIREBASE_PLATFORM_ANDROID || defined(DOXYGEN) - /// Initializes the User Messaging Platform Consent API without Firebase for + /// Initializes the User Messaging Platform Consent SDK without Firebase for /// Android. /// /// The arguments to @ref Initialize are platform-specific so the caller must @@ -89,7 +90,7 @@ class ConsentInfo { #endif // FIREBASE_PLATFORM_ANDROID || defined(DOXYGEN) #if !FIREBASE_PLATFORM_ANDROID || defined(DOXYGEN) - /// Initializes Google Mobile Ads (GMA) without Firebase for iOS. + /// Initializes User Messaging Platform for iOS without Firebase. /// /// @param[out] init_result_out Optional: If provided, write the basic init /// result here. kInitResultSuccess if initialization succeeded, or @@ -137,6 +138,21 @@ class ConsentInfo { void Reset(); private: + ConsentInfo(); +#if FIREBASE_PLATFORM_ANDROID + InitResult Initialize(/* JNIEnv* jni_env, jobject activity */); // TODO +#else + InitResult Initialize(); +#endif // FIREBASE_PLATFORM_ANDROID + void Terminate(); + + static ConsentInfo* instance_; + +#if FIREBASE_PLATFORM_ANDROID + JavaVM* java_vm() { return java_vm_; } + JavaVM* java_vm_; +#endif + // An internal, platform-specific implementation object that this class uses // to interact with the User Messaging Platform SDKs for iOS and Android. internal::ConsentInfoInternal* internal_; diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index 70ad10a735..34361710c3 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -21,6 +21,11 @@ namespace gma { namespace ump { namespace internal { +// This explicitly implements the constructor for the outer class. +ConsentInfoInternal* ConsentInfoInternal::CreateInstance() { + return new ConsentInfoInternalStub(); +}; + ConsentInfoInternalStub::~ConsentInfoInternalStub() {} } // namespace internal diff --git a/gma/src/stub/ump/consent_info_internal_stub.h b/gma/src/stub/ump/consent_info_internal_stub.h index f215fc15fb..2c10b88e2d 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.h +++ b/gma/src/stub/ump/consent_info_internal_stub.h @@ -24,7 +24,7 @@ namespace gma { namespace ump { namespace internal { -class ConsentInfoInternalStub : ConsentInfoInternal { +class ConsentInfoInternalStub : public ConsentInfoInternal { public: ConsentInfoInternalStub() {} ~ConsentInfoInternalStub() override; From 5dfcf28e30596c3233c3af38125f9d792fb9ec2c Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 16:10:00 -0700 Subject: [PATCH 09/50] Fix build. --- gma/CMakeLists.txt | 1 + gma/src/common/ump/consent_info_internal.cc | 2 +- gma/src/common/ump/consent_info_internal.h | 2 -- gma/src/include/firebase/gma/ump/consent_info.h | 4 +--- gma/src/stub/ump/consent_info_internal_stub.cc | 3 ++- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/gma/CMakeLists.txt b/gma/CMakeLists.txt index 9e57c0c7eb..440d0db7f0 100644 --- a/gma/CMakeLists.txt +++ b/gma/CMakeLists.txt @@ -17,6 +17,7 @@ # Common source files used by all platforms set(common_SRCS src/common/ump/consent_info.cc + src/common/ump/consent_info_internal.cc src/common/gma_common.cc src/common/ad_view.cc src/common/ad_view_internal.cc diff --git a/gma/src/common/ump/consent_info_internal.cc b/gma/src/common/ump/consent_info_internal.cc index f58f892c7a..ad8ad2e76a 100644 --- a/gma/src/common/ump/consent_info_internal.cc +++ b/gma/src/common/ump/consent_info_internal.cc @@ -21,7 +21,7 @@ namespace gma { namespace ump { namespace internal { -virtual ConsentInfoInternal::~ConsentInfoInternal() {} +ConsentInfoInternal::~ConsentInfoInternal() {} } // namespace internal } // namespace ump diff --git a/gma/src/common/ump/consent_info_internal.h b/gma/src/common/ump/consent_info_internal.h index 58a5dbef00..78c71d7de0 100644 --- a/gma/src/common/ump/consent_info_internal.h +++ b/gma/src/common/ump/consent_info_internal.h @@ -17,8 +17,6 @@ #ifndef FIREBASE_GMA_SRC_COMMON_UMP_CONSENT_INFO_INTERNAL_H_ #define FIREBASE_GMA_SRC_COMMON_UMP_CONSENT_INFO_INTERNAL_H_ -#include "firebase/gma/ump.h" - namespace firebase { namespace gma { namespace ump { diff --git a/gma/src/include/firebase/gma/ump/consent_info.h b/gma/src/include/firebase/gma/ump/consent_info.h index ad830bb34d..f556d46e99 100644 --- a/gma/src/include/firebase/gma/ump/consent_info.h +++ b/gma/src/include/firebase/gma/ump/consent_info.h @@ -17,11 +17,9 @@ #ifndef FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_UMP_CONSENT_INFO_H_ #define FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_UMP_CONSENT_INFO_H_ -#include "app/src/assert.h" #include "firebase/app.h" #include "firebase/future.h" #include "firebase/gma/ump/types.h" -#include "firebase/internal/common.h" #include "firebase/internal/platform.h" #if FIREBASE_PLATFORM_ANDROID @@ -146,7 +144,7 @@ class ConsentInfo { #endif // FIREBASE_PLATFORM_ANDROID void Terminate(); - static ConsentInfo* instance_; + static ConsentInfo* s_instance_; #if FIREBASE_PLATFORM_ANDROID JavaVM* java_vm() { return java_vm_; } diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index 34361710c3..459903bbb6 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -21,7 +21,8 @@ namespace gma { namespace ump { namespace internal { -// This explicitly implements the constructor for the outer class. +// This explicitly implements the constructor for the outer class, +// ConsentInfoInternal. ConsentInfoInternal* ConsentInfoInternal::CreateInstance() { return new ConsentInfoInternalStub(); }; From 9c21d3b6c4245df8958d479da9bb3c228bbff3c6 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 16:17:44 -0700 Subject: [PATCH 10/50] Fix lint errors. --- gma/integration_test/src/integration_test.cc | 36 +++++++++++++++++++ .../include/firebase/gma/ump/consent_info.h | 3 +- .../stub/ump/consent_info_internal_stub.cc | 2 +- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/gma/integration_test/src/integration_test.cc b/gma/integration_test/src/integration_test.cc index 2a48d0066f..fb50f31492 100644 --- a/gma/integration_test/src/integration_test.cc +++ b/gma/integration_test/src/integration_test.cc @@ -26,6 +26,7 @@ #include "firebase/app.h" #include "firebase/gma.h" #include "firebase/gma/types.h" +#include "firebase/gma/ump.h" #include "firebase/util.h" #include "firebase_test_framework.h" // NOLINT @@ -2439,4 +2440,39 @@ TEST_F(FirebaseGmaTest, TestAdViewMultithreadDeletion) { #endif // #if defined(ANDROID) || (defined(TARGET_OS_IPHONE) && // TARGET_OS_IPHONE) + +class FirebaseGmaUmpTest : public FirebaseTest { + void SetUpTestSuite(); + void TearDownTestSuite(); + + static firebase::App* shared_app_; +}; + +void FirebaseGmaUmpTest::SetUpTestSuite() { + LogDebug("Initialize Firebase App."); + + FindFirebaseConfig(FIREBASE_CONFIG_STRING); + +#if defined(ANDROID) + shared_app_ = ::firebase::App::Create(app_framework::GetJniEnv(), + app_framework::GetActivity()); +#else + shared_app_ = ::firebase::App::Create(); +#endif // defined(ANDROID) +} + +void FirebaseGmaTest::TearDownTestSuite() { + LogDebug("Shutdown Firebase App."); + delete shared_app_; + shared_app_ = nullptr; +} + +TEST_F(FirebaseGmaUmpTest, TestInitialization) { + using firebase::gma::ump::ConsentInfo; + ConsentInfo* consent_info = ConsentInfo::GetInstance(); + + delete consent_info; + consent_info = nullptr; +} + } // namespace firebase_testapp_automated diff --git a/gma/src/include/firebase/gma/ump/consent_info.h b/gma/src/include/firebase/gma/ump/consent_info.h index f556d46e99..a50043a356 100644 --- a/gma/src/include/firebase/gma/ump/consent_info.h +++ b/gma/src/include/firebase/gma/ump/consent_info.h @@ -138,7 +138,8 @@ class ConsentInfo { private: ConsentInfo(); #if FIREBASE_PLATFORM_ANDROID - InitResult Initialize(/* JNIEnv* jni_env, jobject activity */); // TODO + // TODO(b/291622888) Implement Android-specific Initialize.. + InitResult Initialize(/* JNIEnv* jni_env, jobject activity */); #else InitResult Initialize(); #endif // FIREBASE_PLATFORM_ANDROID diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index 459903bbb6..a6cce722c7 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -25,7 +25,7 @@ namespace internal { // ConsentInfoInternal. ConsentInfoInternal* ConsentInfoInternal::CreateInstance() { return new ConsentInfoInternalStub(); -}; +} ConsentInfoInternalStub::~ConsentInfoInternalStub() {} From 9552f7a8e9f05cec8eba3ca453327079218a69f8 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 16:28:05 -0700 Subject: [PATCH 11/50] Added integration test for initializing library. --- gma/integration_test/src/integration_test.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/gma/integration_test/src/integration_test.cc b/gma/integration_test/src/integration_test.cc index fb50f31492..ce655c0488 100644 --- a/gma/integration_test/src/integration_test.cc +++ b/gma/integration_test/src/integration_test.cc @@ -2440,11 +2440,13 @@ TEST_F(FirebaseGmaTest, TestAdViewMultithreadDeletion) { #endif // #if defined(ANDROID) || (defined(TARGET_OS_IPHONE) && // TARGET_OS_IPHONE) - +// Tests for User Messaging Platform class FirebaseGmaUmpTest : public FirebaseTest { +public: void SetUpTestSuite(); void TearDownTestSuite(); - + +protected: static firebase::App* shared_app_; }; @@ -2461,7 +2463,7 @@ void FirebaseGmaUmpTest::SetUpTestSuite() { #endif // defined(ANDROID) } -void FirebaseGmaTest::TearDownTestSuite() { +void FirebaseGmaUmpTest::TearDownTestSuite() { LogDebug("Shutdown Firebase App."); delete shared_app_; shared_app_ = nullptr; From f6efa69018b842fc2f1cc9f52bade9a17e57d68d Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 16:32:41 -0700 Subject: [PATCH 12/50] Update test. --- gma/integration_test/src/integration_test.cc | 13 +++++++++-- gma/src/common/ump/consent_info_internal.cc | 2 ++ gma/src/common/ump/consent_info_internal.h | 23 +++++++++++++++++++- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/gma/integration_test/src/integration_test.cc b/gma/integration_test/src/integration_test.cc index ce655c0488..ed25f2e5a8 100644 --- a/gma/integration_test/src/integration_test.cc +++ b/gma/integration_test/src/integration_test.cc @@ -2442,14 +2442,21 @@ TEST_F(FirebaseGmaTest, TestAdViewMultithreadDeletion) { // Tests for User Messaging Platform class FirebaseGmaUmpTest : public FirebaseTest { -public: + public: + FirebaseGmaUmpTest(); + ~FirebaseGmaUmpTest() override; + void SetUpTestSuite(); void TearDownTestSuite(); -protected: + protected: static firebase::App* shared_app_; }; +FirebaseGmaUmpTest::FirebaseGmaUmpTest() { shared_app_ = nullptr; } + +FirebaseGmaUmpTest::~FirebaseGmaUmpTest() { assert(shared_app_ = nullptr); } + void FirebaseGmaUmpTest::SetUpTestSuite() { LogDebug("Initialize Firebase App."); @@ -2473,6 +2480,8 @@ TEST_F(FirebaseGmaUmpTest, TestInitialization) { using firebase::gma::ump::ConsentInfo; ConsentInfo* consent_info = ConsentInfo::GetInstance(); + EXPECT_NE(consent_info, nullptr); + delete consent_info; consent_info = nullptr; } diff --git a/gma/src/common/ump/consent_info_internal.cc b/gma/src/common/ump/consent_info_internal.cc index ad8ad2e76a..ecbe48a289 100644 --- a/gma/src/common/ump/consent_info_internal.cc +++ b/gma/src/common/ump/consent_info_internal.cc @@ -21,6 +21,8 @@ namespace gma { namespace ump { namespace internal { +ConsentInfoInternal::ConsentInfoInternal() : futures_(kConsentInfoFnCount) {} + ConsentInfoInternal::~ConsentInfoInternal() {} } // namespace internal diff --git a/gma/src/common/ump/consent_info_internal.h b/gma/src/common/ump/consent_info_internal.h index 78c71d7de0..3e2cb59698 100644 --- a/gma/src/common/ump/consent_info_internal.h +++ b/gma/src/common/ump/consent_info_internal.h @@ -17,19 +17,40 @@ #ifndef FIREBASE_GMA_SRC_COMMON_UMP_CONSENT_INFO_INTERNAL_H_ #define FIREBASE_GMA_SRC_COMMON_UMP_CONSENT_INFO_INTERNAL_H_ +#include "app/src/cleanup_notifier.h" +#include "app/src/reference_counted_future_impl.h" +#include "firebase/future.h" + namespace firebase { namespace gma { namespace ump { namespace internal { +// Constants representing each ConsentInfo function that returns a Future. +enum ConsentInfoFn { + kConsentInfoFnRequestConsentStatus, + kConsentInfoFnLoadConsentForm, + kConsentInfoFnShowConsentForm, + kConsentInfoFnCount +}; + class ConsentInfoInternal { public: virtual ~ConsentInfoInternal(); + // Implemented in platform-specific code to instantiate a + // platform-specific subclass. static ConsentInfoInternal* CreateInstance(); protected: - ConsentInfoInternal() {} + ConsentInfoInternal(); + + ReferenceCountedFutureImpl* futures() { return &futures_; } + CleanupNotifier* cleanup() { return &cleanup_; } + + private: + ReferenceCountedFutureImpl futures_; + CleanupNotifier cleanup_; }; } // namespace internal From 0727c9ebf5c9bfe5b110606893c9fea3241de40a Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 16:36:50 -0700 Subject: [PATCH 13/50] Fix initialization. --- gma/integration_test/src/integration_test.cc | 37 +------------------- 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/gma/integration_test/src/integration_test.cc b/gma/integration_test/src/integration_test.cc index ed25f2e5a8..0bf555cc1d 100644 --- a/gma/integration_test/src/integration_test.cc +++ b/gma/integration_test/src/integration_test.cc @@ -2441,42 +2441,7 @@ TEST_F(FirebaseGmaTest, TestAdViewMultithreadDeletion) { // TARGET_OS_IPHONE) // Tests for User Messaging Platform -class FirebaseGmaUmpTest : public FirebaseTest { - public: - FirebaseGmaUmpTest(); - ~FirebaseGmaUmpTest() override; - - void SetUpTestSuite(); - void TearDownTestSuite(); - - protected: - static firebase::App* shared_app_; -}; - -FirebaseGmaUmpTest::FirebaseGmaUmpTest() { shared_app_ = nullptr; } - -FirebaseGmaUmpTest::~FirebaseGmaUmpTest() { assert(shared_app_ = nullptr); } - -void FirebaseGmaUmpTest::SetUpTestSuite() { - LogDebug("Initialize Firebase App."); - - FindFirebaseConfig(FIREBASE_CONFIG_STRING); - -#if defined(ANDROID) - shared_app_ = ::firebase::App::Create(app_framework::GetJniEnv(), - app_framework::GetActivity()); -#else - shared_app_ = ::firebase::App::Create(); -#endif // defined(ANDROID) -} - -void FirebaseGmaUmpTest::TearDownTestSuite() { - LogDebug("Shutdown Firebase App."); - delete shared_app_; - shared_app_ = nullptr; -} - -TEST_F(FirebaseGmaUmpTest, TestInitialization) { +TEST_F(FirebaseGmaTest, TestUmpInitialization) { using firebase::gma::ump::ConsentInfo; ConsentInfo* consent_info = ConsentInfo::GetInstance(); From 29f1334e903fbb8499c1eba5ac2164b315256c44 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 16:46:55 -0700 Subject: [PATCH 14/50] Add internal methods. --- gma/src/common/ump/consent_info_internal.h | 8 +++++++ gma/src/include/firebase/gma/ump/types.h | 8 +++---- .../stub/ump/consent_info_internal_stub.cc | 24 +++++++++++++++++++ gma/src/stub/ump/consent_info_internal_stub.h | 7 ++++++ 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/gma/src/common/ump/consent_info_internal.h b/gma/src/common/ump/consent_info_internal.h index 3e2cb59698..f36d85b4f7 100644 --- a/gma/src/common/ump/consent_info_internal.h +++ b/gma/src/common/ump/consent_info_internal.h @@ -20,6 +20,7 @@ #include "app/src/cleanup_notifier.h" #include "app/src/reference_counted_future_impl.h" #include "firebase/future.h" +#include "firebase/gma/ump/types.h" namespace firebase { namespace gma { @@ -42,6 +43,13 @@ class ConsentInfoInternal { // platform-specific subclass. static ConsentInfoInternal* CreateInstance(); + virtual ConsentStatus GetConsentStatus() = 0; + virtual ConsentFormStatus GetConsentFormStatus() = 0; + + virtual Future RequestConsentStatus(const ConsentRequestParameters& params) = 0; + virtual Future LoadConsentForm() = 0; + virtual Future ShowConsentForm(FormParent parent) = 0; + protected: ConsentInfoInternal(); diff --git a/gma/src/include/firebase/gma/ump/types.h b/gma/src/include/firebase/gma/ump/types.h index 2127137314..feaab29099 100644 --- a/gma/src/include/firebase/gma/ump/types.h +++ b/gma/src/include/firebase/gma/ump/types.h @@ -53,9 +53,9 @@ class ConsentRequestParameters { has_tag_for_under_age_of_consent_ = true; } // Get the age of consent tag. - bool tag_for_under_age_of_consent() { return tag_for_under_age_of_consent_; } + bool tag_for_under_age_of_consent() const { return tag_for_under_age_of_consent_; } // Get whether the age of consent tag was previously set. - bool has_tag_for_under_age_of_consent() { + bool has_tag_for_under_age_of_consent() const { return has_tag_for_under_age_of_consent_; } @@ -71,9 +71,9 @@ class ConsentRequestParameters { has_debug_settings_ = true; } // Get the debug settings. - ConsentDebugSettings debug_settings() { return debug_settings_; } + ConsentDebugSettings debug_settings() const { return debug_settings_; } // Get whether debug settings were set. - bool has_debug_settings() { return has_debug_settings_; } + bool has_debug_settings() const { return has_debug_settings_; } private: ConsentDebugSettings debug_settings_; diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index a6cce722c7..accea59383 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -29,6 +29,30 @@ ConsentInfoInternal* ConsentInfoInternal::CreateInstance() { ConsentInfoInternalStub::~ConsentInfoInternalStub() {} +ConsentStatus ConsentInfoInternalStub::GetConsentStatus() { + return kConsentStatusUnknown; +} + +ConsentFormStatus ConsentInfoInternalStub::GetConsentFormStatus() { + return kConsentFormStatusUnknown; +} + +Future ConsentInfoInternalStub::RequestConsentStatus(const ConsentRequestParameters& params) { + ConsentRequestError error = kConsentRequestSuccess; + if (!params.has_tag_for_under_age_of_consent()) { + error = kConsentRequestErrorTagForAgeOfConsentNotSet; + } + return Future(); +} + +Future ConsentInfoInternalStub::LoadConsentForm() { + return Future(); +} + +Future ConsentInfoInternalStub::ShowConsentForm(FormParent parent) { + return Future(); +} + } // namespace internal } // namespace ump } // namespace gma diff --git a/gma/src/stub/ump/consent_info_internal_stub.h b/gma/src/stub/ump/consent_info_internal_stub.h index 2c10b88e2d..8dc2261acb 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.h +++ b/gma/src/stub/ump/consent_info_internal_stub.h @@ -28,6 +28,13 @@ class ConsentInfoInternalStub : public ConsentInfoInternal { public: ConsentInfoInternalStub() {} ~ConsentInfoInternalStub() override; + + ConsentStatus GetConsentStatus() override; + ConsentFormStatus GetConsentFormStatus() override; + + Future RequestConsentStatus(const ConsentRequestParameters& params) override; + Future LoadConsentForm() override; + Future ShowConsentForm(FormParent parent) override; }; } // namespace internal From 93bdab834b6707385b30ad90390275d800c6bfd7 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 16:50:08 -0700 Subject: [PATCH 15/50] Add mappings from interface class to internal class. --- gma/src/common/ump/consent_info_internal.h | 7 +++++-- gma/src/include/firebase/gma/ump/types.h | 4 +++- gma/src/stub/ump/consent_info_internal_stub.cc | 10 +++++++--- gma/src/stub/ump/consent_info_internal_stub.h | 7 +++++-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/gma/src/common/ump/consent_info_internal.h b/gma/src/common/ump/consent_info_internal.h index f36d85b4f7..55df877049 100644 --- a/gma/src/common/ump/consent_info_internal.h +++ b/gma/src/common/ump/consent_info_internal.h @@ -45,11 +45,14 @@ class ConsentInfoInternal { virtual ConsentStatus GetConsentStatus() = 0; virtual ConsentFormStatus GetConsentFormStatus() = 0; - - virtual Future RequestConsentStatus(const ConsentRequestParameters& params) = 0; + + virtual Future RequestConsentStatus( + const ConsentRequestParameters& params) = 0; virtual Future LoadConsentForm() = 0; virtual Future ShowConsentForm(FormParent parent) = 0; + virtual void Reset() = 0; + protected: ConsentInfoInternal(); diff --git a/gma/src/include/firebase/gma/ump/types.h b/gma/src/include/firebase/gma/ump/types.h index feaab29099..a0bc9554f9 100644 --- a/gma/src/include/firebase/gma/ump/types.h +++ b/gma/src/include/firebase/gma/ump/types.h @@ -53,7 +53,9 @@ class ConsentRequestParameters { has_tag_for_under_age_of_consent_ = true; } // Get the age of consent tag. - bool tag_for_under_age_of_consent() const { return tag_for_under_age_of_consent_; } + bool tag_for_under_age_of_consent() const { + return tag_for_under_age_of_consent_; + } // Get whether the age of consent tag was previously set. bool has_tag_for_under_age_of_consent() const { return has_tag_for_under_age_of_consent_; diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index accea59383..d44d1b36e8 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -36,8 +36,9 @@ ConsentStatus ConsentInfoInternalStub::GetConsentStatus() { ConsentFormStatus ConsentInfoInternalStub::GetConsentFormStatus() { return kConsentFormStatusUnknown; } - -Future ConsentInfoInternalStub::RequestConsentStatus(const ConsentRequestParameters& params) { + +Future ConsentInfoInternalStub::RequestConsentStatus( + const ConsentRequestParameters& params) { ConsentRequestError error = kConsentRequestSuccess; if (!params.has_tag_for_under_age_of_consent()) { error = kConsentRequestErrorTagForAgeOfConsentNotSet; @@ -49,10 +50,13 @@ Future ConsentInfoInternalStub::LoadConsentForm() { return Future(); } -Future ConsentInfoInternalStub::ShowConsentForm(FormParent parent) { +Future ConsentInfoInternalStub::ShowConsentForm( + FormParent parent) { return Future(); } +void ConsentInfoInternalStub::Reset() {} + } // namespace internal } // namespace ump } // namespace gma diff --git a/gma/src/stub/ump/consent_info_internal_stub.h b/gma/src/stub/ump/consent_info_internal_stub.h index 8dc2261acb..83cbc000fa 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.h +++ b/gma/src/stub/ump/consent_info_internal_stub.h @@ -31,10 +31,13 @@ class ConsentInfoInternalStub : public ConsentInfoInternal { ConsentStatus GetConsentStatus() override; ConsentFormStatus GetConsentFormStatus() override; - - Future RequestConsentStatus(const ConsentRequestParameters& params) override; + + Future RequestConsentStatus( + const ConsentRequestParameters& params) override; Future LoadConsentForm() override; Future ShowConsentForm(FormParent parent) override; + + void Reset() override; }; } // namespace internal From 493c26f63039b65d1ea608c74e9991ac969829ca Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 17:00:03 -0700 Subject: [PATCH 16/50] Add string conversion for error code. --- gma/CMakeLists.txt | 1 + gma/src/common/ump/ump_common.cc | 55 ++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 gma/src/common/ump/ump_common.cc diff --git a/gma/CMakeLists.txt b/gma/CMakeLists.txt index 440d0db7f0..166f1eaf74 100644 --- a/gma/CMakeLists.txt +++ b/gma/CMakeLists.txt @@ -18,6 +18,7 @@ set(common_SRCS src/common/ump/consent_info.cc src/common/ump/consent_info_internal.cc + src/common/ump/ump_common.cc src/common/gma_common.cc src/common/ad_view.cc src/common/ad_view_internal.cc diff --git a/gma/src/common/ump/ump_common.cc b/gma/src/common/ump/ump_common.cc new file mode 100644 index 0000000000..4b817b1ce9 --- /dev/null +++ b/gma/src/common/ump/ump_common.cc @@ -0,0 +1,55 @@ +/* + * Copyright 2023 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. + */ + +#include "firebase/gma/ump/ump.h" + +namespace firebase { +namespace gma { +namespace ump { + + const char* GetConsentRequestErrorMessage(ConsentRequestError error_code) { + switch(error_code) { + case kConsentRequestSuccess: + return "Success"; + case kConsentRequestErrorInvalidAppId: +#if FIREBASE_PLATFORM_ANDROID + return "Missing or invalid com.google.android.gms.ads.APPLICATION_ID in AndroidManifest.xml."; +#elif FIREBASE_PLATFORM_IOS + return "Missing or invalid GADApplicationidentifier in Info.plist."; +#else + return "Missing or invalid App ID."; +#endif + case kConsentRequestErrorNetwork: + return "Network error."; + case kConsentRequestErrorTagForAgeOfConsentNotSet: + return "You must explicitly call ConsentRequestParameters.set_tag_for_under_age_of_consent()." + case kConsentRequestErrorInternal: + return "Internal error"; + case kConsentRequestErrorCodeMisconfiguration: + return "Code misconfiguration error"; + case kConsentRequestErrorUnknown: + return "Unknown error"; + default: + return "Bad error code" + } + } + + +} // namespace ump +} // namespace gma +} // namespace firebase + + From 4372451cd398ea896d5e35c53e2318d4e49c5a19 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 17:02:35 -0700 Subject: [PATCH 17/50] Add conversion of form errors. --- gma/src/common/ump/ump_common.cc | 51 +++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/gma/src/common/ump/ump_common.cc b/gma/src/common/ump/ump_common.cc index 4b817b1ce9..4abadc6d23 100644 --- a/gma/src/common/ump/ump_common.cc +++ b/gma/src/common/ump/ump_common.cc @@ -14,28 +14,31 @@ * limitations under the License. */ -#include "firebase/gma/ump/ump.h" +#include "firebase/gma/ump.h" namespace firebase { namespace gma { namespace ump { - const char* GetConsentRequestErrorMessage(ConsentRequestError error_code) { - switch(error_code) { +const char* GetConsentRequestErrorMessage(ConsentRequestError error_code) { + switch (error_code) { case kConsentRequestSuccess: return "Success"; - case kConsentRequestErrorInvalidAppId: + case kConsentRequestErrorInvalidAppId: #if FIREBASE_PLATFORM_ANDROID - return "Missing or invalid com.google.android.gms.ads.APPLICATION_ID in AndroidManifest.xml."; + return "Missing or invalid com.google.android.gms.ads.APPLICATION_ID in " + "AndroidManifest.xml"; #elif FIREBASE_PLATFORM_IOS - return "Missing or invalid GADApplicationidentifier in Info.plist."; + return "Missing or invalid GADApplicationidentifier in Info.plist"; #else - return "Missing or invalid App ID."; + return "Missing or invalid App ID"; #endif case kConsentRequestErrorNetwork: - return "Network error."; + return "Network error"; case kConsentRequestErrorTagForAgeOfConsentNotSet: - return "You must explicitly call ConsentRequestParameters.set_tag_for_under_age_of_consent()." + return "You must explicitly call " + "ConsentRequestParameters.set_tag_for_under_age_of_consent() " + "before calling RequestConsentStatus()"; case kConsentRequestErrorInternal: return "Internal error"; case kConsentRequestErrorCodeMisconfiguration: @@ -43,13 +46,33 @@ namespace ump { case kConsentRequestErrorUnknown: return "Unknown error"; default: - return "Bad error code" - } + return "Bad error code"; } +} + +const char* GetConsentFormErrorMessage(ConsentFormError error_code) { + switch (error_code) { + case kConsentFormSuccess: + return "Success"; + case kConsentFormErrorTimeout: + return "Timed out"; + case kConsentFormErrorNotLoaded: + return "Form not loaded"; + case kConsentFormErrorInternal: + return "Internal error"; + case kConsentFormErrorUnknown: + return "Unknown error"; + case kConsentFormErrorCodeAlreadyUsed: + return "Code already used"; + case kConsentFormErrorInvalidOperation: + return "Invalid operation"; + case kConsentFormErrorNetwork: + return "Network error"; + default: + return "Bad error code"; + } +} - } // namespace ump } // namespace gma } // namespace firebase - - From 1ffa00d3d58b2daf65ee6c8715a1ffee674bea07 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 18 Jul 2023 20:04:36 -0700 Subject: [PATCH 18/50] Add stub function implementations. --- gma/src/common/ump/consent_info_internal.h | 26 ++++++++++++++++ gma/src/common/ump/ump_common.cc | 4 +++ gma/src/include/firebase/gma/ump/types.h | 4 ++- .../stub/ump/consent_info_internal_stub.cc | 30 +++++++++++++++---- gma/src/stub/ump/consent_info_internal_stub.h | 5 +++- 5 files changed, 62 insertions(+), 7 deletions(-) diff --git a/gma/src/common/ump/consent_info_internal.h b/gma/src/common/ump/consent_info_internal.h index 55df877049..74e045e73b 100644 --- a/gma/src/common/ump/consent_info_internal.h +++ b/gma/src/common/ump/consent_info_internal.h @@ -56,6 +56,32 @@ class ConsentInfoInternal { protected: ConsentInfoInternal(); + template + SafeFutureHandle CreateFuture() { + return futures()->SafeAlloc(); + } + template + SafeFutureHandle CreateFuture(ConsentInfoFn fn_idx) { + return futures()->SafeAlloc(fn_idx); + } + + // With result and automatically generated error message. + template + void CompleteFuture(SafeFutureHandle handle, ConsentRequestError error, T& result) { + return futures()->CompleteWithResult(handle, error, + GetConsentRequestErrorMessage(error), + result); + } + template + void CompleteFuture(SafeFutureHandle handle, ConsentFormError error, T& result) { + return futures()->CompleteWithResult(handle, error, + GetConsentFormErrorMessage(error), + result); + } + + // No result. + void CompleteFuture(SafeFutureHandle handle, int error); + ReferenceCountedFutureImpl* futures() { return &futures_; } CleanupNotifier* cleanup() { return &cleanup_; } diff --git a/gma/src/common/ump/ump_common.cc b/gma/src/common/ump/ump_common.cc index 4abadc6d23..feae205c5f 100644 --- a/gma/src/common/ump/ump_common.cc +++ b/gma/src/common/ump/ump_common.cc @@ -45,6 +45,8 @@ const char* GetConsentRequestErrorMessage(ConsentRequestError error_code) { return "Code misconfiguration error"; case kConsentRequestErrorUnknown: return "Unknown error"; + case kConsentFormErrorOperationInProgress: + return "Operation already in progress. Please wait for it to finish by checking RequestConsentStatusLastResult()." default: return "Bad error code"; } @@ -68,6 +70,8 @@ const char* GetConsentFormErrorMessage(ConsentFormError error_code) { return "Invalid operation"; case kConsentFormErrorNetwork: return "Network error"; + case kConsentFormErrorOperationInProgress: + return "Operation already in progress. Please wait for it to finish by checking LoadFormLastResult() or ShowFormLastResult()." default: return "Bad error code"; } diff --git a/gma/src/include/firebase/gma/ump/types.h b/gma/src/include/firebase/gma/ump/types.h index a0bc9554f9..3974bc5176 100644 --- a/gma/src/include/firebase/gma/ump/types.h +++ b/gma/src/include/firebase/gma/ump/types.h @@ -123,6 +123,7 @@ enum ConsentRequestError { kConsentRequestErrorInternal, kConsentRequestErrorCodeMisconfiguration, kConsentRequestErrorUnknown, + kConsentRequestErrorOperationInProgress }; enum ConsentFormStatus { @@ -139,7 +140,8 @@ enum ConsentFormError { kConsentFormErrorUnknown, kConsentFormErrorCodeAlreadyUsed, kConsentFormErrorInvalidOperation, - kConsentFormErrorNetwork + kConsentFormErrorNetwork, + kConsentFormErrorOperationInProgress }; } // namespace ump diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index d44d1b36e8..e3c533c924 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -16,6 +16,8 @@ #include "gma/src/stub/ump/consent_info_internal_stub.h" +#include "app/src/thread.h" + namespace firebase { namespace gma { namespace ump { @@ -27,6 +29,11 @@ ConsentInfoInternal* ConsentInfoInternal::CreateInstance() { return new ConsentInfoInternalStub(); } +ConsentInfoInternalStub::ConsentInfoInternalStub() : + consent_status_(kConsentStatusUnknown), + consent_form_status_(kConsentFormStatusUnknown) {} + + ConsentInfoInternalStub::~ConsentInfoInternalStub() {} ConsentStatus ConsentInfoInternalStub::GetConsentStatus() { @@ -39,20 +46,33 @@ ConsentFormStatus ConsentInfoInternalStub::GetConsentFormStatus() { Future ConsentInfoInternalStub::RequestConsentStatus( const ConsentRequestParameters& params) { - ConsentRequestError error = kConsentRequestSuccess; + SafeFutureHandle = CreateFuture(kConsentInfoFnRequestConsentStatus); + if (!params.has_tag_for_under_age_of_consent()) { - error = kConsentRequestErrorTagForAgeOfConsentNotSet; + CompleteFuture(handle, kConsentRequestErrorTagForAgeOfConsentNotSet); + return MakeFuture(futures(), handle); } - return Future(); + + consent_status_ = kConsentStatusRequired; + CompleteFuture(handle, kConsentRequestSuccess, consent_status_); + return MakeFuture(futures(), handle); } Future ConsentInfoInternalStub::LoadConsentForm() { - return Future(); + SafeFutureHandle = CreateFuture(kConsentInfoFnLoadConsentForm); + + consent_form_status_ = kConsentFormStatusAvailable; + CompleteFuture(handle, kConsentFormSuccess, consent_form_status_); + return MakeFuture(futures(), handle); } Future ConsentInfoInternalStub::ShowConsentForm( FormParent parent) { - return Future(); + SafeFutureHandle = CreateFuture(kConsentInfoFnShowConsentForm); + + consent_status_ = kConsentStatusObtained; + CompleteFuture(handle, kConsentRequestSuccess, consent_status_); + return MakeFuture(futures(), handle); } void ConsentInfoInternalStub::Reset() {} diff --git a/gma/src/stub/ump/consent_info_internal_stub.h b/gma/src/stub/ump/consent_info_internal_stub.h index 83cbc000fa..52fbdcb006 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.h +++ b/gma/src/stub/ump/consent_info_internal_stub.h @@ -26,7 +26,7 @@ namespace internal { class ConsentInfoInternalStub : public ConsentInfoInternal { public: - ConsentInfoInternalStub() {} + ConsentInfoInternalStub(); ~ConsentInfoInternalStub() override; ConsentStatus GetConsentStatus() override; @@ -38,6 +38,9 @@ class ConsentInfoInternalStub : public ConsentInfoInternal { Future ShowConsentForm(FormParent parent) override; void Reset() override; +private: + ConsentStatus consent_status_; + ConsentFormStatus consent_form_status_; }; } // namespace internal From 5f03ca85eb5752e0e6b8c09351983c3275d6cf18 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 19 Jul 2023 11:03:32 -0700 Subject: [PATCH 19/50] Add stub operations and unit tests. --- gma/integration_test/src/integration_test.cc | 233 +++++++++++++++++- gma/src/common/ump/consent_info_internal.h | 58 +++-- gma/src/common/ump/ump_common.cc | 10 +- gma/src/include/firebase/gma/ump/types.h | 2 +- .../stub/ump/consent_info_internal_stub.cc | 51 ++-- gma/src/stub/ump/consent_info_internal_stub.h | 9 +- 6 files changed, 318 insertions(+), 45 deletions(-) diff --git a/gma/integration_test/src/integration_test.cc b/gma/integration_test/src/integration_test.cc index 0bf555cc1d..120d5e9898 100644 --- a/gma/integration_test/src/integration_test.cc +++ b/gma/integration_test/src/integration_test.cc @@ -2444,11 +2444,242 @@ TEST_F(FirebaseGmaTest, TestAdViewMultithreadDeletion) { TEST_F(FirebaseGmaTest, TestUmpInitialization) { using firebase::gma::ump::ConsentInfo; ConsentInfo* consent_info = ConsentInfo::GetInstance(); + consent_info->Reset(); - EXPECT_NE(consent_info, nullptr); + ASSERT_NE(consent_info, nullptr); delete consent_info; consent_info = nullptr; } +TEST_F(FirebaseGmaTest, TestUmpRequestConsentStatus) { + using firebase::gma::ump::ConsentInfo; + using firebase::gma::ump::ConsentRequestParameters; + using firebase::gma::ump::ConsentStatus; + ConsentInfo* consent_info = ConsentInfo::GetInstance(); + + ASSERT_NE(consent_info, nullptr); + consent_info->Reset(); + + ConsentRequestParameters params; + params.set_tag_for_under_age_of_consent(false); + + firebase::Future future = + consent_info->RequestConsentStatus(params); + + WaitForCompletion(future, "RequestConsentStatus"); + + EXPECT_NE(future.result(), nullptr); + EXPECT_EQ(*future.result(), consent_info->GetConsentStatus()); + EXPECT_NE(consent_info->GetConsentStatus(), + firebase::gma::ump::kConsentStatusUnknown); + + delete consent_info; + consent_info = nullptr; +} + +TEST_F(FirebaseGmaTest, TestUmpRequestConsentStatusDebugEEA) { + using firebase::gma::ump::ConsentDebugSettings; + using firebase::gma::ump::ConsentInfo; + using firebase::gma::ump::ConsentRequestParameters; + using firebase::gma::ump::ConsentStatus; + ConsentInfo* consent_info = ConsentInfo::GetInstance(); + + ASSERT_NE(consent_info, nullptr); + consent_info->Reset(); + + ConsentRequestParameters params; + params.set_tag_for_under_age_of_consent(false); + ConsentDebugSettings debug_settings; + debug_settings.debug_geography = + firebase::gma::ump::kConsentDebugGeographyEEA; + params.set_debug_settings(debug_settings); + + firebase::Future future = + consent_info->RequestConsentStatus(params); + + WaitForCompletion(future, "RequestConsentStatus"); + + EXPECT_NE(future.result(), nullptr); + EXPECT_EQ(*future.result(), consent_info->GetConsentStatus()); + EXPECT_EQ(consent_info->GetConsentStatus(), + firebase::gma::ump::kConsentStatusRequired); + + delete consent_info; + consent_info = nullptr; +} + +TEST_F(FirebaseGmaTest, TestUmpRequestConsentStatusDebugNonEEA) { + using firebase::gma::ump::ConsentDebugSettings; + using firebase::gma::ump::ConsentInfo; + using firebase::gma::ump::ConsentRequestParameters; + using firebase::gma::ump::ConsentStatus; + ConsentInfo* consent_info = ConsentInfo::GetInstance(); + + ASSERT_NE(consent_info, nullptr); + consent_info->Reset(); + + ConsentRequestParameters params; + params.set_tag_for_under_age_of_consent(false); + ConsentDebugSettings debug_settings; + debug_settings.debug_geography = + firebase::gma::ump::kConsentDebugGeographyNonEEA; + params.set_debug_settings(debug_settings); + + firebase::Future future = + consent_info->RequestConsentStatus(params); + + WaitForCompletion(future, "RequestConsentStatus"); + + EXPECT_NE(future.result(), nullptr); + EXPECT_EQ(*future.result(), consent_info->GetConsentStatus()); + EXPECT_EQ(consent_info->GetConsentStatus(), + firebase::gma::ump::kConsentStatusNotRequired); + + delete consent_info; + consent_info = nullptr; +} + +TEST_F(FirebaseGmaTest, TestUmpLoadForm) { + using firebase::gma::ump::ConsentDebugSettings; + using firebase::gma::ump::ConsentFormStatus; + using firebase::gma::ump::ConsentInfo; + using firebase::gma::ump::ConsentRequestParameters; + using firebase::gma::ump::ConsentStatus; + ConsentInfo* consent_info = ConsentInfo::GetInstance(); + + ASSERT_NE(consent_info, nullptr); + consent_info->Reset(); + + ConsentRequestParameters params; + params.set_tag_for_under_age_of_consent(false); + ConsentDebugSettings debug_settings; + debug_settings.debug_geography = + firebase::gma::ump::kConsentDebugGeographyEEA; + params.set_debug_settings(debug_settings); + + { + firebase::Future future = + consent_info->RequestConsentStatus(params); + + WaitForCompletion(future, "RequestConsentStatus"); + + EXPECT_NE(future.result(), nullptr); + EXPECT_EQ(*future.result(), consent_info->GetConsentStatus()); + } + + EXPECT_EQ(consent_info->GetConsentStatus(), + firebase::gma::ump::kConsentStatusRequired); + + if (consent_info->GetConsentFormStatus() == + firebase::gma::ump::kConsentFormStatusUnavailable) { + // Load the form. + firebase::Future future = + consent_info->LoadConsentForm(); + + WaitForCompletion(future, "LoadConsentForm"); + + EXPECT_NE(future.result(), nullptr); + EXPECT_EQ(*future.result(), consent_info->GetConsentFormStatus()); + } + + EXPECT_EQ(consent_info->GetConsentFormStatus(), + firebase::gma::ump::kConsentFormStatusAvailable); + + delete consent_info; + consent_info = nullptr; +} + +TEST_F(FirebaseGmaTest, TestUmpShowForm) { + TEST_REQUIRES_USER_INTERACTION; + + using firebase::gma::ump::ConsentDebugSettings; + using firebase::gma::ump::ConsentFormStatus; + using firebase::gma::ump::ConsentInfo; + using firebase::gma::ump::ConsentRequestParameters; + using firebase::gma::ump::ConsentStatus; + ConsentInfo* consent_info = ConsentInfo::GetInstance(); + + ASSERT_NE(consent_info, nullptr); + consent_info->Reset(); + + ConsentRequestParameters params; + params.set_tag_for_under_age_of_consent(false); + ConsentDebugSettings debug_settings; + debug_settings.debug_geography = + firebase::gma::ump::kConsentDebugGeographyEEA; + params.set_debug_settings(debug_settings); + + { + firebase::Future future = + consent_info->RequestConsentStatus(params); + + WaitForCompletion(future, "RequestConsentStatus"); + + EXPECT_NE(future.result(), nullptr); + EXPECT_EQ(*future.result(), consent_info->GetConsentStatus()); + } + + EXPECT_EQ(consent_info->GetConsentStatus(), + firebase::gma::ump::kConsentStatusRequired); + + if (consent_info->GetConsentFormStatus() == + firebase::gma::ump::kConsentFormStatusUnavailable) { + // Load the form. + firebase::Future future = + consent_info->LoadConsentForm(); + + WaitForCompletion(future, "LoadConsentForm"); + + EXPECT_NE(future.result(), nullptr); + EXPECT_EQ(*future.result(), consent_info->GetConsentFormStatus()); + } + + EXPECT_EQ(consent_info->GetConsentFormStatus(), + firebase::gma::ump::kConsentFormStatusAvailable); + + { + firebase::Future future = + consent_info->ShowConsentForm(nullptr); + + WaitForCompletion(future, "ShowConsentForm"); + + EXPECT_NE(future.result(), nullptr); + EXPECT_EQ(*future.result(), consent_info->GetConsentStatus()); + } + + EXPECT_EQ(consent_info->GetConsentStatus(), + firebase::gma::ump::kConsentStatusObtained); + + delete consent_info; + consent_info = nullptr; +} + +TEST_F(FirebaseGmaTest, TestUmpCleanup) { + using firebase::gma::ump::ConsentFormStatus; + using firebase::gma::ump::ConsentInfo; + using firebase::gma::ump::ConsentRequestParameters; + using firebase::gma::ump::ConsentStatus; + ConsentInfo* consent_info = ConsentInfo::GetInstance(); + consent_info->Reset(); + + ASSERT_NE(consent_info, nullptr); + + ConsentRequestParameters params; + params.set_tag_for_under_age_of_consent(false); + firebase::Future future_request = + consent_info->RequestConsentStatus(params); + firebase::Future future_load = + consent_info->LoadConsentForm(); + firebase::Future future_show = + consent_info->ShowConsentForm(nullptr); + + delete consent_info; + consent_info = nullptr; + + EXPECT_EQ(future_request.status(), firebase::kFutureStatusInvalid); + EXPECT_EQ(future_load.status(), firebase::kFutureStatusInvalid); + EXPECT_EQ(future_show.status(), firebase::kFutureStatusInvalid); +} + } // namespace firebase_testapp_automated diff --git a/gma/src/common/ump/consent_info_internal.h b/gma/src/common/ump/consent_info_internal.h index 74e045e73b..27ba205c16 100644 --- a/gma/src/common/ump/consent_info_internal.h +++ b/gma/src/common/ump/consent_info_internal.h @@ -20,6 +20,7 @@ #include "app/src/cleanup_notifier.h" #include "app/src/reference_counted_future_impl.h" #include "firebase/future.h" +#include "firebase/gma/ump.h" #include "firebase/gma/ump/types.h" namespace firebase { @@ -43,44 +44,69 @@ class ConsentInfoInternal { // platform-specific subclass. static ConsentInfoInternal* CreateInstance(); - virtual ConsentStatus GetConsentStatus() = 0; - virtual ConsentFormStatus GetConsentFormStatus() = 0; + virtual ConsentStatus GetConsentStatus() const = 0; + virtual ConsentFormStatus GetConsentFormStatus() const = 0; virtual Future RequestConsentStatus( const ConsentRequestParameters& params) = 0; + Future RequestConsentStatusLastResult() { + return static_cast&>( + futures()->LastResult(kConsentInfoFnRequestConsentStatus)); + } virtual Future LoadConsentForm() = 0; + + Future LoadConsentFormLastResult() { + return static_cast&>( + futures()->LastResult(kConsentInfoFnLoadConsentForm)); + } + virtual Future ShowConsentForm(FormParent parent) = 0; + Future ShowConsentFormLastResult() { + return static_cast&>( + futures()->LastResult(kConsentInfoFnShowConsentForm)); + } + virtual void Reset() = 0; protected: ConsentInfoInternal(); - template + template SafeFutureHandle CreateFuture() { return futures()->SafeAlloc(); } - template + template SafeFutureHandle CreateFuture(ConsentInfoFn fn_idx) { return futures()->SafeAlloc(fn_idx); } // With result and automatically generated error message. - template - void CompleteFuture(SafeFutureHandle handle, ConsentRequestError error, T& result) { - return futures()->CompleteWithResult(handle, error, - GetConsentRequestErrorMessage(error), - result); + template + void CompleteFuture(SafeFutureHandle handle, ConsentRequestError error, + T& result) { + return futures()->CompleteWithResult( + handle, error, GetConsentRequestErrorMessage(error), result); } - template - void CompleteFuture(SafeFutureHandle handle, ConsentFormError error, T& result) { - return futures()->CompleteWithResult(handle, error, - GetConsentFormErrorMessage(error), - result); + template + void CompleteFuture(SafeFutureHandle handle, ConsentFormError error, + T& result) { + return futures()->CompleteWithResult( + handle, error, GetConsentFormErrorMessage(error), result); } - // No result. - void CompleteFuture(SafeFutureHandle handle, int error); + // No result data, just an error code. + template + void CompleteFuture(SafeFutureHandle handle, ConsentRequestError error) { + return futures()->Complete(handle, error, + GetConsentRequestErrorMessage(error)); + } + // No result data, just an error code. + template + void CompleteFuture(SafeFutureHandle handle, ConsentFormError error) { + return futures()->Complete(handle, error, + GetConsentFormErrorMessage(error)); + } ReferenceCountedFutureImpl* futures() { return &futures_; } CleanupNotifier* cleanup() { return &cleanup_; } diff --git a/gma/src/common/ump/ump_common.cc b/gma/src/common/ump/ump_common.cc index feae205c5f..82b96bdead 100644 --- a/gma/src/common/ump/ump_common.cc +++ b/gma/src/common/ump/ump_common.cc @@ -45,8 +45,9 @@ const char* GetConsentRequestErrorMessage(ConsentRequestError error_code) { return "Code misconfiguration error"; case kConsentRequestErrorUnknown: return "Unknown error"; - case kConsentFormErrorOperationInProgress: - return "Operation already in progress. Please wait for it to finish by checking RequestConsentStatusLastResult()." + case kConsentRequestErrorOperationInProgress: + return "Operation already in progress. Please wait for it to finish by " + "checking RequestConsentStatusLastResult()."; default: return "Bad error code"; } @@ -70,8 +71,9 @@ const char* GetConsentFormErrorMessage(ConsentFormError error_code) { return "Invalid operation"; case kConsentFormErrorNetwork: return "Network error"; - case kConsentFormErrorOperationInProgress: - return "Operation already in progress. Please wait for it to finish by checking LoadFormLastResult() or ShowFormLastResult()." + case kConsentFormErrorOperationInProgress: + return "Operation already in progress. Please wait for it to finish by " + "checking LoadFormLastResult() or ShowFormLastResult()."; default: return "Bad error code"; } diff --git a/gma/src/include/firebase/gma/ump/types.h b/gma/src/include/firebase/gma/ump/types.h index 3974bc5176..644b1f678c 100644 --- a/gma/src/include/firebase/gma/ump/types.h +++ b/gma/src/include/firebase/gma/ump/types.h @@ -73,7 +73,7 @@ class ConsentRequestParameters { has_debug_settings_ = true; } // Get the debug settings. - ConsentDebugSettings debug_settings() const { return debug_settings_; } + const ConsentDebugSettings& debug_settings() const { return debug_settings_; } // Get whether debug settings were set. bool has_debug_settings() const { return has_debug_settings_; } diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index e3c533c924..a25c2c6517 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -29,53 +29,64 @@ ConsentInfoInternal* ConsentInfoInternal::CreateInstance() { return new ConsentInfoInternalStub(); } -ConsentInfoInternalStub::ConsentInfoInternalStub() : - consent_status_(kConsentStatusUnknown), - consent_form_status_(kConsentFormStatusUnknown) {} - +ConsentInfoInternalStub::ConsentInfoInternalStub() + : consent_status_(kConsentStatusUnknown), + consent_form_status_(kConsentFormStatusUnknown) {} ConsentInfoInternalStub::~ConsentInfoInternalStub() {} -ConsentStatus ConsentInfoInternalStub::GetConsentStatus() { - return kConsentStatusUnknown; -} - -ConsentFormStatus ConsentInfoInternalStub::GetConsentFormStatus() { - return kConsentFormStatusUnknown; -} - Future ConsentInfoInternalStub::RequestConsentStatus( const ConsentRequestParameters& params) { - SafeFutureHandle = CreateFuture(kConsentInfoFnRequestConsentStatus); + SafeFutureHandle handle = + CreateFuture(kConsentInfoFnRequestConsentStatus); if (!params.has_tag_for_under_age_of_consent()) { CompleteFuture(handle, kConsentRequestErrorTagForAgeOfConsentNotSet); return MakeFuture(futures(), handle); } - consent_status_ = kConsentStatusRequired; - CompleteFuture(handle, kConsentRequestSuccess, consent_status_); + ConsentStatus new_consent_status = kConsentStatusObtained; + if (params.has_debug_settings()) { + if (params.debug_settings().debug_geography == kConsentDebugGeographyEEA) { + new_consent_status = kConsentStatusRequired; + } else if (params.debug_settings().debug_geography == + kConsentDebugGeographyNonEEA) { + new_consent_status = kConsentStatusNotRequired; + } + } + consent_status_ = new_consent_status; + consent_form_status_ = kConsentFormStatusUnavailable; + + CompleteFuture(handle, kConsentRequestSuccess, + consent_status_); return MakeFuture(futures(), handle); } Future ConsentInfoInternalStub::LoadConsentForm() { - SafeFutureHandle = CreateFuture(kConsentInfoFnLoadConsentForm); + SafeFutureHandle handle = + CreateFuture(kConsentInfoFnLoadConsentForm); consent_form_status_ = kConsentFormStatusAvailable; - CompleteFuture(handle, kConsentFormSuccess, consent_form_status_); + CompleteFuture(handle, kConsentFormSuccess, + consent_form_status_); return MakeFuture(futures(), handle); } Future ConsentInfoInternalStub::ShowConsentForm( FormParent parent) { - SafeFutureHandle = CreateFuture(kConsentInfoFnShowConsentForm); + SafeFutureHandle handle = + CreateFuture(kConsentInfoFnShowConsentForm); consent_status_ = kConsentStatusObtained; - CompleteFuture(handle, kConsentRequestSuccess, consent_status_); + CompleteFuture(handle, kConsentRequestSuccess, + consent_status_); return MakeFuture(futures(), handle); } -void ConsentInfoInternalStub::Reset() {} +void ConsentInfoInternalStub::Reset() { + consent_status_ = kConsentStatusUnknown; + consent_form_status_ = kConsentFormStatusUnknown; +} } // namespace internal } // namespace ump diff --git a/gma/src/stub/ump/consent_info_internal_stub.h b/gma/src/stub/ump/consent_info_internal_stub.h index 52fbdcb006..4c6916336a 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.h +++ b/gma/src/stub/ump/consent_info_internal_stub.h @@ -29,8 +29,10 @@ class ConsentInfoInternalStub : public ConsentInfoInternal { ConsentInfoInternalStub(); ~ConsentInfoInternalStub() override; - ConsentStatus GetConsentStatus() override; - ConsentFormStatus GetConsentFormStatus() override; + ConsentStatus GetConsentStatus() const override { return consent_status_; } + ConsentFormStatus GetConsentFormStatus() const override { + return consent_form_status_; + } Future RequestConsentStatus( const ConsentRequestParameters& params) override; @@ -38,7 +40,8 @@ class ConsentInfoInternalStub : public ConsentInfoInternal { Future ShowConsentForm(FormParent parent) override; void Reset() override; -private: + + private: ConsentStatus consent_status_; ConsentFormStatus consent_form_status_; }; From 1b20566f6cf1bf07c79df339cf890a0c8e06e7eb Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 19 Jul 2023 11:26:00 -0700 Subject: [PATCH 20/50] Add missing file. --- gma/src/common/ump/consent_info.cc | 125 +++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 gma/src/common/ump/consent_info.cc diff --git a/gma/src/common/ump/consent_info.cc b/gma/src/common/ump/consent_info.cc new file mode 100644 index 0000000000..96a1f4b216 --- /dev/null +++ b/gma/src/common/ump/consent_info.cc @@ -0,0 +1,125 @@ +/* + * Copyright 2023 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. + */ + +#include "firebase/gma/ump/consent_info.h" + +#include "app/src/assert.h" +#include "firebase/app.h" +#include "firebase/internal/platform.h" +#include "firebase/gma/ump.h" +#include "gma/src/common/ump/consent_info_internal.h" + +namespace firebase { +namespace gma { +namespace ump { + +ConsentInfo* ConsentInfo::s_instance_ = nullptr; + +ConsentInfo* ConsentInfo::GetInstance(const ::firebase::App& app, + ::firebase::InitResult *init_result_out) { + if (s_instance_) { + if (init_result_out) *init_result_out = kInitResultSuccess; + return s_instance_; + } +#if FIREBASE_PLATFORM_ANDROID + return GetInstance(app.GetJNIEnv(), app.activity(), init_result_out); +#else // !FIREBASE_PLATFORM_ANDROID + return GetInstance(init_result_out); +#endif // FIREBASE_PLATFORM_ANDROID +}; + +#if FIREBASE_PLATFORM_ANDROID +ConsentInfo* ConsentInfo::GetInstance(JNIEnv* jni_env, jobject activity, + ::firebase::InitResult *init_result_out) { +#else // !FIREBASE_PLATFORM_ANDROID +ConsentInfo* ConsentInfo::GetInstance(::firebase::InitResult *init_result_out) { +#endif + if (s_instance_) { + if (init_result_out) *init_result_out = kInitResultSuccess; + return s_instance_; + } + + ConsentInfo* consent_info = new ConsentInfo(); +#if FIREBASE_PLATFORM_ANDROID + InitResult result = consent_info->Initialize(/* jni_env, activity */); // TODO +#else + InitResult result = consent_info->Initialize(); +#endif + if (result != kInitResultSuccess) { + if (init_result_out) *init_result_out = result; + delete consent_info; + return nullptr; + } + return consent_info; +}; + +ConsentInfo::ConsentInfo() { + internal_ = nullptr; +#if FIREBASE_PLATFORM_ANDROID + java_vm_ = nullptr; +#endif + s_instance_ = this; +} + +ConsentInfo::~ConsentInfo() { + if (internal_) { + delete internal_; + internal_ = nullptr; + } + s_instance_ = nullptr; +} + +InitResult ConsentInfo::Initialize() { + FIREBASE_ASSERT(internal_ == nullptr); + internal_ = internal::ConsentInfoInternal::CreateInstance(); + return kInitResultSuccess; +} + +ConsentStatus ConsentInfo::GetConsentStatus() { + FIREBASE_ASSERT(internal_); + return internal_->GetConsentStatus(); +} + +ConsentFormStatus ConsentInfo::GetConsentFormStatus() { + FIREBASE_ASSERT(internal_); + return internal_->GetConsentFormStatus(); +} + +Future ConsentInfo::RequestConsentStatus(const ConsentRequestParameters& params) { + FIREBASE_ASSERT(internal_); + return internal_->RequestConsentStatus(params); +} + +Future ConsentInfo::LoadConsentForm() { + FIREBASE_ASSERT(internal_); + return internal_->LoadConsentForm(); +} + +Future ConsentInfo::ShowConsentForm(FormParent parent) { + return internal_->ShowConsentForm(parent); +} + +void ConsentInfo::Reset() { + return internal_->Reset(); +} + + + +} // namespace ump +} // namespace gma +} // namespace firebase + + From 1cec99383901d04e6537db0eff80c53ecc92e0bb Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 19 Jul 2023 11:27:33 -0700 Subject: [PATCH 21/50] Format code. --- gma/src/common/ump/consent_info.cc | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/gma/src/common/ump/consent_info.cc b/gma/src/common/ump/consent_info.cc index 96a1f4b216..9f8b53d15e 100644 --- a/gma/src/common/ump/consent_info.cc +++ b/gma/src/common/ump/consent_info.cc @@ -18,8 +18,8 @@ #include "app/src/assert.h" #include "firebase/app.h" -#include "firebase/internal/platform.h" #include "firebase/gma/ump.h" +#include "firebase/internal/platform.h" #include "gma/src/common/ump/consent_info_internal.h" namespace firebase { @@ -29,23 +29,23 @@ namespace ump { ConsentInfo* ConsentInfo::s_instance_ = nullptr; ConsentInfo* ConsentInfo::GetInstance(const ::firebase::App& app, - ::firebase::InitResult *init_result_out) { + ::firebase::InitResult* init_result_out) { if (s_instance_) { if (init_result_out) *init_result_out = kInitResultSuccess; return s_instance_; } #if FIREBASE_PLATFORM_ANDROID return GetInstance(app.GetJNIEnv(), app.activity(), init_result_out); -#else // !FIREBASE_PLATFORM_ANDROID +#else // !FIREBASE_PLATFORM_ANDROID return GetInstance(init_result_out); #endif // FIREBASE_PLATFORM_ANDROID }; - + #if FIREBASE_PLATFORM_ANDROID ConsentInfo* ConsentInfo::GetInstance(JNIEnv* jni_env, jobject activity, - ::firebase::InitResult *init_result_out) { + ::firebase::InitResult* init_result_out) { #else // !FIREBASE_PLATFORM_ANDROID -ConsentInfo* ConsentInfo::GetInstance(::firebase::InitResult *init_result_out) { +ConsentInfo* ConsentInfo::GetInstance(::firebase::InitResult* init_result_out) { #endif if (s_instance_) { if (init_result_out) *init_result_out = kInitResultSuccess; @@ -54,7 +54,8 @@ ConsentInfo* ConsentInfo::GetInstance(::firebase::InitResult *init_result_out) { ConsentInfo* consent_info = new ConsentInfo(); #if FIREBASE_PLATFORM_ANDROID - InitResult result = consent_info->Initialize(/* jni_env, activity */); // TODO + InitResult result = + consent_info->Initialize(/* jni_env, activity */); // TODO #else InitResult result = consent_info->Initialize(); #endif @@ -65,7 +66,7 @@ ConsentInfo* ConsentInfo::GetInstance(::firebase::InitResult *init_result_out) { } return consent_info; }; - + ConsentInfo::ConsentInfo() { internal_ = nullptr; #if FIREBASE_PLATFORM_ANDROID @@ -97,8 +98,9 @@ ConsentFormStatus ConsentInfo::GetConsentFormStatus() { FIREBASE_ASSERT(internal_); return internal_->GetConsentFormStatus(); } - -Future ConsentInfo::RequestConsentStatus(const ConsentRequestParameters& params) { + +Future ConsentInfo::RequestConsentStatus( + const ConsentRequestParameters& params) { FIREBASE_ASSERT(internal_); return internal_->RequestConsentStatus(params); } @@ -112,14 +114,8 @@ Future ConsentInfo::ShowConsentForm(FormParent parent) { return internal_->ShowConsentForm(parent); } -void ConsentInfo::Reset() { - return internal_->Reset(); -} - +void ConsentInfo::Reset() { return internal_->Reset(); } - } // namespace ump } // namespace gma } // namespace firebase - - From 3d9a822f93523645ee437fb265885eee1c521037 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 19 Jul 2023 11:30:09 -0700 Subject: [PATCH 22/50] Add check for form. --- gma/integration_test/src/integration_test.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gma/integration_test/src/integration_test.cc b/gma/integration_test/src/integration_test.cc index 120d5e9898..ee8c7216b9 100644 --- a/gma/integration_test/src/integration_test.cc +++ b/gma/integration_test/src/integration_test.cc @@ -2473,6 +2473,8 @@ TEST_F(FirebaseGmaTest, TestUmpRequestConsentStatus) { EXPECT_EQ(*future.result(), consent_info->GetConsentStatus()); EXPECT_NE(consent_info->GetConsentStatus(), firebase::gma::ump::kConsentStatusUnknown); + EXPECT_NE(consent_info->GetConsentFormStatus(), + firebase::gma::ump::kConsentFormStatusUnknown); delete consent_info; consent_info = nullptr; From ff0b328ee609a0b6f27c7e47a3ba354ad4a3a3ec Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 19 Jul 2023 11:36:11 -0700 Subject: [PATCH 23/50] Add test for expected error not specifying tag for age of consent. --- gma/integration_test/src/integration_test.cc | 26 +++++++++++++++++++ .../stub/ump/consent_info_internal_stub.cc | 3 ++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/gma/integration_test/src/integration_test.cc b/gma/integration_test/src/integration_test.cc index ee8c7216b9..3c121e6c95 100644 --- a/gma/integration_test/src/integration_test.cc +++ b/gma/integration_test/src/integration_test.cc @@ -2480,6 +2480,32 @@ TEST_F(FirebaseGmaTest, TestUmpRequestConsentStatus) { consent_info = nullptr; } +TEST_F(FirebaseGmaTest, TestUmpRequestErrorWithoutTagForUnderAgeOfConsent) { + using firebase::gma::ump::ConsentInfo; + using firebase::gma::ump::ConsentRequestParameters; + using firebase::gma::ump::ConsentStatus; + ConsentInfo* consent_info = ConsentInfo::GetInstance(); + + ASSERT_NE(consent_info, nullptr); + consent_info->Reset(); + + ConsentRequestParameters params; + // Do not call set_tag_for_under_age_of_consent(). + + firebase::Future future = + consent_info->RequestConsentStatus(params); + + WaitForCompletion(future, "RequestConsentStatus", + firebase::gma::ump::kConsentRequestErrorTagForAgeOfConsentNotSet); + + EXPECT_EQ(*future.result(), consent_info->GetConsentStatus()); + EXPECT_EQ(consent_info->GetConsentStatus(), + firebase::gma::ump::kConsentStatusUnknown); + + delete consent_info; + consent_info = nullptr; +} + TEST_F(FirebaseGmaTest, TestUmpRequestConsentStatusDebugEEA) { using firebase::gma::ump::ConsentDebugSettings; using firebase::gma::ump::ConsentInfo; diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index a25c2c6517..9665bb9ed4 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -41,7 +41,8 @@ Future ConsentInfoInternalStub::RequestConsentStatus( CreateFuture(kConsentInfoFnRequestConsentStatus); if (!params.has_tag_for_under_age_of_consent()) { - CompleteFuture(handle, kConsentRequestErrorTagForAgeOfConsentNotSet); + CompleteFuture(handle, kConsentRequestErrorTagForAgeOfConsentNotSet, + consent_status_); return MakeFuture(futures(), handle); } From 56e18e202c28bca688604a2190229076218078e8 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 19 Jul 2023 11:47:45 -0700 Subject: [PATCH 24/50] Clean up tests by moving initialization into shared method. --- gma/integration_test/src/integration_test.cc | 193 ++++++++---------- .../stub/ump/consent_info_internal_stub.cc | 4 +- 2 files changed, 91 insertions(+), 106 deletions(-) diff --git a/gma/integration_test/src/integration_test.cc b/gma/integration_test/src/integration_test.cc index 3c121e6c95..cdb63c257d 100644 --- a/gma/integration_test/src/integration_test.cc +++ b/gma/integration_test/src/integration_test.cc @@ -2440,81 +2440,98 @@ TEST_F(FirebaseGmaTest, TestAdViewMultithreadDeletion) { #endif // #if defined(ANDROID) || (defined(TARGET_OS_IPHONE) && // TARGET_OS_IPHONE) -// Tests for User Messaging Platform -TEST_F(FirebaseGmaTest, TestUmpInitialization) { +class FirebaseGmaUmpTest : public FirebaseGmaTest { + public: + FirebaseGmaUmpTest() : consent_info_(nullptr) {} + + enum ResetOption { kReset, kNoReset }; + + void InitializeUmp(ResetOption reset = kReset); + void TerminateUmp(); + + void SetUp() override; + void TearDown() override; + + protected: + firebase::gma::ump::ConsentInfo* consent_info_; +}; + +void FirebaseGmaUmpTest::InitializeUmp(ResetOption reset) { using firebase::gma::ump::ConsentInfo; - ConsentInfo* consent_info = ConsentInfo::GetInstance(); - consent_info->Reset(); + consent_info_ = ConsentInfo::GetInstance(*shared_app_); + if (consent_info_ != nullptr && reset == kReset) { + consent_info_->Reset(); + } +} - ASSERT_NE(consent_info, nullptr); +void FirebaseGmaUmpTest::TerminateUmp() { + if (consent_info_) { + delete consent_info_; + consent_info_ = nullptr; + } +} - delete consent_info; - consent_info = nullptr; +void FirebaseGmaUmpTest::SetUp() { + FirebaseGmaTest::SetUp(); + InitializeUmp(); + ASSERT_NE(consent_info_, nullptr); } -TEST_F(FirebaseGmaTest, TestUmpRequestConsentStatus) { - using firebase::gma::ump::ConsentInfo; +void FirebaseGmaUmpTest::TearDown() { + TerminateUmp(); + FirebaseGmaTest::TearDown(); +} + +// Tests for User Messaging Platform +TEST_F(FirebaseGmaUmpTest, TestUmpInitialization) { + // Initialize handled automatically in test setup. + EXPECT_NE(consent_info_, nullptr); + // Terminate handled automatically in test teardown. +} + +TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentStatus) { using firebase::gma::ump::ConsentRequestParameters; using firebase::gma::ump::ConsentStatus; - ConsentInfo* consent_info = ConsentInfo::GetInstance(); - - ASSERT_NE(consent_info, nullptr); - consent_info->Reset(); ConsentRequestParameters params; params.set_tag_for_under_age_of_consent(false); firebase::Future future = - consent_info->RequestConsentStatus(params); + consent_info_->RequestConsentStatus(params); WaitForCompletion(future, "RequestConsentStatus"); EXPECT_NE(future.result(), nullptr); - EXPECT_EQ(*future.result(), consent_info->GetConsentStatus()); - EXPECT_NE(consent_info->GetConsentStatus(), + EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); + EXPECT_NE(consent_info_->GetConsentStatus(), firebase::gma::ump::kConsentStatusUnknown); - EXPECT_NE(consent_info->GetConsentFormStatus(), + EXPECT_NE(consent_info_->GetConsentFormStatus(), firebase::gma::ump::kConsentFormStatusUnknown); - - delete consent_info; - consent_info = nullptr; } -TEST_F(FirebaseGmaTest, TestUmpRequestErrorWithoutTagForUnderAgeOfConsent) { - using firebase::gma::ump::ConsentInfo; +TEST_F(FirebaseGmaUmpTest, TestUmpRequestErrorWithoutTagForUnderAgeOfConsent) { using firebase::gma::ump::ConsentRequestParameters; using firebase::gma::ump::ConsentStatus; - ConsentInfo* consent_info = ConsentInfo::GetInstance(); - - ASSERT_NE(consent_info, nullptr); - consent_info->Reset(); ConsentRequestParameters params; // Do not call set_tag_for_under_age_of_consent(). firebase::Future future = - consent_info->RequestConsentStatus(params); + consent_info_->RequestConsentStatus(params); - WaitForCompletion(future, "RequestConsentStatus", - firebase::gma::ump::kConsentRequestErrorTagForAgeOfConsentNotSet); + WaitForCompletion( + future, "RequestConsentStatus", + firebase::gma::ump::kConsentRequestErrorTagForAgeOfConsentNotSet); - EXPECT_EQ(*future.result(), consent_info->GetConsentStatus()); - EXPECT_EQ(consent_info->GetConsentStatus(), + EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); + EXPECT_EQ(consent_info_->GetConsentStatus(), firebase::gma::ump::kConsentStatusUnknown); - - delete consent_info; - consent_info = nullptr; } -TEST_F(FirebaseGmaTest, TestUmpRequestConsentStatusDebugEEA) { +TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentStatusDebugEEA) { using firebase::gma::ump::ConsentDebugSettings; - using firebase::gma::ump::ConsentInfo; using firebase::gma::ump::ConsentRequestParameters; using firebase::gma::ump::ConsentStatus; - ConsentInfo* consent_info = ConsentInfo::GetInstance(); - - ASSERT_NE(consent_info, nullptr); - consent_info->Reset(); ConsentRequestParameters params; params.set_tag_for_under_age_of_consent(false); @@ -2524,28 +2541,20 @@ TEST_F(FirebaseGmaTest, TestUmpRequestConsentStatusDebugEEA) { params.set_debug_settings(debug_settings); firebase::Future future = - consent_info->RequestConsentStatus(params); + consent_info_->RequestConsentStatus(params); WaitForCompletion(future, "RequestConsentStatus"); EXPECT_NE(future.result(), nullptr); - EXPECT_EQ(*future.result(), consent_info->GetConsentStatus()); - EXPECT_EQ(consent_info->GetConsentStatus(), + EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); + EXPECT_EQ(consent_info_->GetConsentStatus(), firebase::gma::ump::kConsentStatusRequired); - - delete consent_info; - consent_info = nullptr; } -TEST_F(FirebaseGmaTest, TestUmpRequestConsentStatusDebugNonEEA) { +TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentStatusDebugNonEEA) { using firebase::gma::ump::ConsentDebugSettings; - using firebase::gma::ump::ConsentInfo; using firebase::gma::ump::ConsentRequestParameters; using firebase::gma::ump::ConsentStatus; - ConsentInfo* consent_info = ConsentInfo::GetInstance(); - - ASSERT_NE(consent_info, nullptr); - consent_info->Reset(); ConsentRequestParameters params; params.set_tag_for_under_age_of_consent(false); @@ -2555,29 +2564,21 @@ TEST_F(FirebaseGmaTest, TestUmpRequestConsentStatusDebugNonEEA) { params.set_debug_settings(debug_settings); firebase::Future future = - consent_info->RequestConsentStatus(params); + consent_info_->RequestConsentStatus(params); WaitForCompletion(future, "RequestConsentStatus"); EXPECT_NE(future.result(), nullptr); - EXPECT_EQ(*future.result(), consent_info->GetConsentStatus()); - EXPECT_EQ(consent_info->GetConsentStatus(), + EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); + EXPECT_EQ(consent_info_->GetConsentStatus(), firebase::gma::ump::kConsentStatusNotRequired); - - delete consent_info; - consent_info = nullptr; } -TEST_F(FirebaseGmaTest, TestUmpLoadForm) { +TEST_F(FirebaseGmaUmpTest, TestUmpLoadForm) { using firebase::gma::ump::ConsentDebugSettings; using firebase::gma::ump::ConsentFormStatus; - using firebase::gma::ump::ConsentInfo; using firebase::gma::ump::ConsentRequestParameters; using firebase::gma::ump::ConsentStatus; - ConsentInfo* consent_info = ConsentInfo::GetInstance(); - - ASSERT_NE(consent_info, nullptr); - consent_info->Reset(); ConsentRequestParameters params; params.set_tag_for_under_age_of_consent(false); @@ -2588,48 +2589,40 @@ TEST_F(FirebaseGmaTest, TestUmpLoadForm) { { firebase::Future future = - consent_info->RequestConsentStatus(params); + consent_info_->RequestConsentStatus(params); WaitForCompletion(future, "RequestConsentStatus"); EXPECT_NE(future.result(), nullptr); - EXPECT_EQ(*future.result(), consent_info->GetConsentStatus()); + EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); } - EXPECT_EQ(consent_info->GetConsentStatus(), + EXPECT_EQ(consent_info_->GetConsentStatus(), firebase::gma::ump::kConsentStatusRequired); - if (consent_info->GetConsentFormStatus() == + if (consent_info_->GetConsentFormStatus() == firebase::gma::ump::kConsentFormStatusUnavailable) { // Load the form. firebase::Future future = - consent_info->LoadConsentForm(); + consent_info_->LoadConsentForm(); WaitForCompletion(future, "LoadConsentForm"); EXPECT_NE(future.result(), nullptr); - EXPECT_EQ(*future.result(), consent_info->GetConsentFormStatus()); + EXPECT_EQ(*future.result(), consent_info_->GetConsentFormStatus()); } - EXPECT_EQ(consent_info->GetConsentFormStatus(), + EXPECT_EQ(consent_info_->GetConsentFormStatus(), firebase::gma::ump::kConsentFormStatusAvailable); - - delete consent_info; - consent_info = nullptr; } -TEST_F(FirebaseGmaTest, TestUmpShowForm) { +TEST_F(FirebaseGmaUmpTest, TestUmpShowForm) { TEST_REQUIRES_USER_INTERACTION; using firebase::gma::ump::ConsentDebugSettings; using firebase::gma::ump::ConsentFormStatus; - using firebase::gma::ump::ConsentInfo; using firebase::gma::ump::ConsentRequestParameters; using firebase::gma::ump::ConsentStatus; - ConsentInfo* consent_info = ConsentInfo::GetInstance(); - - ASSERT_NE(consent_info, nullptr); - consent_info->Reset(); ConsentRequestParameters params; params.set_tag_for_under_age_of_consent(false); @@ -2640,70 +2633,62 @@ TEST_F(FirebaseGmaTest, TestUmpShowForm) { { firebase::Future future = - consent_info->RequestConsentStatus(params); + consent_info_->RequestConsentStatus(params); WaitForCompletion(future, "RequestConsentStatus"); EXPECT_NE(future.result(), nullptr); - EXPECT_EQ(*future.result(), consent_info->GetConsentStatus()); + EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); } - EXPECT_EQ(consent_info->GetConsentStatus(), + EXPECT_EQ(consent_info_->GetConsentStatus(), firebase::gma::ump::kConsentStatusRequired); - if (consent_info->GetConsentFormStatus() == + if (consent_info_->GetConsentFormStatus() == firebase::gma::ump::kConsentFormStatusUnavailable) { // Load the form. firebase::Future future = - consent_info->LoadConsentForm(); + consent_info_->LoadConsentForm(); WaitForCompletion(future, "LoadConsentForm"); EXPECT_NE(future.result(), nullptr); - EXPECT_EQ(*future.result(), consent_info->GetConsentFormStatus()); + EXPECT_EQ(*future.result(), consent_info_->GetConsentFormStatus()); } - EXPECT_EQ(consent_info->GetConsentFormStatus(), + EXPECT_EQ(consent_info_->GetConsentFormStatus(), firebase::gma::ump::kConsentFormStatusAvailable); { firebase::Future future = - consent_info->ShowConsentForm(nullptr); + consent_info_->ShowConsentForm(nullptr); WaitForCompletion(future, "ShowConsentForm"); EXPECT_NE(future.result(), nullptr); - EXPECT_EQ(*future.result(), consent_info->GetConsentStatus()); + EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); } - EXPECT_EQ(consent_info->GetConsentStatus(), + EXPECT_EQ(consent_info_->GetConsentStatus(), firebase::gma::ump::kConsentStatusObtained); - - delete consent_info; - consent_info = nullptr; } -TEST_F(FirebaseGmaTest, TestUmpCleanup) { +TEST_F(FirebaseGmaUmpTest, TestUmpCleanup) { using firebase::gma::ump::ConsentFormStatus; - using firebase::gma::ump::ConsentInfo; using firebase::gma::ump::ConsentRequestParameters; using firebase::gma::ump::ConsentStatus; - ConsentInfo* consent_info = ConsentInfo::GetInstance(); - consent_info->Reset(); - - ASSERT_NE(consent_info, nullptr); ConsentRequestParameters params; params.set_tag_for_under_age_of_consent(false); firebase::Future future_request = - consent_info->RequestConsentStatus(params); + consent_info_->RequestConsentStatus(params); firebase::Future future_load = - consent_info->LoadConsentForm(); + consent_info_->LoadConsentForm(); firebase::Future future_show = - consent_info->ShowConsentForm(nullptr); + consent_info_->ShowConsentForm(nullptr); - delete consent_info; - consent_info = nullptr; + delete consent_info_; + consent_info_ = nullptr; EXPECT_EQ(future_request.status(), firebase::kFutureStatusInvalid); EXPECT_EQ(future_load.status(), firebase::kFutureStatusInvalid); diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index 9665bb9ed4..c124ce6beb 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -41,8 +41,8 @@ Future ConsentInfoInternalStub::RequestConsentStatus( CreateFuture(kConsentInfoFnRequestConsentStatus); if (!params.has_tag_for_under_age_of_consent()) { - CompleteFuture(handle, kConsentRequestErrorTagForAgeOfConsentNotSet, - consent_status_); + CompleteFuture( + handle, kConsentRequestErrorTagForAgeOfConsentNotSet, consent_status_); return MakeFuture(futures(), handle); } From 6934de7c6a7dc61cade34457e67e1702b364d4c2 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 19 Jul 2023 12:08:44 -0700 Subject: [PATCH 25/50] Fix TODO. --- gma/src/common/ump/consent_info.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gma/src/common/ump/consent_info.cc b/gma/src/common/ump/consent_info.cc index 9f8b53d15e..d5e0bae592 100644 --- a/gma/src/common/ump/consent_info.cc +++ b/gma/src/common/ump/consent_info.cc @@ -55,7 +55,7 @@ ConsentInfo* ConsentInfo::GetInstance(::firebase::InitResult* init_result_out) { ConsentInfo* consent_info = new ConsentInfo(); #if FIREBASE_PLATFORM_ANDROID InitResult result = - consent_info->Initialize(/* jni_env, activity */); // TODO + consent_info->Initialize(/* jni_env, activity */); // TODO(b/291622888) #else InitResult result = consent_info->Initialize(); #endif From 3601d3c01ab93222be363fd2d28adecd0eedd041 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 19 Jul 2023 12:09:35 -0700 Subject: [PATCH 26/50] Fix lint issues. --- gma/src/common/ump/consent_info.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gma/src/common/ump/consent_info.cc b/gma/src/common/ump/consent_info.cc index d5e0bae592..614e6ff0b8 100644 --- a/gma/src/common/ump/consent_info.cc +++ b/gma/src/common/ump/consent_info.cc @@ -39,7 +39,7 @@ ConsentInfo* ConsentInfo::GetInstance(const ::firebase::App& app, #else // !FIREBASE_PLATFORM_ANDROID return GetInstance(init_result_out); #endif // FIREBASE_PLATFORM_ANDROID -}; +} #if FIREBASE_PLATFORM_ANDROID ConsentInfo* ConsentInfo::GetInstance(JNIEnv* jni_env, jobject activity, @@ -65,7 +65,7 @@ ConsentInfo* ConsentInfo::GetInstance(::firebase::InitResult* init_result_out) { return nullptr; } return consent_info; -}; +} ConsentInfo::ConsentInfo() { internal_ = nullptr; From 1a27b779e3eac777a30175c73002410780aae986 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 19 Jul 2023 12:26:15 -0700 Subject: [PATCH 27/50] Add Doxygen comments to public interface. --- .../include/firebase/gma/ump/consent_info.h | 4 +- gma/src/include/firebase/gma/ump/types.h | 74 +++++++++++++++---- 2 files changed, 64 insertions(+), 14 deletions(-) diff --git a/gma/src/include/firebase/gma/ump/consent_info.h b/gma/src/include/firebase/gma/ump/consent_info.h index a50043a356..3a374ff97a 100644 --- a/gma/src/include/firebase/gma/ump/consent_info.h +++ b/gma/src/include/firebase/gma/ump/consent_info.h @@ -39,6 +39,8 @@ namespace internal { class ConsentInfoInternal; } // namespace internal +/// This class contains all of the methods necessary for obtaining +/// consent from the user. class ConsentInfo { public: /// Shut down the User Messaging Platform Consent SDK @@ -64,7 +66,7 @@ class ConsentInfo { /// Initializes the User Messaging Platform Consent SDK without Firebase for /// Android. /// - /// The arguments to @ref Initialize are platform-specific so the caller must + /// The arguments to GetInstance() are platform-specific so the caller must /// do something like this: /// @code /// #if defined(__ANDROID__) diff --git a/gma/src/include/firebase/gma/ump/types.h b/gma/src/include/firebase/gma/ump/types.h index 644b1f678c..14ab1aede8 100644 --- a/gma/src/include/firebase/gma/ump/types.h +++ b/gma/src/include/firebase/gma/ump/types.h @@ -27,54 +27,69 @@ namespace firebase { namespace gma { namespace ump { +/// Debug values for testing geography. enum ConsentDebugGeography { + /// Disable geography debugging. kConsentDebugGeographyDisabled = 0, + /// Geography appears as in EEA for debug devices. kConsentDebugGeographyEEA, + /// Geography appears as not in EEA for debug devices. kConsentDebugGeographyNonEEA }; +/// Debug settings for `ConsentInfo::RequestConsentStatus()`. These let you +/// force a speific geographic location. Be sure to include debug device IDs to +/// enable this on hardware. Debug features are always enabled for simulators. struct ConsentDebugSettings { + /// Create a default debug setting, with debugging disabled. ConsentDebugSettings() : debug_geography(kConsentDebugGeographyDisabled) {} + /// The geographical location, for debugging. ConsentDebugGeography debug_geography; + /// A list of all device IDs that are allowed to use debug settings. You can + /// obtain this from the device log after running with debug settings enabled. std::vector debug_device_ids; }; -// Parameters for the consent info request operation. +/// Parameters for the `ConsentInfo::RequestConsentStatus()` operation. You must +/// explicitly set the age of consent tag (to true or false) or the operation +/// will fail. class ConsentRequestParameters { public: ConsentRequestParameters() : has_debug_settings_(false), tag_for_under_age_of_consent_(false), has_tag_for_under_age_of_consent_(false) {} - // Set the age of consent tag. + /// Set the age of consent tag. This indicates whether the user is tagged for + /// under age of consent. This is a required setting. void set_tag_for_under_age_of_consent(bool tag) { tag_for_under_age_of_consent_ = tag; has_tag_for_under_age_of_consent_ = true; } - // Get the age of consent tag. + /// Get the age of consent tag. This indicates whether the user is tagged for + /// under age of consent. bool tag_for_under_age_of_consent() const { return tag_for_under_age_of_consent_; } - // Get whether the age of consent tag was previously set. + /// Get whether the age of consent tag was previously set. bool has_tag_for_under_age_of_consent() const { return has_tag_for_under_age_of_consent_; } - // Set the debug settings. + /// Set the debug settings. void set_debug_settings(const ConsentDebugSettings& settings) { debug_settings_ = settings; has_debug_settings_ = true; } - // Set the debug settings without copying data, useful if you have a large - // list of debug device IDs. + /// Set the debug settings without copying data, which could be useful if you + /// have a large list of debug device IDs. void set_debug_settings(const ConsentDebugSettings&& settings) { debug_settings_ = std::move(settings); has_debug_settings_ = true; } - // Get the debug settings. + /// Get the debug settings. const ConsentDebugSettings& debug_settings() const { return debug_settings_; } - // Get whether debug settings were set. + /// Get whether debug settings were set. bool has_debug_settings() const { return has_debug_settings_; } private: @@ -104,43 +119,76 @@ typedef void* FormParent; #endif // FIREBASE_PLATFORM_ANDROID, FIREBASE_PLATFORM_IOS, // FIREBASE_PLATFORM_TVOS +/// Consent status values. enum ConsentStatus { - // Unknown status, e.g. prior to calling Request, or if the request fails. + /// Unknown status, e.g. prior to calling Request, or if the request fails. kConsentStatusUnknown = 0, - // Consent is required, but not obtained + /// Consent is required, but not obtained kConsentStatusRequired, - // Consent is not required + /// Consent is not required kConsentStatusNotRequired, - // Consent was required, and has been obtained + /// Consent was required, and has been obtained kConsentStatusObtained }; +/// Errors that can occur during a RequestConsentStatus operation. enum ConsentRequestError { + /// The operation succeeded. kConsentRequestSuccess = 0, + /// Invalid GMA App ID specified in AndroidManifest.xml or Info.plist. kConsentRequestErrorInvalidAppId, + /// A network error occurred. kConsentRequestErrorNetwork, + /// The tag for age of consent was not set. You must call + /// `ConsentRequestParameters::set_tag_for_under_age_of_consent()` before the + /// request. kConsentRequestErrorTagForAgeOfConsentNotSet, + /// An internal error occurred. kConsentRequestErrorInternal, + /// This error is undocumented. kConsentRequestErrorCodeMisconfiguration, + /// An unknown error occurred. kConsentRequestErrorUnknown, + /// The operation is already in progress. Use + /// `ConsentInfo::RequestConsentStatusLastResult()` + /// to get the status. kConsentRequestErrorOperationInProgress }; +/// Status of the consent form, whether it is available to show or not. enum ConsentFormStatus { + /// Status is unknown. Call `ConsentInfo::RequestConsentStatus()` to update + /// this. kConsentFormStatusUnknown = 0, + /// The consent form is unavailable. Call `ConsentInfo::LoadConsentForm()` to + /// load it. kConsentFormStatusUnavailable, + /// The consent form is available. Call `ConsentInfo::ShowConsentForm()` to + /// display it. kConsentFormStatusAvailable, }; +/// Errors when loading or showing the consent form. enum ConsentFormError { + /// The operation succeeded. kConsentFormSuccess = 0, + /// The load request timed out. Try again. kConsentFormErrorTimeout, + /// Failed to show the consent form because it has not been loaded. kConsentFormErrorNotLoaded, + /// An internal error occurred. kConsentFormErrorInternal, + /// An unknown error occurred. kConsentFormErrorUnknown, + /// This form was already used. kConsentFormErrorCodeAlreadyUsed, + /// An invalid operation occurred. Try again. kConsentFormErrorInvalidOperation, + /// General network issues occurred. Try again. kConsentFormErrorNetwork, + /// The operation is already in progress. Call + /// `ConsentInfo::LoadConsentFormLastResult()` or + /// `ConsentInfo::ShowConsentFormLastResult()` to get the status. kConsentFormErrorOperationInProgress }; From 5f9ab35d8780bf203919942e797deb4effe6e796 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 19 Jul 2023 12:38:55 -0700 Subject: [PATCH 28/50] Add LastResult implementations, and tests to confirm. --- gma/integration_test/src/integration_test.cc | 6 ++++++ gma/src/common/ump/consent_info.cc | 12 ++++++++++++ gma/src/include/firebase/gma/ump/consent_info.h | 3 +++ 3 files changed, 21 insertions(+) diff --git a/gma/integration_test/src/integration_test.cc b/gma/integration_test/src/integration_test.cc index cdb63c257d..5af1d4fcaf 100644 --- a/gma/integration_test/src/integration_test.cc +++ b/gma/integration_test/src/integration_test.cc @@ -2499,6 +2499,8 @@ TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentStatus) { firebase::Future future = consent_info_->RequestConsentStatus(params); + EXPECT_TRUE(future == consent_info_->RequestConsentStatusLastResult()); + WaitForCompletion(future, "RequestConsentStatus"); EXPECT_NE(future.result(), nullptr); @@ -2606,6 +2608,8 @@ TEST_F(FirebaseGmaUmpTest, TestUmpLoadForm) { firebase::Future future = consent_info_->LoadConsentForm(); + EXPECT_TRUE(future == consent_info_->LoadConsentFormLastResult()); + WaitForCompletion(future, "LoadConsentForm"); EXPECT_NE(future.result(), nullptr); @@ -2663,6 +2667,8 @@ TEST_F(FirebaseGmaUmpTest, TestUmpShowForm) { firebase::Future future = consent_info_->ShowConsentForm(nullptr); + EXPECT_TRUE(future == consent_info_->ShowConsentFormLastResult()); + WaitForCompletion(future, "ShowConsentForm"); EXPECT_NE(future.result(), nullptr); diff --git a/gma/src/common/ump/consent_info.cc b/gma/src/common/ump/consent_info.cc index 614e6ff0b8..3a70a1be54 100644 --- a/gma/src/common/ump/consent_info.cc +++ b/gma/src/common/ump/consent_info.cc @@ -105,15 +105,27 @@ Future ConsentInfo::RequestConsentStatus( return internal_->RequestConsentStatus(params); } +Future ConsentInfo::RequestConsentStatusLastResult() { + return internal_->RequestConsentStatusLastResult(); +} + Future ConsentInfo::LoadConsentForm() { FIREBASE_ASSERT(internal_); return internal_->LoadConsentForm(); } +Future ConsentInfo::LoadConsentFormLastResult() { + return internal_->LoadConsentFormLastResult(); +} + Future ConsentInfo::ShowConsentForm(FormParent parent) { return internal_->ShowConsentForm(parent); } +Future ConsentInfo::ShowConsentFormLastResult() { + return internal_->ShowConsentFormLastResult(); +} + void ConsentInfo::Reset() { return internal_->Reset(); } } // namespace ump diff --git a/gma/src/include/firebase/gma/ump/consent_info.h b/gma/src/include/firebase/gma/ump/consent_info.h index 3a374ff97a..1642691ea1 100644 --- a/gma/src/include/firebase/gma/ump/consent_info.h +++ b/gma/src/include/firebase/gma/ump/consent_info.h @@ -133,6 +133,9 @@ class ConsentInfo { /// completed. Future ShowConsentForm(FormParent parent); + /// Get the Future from the most recent call to ShowConsentForm(). + Future ShowConsentFormLastResult(); + /// Clears all consent state from persistent storage. This can be used in /// development to simulate a new installation. void Reset(); From f4aef9df7646fe45611b090abaa66fd4f415351c Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 19 Jul 2023 13:19:57 -0700 Subject: [PATCH 29/50] Add method stubs for new UserMessagingPlatform API. --- gma/integration_test/src/integration_test.cc | 162 ++++++++++++++++++ gma/src/common/ump/consent_info.cc | 21 +++ gma/src/common/ump/consent_info_internal.h | 22 +++ .../include/firebase/gma/ump/consent_info.h | 20 +++ gma/src/include/firebase/gma/ump/types.h | 12 ++ .../stub/ump/consent_info_internal_stub.cc | 53 +++++- gma/src/stub/ump/consent_info_internal_stub.h | 11 ++ 7 files changed, 300 insertions(+), 1 deletion(-) diff --git a/gma/integration_test/src/integration_test.cc b/gma/integration_test/src/integration_test.cc index 5af1d4fcaf..f9e16f0572 100644 --- a/gma/integration_test/src/integration_test.cc +++ b/gma/integration_test/src/integration_test.cc @@ -2679,6 +2679,168 @@ TEST_F(FirebaseGmaUmpTest, TestUmpShowForm) { firebase::gma::ump::kConsentStatusObtained); } +TEST_F(FirebaseGmaUmpTest, TestUmpLoadAndShowIfRequired) { + using firebase::gma::ump::ConsentDebugSettings; + using firebase::gma::ump::ConsentRequestParameters; + using firebase::gma::ump::ConsentStatus; + + TEST_REQUIRES_USER_INTERACTION; + + ConsentRequestParameters params; + params.set_tag_for_under_age_of_consent(false); + ConsentDebugSettings debug_settings; + debug_settings.debug_geography = + firebase::gma::ump::kConsentDebugGeographyEEA; + params.set_debug_settings(debug_settings); + + { + firebase::Future future = + consent_info_->RequestConsentStatus(params); + + WaitForCompletion(future, "RequestConsentStatus"); + + EXPECT_NE(future.result(), nullptr); + EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); + } + + EXPECT_EQ(consent_info_->GetConsentStatus(), + firebase::gma::ump::kConsentStatusRequired); + + { + firebase::Future future = + consent_info_->LoadAndShowConsentFormIfRequired(nullptr); + + WaitForCompletion(future, "LoadAndShowConsentFormIfRequired"); + + EXPECT_NE(future.result(), nullptr); + EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); + } + EXPECT_EQ(consent_info_->GetConsentStatus(), + firebase::gma::ump::kConsentStatusObtained); +} + +TEST_F(FirebaseGmaUmpTest, TestUmpPrivacyOptions) { + using firebase::gma::ump::ConsentDebugSettings; + using firebase::gma::ump::ConsentRequestParameters; + using firebase::gma::ump::ConsentStatus; + using firebase::gma::ump::PrivacyOptionsRequirementStatus; + + TEST_REQUIRES_USER_INTERACTION; + + ConsentRequestParameters params; + params.set_tag_for_under_age_of_consent(true); + ConsentDebugSettings debug_settings; + debug_settings.debug_geography = + firebase::gma::ump::kConsentDebugGeographyEEA; + params.set_debug_settings(debug_settings); + + { + firebase::Future future = + consent_info_->RequestConsentStatus(params); + + WaitForCompletion(future, "RequestConsentStatus"); + + EXPECT_NE(future.result(), nullptr); + EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); + } + + EXPECT_EQ(consent_info_->GetConsentStatus(), + firebase::gma::ump::kConsentStatusRequired); + + EXPECT_FALSE(consent_info_->CanRequestAds()); + + { + firebase::Future future = + consent_info_->LoadAndShowConsentFormIfRequired(nullptr); + + WaitForCompletion(future, "LoadAndShowConsentFormIfRequired"); + + EXPECT_NE(future.result(), nullptr); + EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); + } + EXPECT_EQ(consent_info_->GetConsentStatus(), + firebase::gma::ump::kConsentStatusObtained); + + EXPECT_TRUE(consent_info_->CanRequestAds()); + + EXPECT_EQ(consent_info_->GetPrivacyOptionsRequirementStatus(), + firebase::gma::ump::kPrivacyOptionsRequirementStatusRequired); + { + firebase::Future future = + consent_info_->ShowPrivacyOptionsForm(nullptr); + + WaitForCompletion(future, "ShowPrivacyOptionsForm"); + + EXPECT_NE(future.result(), nullptr); + EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); + } + // Ensure that consent was revoked. + EXPECT_EQ(consent_info_->GetConsentStatus(), + firebase::gma::ump::kConsentStatusRequired); + + EXPECT_FALSE(consent_info_->CanRequestAds()); +} + +TEST_F(FirebaseGmaUmpTest, TestCanRequestAdsNonEEA) { + using firebase::gma::ump::ConsentDebugSettings; + using firebase::gma::ump::ConsentRequestParameters; + using firebase::gma::ump::ConsentStatus; + + TEST_REQUIRES_USER_INTERACTION; + + ConsentRequestParameters params; + params.set_tag_for_under_age_of_consent(false); + ConsentDebugSettings debug_settings; + debug_settings.debug_geography = + firebase::gma::ump::kConsentDebugGeographyNonEEA; + params.set_debug_settings(debug_settings); + + { + firebase::Future future = + consent_info_->RequestConsentStatus(params); + + WaitForCompletion(future, "RequestConsentStatus"); + + EXPECT_NE(future.result(), nullptr); + EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); + } + + EXPECT_EQ(consent_info_->GetConsentStatus(), + firebase::gma::ump::kConsentStatusNotRequired); + + EXPECT_TRUE(consent_info_->CanRequestAds()); +} + +TEST_F(FirebaseGmaUmpTest, TestCanRequestAdsEEA) { + using firebase::gma::ump::ConsentDebugSettings; + using firebase::gma::ump::ConsentRequestParameters; + using firebase::gma::ump::ConsentStatus; + + TEST_REQUIRES_USER_INTERACTION; + + ConsentRequestParameters params; + params.set_tag_for_under_age_of_consent(false); + ConsentDebugSettings debug_settings; + debug_settings.debug_geography = + firebase::gma::ump::kConsentDebugGeographyEEA; + params.set_debug_settings(debug_settings); + + { + firebase::Future future = + consent_info_->RequestConsentStatus(params); + + WaitForCompletion(future, "RequestConsentStatus"); + + EXPECT_NE(future.result(), nullptr); + EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); + } + + EXPECT_EQ(consent_info_->GetConsentStatus(), + firebase::gma::ump::kConsentStatusRequired); + + EXPECT_FALSE(consent_info_->CanRequestAds()); +} + TEST_F(FirebaseGmaUmpTest, TestUmpCleanup) { using firebase::gma::ump::ConsentFormStatus; using firebase::gma::ump::ConsentRequestParameters; diff --git a/gma/src/common/ump/consent_info.cc b/gma/src/common/ump/consent_info.cc index 3a70a1be54..f0e487d03a 100644 --- a/gma/src/common/ump/consent_info.cc +++ b/gma/src/common/ump/consent_info.cc @@ -126,6 +126,27 @@ Future ConsentInfo::ShowConsentFormLastResult() { return internal_->ShowConsentFormLastResult(); } +Future ConsentInfo::LoadAndShowConsentFormIfRequired( + FormParent parent) { + return internal_->LoadAndShowConsentFormIfRequired(parent); +} + +Future +ConsentInfo::LoadAndShowConsentFormIfRequiredLastResult() { + return internal_->LoadAndShowConsentFormIfRequiredLastResult(); +} + +PrivacyOptionsRequirementStatus +ConsentInfo::GetPrivacyOptionsRequirementStatus() { + return internal_->GetPrivacyOptionsRequirementStatus(); +} + +Future ConsentInfo::ShowPrivacyOptionsForm(FormParent parent) { + return internal_->ShowPrivacyOptionsForm(parent); +} + +bool ConsentInfo::CanRequestAds() { return internal_->CanRequestAds(); } + void ConsentInfo::Reset() { return internal_->Reset(); } } // namespace ump diff --git a/gma/src/common/ump/consent_info_internal.h b/gma/src/common/ump/consent_info_internal.h index 27ba205c16..768af58769 100644 --- a/gma/src/common/ump/consent_info_internal.h +++ b/gma/src/common/ump/consent_info_internal.h @@ -33,6 +33,8 @@ enum ConsentInfoFn { kConsentInfoFnRequestConsentStatus, kConsentInfoFnLoadConsentForm, kConsentInfoFnShowConsentForm, + kConsentInfoFnLoadAndShowConsentFormIfRequired, + kConsentInfoFnShowPrivacyOptionsForm, kConsentInfoFnCount }; @@ -67,6 +69,26 @@ class ConsentInfoInternal { futures()->LastResult(kConsentInfoFnShowConsentForm)); } + virtual Future LoadAndShowConsentFormIfRequired( + FormParent parent) = 0; + + Future LoadAndShowConsentFormIfRequiredLastResult() { + return static_cast&>( + futures()->LastResult(kConsentInfoFnLoadAndShowConsentFormIfRequired)); + } + + virtual PrivacyOptionsRequirementStatus + GetPrivacyOptionsRequirementStatus() = 0; + + virtual Future ShowPrivacyOptionsForm(FormParent parent) = 0; + + Future ShowPrivacyOptionsFormLastResult() { + return static_cast&>( + futures()->LastResult(kConsentInfoFnShowPrivacyOptionsForm)); + } + + virtual bool CanRequestAds() = 0; + virtual void Reset() = 0; protected: diff --git a/gma/src/include/firebase/gma/ump/consent_info.h b/gma/src/include/firebase/gma/ump/consent_info.h index 1642691ea1..838fe6d7c7 100644 --- a/gma/src/include/firebase/gma/ump/consent_info.h +++ b/gma/src/include/firebase/gma/ump/consent_info.h @@ -136,6 +136,26 @@ class ConsentInfo { /// Get the Future from the most recent call to ShowConsentForm(). Future ShowConsentFormLastResult(); + /// If required, load and then show the consent form. You can call this + /// instead of LoadConsentForm() and ShowConsentForm(). + Future LoadAndShowConsentFormIfRequired(FormParent parent); + + /// Get the Future from the most recent call to + /// LoadAndShowConsentFormIfRequired(). + Future LoadAndShowConsentFormIfRequiredLastResult(); + + /// Check whether the privacy options form needs to be displayed. + /// This is updated by RequestConsentStatus(). + PrivacyOptionsRequirementStatus GetPrivacyOptionsRequirementStatus(); + + /// If needed, show the privacy options form to the user. This allows them to + /// revoke their consent. + Future ShowPrivacyOptionsForm(FormParent parent); + + /// If this returns true, it is now safe to request ads. If not, do not show + /// ads to the user. This is updated by RequestConsentStatus(). + bool CanRequestAds(); + /// Clears all consent state from persistent storage. This can be used in /// development to simulate a new installation. void Reset(); diff --git a/gma/src/include/firebase/gma/ump/types.h b/gma/src/include/firebase/gma/ump/types.h index 14ab1aede8..06bc11e654 100644 --- a/gma/src/include/firebase/gma/ump/types.h +++ b/gma/src/include/firebase/gma/ump/types.h @@ -192,6 +192,18 @@ enum ConsentFormError { kConsentFormErrorOperationInProgress }; +/// Whether the privacy options need to be displayed. +enum PrivacyOptionsRequirementStatus { + /// Privacy options requirement status is unknown. Call + /// `ConsentInfo::RequestConsentStatus()` to update. + kPrivacyOptionsRequirementStatusUnknown = 0, + /// Privacy options are not required to be shown. + kPrivacyOptionsRequirementStatusNotRequired, + /// Privacy options must be shown. Call + /// `ConsentInfo::ShowPrivacyOptionsForm()` to fulfil this requirement. + kPrivacyOptionsRequirementStatusRequired +}; + } // namespace ump } // namespace gma } // namespace firebase diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index c124ce6beb..2005a9ab6c 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -31,7 +31,9 @@ ConsentInfoInternal* ConsentInfoInternal::CreateInstance() { ConsentInfoInternalStub::ConsentInfoInternalStub() : consent_status_(kConsentStatusUnknown), - consent_form_status_(kConsentFormStatusUnknown) {} + consent_form_status_(kConsentFormStatusUnknown), + privacy_options_requirement_status_( + kPrivacyOptionsRequirementStatusUnknown) {} ConsentInfoInternalStub::~ConsentInfoInternalStub() {} @@ -47,6 +49,7 @@ Future ConsentInfoInternalStub::RequestConsentStatus( } ConsentStatus new_consent_status = kConsentStatusObtained; + // Simulate consent status based on debug geo. if (params.has_debug_settings()) { if (params.debug_settings().debug_geography == kConsentDebugGeographyEEA) { new_consent_status = kConsentStatusRequired; @@ -58,6 +61,15 @@ Future ConsentInfoInternalStub::RequestConsentStatus( consent_status_ = new_consent_status; consent_form_status_ = kConsentFormStatusUnavailable; + // Simulate privacy options based on under age of consent. + if (params.tag_for_under_age_of_consent()) { + privacy_options_requirement_status_ = + kPrivacyOptionsRequirementStatusRequired; + } else { + privacy_options_requirement_status_ = + kPrivacyOptionsRequirementStatusNotRequired; + } + CompleteFuture(handle, kConsentRequestSuccess, consent_status_); return MakeFuture(futures(), handle); @@ -84,6 +96,45 @@ Future ConsentInfoInternalStub::ShowConsentForm( return MakeFuture(futures(), handle); } +Future ConsentInfoInternalStub::LoadAndShowConsentFormIfRequired( + FormParent parent) { + SafeFutureHandle handle = CreateFuture( + kConsentInfoFnLoadAndShowConsentFormIfRequired); + + if (consent_status_ == kConsentStatusRequired) { + consent_status_ = kConsentStatusObtained; + } + CompleteFuture(handle, kConsentRequestSuccess, + consent_status_); + return MakeFuture(futures(), handle); +} + +PrivacyOptionsRequirementStatus +ConsentInfoInternalStub::GetPrivacyOptionsRequirementStatus() { + return privacy_options_requirement_status_; +} + +Future ConsentInfoInternalStub::ShowPrivacyOptionsForm( + FormParent parent) { + SafeFutureHandle handle = + CreateFuture(kConsentInfoFnShowPrivacyOptionsForm); + + if (consent_status_ == kConsentStatusObtained) { + consent_status_ = kConsentStatusRequired; + } + CompleteFuture(handle, kConsentRequestSuccess, + consent_status_); + return MakeFuture(futures(), handle); +} + +bool ConsentInfoInternalStub::CanRequestAds() { + bool consent_status_ok = (consent_status_ == kConsentStatusObtained || + consent_status_ == kConsentStatusNotRequired); + bool privacy_options_ok = (privacy_options_requirement_status_ != + kPrivacyOptionsRequirementStatusUnknown); + return consent_status_ok && privacy_options_ok; +} + void ConsentInfoInternalStub::Reset() { consent_status_ = kConsentStatusUnknown; consent_form_status_ = kConsentFormStatusUnknown; diff --git a/gma/src/stub/ump/consent_info_internal_stub.h b/gma/src/stub/ump/consent_info_internal_stub.h index 4c6916336a..e24cea14f8 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.h +++ b/gma/src/stub/ump/consent_info_internal_stub.h @@ -39,11 +39,22 @@ class ConsentInfoInternalStub : public ConsentInfoInternal { Future LoadConsentForm() override; Future ShowConsentForm(FormParent parent) override; + virtual Future LoadAndShowConsentFormIfRequired( + FormParent parent) override; + + virtual PrivacyOptionsRequirementStatus GetPrivacyOptionsRequirementStatus() + override; + virtual Future ShowPrivacyOptionsForm( + FormParent parent) override; + + virtual bool CanRequestAds() override; + void Reset() override; private: ConsentStatus consent_status_; ConsentFormStatus consent_form_status_; + PrivacyOptionsRequirementStatus privacy_options_requirement_status_; }; } // namespace internal From d2706077606f4568744219102c1bd6901573ec06 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 19 Jul 2023 13:26:30 -0700 Subject: [PATCH 30/50] Handle invalid internal pointers. --- gma/src/common/ump/consent_info.cc | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/gma/src/common/ump/consent_info.cc b/gma/src/common/ump/consent_info.cc index 3a70a1be54..af7cdbcbd2 100644 --- a/gma/src/common/ump/consent_info.cc +++ b/gma/src/common/ump/consent_info.cc @@ -89,44 +89,55 @@ InitResult ConsentInfo::Initialize() { return kInitResultSuccess; } +// Below this, everything is a passthrough to ConsentInfoInternal. If there is +// no internal_ pointer (e.g. it's been cleaned up), return default values and +// invalid futures. + ConsentStatus ConsentInfo::GetConsentStatus() { - FIREBASE_ASSERT(internal_); + if (!internal_) return kConsentStatusUnknown; return internal_->GetConsentStatus(); } ConsentFormStatus ConsentInfo::GetConsentFormStatus() { - FIREBASE_ASSERT(internal_); + if (!internal_) return kConsentFormStatusUnknown; return internal_->GetConsentFormStatus(); } Future ConsentInfo::RequestConsentStatus( const ConsentRequestParameters& params) { - FIREBASE_ASSERT(internal_); + if (!internal_) return Future(); return internal_->RequestConsentStatus(params); } Future ConsentInfo::RequestConsentStatusLastResult() { + if (!internal_) return Future(); return internal_->RequestConsentStatusLastResult(); } Future ConsentInfo::LoadConsentForm() { - FIREBASE_ASSERT(internal_); + if (!internal_) return Future(); return internal_->LoadConsentForm(); } Future ConsentInfo::LoadConsentFormLastResult() { + if (!internal_) return Future(); return internal_->LoadConsentFormLastResult(); } Future ConsentInfo::ShowConsentForm(FormParent parent) { + if (!internal_) return Future(); return internal_->ShowConsentForm(parent); } Future ConsentInfo::ShowConsentFormLastResult() { + if (!internal_) return Future(); return internal_->ShowConsentFormLastResult(); } -void ConsentInfo::Reset() { return internal_->Reset(); } +void ConsentInfo::Reset() { + if (!internal_) return; + internal_->Reset(); +} } // namespace ump } // namespace gma From d275462c3225e9dd8e798454206e9e72c881b1e8 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 19 Jul 2023 13:30:38 -0700 Subject: [PATCH 31/50] Format code. --- gma/src/common/ump/consent_info.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gma/src/common/ump/consent_info.cc b/gma/src/common/ump/consent_info.cc index af7cdbcbd2..179fb0b3a3 100644 --- a/gma/src/common/ump/consent_info.cc +++ b/gma/src/common/ump/consent_info.cc @@ -92,7 +92,7 @@ InitResult ConsentInfo::Initialize() { // Below this, everything is a passthrough to ConsentInfoInternal. If there is // no internal_ pointer (e.g. it's been cleaned up), return default values and // invalid futures. - + ConsentStatus ConsentInfo::GetConsentStatus() { if (!internal_) return kConsentStatusUnknown; return internal_->GetConsentStatus(); From b4360273932351e2738c2b90a237adb6f90182e8 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 19 Jul 2023 13:35:09 -0700 Subject: [PATCH 32/50] Add objective-C header for FormParent. --- gma/src/include/firebase/gma/ump/types.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gma/src/include/firebase/gma/ump/types.h b/gma/src/include/firebase/gma/ump/types.h index 14ab1aede8..d9f42a9a10 100644 --- a/gma/src/include/firebase/gma/ump/types.h +++ b/gma/src/include/firebase/gma/ump/types.h @@ -23,6 +23,15 @@ #include "firebase/internal/platform.h" +#if FIREBASE_PLATFORM_ANDROID +#include +#elif FIREBASE_PLATFORM_IOS || FIREBASE_PLATFORM_TVOS +extern "C" { +#include +} // extern "C" +#endif // FIREBASE_PLATFORM_ANDROID, FIREBASE_PLATFORM_IOS, + // FIREBASE_PLATFORM_TVOS + namespace firebase { namespace gma { namespace ump { From 4e7609b3e96c81890d9a2bb12fc2b65b168cead7 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 19 Jul 2023 15:11:00 -0700 Subject: [PATCH 33/50] Add ump.h to top-level CMake file, so it gets added to the framework. --- app/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index b008b7de78..ac52251529 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -546,7 +546,10 @@ if (IOS) ${FIREBASE_SOURCE_DIR}/gma/src/include/firebase/gma/interstitial_ad.h ${FIREBASE_SOURCE_DIR}/gma/src/include/firebase/gma/internal/native_ad.h ${FIREBASE_SOURCE_DIR}/gma/src/include/firebase/gma/rewarded_ad.h - ${FIREBASE_SOURCE_DIR}/gma/src/include/firebase/gma/types.h) + ${FIREBASE_SOURCE_DIR}/gma/src/include/firebase/gma/types.h + ${FIREBASE_SOURCE_DIR}/gma/src/include/firebase/gma/ump.h + ${FIREBASE_SOURCE_DIR}/gma/src/include/firebase/gma/ump/consent_info.h + ${FIREBASE_SOURCE_DIR}/gma/src/include/firebase/gma/ump/types.h) set(installations_HDRS ${FIREBASE_SOURCE_DIR}/installations/src/include/firebase/installations.h) set(messaging_HDRS From 134bd3f223f5f75c35ec6715a8b6ae3c76ebd3ce Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 20 Jul 2023 11:59:11 -0700 Subject: [PATCH 34/50] Change RequestConsentStatus to RequestConsentInfoUpdate. --- gma/src/common/ump/consent_info.cc | 8 ++++---- gma/src/common/ump/consent_info_internal.h | 8 ++++---- gma/src/common/ump/ump_common.cc | 4 ++-- gma/src/include/firebase/gma/ump/consent_info.h | 10 +++++----- gma/src/include/firebase/gma/ump/types.h | 15 ++++++++------- gma/src/stub/ump/consent_info_internal_stub.cc | 4 ++-- gma/src/stub/ump/consent_info_internal_stub.h | 2 +- 7 files changed, 26 insertions(+), 25 deletions(-) diff --git a/gma/src/common/ump/consent_info.cc b/gma/src/common/ump/consent_info.cc index 179fb0b3a3..131d95e9ae 100644 --- a/gma/src/common/ump/consent_info.cc +++ b/gma/src/common/ump/consent_info.cc @@ -103,15 +103,15 @@ ConsentFormStatus ConsentInfo::GetConsentFormStatus() { return internal_->GetConsentFormStatus(); } -Future ConsentInfo::RequestConsentStatus( +Future ConsentInfo::RequestConsentInfoUpdate( const ConsentRequestParameters& params) { if (!internal_) return Future(); - return internal_->RequestConsentStatus(params); + return internal_->RequestConsentInfoUpdate(params); } -Future ConsentInfo::RequestConsentStatusLastResult() { +Future ConsentInfo::RequestConsentInfoUpdateLastResult() { if (!internal_) return Future(); - return internal_->RequestConsentStatusLastResult(); + return internal_->RequestConsentInfoUpdateLastResult(); } Future ConsentInfo::LoadConsentForm() { diff --git a/gma/src/common/ump/consent_info_internal.h b/gma/src/common/ump/consent_info_internal.h index 27ba205c16..edec29558d 100644 --- a/gma/src/common/ump/consent_info_internal.h +++ b/gma/src/common/ump/consent_info_internal.h @@ -30,7 +30,7 @@ namespace internal { // Constants representing each ConsentInfo function that returns a Future. enum ConsentInfoFn { - kConsentInfoFnRequestConsentStatus, + kConsentInfoFnRequestConsentInfoUpdate, kConsentInfoFnLoadConsentForm, kConsentInfoFnShowConsentForm, kConsentInfoFnCount @@ -47,11 +47,11 @@ class ConsentInfoInternal { virtual ConsentStatus GetConsentStatus() const = 0; virtual ConsentFormStatus GetConsentFormStatus() const = 0; - virtual Future RequestConsentStatus( + virtual Future RequestConsentInfoUpdate( const ConsentRequestParameters& params) = 0; - Future RequestConsentStatusLastResult() { + Future RequestConsentInfoUpdateLastResult() { return static_cast&>( - futures()->LastResult(kConsentInfoFnRequestConsentStatus)); + futures()->LastResult(kConsentInfoFnRequestConsentInfoUpdate)); } virtual Future LoadConsentForm() = 0; diff --git a/gma/src/common/ump/ump_common.cc b/gma/src/common/ump/ump_common.cc index 82b96bdead..cf5780b288 100644 --- a/gma/src/common/ump/ump_common.cc +++ b/gma/src/common/ump/ump_common.cc @@ -38,7 +38,7 @@ const char* GetConsentRequestErrorMessage(ConsentRequestError error_code) { case kConsentRequestErrorTagForAgeOfConsentNotSet: return "You must explicitly call " "ConsentRequestParameters.set_tag_for_under_age_of_consent() " - "before calling RequestConsentStatus()"; + "before calling RequestConsentInfoUpdate()"; case kConsentRequestErrorInternal: return "Internal error"; case kConsentRequestErrorCodeMisconfiguration: @@ -47,7 +47,7 @@ const char* GetConsentRequestErrorMessage(ConsentRequestError error_code) { return "Unknown error"; case kConsentRequestErrorOperationInProgress: return "Operation already in progress. Please wait for it to finish by " - "checking RequestConsentStatusLastResult()."; + "checking RequestConsentInfoUpdateLastResult()."; default: return "Bad error code"; } diff --git a/gma/src/include/firebase/gma/ump/consent_info.h b/gma/src/include/firebase/gma/ump/consent_info.h index 1642691ea1..d1f1a887bb 100644 --- a/gma/src/include/firebase/gma/ump/consent_info.h +++ b/gma/src/include/firebase/gma/ump/consent_info.h @@ -106,18 +106,18 @@ class ConsentInfo { /// Requests consent information update. Must be called before loading a /// consent form. - Future RequestConsentStatus( + Future RequestConsentInfoUpdate( const ConsentRequestParameters& params); - /// Get the Future from the most recent call to RequestConsentStatus(). - Future RequestConsentStatusLastResult(); + /// Get the Future from the most recent call to RequestConsentInfoUpdate(). + Future RequestConsentInfoUpdateLastResult(); /// The user’s consent status. This value is cached between app sessions and - /// can be read before calling RequestConsentStatus(). + /// can be read before calling RequestConsentInfoUpdate(). ConsentStatus GetConsentStatus(); /// Consent form status. This value defaults to kConsentFormStatusUnknown and - /// requires a call to RequestConsentStatus() to update. + /// requires a call to RequestConsentInfoUpdate() to update. ConsentFormStatus GetConsentFormStatus(); /// Loads a consent form. diff --git a/gma/src/include/firebase/gma/ump/types.h b/gma/src/include/firebase/gma/ump/types.h index d9f42a9a10..4f46694664 100644 --- a/gma/src/include/firebase/gma/ump/types.h +++ b/gma/src/include/firebase/gma/ump/types.h @@ -46,7 +46,7 @@ enum ConsentDebugGeography { kConsentDebugGeographyNonEEA }; -/// Debug settings for `ConsentInfo::RequestConsentStatus()`. These let you +/// Debug settings for `ConsentInfo::RequestConsentInfoUpdate()`. These let you /// force a speific geographic location. Be sure to include debug device IDs to /// enable this on hardware. Debug features are always enabled for simulators. struct ConsentDebugSettings { @@ -60,9 +60,9 @@ struct ConsentDebugSettings { std::vector debug_device_ids; }; -/// Parameters for the `ConsentInfo::RequestConsentStatus()` operation. You must -/// explicitly set the age of consent tag (to true or false) or the operation -/// will fail. +/// Parameters for the `ConsentInfo::RequestConsentInfoUpdate()` operation. You +/// must explicitly set the age of consent tag (to true or false) or the +/// operation will fail. class ConsentRequestParameters { public: ConsentRequestParameters() @@ -140,7 +140,7 @@ enum ConsentStatus { kConsentStatusObtained }; -/// Errors that can occur during a RequestConsentStatus operation. +/// Errors that can occur during a RequestConsentInfoUpdate operation. enum ConsentRequestError { /// The operation succeeded. kConsentRequestSuccess = 0, @@ -159,14 +159,15 @@ enum ConsentRequestError { /// An unknown error occurred. kConsentRequestErrorUnknown, /// The operation is already in progress. Use - /// `ConsentInfo::RequestConsentStatusLastResult()` + /// `ConsentInfo::RequestConsentInfoUpdateLastResult()` /// to get the status. kConsentRequestErrorOperationInProgress }; /// Status of the consent form, whether it is available to show or not. enum ConsentFormStatus { - /// Status is unknown. Call `ConsentInfo::RequestConsentStatus()` to update + /// Status is unknown. Call `ConsentInfo::RequestConsentInfoUpdate()` to + /// update /// this. kConsentFormStatusUnknown = 0, /// The consent form is unavailable. Call `ConsentInfo::LoadConsentForm()` to diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index c124ce6beb..3d9cc61313 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -35,10 +35,10 @@ ConsentInfoInternalStub::ConsentInfoInternalStub() ConsentInfoInternalStub::~ConsentInfoInternalStub() {} -Future ConsentInfoInternalStub::RequestConsentStatus( +Future ConsentInfoInternalStub::RequestConsentInfoUpdate( const ConsentRequestParameters& params) { SafeFutureHandle handle = - CreateFuture(kConsentInfoFnRequestConsentStatus); + CreateFuture(kConsentInfoFnRequestConsentInfoUpdate); if (!params.has_tag_for_under_age_of_consent()) { CompleteFuture( diff --git a/gma/src/stub/ump/consent_info_internal_stub.h b/gma/src/stub/ump/consent_info_internal_stub.h index 4c6916336a..f68260ac76 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.h +++ b/gma/src/stub/ump/consent_info_internal_stub.h @@ -34,7 +34,7 @@ class ConsentInfoInternalStub : public ConsentInfoInternal { return consent_form_status_; } - Future RequestConsentStatus( + Future RequestConsentInfoUpdate( const ConsentRequestParameters& params) override; Future LoadConsentForm() override; Future ShowConsentForm(FormParent parent) override; From 8ce86c5fe6f367cf907a7d7be04dc63c8a4010be Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 20 Jul 2023 12:00:03 -0700 Subject: [PATCH 35/50] Update integration test method name. --- gma/integration_test/src/integration_test.cc | 34 ++++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/gma/integration_test/src/integration_test.cc b/gma/integration_test/src/integration_test.cc index 5af1d4fcaf..ff8c32ef9d 100644 --- a/gma/integration_test/src/integration_test.cc +++ b/gma/integration_test/src/integration_test.cc @@ -2489,7 +2489,7 @@ TEST_F(FirebaseGmaUmpTest, TestUmpInitialization) { // Terminate handled automatically in test teardown. } -TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentStatus) { +TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentInfoUpdate) { using firebase::gma::ump::ConsentRequestParameters; using firebase::gma::ump::ConsentStatus; @@ -2497,11 +2497,11 @@ TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentStatus) { params.set_tag_for_under_age_of_consent(false); firebase::Future future = - consent_info_->RequestConsentStatus(params); + consent_info_->RequestConsentInfoUpdate(params); - EXPECT_TRUE(future == consent_info_->RequestConsentStatusLastResult()); + EXPECT_TRUE(future == consent_info_->RequestConsentInfoUpdateLastResult()); - WaitForCompletion(future, "RequestConsentStatus"); + WaitForCompletion(future, "RequestConsentInfoUpdate"); EXPECT_NE(future.result(), nullptr); EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); @@ -2519,10 +2519,10 @@ TEST_F(FirebaseGmaUmpTest, TestUmpRequestErrorWithoutTagForUnderAgeOfConsent) { // Do not call set_tag_for_under_age_of_consent(). firebase::Future future = - consent_info_->RequestConsentStatus(params); + consent_info_->RequestConsentInfoUpdate(params); WaitForCompletion( - future, "RequestConsentStatus", + future, "RequestConsentInfoUpdate", firebase::gma::ump::kConsentRequestErrorTagForAgeOfConsentNotSet); EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); @@ -2530,7 +2530,7 @@ TEST_F(FirebaseGmaUmpTest, TestUmpRequestErrorWithoutTagForUnderAgeOfConsent) { firebase::gma::ump::kConsentStatusUnknown); } -TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentStatusDebugEEA) { +TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentInfoUpdateDebugEEA) { using firebase::gma::ump::ConsentDebugSettings; using firebase::gma::ump::ConsentRequestParameters; using firebase::gma::ump::ConsentStatus; @@ -2543,9 +2543,9 @@ TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentStatusDebugEEA) { params.set_debug_settings(debug_settings); firebase::Future future = - consent_info_->RequestConsentStatus(params); + consent_info_->RequestConsentInfoUpdate(params); - WaitForCompletion(future, "RequestConsentStatus"); + WaitForCompletion(future, "RequestConsentInfoUpdate"); EXPECT_NE(future.result(), nullptr); EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); @@ -2553,7 +2553,7 @@ TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentStatusDebugEEA) { firebase::gma::ump::kConsentStatusRequired); } -TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentStatusDebugNonEEA) { +TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentInfoUpdateDebugNonEEA) { using firebase::gma::ump::ConsentDebugSettings; using firebase::gma::ump::ConsentRequestParameters; using firebase::gma::ump::ConsentStatus; @@ -2566,9 +2566,9 @@ TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentStatusDebugNonEEA) { params.set_debug_settings(debug_settings); firebase::Future future = - consent_info_->RequestConsentStatus(params); + consent_info_->RequestConsentInfoUpdate(params); - WaitForCompletion(future, "RequestConsentStatus"); + WaitForCompletion(future, "RequestConsentInfoUpdate"); EXPECT_NE(future.result(), nullptr); EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); @@ -2591,9 +2591,9 @@ TEST_F(FirebaseGmaUmpTest, TestUmpLoadForm) { { firebase::Future future = - consent_info_->RequestConsentStatus(params); + consent_info_->RequestConsentInfoUpdate(params); - WaitForCompletion(future, "RequestConsentStatus"); + WaitForCompletion(future, "RequestConsentInfoUpdate"); EXPECT_NE(future.result(), nullptr); EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); @@ -2637,9 +2637,9 @@ TEST_F(FirebaseGmaUmpTest, TestUmpShowForm) { { firebase::Future future = - consent_info_->RequestConsentStatus(params); + consent_info_->RequestConsentInfoUpdate(params); - WaitForCompletion(future, "RequestConsentStatus"); + WaitForCompletion(future, "RequestConsentInfoUpdate"); EXPECT_NE(future.result(), nullptr); EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); @@ -2687,7 +2687,7 @@ TEST_F(FirebaseGmaUmpTest, TestUmpCleanup) { ConsentRequestParameters params; params.set_tag_for_under_age_of_consent(false); firebase::Future future_request = - consent_info_->RequestConsentStatus(params); + consent_info_->RequestConsentInfoUpdate(params); firebase::Future future_load = consent_info_->LoadConsentForm(); firebase::Future future_show = From 6a050a622c6fbbf8cc6b54f9953ded82132a6a0b Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 20 Jul 2023 12:34:42 -0700 Subject: [PATCH 36/50] Update all Future return types to Future. Added GetInstance() with no parameters for Android, for convenience. --- gma/integration_test/src/integration_test.cc | 85 ++++++------------- gma/src/common/ump/consent_info.cc | 28 +++--- gma/src/common/ump/consent_info_internal.h | 63 +++++--------- .../include/firebase/gma/ump/consent_info.h | 37 ++++---- .../stub/ump/consent_info_internal_stub.cc | 38 ++++----- gma/src/stub/ump/consent_info_internal_stub.h | 6 +- 6 files changed, 103 insertions(+), 154 deletions(-) diff --git a/gma/integration_test/src/integration_test.cc b/gma/integration_test/src/integration_test.cc index ff8c32ef9d..891f97465c 100644 --- a/gma/integration_test/src/integration_test.cc +++ b/gma/integration_test/src/integration_test.cc @@ -2496,15 +2496,13 @@ TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentInfoUpdate) { ConsentRequestParameters params; params.set_tag_for_under_age_of_consent(false); - firebase::Future future = + firebase::Future future = consent_info_->RequestConsentInfoUpdate(params); EXPECT_TRUE(future == consent_info_->RequestConsentInfoUpdateLastResult()); WaitForCompletion(future, "RequestConsentInfoUpdate"); - EXPECT_NE(future.result(), nullptr); - EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); EXPECT_NE(consent_info_->GetConsentStatus(), firebase::gma::ump::kConsentStatusUnknown); EXPECT_NE(consent_info_->GetConsentFormStatus(), @@ -2518,14 +2516,13 @@ TEST_F(FirebaseGmaUmpTest, TestUmpRequestErrorWithoutTagForUnderAgeOfConsent) { ConsentRequestParameters params; // Do not call set_tag_for_under_age_of_consent(). - firebase::Future future = + firebase::Future future = consent_info_->RequestConsentInfoUpdate(params); WaitForCompletion( future, "RequestConsentInfoUpdate", firebase::gma::ump::kConsentRequestErrorTagForAgeOfConsentNotSet); - EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); EXPECT_EQ(consent_info_->GetConsentStatus(), firebase::gma::ump::kConsentStatusUnknown); } @@ -2542,13 +2539,11 @@ TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentInfoUpdateDebugEEA) { firebase::gma::ump::kConsentDebugGeographyEEA; params.set_debug_settings(debug_settings); - firebase::Future future = + firebase::Future future = consent_info_->RequestConsentInfoUpdate(params); WaitForCompletion(future, "RequestConsentInfoUpdate"); - EXPECT_NE(future.result(), nullptr); - EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); EXPECT_EQ(consent_info_->GetConsentStatus(), firebase::gma::ump::kConsentStatusRequired); } @@ -2565,13 +2560,11 @@ TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentInfoUpdateDebugNonEEA) { firebase::gma::ump::kConsentDebugGeographyNonEEA; params.set_debug_settings(debug_settings); - firebase::Future future = + firebase::Future future = consent_info_->RequestConsentInfoUpdate(params); WaitForCompletion(future, "RequestConsentInfoUpdate"); - EXPECT_NE(future.result(), nullptr); - EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); EXPECT_EQ(consent_info_->GetConsentStatus(), firebase::gma::ump::kConsentStatusNotRequired); } @@ -2589,32 +2582,21 @@ TEST_F(FirebaseGmaUmpTest, TestUmpLoadForm) { firebase::gma::ump::kConsentDebugGeographyEEA; params.set_debug_settings(debug_settings); - { - firebase::Future future = - consent_info_->RequestConsentInfoUpdate(params); - - WaitForCompletion(future, "RequestConsentInfoUpdate"); - - EXPECT_NE(future.result(), nullptr); - EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); - } + WaitForCompletion(consent_info_->RequestConsentInfoUpdate(params), + "RequestConsentInfoUpdate"); EXPECT_EQ(consent_info_->GetConsentStatus(), firebase::gma::ump::kConsentStatusRequired); - if (consent_info_->GetConsentFormStatus() == - firebase::gma::ump::kConsentFormStatusUnavailable) { - // Load the form. - firebase::Future future = - consent_info_->LoadConsentForm(); + EXPECT_EQ(consent_info_->GetConsentFormStatus(), + firebase::gma::ump::kConsentFormStatusUnavailable); - EXPECT_TRUE(future == consent_info_->LoadConsentFormLastResult()); + // Load the form. + firebase::Future future = consent_info_->LoadConsentForm(); - WaitForCompletion(future, "LoadConsentForm"); + EXPECT_TRUE(future == consent_info_->LoadConsentFormLastResult()); - EXPECT_NE(future.result(), nullptr); - EXPECT_EQ(*future.result(), consent_info_->GetConsentFormStatus()); - } + WaitForCompletion(future, "LoadConsentForm"); EXPECT_EQ(consent_info_->GetConsentFormStatus(), firebase::gma::ump::kConsentFormStatusAvailable); @@ -2635,45 +2617,26 @@ TEST_F(FirebaseGmaUmpTest, TestUmpShowForm) { firebase::gma::ump::kConsentDebugGeographyEEA; params.set_debug_settings(debug_settings); - { - firebase::Future future = - consent_info_->RequestConsentInfoUpdate(params); - - WaitForCompletion(future, "RequestConsentInfoUpdate"); - - EXPECT_NE(future.result(), nullptr); - EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); - } + WaitForCompletion(consent_info_->RequestConsentInfoUpdate(params), + "RequestConsentInfoUpdate"); EXPECT_EQ(consent_info_->GetConsentStatus(), firebase::gma::ump::kConsentStatusRequired); - if (consent_info_->GetConsentFormStatus() == - firebase::gma::ump::kConsentFormStatusUnavailable) { - // Load the form. - firebase::Future future = - consent_info_->LoadConsentForm(); - - WaitForCompletion(future, "LoadConsentForm"); + EXPECT_EQ(consent_info_->GetConsentFormStatus(), + firebase::gma::ump::kConsentFormStatusUnavailable); - EXPECT_NE(future.result(), nullptr); - EXPECT_EQ(*future.result(), consent_info_->GetConsentFormStatus()); - } + WaitForCompletion(consent_info_->LoadConsentForm(), "LoadConsentForm"); EXPECT_EQ(consent_info_->GetConsentFormStatus(), firebase::gma::ump::kConsentFormStatusAvailable); - { - firebase::Future future = - consent_info_->ShowConsentForm(nullptr); - - EXPECT_TRUE(future == consent_info_->ShowConsentFormLastResult()); + firebase::Future future = + consent_info_->ShowConsentForm(nullptr); - WaitForCompletion(future, "ShowConsentForm"); + EXPECT_TRUE(future == consent_info_->ShowConsentFormLastResult()); - EXPECT_NE(future.result(), nullptr); - EXPECT_EQ(*future.result(), consent_info_->GetConsentStatus()); - } + WaitForCompletion(future, "ShowConsentForm"); EXPECT_EQ(consent_info_->GetConsentStatus(), firebase::gma::ump::kConsentStatusObtained); @@ -2686,11 +2649,11 @@ TEST_F(FirebaseGmaUmpTest, TestUmpCleanup) { ConsentRequestParameters params; params.set_tag_for_under_age_of_consent(false); - firebase::Future future_request = + firebase::Future future_request = consent_info_->RequestConsentInfoUpdate(params); - firebase::Future future_load = + firebase::Future future_load = consent_info_->LoadConsentForm(); - firebase::Future future_show = + firebase::Future future_show = consent_info_->ShowConsentForm(nullptr); delete consent_info_; diff --git a/gma/src/common/ump/consent_info.cc b/gma/src/common/ump/consent_info.cc index 131d95e9ae..d8f6908653 100644 --- a/gma/src/common/ump/consent_info.cc +++ b/gma/src/common/ump/consent_info.cc @@ -42,6 +42,8 @@ ConsentInfo* ConsentInfo::GetInstance(const ::firebase::App& app, } #if FIREBASE_PLATFORM_ANDROID +ConsentInfo* ConsentInfo::GetInstance() { return s_instance_; } + ConsentInfo* ConsentInfo::GetInstance(JNIEnv* jni_env, jobject activity, ::firebase::InitResult* init_result_out) { #else // !FIREBASE_PLATFORM_ANDROID @@ -84,7 +86,7 @@ ConsentInfo::~ConsentInfo() { } InitResult ConsentInfo::Initialize() { - FIREBASE_ASSERT(internal_ == nullptr); + FIREBASE_ASSERT(!internal_); internal_ = internal::ConsentInfoInternal::CreateInstance(); return kInitResultSuccess; } @@ -103,34 +105,34 @@ ConsentFormStatus ConsentInfo::GetConsentFormStatus() { return internal_->GetConsentFormStatus(); } -Future ConsentInfo::RequestConsentInfoUpdate( +Future ConsentInfo::RequestConsentInfoUpdate( const ConsentRequestParameters& params) { - if (!internal_) return Future(); + if (!internal_) return Future(); return internal_->RequestConsentInfoUpdate(params); } -Future ConsentInfo::RequestConsentInfoUpdateLastResult() { - if (!internal_) return Future(); +Future ConsentInfo::RequestConsentInfoUpdateLastResult() { + if (!internal_) return Future(); return internal_->RequestConsentInfoUpdateLastResult(); } -Future ConsentInfo::LoadConsentForm() { - if (!internal_) return Future(); +Future ConsentInfo::LoadConsentForm() { + if (!internal_) return Future(); return internal_->LoadConsentForm(); } -Future ConsentInfo::LoadConsentFormLastResult() { - if (!internal_) return Future(); +Future ConsentInfo::LoadConsentFormLastResult() { + if (!internal_) return Future(); return internal_->LoadConsentFormLastResult(); } -Future ConsentInfo::ShowConsentForm(FormParent parent) { - if (!internal_) return Future(); +Future ConsentInfo::ShowConsentForm(FormParent parent) { + if (!internal_) return Future(); return internal_->ShowConsentForm(parent); } -Future ConsentInfo::ShowConsentFormLastResult() { - if (!internal_) return Future(); +Future ConsentInfo::ShowConsentFormLastResult() { + if (!internal_) return Future(); return internal_->ShowConsentFormLastResult(); } diff --git a/gma/src/common/ump/consent_info_internal.h b/gma/src/common/ump/consent_info_internal.h index edec29558d..c744f582f3 100644 --- a/gma/src/common/ump/consent_info_internal.h +++ b/gma/src/common/ump/consent_info_internal.h @@ -47,23 +47,23 @@ class ConsentInfoInternal { virtual ConsentStatus GetConsentStatus() const = 0; virtual ConsentFormStatus GetConsentFormStatus() const = 0; - virtual Future RequestConsentInfoUpdate( + virtual Future RequestConsentInfoUpdate( const ConsentRequestParameters& params) = 0; - Future RequestConsentInfoUpdateLastResult() { - return static_cast&>( + Future RequestConsentInfoUpdateLastResult() { + return static_cast&>( futures()->LastResult(kConsentInfoFnRequestConsentInfoUpdate)); } - virtual Future LoadConsentForm() = 0; + virtual Future LoadConsentForm() = 0; - Future LoadConsentFormLastResult() { - return static_cast&>( + Future LoadConsentFormLastResult() { + return static_cast&>( futures()->LastResult(kConsentInfoFnLoadConsentForm)); } - virtual Future ShowConsentForm(FormParent parent) = 0; + virtual Future ShowConsentForm(FormParent parent) = 0; - Future ShowConsentFormLastResult() { - return static_cast&>( + Future ShowConsentFormLastResult() { + return static_cast&>( futures()->LastResult(kConsentInfoFnShowConsentForm)); } @@ -72,40 +72,23 @@ class ConsentInfoInternal { protected: ConsentInfoInternal(); - template - SafeFutureHandle CreateFuture() { - return futures()->SafeAlloc(); - } - template - SafeFutureHandle CreateFuture(ConsentInfoFn fn_idx) { - return futures()->SafeAlloc(fn_idx); - } - - // With result and automatically generated error message. - template - void CompleteFuture(SafeFutureHandle handle, ConsentRequestError error, - T& result) { - return futures()->CompleteWithResult( - handle, error, GetConsentRequestErrorMessage(error), result); - } - template - void CompleteFuture(SafeFutureHandle handle, ConsentFormError error, - T& result) { - return futures()->CompleteWithResult( - handle, error, GetConsentFormErrorMessage(error), result); + SafeFutureHandle CreateFuture() { return futures()->SafeAlloc(); } + SafeFutureHandle CreateFuture(ConsentInfoFn fn_idx) { + return futures()->SafeAlloc(fn_idx); } - // No result data, just an error code. - template - void CompleteFuture(SafeFutureHandle handle, ConsentRequestError error) { - return futures()->Complete(handle, error, - GetConsentRequestErrorMessage(error)); + // Complete a Future with the given error code. + void CompleteFuture(SafeFutureHandle handle, ConsentRequestError error, + const char* message = nullptr) { + return futures()->Complete( + handle, error, + message ? message : GetConsentRequestErrorMessage(error)); } - // No result data, just an error code. - template - void CompleteFuture(SafeFutureHandle handle, ConsentFormError error) { - return futures()->Complete(handle, error, - GetConsentFormErrorMessage(error)); + // Complete the future with the given error code. + void CompleteFuture(SafeFutureHandle handle, ConsentFormError error, + const char* message = nullptr) { + return futures()->Complete( + handle, error, message ? message : GetConsentFormErrorMessage(error)); } ReferenceCountedFutureImpl* futures() { return &futures_; } diff --git a/gma/src/include/firebase/gma/ump/consent_info.h b/gma/src/include/firebase/gma/ump/consent_info.h index d1f1a887bb..c894154be9 100644 --- a/gma/src/include/firebase/gma/ump/consent_info.h +++ b/gma/src/include/firebase/gma/ump/consent_info.h @@ -87,6 +87,14 @@ class ConsentInfo { /// pointer and the UMP SDK will shut down. static ConsentInfo* GetInstance(JNIEnv* jni_env, jobject activity, InitResult* init_result_out = nullptr); + +#if !defined(DOXYGEN) + // On Android, this convenience function exists so you can easily get the + // existing ConsentInfo instance after it's first initialized. Returns nullptr + // if no instance has been created yet; make sure you have called + // GetInstance(JNIEnv*, jobject) first. + static ConsentInfo* GetInstance(); +#endif // defined(DOXYGEN) #endif // FIREBASE_PLATFORM_ANDROID || defined(DOXYGEN) #if !FIREBASE_PLATFORM_ANDROID || defined(DOXYGEN) @@ -104,37 +112,36 @@ class ConsentInfo { static ConsentInfo* GetInstance(InitResult* init_result_out = nullptr); #endif // !defined(__ANDROID__) || defined(DOXYGEN) - /// Requests consent information update. Must be called before loading a - /// consent form. - Future RequestConsentInfoUpdate( - const ConsentRequestParameters& params); - - /// Get the Future from the most recent call to RequestConsentInfoUpdate(). - Future RequestConsentInfoUpdateLastResult(); - /// The user’s consent status. This value is cached between app sessions and /// can be read before calling RequestConsentInfoUpdate(). ConsentStatus GetConsentStatus(); + /// Requests consent information update. Must be called before loading a + /// consent form. If successful, GetConsentStatus() will be updated. + Future RequestConsentInfoUpdate(const ConsentRequestParameters& params); + + /// Get the Future from the most recent call to RequestConsentInfoUpdate(). + Future RequestConsentInfoUpdateLastResult(); + /// Consent form status. This value defaults to kConsentFormStatusUnknown and /// requires a call to RequestConsentInfoUpdate() to update. ConsentFormStatus GetConsentFormStatus(); - /// Loads a consent form. - Future LoadConsentForm(); + /// Loads a consent form. If successful, GetConsentFormStatus() will be + /// updated. + Future LoadConsentForm(); /// Get the Future from the most recent call to LoadConsentForm(). - Future LoadConsentFormLastResult(); + Future LoadConsentFormLastResult(); /// Presents the full screen consent form using the given FormParent, which is /// defined as an Activity on Android and a UIViewController on iOS. The form /// will be dismissed and the Future will be completed after the user selects - /// an option. GetConsentStatus() is updated prior to the Future being - /// completed. - Future ShowConsentForm(FormParent parent); + /// an option. GetConsentStatus() is updated when the Future is completed. + Future ShowConsentForm(FormParent parent); /// Get the Future from the most recent call to ShowConsentForm(). - Future ShowConsentFormLastResult(); + Future ShowConsentFormLastResult(); /// Clears all consent state from persistent storage. This can be used in /// development to simulate a new installation. diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index 3d9cc61313..8a827190c2 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -35,15 +35,14 @@ ConsentInfoInternalStub::ConsentInfoInternalStub() ConsentInfoInternalStub::~ConsentInfoInternalStub() {} -Future ConsentInfoInternalStub::RequestConsentInfoUpdate( +Future ConsentInfoInternalStub::RequestConsentInfoUpdate( const ConsentRequestParameters& params) { - SafeFutureHandle handle = - CreateFuture(kConsentInfoFnRequestConsentInfoUpdate); + SafeFutureHandle handle = + CreateFuture(kConsentInfoFnRequestConsentInfoUpdate); if (!params.has_tag_for_under_age_of_consent()) { - CompleteFuture( - handle, kConsentRequestErrorTagForAgeOfConsentNotSet, consent_status_); - return MakeFuture(futures(), handle); + CompleteFuture(handle, kConsentRequestErrorTagForAgeOfConsentNotSet); + return MakeFuture(futures(), handle); } ConsentStatus new_consent_status = kConsentStatusObtained; @@ -58,30 +57,25 @@ Future ConsentInfoInternalStub::RequestConsentInfoUpdate( consent_status_ = new_consent_status; consent_form_status_ = kConsentFormStatusUnavailable; - CompleteFuture(handle, kConsentRequestSuccess, - consent_status_); - return MakeFuture(futures(), handle); + CompleteFuture(handle, kConsentRequestSuccess); + return MakeFuture(futures(), handle); } -Future ConsentInfoInternalStub::LoadConsentForm() { - SafeFutureHandle handle = - CreateFuture(kConsentInfoFnLoadConsentForm); +Future ConsentInfoInternalStub::LoadConsentForm() { + SafeFutureHandle handle = CreateFuture(kConsentInfoFnLoadConsentForm); consent_form_status_ = kConsentFormStatusAvailable; - CompleteFuture(handle, kConsentFormSuccess, - consent_form_status_); - return MakeFuture(futures(), handle); + CompleteFuture(handle, kConsentFormSuccess); + return MakeFuture(futures(), handle); } -Future ConsentInfoInternalStub::ShowConsentForm( - FormParent parent) { - SafeFutureHandle handle = - CreateFuture(kConsentInfoFnShowConsentForm); +Future ConsentInfoInternalStub::ShowConsentForm(FormParent parent) { + SafeFutureHandle handle = + CreateFuture(kConsentInfoFnShowConsentForm); consent_status_ = kConsentStatusObtained; - CompleteFuture(handle, kConsentRequestSuccess, - consent_status_); - return MakeFuture(futures(), handle); + CompleteFuture(handle, kConsentRequestSuccess); + return MakeFuture(futures(), handle); } void ConsentInfoInternalStub::Reset() { diff --git a/gma/src/stub/ump/consent_info_internal_stub.h b/gma/src/stub/ump/consent_info_internal_stub.h index f68260ac76..1ddabc01ba 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.h +++ b/gma/src/stub/ump/consent_info_internal_stub.h @@ -34,10 +34,10 @@ class ConsentInfoInternalStub : public ConsentInfoInternal { return consent_form_status_; } - Future RequestConsentInfoUpdate( + Future RequestConsentInfoUpdate( const ConsentRequestParameters& params) override; - Future LoadConsentForm() override; - Future ShowConsentForm(FormParent parent) override; + Future LoadConsentForm() override; + Future ShowConsentForm(FormParent parent) override; void Reset() override; From 8242fed8b0c416ac7ea129ff658054453d02dbcd Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 20 Jul 2023 12:45:25 -0700 Subject: [PATCH 37/50] Add a test to ensure that GetInstance() always returns the same instance. --- gma/integration_test/src/integration_test.cc | 37 ++++++++++++++++--- .../stub/ump/consent_info_internal_stub.cc | 3 +- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/gma/integration_test/src/integration_test.cc b/gma/integration_test/src/integration_test.cc index 891f97465c..052f9958be 100644 --- a/gma/integration_test/src/integration_test.cc +++ b/gma/integration_test/src/integration_test.cc @@ -2489,6 +2489,34 @@ TEST_F(FirebaseGmaUmpTest, TestUmpInitialization) { // Terminate handled automatically in test teardown. } +// Tests for User Messaging Platform +TEST_F(FirebaseGmaUmpTest, TestUmpGetInstanceIsAlwaysEqual) { + using firebase::gma::ump::ConsentInfo; + + EXPECT_NE(consent_info_, nullptr); + + // Ensure that GetInstance() with any options is always equal. + EXPECT_EQ(consent_info_, ConsentInfo::GetInstance()); + EXPECT_EQ(consent_info_, ConsentInfo::GetInstance(*shared_app_)); + +#if defined(ANDROID) + EXPECT_EQ(consent_info_, + ConsentInfo::GetInstance(app_framework::GetJniEnv(), + app_framework::GetActivity())); + + firebase::App* second_app = firebase::App::Create( + firebase::AppOptions(), "2ndApp", app_framework::GetJniEnv(), + app_framework::GetActivity()); +#else + firebase::App* second_app = + firebase::App::Create(firebase::AppOptions(), "2ndApp"); +#endif // defined(ANDROID) + + EXPECT_EQ(consent_info_, ConsentInfo::GetInstance(*second_app)); + + delete second_app; +} + TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentInfoUpdate) { using firebase::gma::ump::ConsentRequestParameters; using firebase::gma::ump::ConsentStatus; @@ -2631,8 +2659,7 @@ TEST_F(FirebaseGmaUmpTest, TestUmpShowForm) { EXPECT_EQ(consent_info_->GetConsentFormStatus(), firebase::gma::ump::kConsentFormStatusAvailable); - firebase::Future future = - consent_info_->ShowConsentForm(nullptr); + firebase::Future future = consent_info_->ShowConsentForm(nullptr); EXPECT_TRUE(future == consent_info_->ShowConsentFormLastResult()); @@ -2651,10 +2678,8 @@ TEST_F(FirebaseGmaUmpTest, TestUmpCleanup) { params.set_tag_for_under_age_of_consent(false); firebase::Future future_request = consent_info_->RequestConsentInfoUpdate(params); - firebase::Future future_load = - consent_info_->LoadConsentForm(); - firebase::Future future_show = - consent_info_->ShowConsentForm(nullptr); + firebase::Future future_load = consent_info_->LoadConsentForm(); + firebase::Future future_show = consent_info_->ShowConsentForm(nullptr); delete consent_info_; consent_info_ = nullptr; diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index 8a827190c2..ffc19de44f 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -70,8 +70,7 @@ Future ConsentInfoInternalStub::LoadConsentForm() { } Future ConsentInfoInternalStub::ShowConsentForm(FormParent parent) { - SafeFutureHandle handle = - CreateFuture(kConsentInfoFnShowConsentForm); + SafeFutureHandle handle = CreateFuture(kConsentInfoFnShowConsentForm); consent_status_ = kConsentStatusObtained; CompleteFuture(handle, kConsentRequestSuccess); From 2be2571beb28d44e51ee362692cce1fcde24088a Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 25 Jul 2023 13:50:36 -0700 Subject: [PATCH 38/50] Change params to a struct. Add ConsentFormErrorUnavailable and remove some other enum entries. --- gma/integration_test/src/integration_test.cc | 110 +++++++++--------- gma/src/common/ump/ump_common.cc | 12 +- gma/src/include/firebase/gma/ump/types.h | 65 ++--------- .../stub/ump/consent_info_internal_stub.cc | 34 +++--- gma/src/stub/ump/consent_info_internal_stub.h | 1 + 5 files changed, 94 insertions(+), 128 deletions(-) diff --git a/gma/integration_test/src/integration_test.cc b/gma/integration_test/src/integration_test.cc index 4e4d3ac6b6..9cd03e8fbf 100644 --- a/gma/integration_test/src/integration_test.cc +++ b/gma/integration_test/src/integration_test.cc @@ -2489,6 +2489,17 @@ TEST_F(FirebaseGmaUmpTest, TestUmpInitialization) { // Terminate handled automatically in test teardown. } +// Tests for User Messaging Platform +TEST_F(FirebaseGmaUmpTest, TestUmpDefaultsToUnknownStatus) { + EXPECT_EQ(consent_info_->GetConsentStatus(), + firebase::gma::ump::kConsentStatusUnknown); + EXPECT_EQ(consent_info_->GetConsentFormStatus(), + firebase::gma::ump::kConsentFormStatusUnknown); + EXPECT_EQ(consent_info_->GetPrivacyOptionsRequirementStatus(), + firebase::gma::ump::kPrivacyOptionsRequirementStatusUnknown); + EXPECT_FALSE(consent_info_->CanRequestAds()); +} + // Tests for User Messaging Platform TEST_F(FirebaseGmaUmpTest, TestUmpGetInstanceIsAlwaysEqual) { using firebase::gma::ump::ConsentInfo; @@ -2522,7 +2533,7 @@ TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentInfoUpdate) { using firebase::gma::ump::ConsentStatus; ConsentRequestParameters params; - params.set_tag_for_under_age_of_consent(false); + params.tag_for_under_age_of_consent = false; firebase::Future future = consent_info_->RequestConsentInfoUpdate(params); @@ -2537,35 +2548,15 @@ TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentInfoUpdate) { firebase::gma::ump::kConsentFormStatusUnknown); } -TEST_F(FirebaseGmaUmpTest, TestUmpRequestErrorWithoutTagForUnderAgeOfConsent) { - using firebase::gma::ump::ConsentRequestParameters; - using firebase::gma::ump::ConsentStatus; - - ConsentRequestParameters params; - // Do not call set_tag_for_under_age_of_consent(). - - firebase::Future future = - consent_info_->RequestConsentInfoUpdate(params); - - WaitForCompletion( - future, "RequestConsentInfoUpdate", - firebase::gma::ump::kConsentRequestErrorTagForAgeOfConsentNotSet); - - EXPECT_EQ(consent_info_->GetConsentStatus(), - firebase::gma::ump::kConsentStatusUnknown); -} - TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentInfoUpdateDebugEEA) { using firebase::gma::ump::ConsentDebugSettings; using firebase::gma::ump::ConsentRequestParameters; using firebase::gma::ump::ConsentStatus; ConsentRequestParameters params; - params.set_tag_for_under_age_of_consent(false); - ConsentDebugSettings debug_settings; - debug_settings.debug_geography = + params.tag_for_under_age_of_consent = false; + params.debug_settings.debug_geography = firebase::gma::ump::kConsentDebugGeographyEEA; - params.set_debug_settings(debug_settings); firebase::Future future = consent_info_->RequestConsentInfoUpdate(params); @@ -2582,11 +2573,9 @@ TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentInfoUpdateDebugNonEEA) { using firebase::gma::ump::ConsentStatus; ConsentRequestParameters params; - params.set_tag_for_under_age_of_consent(false); - ConsentDebugSettings debug_settings; - debug_settings.debug_geography = + params.tag_for_under_age_of_consent = false; + params.debug_settings.debug_geography = firebase::gma::ump::kConsentDebugGeographyNonEEA; - params.set_debug_settings(debug_settings); firebase::Future future = consent_info_->RequestConsentInfoUpdate(params); @@ -2604,11 +2593,9 @@ TEST_F(FirebaseGmaUmpTest, TestUmpLoadForm) { using firebase::gma::ump::ConsentStatus; ConsentRequestParameters params; - params.set_tag_for_under_age_of_consent(false); - ConsentDebugSettings debug_settings; - debug_settings.debug_geography = + params.tag_for_under_age_of_consent = false; + params.debug_settings.debug_geography = firebase::gma::ump::kConsentDebugGeographyEEA; - params.set_debug_settings(debug_settings); WaitForCompletion(consent_info_->RequestConsentInfoUpdate(params), "RequestConsentInfoUpdate"); @@ -2639,11 +2626,9 @@ TEST_F(FirebaseGmaUmpTest, TestUmpShowForm) { using firebase::gma::ump::ConsentStatus; ConsentRequestParameters params; - params.set_tag_for_under_age_of_consent(false); - ConsentDebugSettings debug_settings; - debug_settings.debug_geography = + params.tag_for_under_age_of_consent = false; + params.debug_settings.debug_geography = firebase::gma::ump::kConsentDebugGeographyEEA; - params.set_debug_settings(debug_settings); WaitForCompletion(consent_info_->RequestConsentInfoUpdate(params), "RequestConsentInfoUpdate"); @@ -2669,6 +2654,35 @@ TEST_F(FirebaseGmaUmpTest, TestUmpShowForm) { firebase::gma::ump::kConsentStatusObtained); } +TEST_F(FirebaseGmaUmpTest, TestUmpLoadFormUnavailableDueUnderAgeOfConsent) { + TEST_REQUIRES_USER_INTERACTION; + + using firebase::gma::ump::ConsentDebugSettings; + using firebase::gma::ump::ConsentFormStatus; + using firebase::gma::ump::ConsentRequestParameters; + using firebase::gma::ump::ConsentStatus; + + ConsentRequestParameters params; + params.tag_for_under_age_of_consent = true; + params.debug_settings.debug_geography = + firebase::gma::ump::kConsentDebugGeographyEEA; + + WaitForCompletion(consent_info_->RequestConsentInfoUpdate(params), + "RequestConsentInfoUpdate"); + + EXPECT_EQ(consent_info_->GetConsentStatus(), + firebase::gma::ump::kConsentStatusRequired); + + EXPECT_EQ(consent_info_->GetConsentFormStatus(), + firebase::gma::ump::kConsentFormStatusUnavailable); + + WaitForCompletion(consent_info_->LoadConsentForm(), "LoadConsentForm", + firebase::gma::ump::kConsentFormErrorUnavailable); + + EXPECT_EQ(consent_info_->GetConsentFormStatus(), + firebase::gma::ump::kConsentFormStatusUnavailable); +} + TEST_F(FirebaseGmaUmpTest, TestUmpLoadAndShowIfRequired) { using firebase::gma::ump::ConsentDebugSettings; using firebase::gma::ump::ConsentRequestParameters; @@ -2677,11 +2691,9 @@ TEST_F(FirebaseGmaUmpTest, TestUmpLoadAndShowIfRequired) { TEST_REQUIRES_USER_INTERACTION; ConsentRequestParameters params; - params.set_tag_for_under_age_of_consent(false); - ConsentDebugSettings debug_settings; - debug_settings.debug_geography = + params.tag_for_under_age_of_consent = false; + params.debug_settings.debug_geography = firebase::gma::ump::kConsentDebugGeographyEEA; - params.set_debug_settings(debug_settings); WaitForCompletion(consent_info_->RequestConsentInfoUpdate(params), "RequestConsentInfoUpdate"); @@ -2710,11 +2722,9 @@ TEST_F(FirebaseGmaUmpTest, TestUmpPrivacyOptions) { TEST_REQUIRES_USER_INTERACTION; ConsentRequestParameters params; - params.set_tag_for_under_age_of_consent(true); - ConsentDebugSettings debug_settings; - debug_settings.debug_geography = + params.tag_for_under_age_of_consent = false; + params.debug_settings.debug_geography = firebase::gma::ump::kConsentDebugGeographyEEA; - params.set_debug_settings(debug_settings); WaitForCompletion(consent_info_->RequestConsentInfoUpdate(params), "RequestConsentInfoUpdate"); @@ -2756,11 +2766,9 @@ TEST_F(FirebaseGmaUmpTest, TestCanRequestAdsNonEEA) { TEST_REQUIRES_USER_INTERACTION; ConsentRequestParameters params; - params.set_tag_for_under_age_of_consent(false); - ConsentDebugSettings debug_settings; - debug_settings.debug_geography = + params.tag_for_under_age_of_consent = false; + params.debug_settings.debug_geography = firebase::gma::ump::kConsentDebugGeographyNonEEA; - params.set_debug_settings(debug_settings); WaitForCompletion(consent_info_->RequestConsentInfoUpdate(params), "RequestConsentInfoUpdate"); @@ -2779,11 +2787,9 @@ TEST_F(FirebaseGmaUmpTest, TestCanRequestAdsEEA) { TEST_REQUIRES_USER_INTERACTION; ConsentRequestParameters params; - params.set_tag_for_under_age_of_consent(false); - ConsentDebugSettings debug_settings; - debug_settings.debug_geography = + params.tag_for_under_age_of_consent = false; + params.debug_settings.debug_geography = firebase::gma::ump::kConsentDebugGeographyEEA; - params.set_debug_settings(debug_settings); WaitForCompletion(consent_info_->RequestConsentInfoUpdate(params), "RequestConsentInfoUpdate"); @@ -2800,7 +2806,7 @@ TEST_F(FirebaseGmaUmpTest, TestUmpCleanup) { using firebase::gma::ump::ConsentStatus; ConsentRequestParameters params; - params.set_tag_for_under_age_of_consent(false); + params.tag_for_under_age_of_consent = false; firebase::Future future_request = consent_info_->RequestConsentInfoUpdate(params); firebase::Future future_load = consent_info_->LoadConsentForm(); diff --git a/gma/src/common/ump/ump_common.cc b/gma/src/common/ump/ump_common.cc index cf5780b288..b9d695d2d1 100644 --- a/gma/src/common/ump/ump_common.cc +++ b/gma/src/common/ump/ump_common.cc @@ -35,16 +35,14 @@ const char* GetConsentRequestErrorMessage(ConsentRequestError error_code) { #endif case kConsentRequestErrorNetwork: return "Network error"; - case kConsentRequestErrorTagForAgeOfConsentNotSet: - return "You must explicitly call " - "ConsentRequestParameters.set_tag_for_under_age_of_consent() " - "before calling RequestConsentInfoUpdate()"; case kConsentRequestErrorInternal: return "Internal error"; case kConsentRequestErrorCodeMisconfiguration: return "Code misconfiguration error"; case kConsentRequestErrorUnknown: return "Unknown error"; + case kConsentRequestErrorInvalidOperation: + return "Invalid operation. Please try again.."; case kConsentRequestErrorOperationInProgress: return "Operation already in progress. Please wait for it to finish by " "checking RequestConsentInfoUpdateLastResult()."; @@ -59,8 +57,8 @@ const char* GetConsentFormErrorMessage(ConsentFormError error_code) { return "Success"; case kConsentFormErrorTimeout: return "Timed out"; - case kConsentFormErrorNotLoaded: - return "Form not loaded"; + case kConsentFormErrorUnavailable: + return "The form is unavailable."; case kConsentFormErrorInternal: return "Internal error"; case kConsentFormErrorUnknown: @@ -69,8 +67,6 @@ const char* GetConsentFormErrorMessage(ConsentFormError error_code) { return "Code already used"; case kConsentFormErrorInvalidOperation: return "Invalid operation"; - case kConsentFormErrorNetwork: - return "Network error"; case kConsentFormErrorOperationInProgress: return "Operation already in progress. Please wait for it to finish by " "checking LoadFormLastResult() or ShowFormLastResult()."; diff --git a/gma/src/include/firebase/gma/ump/types.h b/gma/src/include/firebase/gma/ump/types.h index 0d73b46434..c2b59bce46 100644 --- a/gma/src/include/firebase/gma/ump/types.h +++ b/gma/src/include/firebase/gma/ump/types.h @@ -60,52 +60,12 @@ struct ConsentDebugSettings { std::vector debug_device_ids; }; -/// Parameters for the `ConsentInfo::RequestConsentInfoUpdate()` operation. You -/// must explicitly set the age of consent tag (to true or false) or the -/// operation will fail. -class ConsentRequestParameters { - public: - ConsentRequestParameters() - : has_debug_settings_(false), - tag_for_under_age_of_consent_(false), - has_tag_for_under_age_of_consent_(false) {} - /// Set the age of consent tag. This indicates whether the user is tagged for - /// under age of consent. This is a required setting. - void set_tag_for_under_age_of_consent(bool tag) { - tag_for_under_age_of_consent_ = tag; - has_tag_for_under_age_of_consent_ = true; - } - /// Get the age of consent tag. This indicates whether the user is tagged for - /// under age of consent. - bool tag_for_under_age_of_consent() const { - return tag_for_under_age_of_consent_; - } - /// Get whether the age of consent tag was previously set. - bool has_tag_for_under_age_of_consent() const { - return has_tag_for_under_age_of_consent_; - } - - /// Set the debug settings. - void set_debug_settings(const ConsentDebugSettings& settings) { - debug_settings_ = settings; - has_debug_settings_ = true; - } - /// Set the debug settings without copying data, which could be useful if you - /// have a large list of debug device IDs. - void set_debug_settings(const ConsentDebugSettings&& settings) { - debug_settings_ = std::move(settings); - has_debug_settings_ = true; - } - /// Get the debug settings. - const ConsentDebugSettings& debug_settings() const { return debug_settings_; } - /// Get whether debug settings were set. - bool has_debug_settings() const { return has_debug_settings_; } - - private: - ConsentDebugSettings debug_settings_; - bool tag_for_under_age_of_consent_; - bool has_debug_settings_; - bool has_tag_for_under_age_of_consent_; +/// Parameters for the `ConsentInfo::RequestConsentInfoUpdate()` operation. +struct ConsentRequestParameters { + ConsentRequestParameters() : tag_for_under_age_of_consent(false) {} + + ConsentDebugSettings debug_settings; + bool tag_for_under_age_of_consent; }; /// This is a platform specific datatype that is required to show a consent form @@ -148,16 +108,14 @@ enum ConsentRequestError { kConsentRequestErrorInvalidAppId, /// A network error occurred. kConsentRequestErrorNetwork, - /// The tag for age of consent was not set. You must call - /// `ConsentRequestParameters::set_tag_for_under_age_of_consent()` before the - /// request. - kConsentRequestErrorTagForAgeOfConsentNotSet, /// An internal error occurred. kConsentRequestErrorInternal, /// This error is undocumented. kConsentRequestErrorCodeMisconfiguration, /// An unknown error occurred. kConsentRequestErrorUnknown, + /// An invalid operation occurred. Try again. + kConsentRequestErrorInvalidOperation, /// The operation is already in progress. Use /// `ConsentInfo::RequestConsentInfoUpdateLastResult()` /// to get the status. @@ -180,22 +138,21 @@ enum ConsentFormStatus { /// Errors when loading or showing the consent form. enum ConsentFormError { + /// The operation succeeded. kConsentFormSuccess = 0, /// The load request timed out. Try again. kConsentFormErrorTimeout, - /// Failed to show the consent form because it has not been loaded. - kConsentFormErrorNotLoaded, /// An internal error occurred. kConsentFormErrorInternal, /// An unknown error occurred. kConsentFormErrorUnknown, + /// The form is unavailable. + kConsentFormErrorUnavailable, /// This form was already used. kConsentFormErrorCodeAlreadyUsed, /// An invalid operation occurred. Try again. kConsentFormErrorInvalidOperation, - /// General network issues occurred. Try again. - kConsentFormErrorNetwork, /// The operation is already in progress. Call /// `ConsentInfo::LoadConsentFormLastResult()` or /// `ConsentInfo::ShowConsentFormLastResult()` to get the status. diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index 39b70c0926..06a8e4ce0e 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -42,26 +42,21 @@ Future ConsentInfoInternalStub::RequestConsentInfoUpdate( SafeFutureHandle handle = CreateFuture(kConsentInfoFnRequestConsentInfoUpdate); - if (!params.has_tag_for_under_age_of_consent()) { - CompleteFuture(handle, kConsentRequestErrorTagForAgeOfConsentNotSet); - return MakeFuture(futures(), handle); - } - ConsentStatus new_consent_status = kConsentStatusObtained; // Simulate consent status based on debug geo. - if (params.has_debug_settings()) { - if (params.debug_settings().debug_geography == kConsentDebugGeographyEEA) { - new_consent_status = kConsentStatusRequired; - } else if (params.debug_settings().debug_geography == - kConsentDebugGeographyNonEEA) { - new_consent_status = kConsentStatusNotRequired; - } + if (params.debug_settings.debug_geography == kConsentDebugGeographyEEA) { + new_consent_status = kConsentStatusRequired; + } else if (params.debug_settings.debug_geography == + kConsentDebugGeographyNonEEA) { + new_consent_status = kConsentStatusNotRequired; } + consent_status_ = new_consent_status; consent_form_status_ = kConsentFormStatusUnavailable; + under_age_of_consent_ = params.tag_for_under_age_of_consent; - // Simulate privacy options based on under age of consent. - if (params.tag_for_under_age_of_consent()) { + // Simulate privacy options based on geo. + if (params.debug_settings.debug_geography == kConsentDebugGeographyEEA) { privacy_options_requirement_status_ = kPrivacyOptionsRequirementStatusRequired; } else { @@ -76,6 +71,11 @@ Future ConsentInfoInternalStub::RequestConsentInfoUpdate( Future ConsentInfoInternalStub::LoadConsentForm() { SafeFutureHandle handle = CreateFuture(kConsentInfoFnLoadConsentForm); + if (under_age_of_consent_) { + consent_form_status_ = kConsentFormStatusUnavailable; + CompleteFuture(handle, kConsentFormErrorUnavailable); + return MakeFuture(futures(), handle); + } consent_form_status_ = kConsentFormStatusAvailable; CompleteFuture(handle, kConsentFormSuccess); return MakeFuture(futures(), handle); @@ -94,6 +94,12 @@ Future ConsentInfoInternalStub::LoadAndShowConsentFormIfRequired( SafeFutureHandle handle = CreateFuture(kConsentInfoFnLoadAndShowConsentFormIfRequired); + if (under_age_of_consent_) { + consent_form_status_ = kConsentFormStatusUnavailable; + CompleteFuture(handle, kConsentFormErrorUnavailable); + return MakeFuture(futures(), handle); + } + if (consent_status_ == kConsentStatusRequired) { consent_status_ = kConsentStatusObtained; } diff --git a/gma/src/stub/ump/consent_info_internal_stub.h b/gma/src/stub/ump/consent_info_internal_stub.h index a50297ded2..68d94fbb6f 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.h +++ b/gma/src/stub/ump/consent_info_internal_stub.h @@ -52,6 +52,7 @@ class ConsentInfoInternalStub : public ConsentInfoInternal { ConsentStatus consent_status_; ConsentFormStatus consent_form_status_; PrivacyOptionsRequirementStatus privacy_options_requirement_status_; + bool under_age_of_consent_; }; } // namespace internal From 8a320b4e159fd38f6b2dec118614759cc4438905 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 25 Jul 2023 14:00:36 -0700 Subject: [PATCH 39/50] Document the workflow that the stub simulates. --- gma/src/stub/ump/consent_info_internal_stub.cc | 13 ++++++++----- gma/src/stub/ump/consent_info_internal_stub.h | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index 06a8e4ce0e..d9eaee28a7 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -33,7 +33,8 @@ ConsentInfoInternalStub::ConsentInfoInternalStub() : consent_status_(kConsentStatusUnknown), consent_form_status_(kConsentFormStatusUnknown), privacy_options_requirement_status_( - kPrivacyOptionsRequirementStatusUnknown) {} + kPrivacyOptionsRequirementStatusUnknown), + under_age_of_consent_(false) {} ConsentInfoInternalStub::~ConsentInfoInternalStub() {} @@ -42,7 +43,10 @@ Future ConsentInfoInternalStub::RequestConsentInfoUpdate( SafeFutureHandle handle = CreateFuture(kConsentInfoFnRequestConsentInfoUpdate); + // See the header file for an explanation of these default settings. ConsentStatus new_consent_status = kConsentStatusObtained; + PrivacyOptionsRequirementStatus new_privacy_req = + kPrivacyOptionsRequirementStatusNotRequired; // Simulate consent status based on debug geo. if (params.debug_settings.debug_geography == kConsentDebugGeographyEEA) { new_consent_status = kConsentStatusRequired; @@ -57,12 +61,11 @@ Future ConsentInfoInternalStub::RequestConsentInfoUpdate( // Simulate privacy options based on geo. if (params.debug_settings.debug_geography == kConsentDebugGeographyEEA) { - privacy_options_requirement_status_ = - kPrivacyOptionsRequirementStatusRequired; + new_privacy_req = kPrivacyOptionsRequirementStatusRequired; } else { - privacy_options_requirement_status_ = - kPrivacyOptionsRequirementStatusNotRequired; + new_privacy_req = kPrivacyOptionsRequirementStatusNotRequired; } + privacy_options_requirement_status_ = new_privacy_req; CompleteFuture(handle, kConsentRequestSuccess); return MakeFuture(futures(), handle); diff --git a/gma/src/stub/ump/consent_info_internal_stub.h b/gma/src/stub/ump/consent_info_internal_stub.h index 68d94fbb6f..5e41cf85bf 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.h +++ b/gma/src/stub/ump/consent_info_internal_stub.h @@ -24,6 +24,24 @@ namespace gma { namespace ump { namespace internal { +// The stub interface implements a few specific workflows, for testing: +// +// Before requesting: consent and privacy options will be Unknown. +// +// If debug_geography == EEA, consent will be Required and will change to +// Obtained once the consent form is "shown". Privacy options will be Required, +// and when the privacy options form is shown, consent will go back to Required. +// +// If debug_geography == NotEEA, consent will be NotRequired. No privacy options +// form is required. +// +// If debug_geography == Disabled, consent will be Obtained and privacy options +// will be NotRequired. +// +// If tag_for_under_age_of_consent = true, LoadConsentForm and +// LoadAndShowConsentFormIfRequired will fail with kConsentFormErrorUnavailable. +// +// CanRequestAds returns true if consent is NotRequired or Obtained. class ConsentInfoInternalStub : public ConsentInfoInternal { public: ConsentInfoInternalStub(); From c712a0de3581bf7dab9ff63358766a826db0edde Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 25 Jul 2023 14:06:17 -0700 Subject: [PATCH 40/50] Clean up stub workflow for privacy options. --- .../stub/ump/consent_info_internal_stub.cc | 38 ++++++++++++++----- gma/src/stub/ump/consent_info_internal_stub.h | 15 +++++--- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index d9eaee28a7..b757f52a7a 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -34,7 +34,8 @@ ConsentInfoInternalStub::ConsentInfoInternalStub() consent_form_status_(kConsentFormStatusUnknown), privacy_options_requirement_status_( kPrivacyOptionsRequirementStatusUnknown), - under_age_of_consent_(false) {} + under_age_of_consent_(false), + debug_geo_(kConsentDebugGeographyDisabled) {} ConsentInfoInternalStub::~ConsentInfoInternalStub() {} @@ -58,14 +59,9 @@ Future ConsentInfoInternalStub::RequestConsentInfoUpdate( consent_status_ = new_consent_status; consent_form_status_ = kConsentFormStatusUnavailable; under_age_of_consent_ = params.tag_for_under_age_of_consent; - - // Simulate privacy options based on geo. - if (params.debug_settings.debug_geography == kConsentDebugGeographyEEA) { - new_privacy_req = kPrivacyOptionsRequirementStatusRequired; - } else { - new_privacy_req = kPrivacyOptionsRequirementStatusNotRequired; - } - privacy_options_requirement_status_ = new_privacy_req; + debug_geo_ = params.debug_settings.debug_geography; + privacy_options_requirement_status_ = + kPrivacyOptionsRequirementStatusNotRequired; CompleteFuture(handle, kConsentRequestSuccess); return MakeFuture(futures(), handle); @@ -88,6 +84,18 @@ Future ConsentInfoInternalStub::ShowConsentForm(FormParent parent) { SafeFutureHandle handle = CreateFuture(kConsentInfoFnShowConsentForm); consent_status_ = kConsentStatusObtained; + + if (debug_geo_ == kConsentDebugGeographyEEA) { + privacy_options_requirement_status_ = + kPrivacyOptionsRequirementStatusRequired; + } else if (debug_geo_ == kConsentDebugGeographyNonEEA) { + privacy_options_requirement_status_ = + kPrivacyOptionsRequirementStatusNotRequired; + } else { // no debug option + privacy_options_requirement_status_ = + kPrivacyOptionsRequirementStatusNotRequired; + } + CompleteFuture(handle, kConsentRequestSuccess); return MakeFuture(futures(), handle); } @@ -105,6 +113,16 @@ Future ConsentInfoInternalStub::LoadAndShowConsentFormIfRequired( if (consent_status_ == kConsentStatusRequired) { consent_status_ = kConsentStatusObtained; + if (debug_geo_ == kConsentDebugGeographyEEA) { + privacy_options_requirement_status_ = + kPrivacyOptionsRequirementStatusRequired; + } else if (debug_geo_ == kConsentDebugGeographyNonEEA) { + privacy_options_requirement_status_ = + kPrivacyOptionsRequirementStatusNotRequired; + } else { // no debug option + privacy_options_requirement_status_ = + kPrivacyOptionsRequirementStatusNotRequired; + } } CompleteFuture(handle, kConsentRequestSuccess); return MakeFuture(futures(), handle); @@ -122,6 +140,8 @@ Future ConsentInfoInternalStub::ShowPrivacyOptionsForm( if (consent_status_ == kConsentStatusObtained) { consent_status_ = kConsentStatusRequired; + privacy_options_requirement_status_ = + kPrivacyOptionsRequirementStatusNotRequired; } CompleteFuture(handle, kConsentRequestSuccess); return MakeFuture(futures(), handle); diff --git a/gma/src/stub/ump/consent_info_internal_stub.h b/gma/src/stub/ump/consent_info_internal_stub.h index 5e41cf85bf..23d44dfbaa 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.h +++ b/gma/src/stub/ump/consent_info_internal_stub.h @@ -26,13 +26,17 @@ namespace internal { // The stub interface implements a few specific workflows, for testing: // -// Before requesting: consent and privacy options will be Unknown. +// Before requesting: consent and privacy options requirement will be Unknown. // -// If debug_geography == EEA, consent will be Required and will change to -// Obtained once the consent form is "shown". Privacy options will be Required, -// and when the privacy options form is shown, consent will go back to Required. +// After requesting: // -// If debug_geography == NotEEA, consent will be NotRequired. No privacy options +// If debug_geography == EEA, consent will be Required, privacy options +// NotRequired. After calling ShowConsentForm() or +// LoadAndShowConsentFormIfRequired(), it will change to change to Obtained and +// privacy options will become Required, and when the privacy options form is +// shown, consent will go back to Required. +// +// If debug_geography == NonEEA, consent will be NotRequired. No privacy options // form is required. // // If debug_geography == Disabled, consent will be Obtained and privacy options @@ -70,6 +74,7 @@ class ConsentInfoInternalStub : public ConsentInfoInternal { ConsentStatus consent_status_; ConsentFormStatus consent_form_status_; PrivacyOptionsRequirementStatus privacy_options_requirement_status_; + ConsentDebugGeography debug_geo_; bool under_age_of_consent_; }; From 4b51480e2090f9fd7b7eb7a242664cbff7c8b827 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 25 Jul 2023 14:07:26 -0700 Subject: [PATCH 41/50] Add comment to struct. --- gma/src/include/firebase/gma/ump/types.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gma/src/include/firebase/gma/ump/types.h b/gma/src/include/firebase/gma/ump/types.h index c2b59bce46..14737aee89 100644 --- a/gma/src/include/firebase/gma/ump/types.h +++ b/gma/src/include/firebase/gma/ump/types.h @@ -64,7 +64,10 @@ struct ConsentDebugSettings { struct ConsentRequestParameters { ConsentRequestParameters() : tag_for_under_age_of_consent(false) {} + /// Debug settings for the consent request. ConsentDebugSettings debug_settings; + + /// Whether the user is under the age of consent. bool tag_for_under_age_of_consent; }; From d0aaed706205fcc1ed55095a48e216724ee112f4 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 25 Jul 2023 14:09:03 -0700 Subject: [PATCH 42/50] Fix comments & enum text. --- gma/src/common/ump/ump_common.cc | 4 ++-- gma/src/include/firebase/gma/ump/types.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gma/src/common/ump/ump_common.cc b/gma/src/common/ump/ump_common.cc index b9d695d2d1..9e5c766b19 100644 --- a/gma/src/common/ump/ump_common.cc +++ b/gma/src/common/ump/ump_common.cc @@ -38,11 +38,11 @@ const char* GetConsentRequestErrorMessage(ConsentRequestError error_code) { case kConsentRequestErrorInternal: return "Internal error"; case kConsentRequestErrorCodeMisconfiguration: - return "Code misconfiguration error"; + return "A misconfiguration exists in the UI"; case kConsentRequestErrorUnknown: return "Unknown error"; case kConsentRequestErrorInvalidOperation: - return "Invalid operation. Please try again.."; + return "Invalid operation"; case kConsentRequestErrorOperationInProgress: return "Operation already in progress. Please wait for it to finish by " "checking RequestConsentInfoUpdateLastResult()."; diff --git a/gma/src/include/firebase/gma/ump/types.h b/gma/src/include/firebase/gma/ump/types.h index 14737aee89..c3dd0729dd 100644 --- a/gma/src/include/firebase/gma/ump/types.h +++ b/gma/src/include/firebase/gma/ump/types.h @@ -113,7 +113,7 @@ enum ConsentRequestError { kConsentRequestErrorNetwork, /// An internal error occurred. kConsentRequestErrorInternal, - /// This error is undocumented. + /// A misconfiguration exists in the UI. kConsentRequestErrorCodeMisconfiguration, /// An unknown error occurred. kConsentRequestErrorUnknown, From 3a772dec9f3ea1b82b34543e661fc2354a13a946 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 25 Jul 2023 14:09:34 -0700 Subject: [PATCH 43/50] Newline removed. --- gma/src/include/firebase/gma/ump/types.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gma/src/include/firebase/gma/ump/types.h b/gma/src/include/firebase/gma/ump/types.h index c3dd0729dd..e325b139a1 100644 --- a/gma/src/include/firebase/gma/ump/types.h +++ b/gma/src/include/firebase/gma/ump/types.h @@ -128,8 +128,7 @@ enum ConsentRequestError { /// Status of the consent form, whether it is available to show or not. enum ConsentFormStatus { /// Status is unknown. Call `ConsentInfo::RequestConsentInfoUpdate()` to - /// update - /// this. + /// update this. kConsentFormStatusUnknown = 0, /// The consent form is unavailable. Call `ConsentInfo::LoadConsentForm()` to /// load it. From 64cfce19162b4e9ba1a11d5287c02007dcfded20 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Tue, 25 Jul 2023 14:10:00 -0700 Subject: [PATCH 44/50] Lint error. --- gma/src/include/firebase/gma/ump/types.h | 1 - 1 file changed, 1 deletion(-) diff --git a/gma/src/include/firebase/gma/ump/types.h b/gma/src/include/firebase/gma/ump/types.h index e325b139a1..9edf6b7889 100644 --- a/gma/src/include/firebase/gma/ump/types.h +++ b/gma/src/include/firebase/gma/ump/types.h @@ -140,7 +140,6 @@ enum ConsentFormStatus { /// Errors when loading or showing the consent form. enum ConsentFormError { - /// The operation succeeded. kConsentFormSuccess = 0, /// The load request timed out. Try again. From 8889fbc4281c3d8e90cc8fe14346ea74d7f5c095 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 27 Jul 2023 15:49:53 -0700 Subject: [PATCH 45/50] Added comment explaining what EEA means. --- gma/src/include/firebase/gma/ump/types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gma/src/include/firebase/gma/ump/types.h b/gma/src/include/firebase/gma/ump/types.h index 9edf6b7889..5acea945c1 100644 --- a/gma/src/include/firebase/gma/ump/types.h +++ b/gma/src/include/firebase/gma/ump/types.h @@ -40,7 +40,7 @@ namespace ump { enum ConsentDebugGeography { /// Disable geography debugging. kConsentDebugGeographyDisabled = 0, - /// Geography appears as in EEA for debug devices. + /// Geography appears as in EEA (European Economic Area) for debug devices. kConsentDebugGeographyEEA, /// Geography appears as not in EEA for debug devices. kConsentDebugGeographyNonEEA From 6b05423ecd2af383a9cab0f588da6d9644a395b2 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 2 Aug 2023 14:20:37 -0700 Subject: [PATCH 46/50] Add a comment about ResetInfo in the UMP tests. --- gma/integration_test/src/integration_test.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gma/integration_test/src/integration_test.cc b/gma/integration_test/src/integration_test.cc index 9cd03e8fbf..7910fa5e1c 100644 --- a/gma/integration_test/src/integration_test.cc +++ b/gma/integration_test/src/integration_test.cc @@ -2444,6 +2444,8 @@ class FirebaseGmaUmpTest : public FirebaseGmaTest { public: FirebaseGmaUmpTest() : consent_info_(nullptr) {} + // Whether to call ConsentInfo::Reset() upon initialization, which + // resets UMP's consent state to as if the app was first installed. enum ResetOption { kReset, kNoReset }; void InitializeUmp(ResetOption reset = kReset); From 3c73c908ec84cad5e872c5b6d32e8024742b74a6 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 2 Aug 2023 14:21:43 -0700 Subject: [PATCH 47/50] Add expectation for privacy also being unknown. --- gma/integration_test/src/integration_test.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gma/integration_test/src/integration_test.cc b/gma/integration_test/src/integration_test.cc index 7910fa5e1c..9f9d5203fc 100644 --- a/gma/integration_test/src/integration_test.cc +++ b/gma/integration_test/src/integration_test.cc @@ -2548,6 +2548,8 @@ TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentInfoUpdate) { firebase::gma::ump::kConsentStatusUnknown); EXPECT_NE(consent_info_->GetConsentFormStatus(), firebase::gma::ump::kConsentFormStatusUnknown); + EXPECT_NE(consent_info_->GetPrivacyOptionsRequirementStatus(), + firebase::gma::ump::kPrivacyOptionsRequirementStatusUnknown); } TEST_F(FirebaseGmaUmpTest, TestUmpRequestConsentInfoUpdateDebugEEA) { From 0585ce0122bec5903c08296f330bcc1b6acd33dd Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 2 Aug 2023 14:30:16 -0700 Subject: [PATCH 48/50] Move GetConsent*ErrorMessage to internal. --- gma/CMakeLists.txt | 1 - gma/src/common/ump/consent_info_internal.cc | 59 +++++++++++++++ gma/src/common/ump/consent_info_internal.h | 5 ++ gma/src/common/ump/ump_common.cc | 80 --------------------- gma/src/include/firebase/gma/ump.h | 20 ------ 5 files changed, 64 insertions(+), 101 deletions(-) delete mode 100644 gma/src/common/ump/ump_common.cc diff --git a/gma/CMakeLists.txt b/gma/CMakeLists.txt index 166f1eaf74..440d0db7f0 100644 --- a/gma/CMakeLists.txt +++ b/gma/CMakeLists.txt @@ -18,7 +18,6 @@ set(common_SRCS src/common/ump/consent_info.cc src/common/ump/consent_info_internal.cc - src/common/ump/ump_common.cc src/common/gma_common.cc src/common/ad_view.cc src/common/ad_view_internal.cc diff --git a/gma/src/common/ump/consent_info_internal.cc b/gma/src/common/ump/consent_info_internal.cc index ecbe48a289..ef58873575 100644 --- a/gma/src/common/ump/consent_info_internal.cc +++ b/gma/src/common/ump/consent_info_internal.cc @@ -16,6 +16,8 @@ #include "gma/src/common/ump/consent_info_internal.h" +#include "app/src/include/firebase/internal/platform.h" + namespace firebase { namespace gma { namespace ump { @@ -25,6 +27,63 @@ ConsentInfoInternal::ConsentInfoInternal() : futures_(kConsentInfoFnCount) {} ConsentInfoInternal::~ConsentInfoInternal() {} +const char* ConsentInfoInternal::GetConsentRequestErrorMessage( + ConsentRequestError error_code) { + switch (error_code) { + case kConsentRequestSuccess: + return "Success"; + case kConsentRequestErrorInvalidAppId: +#if FIREBASE_PLATFORM_ANDROID + return "Missing or invalid com.google.android.gms.ads.APPLICATION_ID in " + "AndroidManifest.xml"; +#elif FIREBASE_PLATFORM_IOS + return "Missing or invalid GADApplicationidentifier in Info.plist"; +#else + return "Missing or invalid App ID"; +#endif + case kConsentRequestErrorNetwork: + return "Network error"; + case kConsentRequestErrorInternal: + return "Internal error"; + case kConsentRequestErrorCodeMisconfiguration: + return "A misconfiguration exists in the UI"; + case kConsentRequestErrorUnknown: + return "Unknown error"; + case kConsentRequestErrorInvalidOperation: + return "Invalid operation"; + case kConsentRequestErrorOperationInProgress: + return "Operation already in progress. Please wait for it to finish by " + "checking RequestConsentInfoUpdateLastResult()."; + default: + return "Bad error code"; + } +} + +const char* ConsentInfoInternal::GetConsentFormErrorMessage( + ConsentFormError error_code) { + switch (error_code) { + case kConsentFormSuccess: + return "Success"; + case kConsentFormErrorTimeout: + return "Timed out"; + case kConsentFormErrorUnavailable: + return "The form is unavailable."; + case kConsentFormErrorInternal: + return "Internal error"; + case kConsentFormErrorUnknown: + return "Unknown error"; + case kConsentFormErrorCodeAlreadyUsed: + return "Code already used"; + case kConsentFormErrorInvalidOperation: + return "Invalid operation"; + case kConsentFormErrorOperationInProgress: + return "Operation already in progress. Please wait for it to finish by " + "checking LoadFormLastResult() or ShowFormLastResult()."; + default: + return "Bad error code"; + } +} + } // namespace internal } // namespace ump } // namespace gma diff --git a/gma/src/common/ump/consent_info_internal.h b/gma/src/common/ump/consent_info_internal.h index a2f2f18be5..3438526ef0 100644 --- a/gma/src/common/ump/consent_info_internal.h +++ b/gma/src/common/ump/consent_info_internal.h @@ -93,6 +93,11 @@ class ConsentInfoInternal { protected: ConsentInfoInternal(); + static const char* GetConsentRequestErrorMessage( + ConsentRequestError error_code); + + static const char* GetConsentFormErrorMessage(ConsentFormError error_code); + SafeFutureHandle CreateFuture() { return futures()->SafeAlloc(); } SafeFutureHandle CreateFuture(ConsentInfoFn fn_idx) { return futures()->SafeAlloc(fn_idx); diff --git a/gma/src/common/ump/ump_common.cc b/gma/src/common/ump/ump_common.cc deleted file mode 100644 index 9e5c766b19..0000000000 --- a/gma/src/common/ump/ump_common.cc +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2023 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. - */ - -#include "firebase/gma/ump.h" - -namespace firebase { -namespace gma { -namespace ump { - -const char* GetConsentRequestErrorMessage(ConsentRequestError error_code) { - switch (error_code) { - case kConsentRequestSuccess: - return "Success"; - case kConsentRequestErrorInvalidAppId: -#if FIREBASE_PLATFORM_ANDROID - return "Missing or invalid com.google.android.gms.ads.APPLICATION_ID in " - "AndroidManifest.xml"; -#elif FIREBASE_PLATFORM_IOS - return "Missing or invalid GADApplicationidentifier in Info.plist"; -#else - return "Missing or invalid App ID"; -#endif - case kConsentRequestErrorNetwork: - return "Network error"; - case kConsentRequestErrorInternal: - return "Internal error"; - case kConsentRequestErrorCodeMisconfiguration: - return "A misconfiguration exists in the UI"; - case kConsentRequestErrorUnknown: - return "Unknown error"; - case kConsentRequestErrorInvalidOperation: - return "Invalid operation"; - case kConsentRequestErrorOperationInProgress: - return "Operation already in progress. Please wait for it to finish by " - "checking RequestConsentInfoUpdateLastResult()."; - default: - return "Bad error code"; - } -} - -const char* GetConsentFormErrorMessage(ConsentFormError error_code) { - switch (error_code) { - case kConsentFormSuccess: - return "Success"; - case kConsentFormErrorTimeout: - return "Timed out"; - case kConsentFormErrorUnavailable: - return "The form is unavailable."; - case kConsentFormErrorInternal: - return "Internal error"; - case kConsentFormErrorUnknown: - return "Unknown error"; - case kConsentFormErrorCodeAlreadyUsed: - return "Code already used"; - case kConsentFormErrorInvalidOperation: - return "Invalid operation"; - case kConsentFormErrorOperationInProgress: - return "Operation already in progress. Please wait for it to finish by " - "checking LoadFormLastResult() or ShowFormLastResult()."; - default: - return "Bad error code"; - } -} - -} // namespace ump -} // namespace gma -} // namespace firebase diff --git a/gma/src/include/firebase/gma/ump.h b/gma/src/include/firebase/gma/ump.h index 3468ba6156..26e90d630b 100644 --- a/gma/src/include/firebase/gma/ump.h +++ b/gma/src/include/firebase/gma/ump.h @@ -20,24 +20,4 @@ #include "firebase/gma/ump/consent_info.h" #include "firebase/gma/ump/types.h" -namespace firebase { -namespace gma { -/// @brief API for User Messaging Platform. -/// -/// The User Messaging Platform (UMP) SDK is Google’s option to handle user -/// privacy and consent in mobile apps. -/// -/// See the ConsentInfo class for details. -namespace ump { - -/// Returns a static string describing the given error code. -const char* GetConsentRequestErrorMessage(ConsentRequestError error_code); - -/// Returns a static string describing the given error code. -const char* GetConsentFormErrorMessage(ConsentFormError error_code); - -} // namespace ump -} // namespace gma -} // namespace firebase - #endif // FIREBASE_GMA_SRC_INCLUDE_FIREBASE_GMA_UMP_H_ From a5551d137900cc8c9821fe3a2cbeb8a1e9b81b86 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 2 Aug 2023 14:46:16 -0700 Subject: [PATCH 49/50] Update method documentation and fixed FormUnavailable/Available logic. --- gma/integration_test/src/integration_test.cc | 4 +- .../include/firebase/gma/ump/consent_info.h | 55 ++++++++++++++----- .../stub/ump/consent_info_internal_stub.cc | 10 ++-- 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/gma/integration_test/src/integration_test.cc b/gma/integration_test/src/integration_test.cc index 9f9d5203fc..c98bbb748f 100644 --- a/gma/integration_test/src/integration_test.cc +++ b/gma/integration_test/src/integration_test.cc @@ -2608,7 +2608,7 @@ TEST_F(FirebaseGmaUmpTest, TestUmpLoadForm) { firebase::gma::ump::kConsentStatusRequired); EXPECT_EQ(consent_info_->GetConsentFormStatus(), - firebase::gma::ump::kConsentFormStatusUnavailable); + firebase::gma::ump::kConsentFormStatusAvailable); // Load the form. firebase::Future future = consent_info_->LoadConsentForm(); @@ -2641,7 +2641,7 @@ TEST_F(FirebaseGmaUmpTest, TestUmpShowForm) { firebase::gma::ump::kConsentStatusRequired); EXPECT_EQ(consent_info_->GetConsentFormStatus(), - firebase::gma::ump::kConsentFormStatusUnavailable); + firebase::gma::ump::kConsentFormStatusAvailable); WaitForCompletion(consent_info_->LoadConsentForm(), "LoadConsentForm"); diff --git a/gma/src/include/firebase/gma/ump/consent_info.h b/gma/src/include/firebase/gma/ump/consent_info.h index a0a74cd329..41d14bfc3b 100644 --- a/gma/src/include/firebase/gma/ump/consent_info.h +++ b/gma/src/include/firebase/gma/ump/consent_info.h @@ -112,12 +112,17 @@ class ConsentInfo { static ConsentInfo* GetInstance(InitResult* init_result_out = nullptr); #endif // !defined(__ANDROID__) || defined(DOXYGEN) - /// The user’s consent status. This value is cached between app sessions and - /// can be read before calling RequestConsentInfoUpdate(). + /// The user’s consent status. This value defaults to kConsentStatusUnknown + /// until RequestConsentInfoUpdate() is called, and defaults to the previous + /// session’s value until RequestConsentInfoUpdate() completes. ConsentStatus GetConsentStatus(); - /// Requests consent information update. Must be called before loading a - /// consent form. If successful, GetConsentStatus() will be updated. + /// Requests consent information update. Must be called in every app session + /// before checking the user’s consent status or loading a consent form. After + /// calling this method, GetConsentStatus() will be updated immediately to + /// hold the consent state from the previous app session, if one + /// exists. GetConsentStatus() may be updated again immediately before the + /// returned future is completed. Future RequestConsentInfoUpdate(const ConsentRequestParameters& params); /// Get the Future from the most recent call to RequestConsentInfoUpdate(). @@ -127,8 +132,8 @@ class ConsentInfo { /// requires a call to RequestConsentInfoUpdate() to update. ConsentFormStatus GetConsentFormStatus(); - /// Loads a consent form. If successful, GetConsentFormStatus() will be - /// updated. + /// Loads a consent form. Returns an error if the consent form is unavailable + /// or cannot be loaded. Future LoadConsentForm(); /// Get the Future from the most recent call to LoadConsentForm(). @@ -137,14 +142,25 @@ class ConsentInfo { /// Presents the full screen consent form using the given FormParent, which is /// defined as an Activity on Android and a UIViewController on iOS. The form /// will be dismissed and the Future will be completed after the user selects - /// an option. GetConsentStatus() is updated when the Future is completed. + /// an option. + /// + /// GetConsentStatus() is updated when the returned Future is completed. + /// + /// @note You must call LoadConsentForm() and wait for it to complete before + /// calling this method. Future ShowConsentForm(FormParent parent); /// Get the Future from the most recent call to ShowConsentForm(). Future ShowConsentFormLastResult(); - /// If required, load and then show the consent form. You can call this - /// instead of LoadConsentForm() and ShowConsentForm(). + /// Loads a consent form and immediately presents it using the given + /// FormParent, if ConsentStatus is kConsentStatusRequired. The FormParent is + /// defined as an Activity on Android and a UIViewController on iOS. The + /// Future will be completed successfully after the user selects an option + /// (and the form is dismissed), or if the form is not required. The Future + /// will be completed with an error if the form fails to load or show. + /// + /// GetConsentStatus() will be updated prior to the Future being completed. Future LoadAndShowConsentFormIfRequired(FormParent parent); /// Get the Future from the most recent call to @@ -155,15 +171,28 @@ class ConsentInfo { /// This is updated by RequestConsentStatus(). PrivacyOptionsRequirementStatus GetPrivacyOptionsRequirementStatus(); - /// If needed, show the privacy options form to the user. This allows them to - /// revoke their consent. + /// If GetPrivacyOptionsRequirementStatus() is + /// kPrivacyOptionsRequirementStatusRequired, presents a privacy options form + /// from the provided FormParent, which is defined as an Activity on Android + /// and a UIViewController on iOS. + /// + /// This method should only be called in response to a user input to request a + /// privacy options form to be shown. + /// + /// The future completes when the user selects an option and dismisses the + /// form or is completed immediately with an error code if no form is + /// presented. The privacy options form is preloaded by the SDK automatically + /// when a form becomes available. If no form has been preloaded, the SDK will + /// try to load one asynchronously. Future ShowPrivacyOptionsForm(FormParent parent); /// Get the Future from the most recent call to ShowPrivacyOptionsForm(). Future ShowPrivacyOptionsFormLastResult(); - /// If this returns true, it is now safe to request ads. If not, do not show - /// ads to the user. This is updated by RequestConsentStatus(). + /// Indicates whether the app has completed the necessary steps for gathering + /// updated user consent. Returns true if RequestConsentInfoUpdate() has been + /// called and GetConsentStatus returns either kConsentStatusNotRequired or + /// kConsentStatusObtained. bool CanRequestAds(); /// Clears all consent state from persistent storage. This can be used in diff --git a/gma/src/stub/ump/consent_info_internal_stub.cc b/gma/src/stub/ump/consent_info_internal_stub.cc index b757f52a7a..8f4d033896 100644 --- a/gma/src/stub/ump/consent_info_internal_stub.cc +++ b/gma/src/stub/ump/consent_info_internal_stub.cc @@ -57,8 +57,9 @@ Future ConsentInfoInternalStub::RequestConsentInfoUpdate( } consent_status_ = new_consent_status; - consent_form_status_ = kConsentFormStatusUnavailable; under_age_of_consent_ = params.tag_for_under_age_of_consent; + consent_form_status_ = under_age_of_consent_ ? kConsentFormStatusUnavailable + : kConsentFormStatusAvailable; debug_geo_ = params.debug_settings.debug_geography; privacy_options_requirement_status_ = kPrivacyOptionsRequirementStatusNotRequired; @@ -70,12 +71,10 @@ Future ConsentInfoInternalStub::RequestConsentInfoUpdate( Future ConsentInfoInternalStub::LoadConsentForm() { SafeFutureHandle handle = CreateFuture(kConsentInfoFnLoadConsentForm); - if (under_age_of_consent_) { - consent_form_status_ = kConsentFormStatusUnavailable; + if (consent_form_status_ != kConsentFormStatusAvailable) { CompleteFuture(handle, kConsentFormErrorUnavailable); return MakeFuture(futures(), handle); } - consent_form_status_ = kConsentFormStatusAvailable; CompleteFuture(handle, kConsentFormSuccess); return MakeFuture(futures(), handle); } @@ -105,8 +104,7 @@ Future ConsentInfoInternalStub::LoadAndShowConsentFormIfRequired( SafeFutureHandle handle = CreateFuture(kConsentInfoFnLoadAndShowConsentFormIfRequired); - if (under_age_of_consent_) { - consent_form_status_ = kConsentFormStatusUnavailable; + if (consent_form_status_ != kConsentFormStatusAvailable) { CompleteFuture(handle, kConsentFormErrorUnavailable); return MakeFuture(futures(), handle); } From 0da76afbe8bb0ecd13e7c1001bfc39a3594111eb Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 3 Aug 2023 10:08:44 -0700 Subject: [PATCH 50/50] Fix comments. --- gma/src/include/firebase/gma/ump/consent_info.h | 4 ++-- gma/src/include/firebase/gma/ump/types.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gma/src/include/firebase/gma/ump/consent_info.h b/gma/src/include/firebase/gma/ump/consent_info.h index a0a74cd329..de86045161 100644 --- a/gma/src/include/firebase/gma/ump/consent_info.h +++ b/gma/src/include/firebase/gma/ump/consent_info.h @@ -152,7 +152,7 @@ class ConsentInfo { Future LoadAndShowConsentFormIfRequiredLastResult(); /// Check whether the privacy options form needs to be displayed. - /// This is updated by RequestConsentStatus(). + /// This is updated by RequestConsentInfoUpdate(). PrivacyOptionsRequirementStatus GetPrivacyOptionsRequirementStatus(); /// If needed, show the privacy options form to the user. This allows them to @@ -163,7 +163,7 @@ class ConsentInfo { Future ShowPrivacyOptionsFormLastResult(); /// If this returns true, it is now safe to request ads. If not, do not show - /// ads to the user. This is updated by RequestConsentStatus(). + /// ads to the user. This is updated by RequestConsentInfoUpdate(). bool CanRequestAds(); /// Clears all consent state from persistent storage. This can be used in diff --git a/gma/src/include/firebase/gma/ump/types.h b/gma/src/include/firebase/gma/ump/types.h index 5acea945c1..bf380d16be 100644 --- a/gma/src/include/firebase/gma/ump/types.h +++ b/gma/src/include/firebase/gma/ump/types.h @@ -163,7 +163,7 @@ enum ConsentFormError { /// Whether the privacy options need to be displayed. enum PrivacyOptionsRequirementStatus { /// Privacy options requirement status is unknown. Call - /// `ConsentInfo::RequestConsentStatus()` to update. + /// `ConsentInfo::RequestConsentInfoUpdate()` to update. kPrivacyOptionsRequirementStatusUnknown = 0, /// Privacy options are not required to be shown. kPrivacyOptionsRequirementStatusNotRequired,