Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@ if (IOS)
${FIREBASE_SOURCE_DIR}/gma/src/include/firebase/gma/ad_view.h
${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/internal/query_info.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/ump.h
Expand Down
4 changes: 4 additions & 0 deletions gma/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ set(common_SRCS
src/common/full_screen_ad_event_listener.cc
src/common/native_ad.cc
src/common/native_ad_internal.cc
src/common/query_info.cc
src/common/query_info_internal.cc
src/common/rewarded_ad.cc
src/common/rewarded_ad_internal.cc)

Expand All @@ -49,6 +51,7 @@ set(android_SRCS
src/android/interstitial_ad_internal_android.cc
src/android/native_ad_image_android.cc
src/android/native_ad_internal_android.cc
src/android/query_info_internal_android.cc
src/android/response_info_android.cc
src/android/rewarded_ad_internal_android.cc)

Expand All @@ -68,6 +71,7 @@ set(ios_SRCS
src/ios/interstitial_ad_internal_ios.mm
src/ios/native_ad_image_ios.mm
src/ios/native_ad_internal_ios.mm
src/ios/query_info_internal_ios.mm
src/ios/response_info_ios.mm
src/ios/rewarded_ad_internal_ios.mm)

Expand Down
66 changes: 66 additions & 0 deletions gma/integration_test/src/integration_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,72 @@ TEST_F(FirebaseGmaTest, TestNativeAdLoad) {
delete native_ad;
}

TEST_F(FirebaseGmaTest, TestCreateQueryInfo) {
SKIP_TEST_ON_DESKTOP;
SKIP_TEST_ON_SIMULATOR;

firebase::gma::QueryInfo* query_info = new firebase::gma::QueryInfo();

WaitForCompletion(query_info->Initialize(app_framework::GetWindowContext()),
"Initialize");

firebase::gma::AdRequest request = GetAdRequest();
// Set the requester type to 8. QueryInfo gets generated without a
// query_info_type set, but throws a warning that it is missing.
request.add_extra(kAdNetworkExtrasClassName, "query_info_type",
"requester_type_8");
// When the QueryInfo is initialized, generate a query info string.
firebase::Future<firebase::gma::QueryInfoResult> create_query_info_future =
query_info->CreateQueryInfo(firebase::gma::kAdFormatNative, request);

WaitForCompletion(create_query_info_future, "CreateQueryInfo");

if (create_query_info_future.error() == firebase::gma::kAdErrorCodeNone) {
const firebase::gma::QueryInfoResult* result_ptr =
create_query_info_future.result();
ASSERT_NE(result_ptr, nullptr);
EXPECT_TRUE(result_ptr->is_successful());
EXPECT_FALSE(result_ptr->query_info().empty());
}

create_query_info_future.Release();
delete query_info;
}

TEST_F(FirebaseGmaTest, TestCreateQueryInfoWithAdUnit) {
SKIP_TEST_ON_DESKTOP;
SKIP_TEST_ON_SIMULATOR;

firebase::gma::QueryInfo* query_info = new firebase::gma::QueryInfo();

WaitForCompletion(query_info->Initialize(app_framework::GetWindowContext()),
"Initialize");

firebase::gma::AdRequest request = GetAdRequest();
// Set the requester type to 8. QueryInfo gets generated without a
// query_info_type set, but throws a warning that it is missing.
request.add_extra(kAdNetworkExtrasClassName, "query_info_type",
"requester_type_8");
// When the QueryInfo is initialized, generate a query info string.
// Providing a bad/empty ad unit does not affect the query info generation.
firebase::Future<firebase::gma::QueryInfoResult> create_query_info_future =
query_info->CreateQueryInfoWithAdUnit(firebase::gma::kAdFormatNative,
request, kNativeAdUnit);

WaitForCompletion(create_query_info_future, "CreateQueryInfoWithAdUnit");

if (create_query_info_future.error() == firebase::gma::kAdErrorCodeNone) {
const firebase::gma::QueryInfoResult* result_ptr =
create_query_info_future.result();
ASSERT_NE(result_ptr, nullptr);
EXPECT_TRUE(result_ptr->is_successful());
EXPECT_FALSE(result_ptr->query_info().empty());
}

create_query_info_future.Release();
delete query_info;
}

// Interactive test section. These have been placed up front so that the
// tester doesn't get bored waiting for them.
TEST_F(FirebaseGmaUITest, TestAdViewAdOpenedAdClosed) {
Expand Down
45 changes: 45 additions & 0 deletions gma/src/android/gma_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "gma/src/android/interstitial_ad_internal_android.h"
#include "gma/src/android/native_ad_image_android.h"
#include "gma/src/android/native_ad_internal_android.h"
#include "gma/src/android/query_info_internal_android.h"
#include "gma/src/android/response_info_android.h"
#include "gma/src/android/rewarded_ad_internal_android.h"
#include "gma/src/common/gma_common.h"
Expand Down Expand Up @@ -363,6 +364,9 @@ Future<AdapterInitializationStatus> Initialize(JNIEnv* env, jobject activity,
download_helper::CacheClassFromFiles(env, activity, &embedded_files) !=
nullptr &&
download_helper::CacheMethodIds(env, activity) &&
query_info_helper::CacheClassFromFiles(env, activity,
&embedded_files) != nullptr &&
query_info_helper::CacheMethodIds(env, activity) &&
rewarded_ad_helper::CacheClassFromFiles(env, activity,
&embedded_files) != nullptr &&
rewarded_ad_helper::CacheMethodIds(env, activity) &&
Expand Down Expand Up @@ -705,6 +709,7 @@ void ReleaseClasses(JNIEnv* env) {
native_ad_helper::ReleaseClass(env);
native_image::ReleaseClass(env);
download_helper::ReleaseClass(env);
query_info_helper::ReleaseClass(env);
rewarded_ad_helper::ReleaseClass(env);
load_ad_error::ReleaseClass(env);
}
Expand Down Expand Up @@ -917,6 +922,35 @@ void JNI_completeLoadedAd(JNIEnv* env, jclass clazz, jlong data_ptr,
env->DeleteLocalRef(j_response_info);
}

void JNI_completeCreateQueryInfoSuccess(JNIEnv* env, jclass clazz,
jlong data_ptr, jstring j_query_info) {
FIREBASE_ASSERT(env);
FIREBASE_ASSERT(data_ptr);
FIREBASE_ASSERT(j_query_info);

std::string query_info = util::JStringToString(env, j_query_info);
FutureCallbackData<QueryInfoResult>* callback_data =
reinterpret_cast<FutureCallbackData<QueryInfoResult>*>(data_ptr);
GmaInternal::CompleteCreateQueryInfoFutureSuccess(callback_data, query_info);
env->DeleteLocalRef(j_query_info);
}

void JNI_completeQueryInfoError(JNIEnv* env, jclass clazz, jlong data_ptr,
jint j_error_code, jstring j_error_message) {
FIREBASE_ASSERT(env);
FIREBASE_ASSERT(data_ptr);
FIREBASE_ASSERT(j_error_message);

// QueryInfo errors return only internal AdErrorCode values.
const AdErrorCode error_code = static_cast<AdErrorCode>(j_error_code);
std::string error_message = util::JStringToString(env, j_error_message);

FutureCallbackData<QueryInfoResult>* callback_data =
reinterpret_cast<FutureCallbackData<QueryInfoResult>*>(data_ptr);
GmaInternal::CompleteCreateQueryInfoFutureFailure(callback_data, error_code,
error_message);
}

void JNI_NativeAd_completeLoadedAd(JNIEnv* env, jclass clazz, jlong data_ptr,
jlong native_internal_data_ptr,
jobject j_icon, jobjectArray j_images,
Expand Down Expand Up @@ -1307,6 +1341,15 @@ bool RegisterNatives() {
reinterpret_cast<void*>(&JNI_NativeAd_notifyAdOpened)},
};

static const JNINativeMethod kQueryInfoMethods[] = {
{"completeQueryInfoFutureCallback", "(JILjava/lang/String;)V",
reinterpret_cast<void*>(&JNI_completeAdFutureCallback)},
{"completeCreateQueryInfoSuccess", "(JLjava/lang/String;)V",
reinterpret_cast<void*>(&JNI_completeCreateQueryInfoSuccess)},
{"completeCreateQueryInfoError", "(JILjava/lang/String;)V",
reinterpret_cast<void*>(&JNI_completeQueryInfoError)},
};

static const JNINativeMethod kNativeImageMethods[] = {
{"completeNativeImageFutureCallback", "(JILjava/lang/String;)V",
reinterpret_cast<void*>(&JNI_completeAdFutureCallback)},
Expand Down Expand Up @@ -1370,6 +1413,8 @@ bool RegisterNatives() {
download_helper::RegisterNatives(
env, kNativeImageMethods,
FIREBASE_ARRAYSIZE(kNativeImageMethods)) &&
query_info_helper::RegisterNatives(
env, kQueryInfoMethods, FIREBASE_ARRAYSIZE(kQueryInfoMethods)) &&
rewarded_ad_helper::RegisterNatives(
env, kRewardedAdMethods, FIREBASE_ARRAYSIZE(kRewardedAdMethods)) &&
gma_initialization_helper::RegisterNatives(
Expand Down
192 changes: 192 additions & 0 deletions gma/src/android/query_info_internal_android.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/*
* Copyright 2024 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/android/query_info_internal_android.h"

#include <assert.h>
#include <jni.h>

#include <cstdarg>
#include <cstddef>

#include "app/src/assert.h"
#include "app/src/util_android.h"
#include "gma/src/android/ad_request_converter.h"
#include "gma/src/android/gma_android.h"
#include "gma/src/common/gma_common.h"
#include "gma/src/include/firebase/gma.h"
#include "gma/src/include/firebase/gma/internal/query_info.h"
#include "gma/src/include/firebase/gma/types.h"

namespace firebase {
namespace gma {

METHOD_LOOKUP_DEFINITION(query_info_helper,
"com/google/firebase/gma/internal/cpp/QueryInfoHelper",
QUERYINFOHELPER_METHODS);

namespace internal {

QueryInfoInternalAndroid::QueryInfoInternalAndroid(QueryInfo* base)
: QueryInfoInternal(base), helper_(nullptr), initialized_(false) {
firebase::MutexLock lock(mutex_);
JNIEnv* env = ::firebase::gma::GetJNI();
jobject helper_ref = env->NewObject(
query_info_helper::GetClass(),
query_info_helper::GetMethodId(query_info_helper::kConstructor),
reinterpret_cast<jlong>(this));
util::CheckAndClearJniExceptions(env);

FIREBASE_ASSERT(helper_ref);
helper_ = env->NewGlobalRef(helper_ref);
FIREBASE_ASSERT(helper_);
env->DeleteLocalRef(helper_ref);
}

QueryInfoInternalAndroid::~QueryInfoInternalAndroid() {
firebase::MutexLock lock(mutex_);
JNIEnv* env = ::firebase::gma::GetJNI();

env->CallVoidMethod(
helper_, query_info_helper::GetMethodId(query_info_helper::kDisconnect));
util::CheckAndClearJniExceptions(env);
env->DeleteGlobalRef(helper_);
helper_ = nullptr;
}

Future<void> QueryInfoInternalAndroid::Initialize(AdParent parent) {
firebase::MutexLock lock(mutex_);

if (initialized_) {
const SafeFutureHandle<void> future_handle =
future_data_.future_impl.SafeAlloc<void>(kQueryInfoFnInitialize);
Future<void> future = MakeFuture(&future_data_.future_impl, future_handle);
CompleteFuture(kAdErrorCodeAlreadyInitialized,
kAdAlreadyInitializedErrorMessage, future_handle,
&future_data_);
return future;
}

initialized_ = true;
JNIEnv* env = ::firebase::gma::GetJNI();
FIREBASE_ASSERT(env);

FutureCallbackData<void>* callback_data =
CreateVoidFutureCallbackData(kQueryInfoFnInitialize, &future_data_);
Future<void> future =
MakeFuture(&future_data_.future_impl, callback_data->future_handle);
env->CallVoidMethod(
helper_, query_info_helper::GetMethodId(query_info_helper::kInitialize),
reinterpret_cast<jlong>(callback_data), parent);
util::CheckAndClearJniExceptions(env);
return future;
}

Future<QueryInfoResult> QueryInfoInternalAndroid::CreateQueryInfo(
AdFormat format, const AdRequest& request) {
firebase::MutexLock lock(mutex_);

if (!initialized_) {
SafeFutureHandle<QueryInfoResult> future_handle =
CreateFuture<QueryInfoResult>(kQueryInfoFnCreateQueryInfo,
&future_data_);
Future<QueryInfoResult> future =
MakeFuture(&future_data_.future_impl, future_handle);
CompleteFuture(kAdErrorCodeUninitialized, kAdUninitializedErrorMessage,
future_handle, &future_data_, QueryInfoResult());
return future;
}

gma::AdErrorCode error = kAdErrorCodeNone;
jobject j_request = GetJavaAdRequestFromCPPAdRequest(request, &error);
if (j_request == nullptr) {
if (error == kAdErrorCodeNone) {
error = kAdErrorCodeInternalError;
}
return CreateAndCompleteFutureWithQueryInfoResult(
kQueryInfoFnCreateQueryInfo, error,
kAdCouldNotParseAdRequestErrorMessage, &future_data_,
QueryInfoResult());
}
JNIEnv* env = GetJNI();
FIREBASE_ASSERT(env);
FutureCallbackData<QueryInfoResult>* callback_data =
CreateQueryInfoResultFutureCallbackData(kQueryInfoFnCreateQueryInfo,
&future_data_);
Future<QueryInfoResult> future =
MakeFuture(&future_data_.future_impl, callback_data->future_handle);

jstring j_ad_unit_str = env->NewStringUTF("");
::firebase::gma::GetJNI()->CallVoidMethod(
helper_,
query_info_helper::GetMethodId(query_info_helper::kCreateQueryInfo),
reinterpret_cast<jlong>(callback_data), static_cast<int>(format),
j_ad_unit_str, j_request);
util::CheckAndClearJniExceptions(env);
env->DeleteLocalRef(j_ad_unit_str);
env->DeleteLocalRef(j_request);
return future;
}

Future<QueryInfoResult> QueryInfoInternalAndroid::CreateQueryInfoWithAdUnit(
AdFormat format, const AdRequest& request, const char* ad_unit_id) {
firebase::MutexLock lock(mutex_);

if (!initialized_) {
SafeFutureHandle<QueryInfoResult> future_handle =
CreateFuture<QueryInfoResult>(kQueryInfoFnCreateQueryInfoWithAdUnit,
&future_data_);
Future<QueryInfoResult> future =
MakeFuture(&future_data_.future_impl, future_handle);
CompleteFuture(kAdErrorCodeUninitialized, kAdUninitializedErrorMessage,
future_handle, &future_data_, QueryInfoResult());
return future;
}

gma::AdErrorCode error = kAdErrorCodeNone;
jobject j_request = GetJavaAdRequestFromCPPAdRequest(request, &error);
if (j_request == nullptr) {
if (error == kAdErrorCodeNone) {
error = kAdErrorCodeInternalError;
}
return CreateAndCompleteFutureWithQueryInfoResult(
kQueryInfoFnCreateQueryInfoWithAdUnit, error,
kAdCouldNotParseAdRequestErrorMessage, &future_data_,
QueryInfoResult());
}
JNIEnv* env = GetJNI();
FIREBASE_ASSERT(env);
FutureCallbackData<QueryInfoResult>* callback_data =
CreateQueryInfoResultFutureCallbackData(
kQueryInfoFnCreateQueryInfoWithAdUnit, &future_data_);
Future<QueryInfoResult> future =
MakeFuture(&future_data_.future_impl, callback_data->future_handle);

jstring j_ad_unit_str = env->NewStringUTF(ad_unit_id);
::firebase::gma::GetJNI()->CallVoidMethod(
helper_,
query_info_helper::GetMethodId(query_info_helper::kCreateQueryInfo),
reinterpret_cast<jlong>(callback_data), static_cast<int>(format),
j_ad_unit_str, j_request);
util::CheckAndClearJniExceptions(env);
env->DeleteLocalRef(j_ad_unit_str);
env->DeleteLocalRef(j_request);
return future;
}

} // namespace internal
} // namespace gma
} // namespace firebase
Loading