Skip to content

Commit 177ec1e

Browse files
committed
iOS integration for QueryInfo support
1 parent a4ffb69 commit 177ec1e

File tree

6 files changed

+323
-0
lines changed

6 files changed

+323
-0
lines changed

gma/src/ios/FADRequest.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ AdErrorCode MapAdRequestErrorCodeToCPPErrorCode(GADErrorCode error_code);
5151
AdErrorCode MapFullScreenContentErrorCodeToCPPErrorCode(
5252
GADPresentationErrorCode error_code);
5353

54+
// Converts the platform independent ad format defined in AdFormat to the iOS
55+
// ad format.
56+
GADAdFormat MapCPPAdFormatToGADAdformat(AdFormat format);
57+
5458
} // namespace gma
5559
} // namespace firebase
5660

gma/src/ios/FADRequest.mm

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,5 +164,24 @@ AdErrorCode MapFullScreenContentErrorCodeToCPPErrorCode(GADPresentationErrorCode
164164
}
165165
}
166166

167+
GADAdFormat MapCPPAdFormatToGADAdformat(AdFormat format) {
168+
switch (format) {
169+
case kAdFormatBanner:
170+
return GADAdFormatBanner;
171+
case kAdFormatInterstitial:
172+
return GADAdFormatInterstitial;
173+
case kAdFormatRewarded:
174+
return GADAdFormatRewarded;
175+
case kAdFormatRewardedInterstitial:
176+
return GADAdFormatRewardedInterstitial;
177+
case kAdFormatNative:
178+
return GADAdFormatNative;
179+
case kAdFormatAppOpen:
180+
return GADAdFormatAppOpen;
181+
default:
182+
return GADAdFormatBanner;
183+
}
184+
}
185+
167186
} // namespace gma
168187
} // namespace firebase

gma/src/ios/gma_ios.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,17 @@ void CompleteLoadImageInternalSuccess(
4747
FutureCallbackData<ImageResult>* callback_data,
4848
const std::vector<unsigned char>& img_data);
4949

50+
// Pipes query info generation errors that exist in the C++ SDK.
51+
void CompleteQueryInfoInternalError(
52+
FutureCallbackData<QueryInfoResult>* callback_data,
53+
int error_code,
54+
const char* error_message);
55+
56+
// Completes QueryInfoResult futures for successful query info generation.
57+
void CompleteQueryInfoInternalSuccess(
58+
FutureCallbackData<QueryInfoResult>* callback_data,
59+
NSString* query_info);
60+
5061
// Resolves LoadImage errors that exist in the C++ SDK before initiating image
5162
// loads.
5263
void CompleteLoadImageInternalError(

gma/src/ios/gma_ios.mm

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,23 @@ void CompleteLoadImageInternalError(FutureCallbackData<ImageResult>* callback_da
357357
GmaInternal::CompleteLoadImageFutureFailure(callback_data, error_code, std::string(error_message));
358358
}
359359

360+
void CompleteQueryInfoInternalSuccess(FutureCallbackData<QueryInfoResult>* callback_data,
361+
NSString* query_info) {
362+
FIREBASE_ASSERT(callback_data);
363+
364+
GmaInternal::CompleteCreateQueryInfoFutureSuccess(callback_data,
365+
util::NSStringToString(query_info));
366+
}
367+
368+
void CompleteQueryInfoInternalError(FutureCallbackData<QueryInfoResult>* callback_data,
369+
int error_code, const char* error_message) {
370+
FIREBASE_ASSERT(callback_data);
371+
FIREBASE_ASSERT(error_message);
372+
373+
GmaInternal::CompleteCreateQueryInfoFutureFailure(callback_data, error_code,
374+
std::string(error_message));
375+
}
376+
360377
void CompleteAdResultError(FutureCallbackData<AdResult>* callback_data, NSError* gad_error,
361378
bool is_load_ad_error) {
362379
FIREBASE_ASSERT(callback_data);

gma/src/ios/query_info_internal_ios.h

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef FIREBASE_GMA_SRC_IOS_QUERY_INFO_INTERNAL_IOS_H_
18+
#define FIREBASE_GMA_SRC_IOS_QUERY_INFO_INTERNAL_IOS_H_
19+
20+
#ifdef __OBJC__
21+
#import <Foundation/Foundation.h>
22+
#import <GoogleMobileAds/GoogleMobileAds.h>
23+
#endif // __OBJC__
24+
25+
extern "C" {
26+
#include <objc/objc.h>
27+
} // extern "C"
28+
29+
#include "app/src/include/firebase/internal/mutex.h"
30+
#include "gma/src/common/query_info_internal.h"
31+
32+
namespace firebase {
33+
namespace gma {
34+
namespace internal {
35+
36+
class QueryInfoInternalIOS : public QueryInfoInternal {
37+
public:
38+
explicit QueryInfoInternalIOS(QueryInfo* base);
39+
~QueryInfoInternalIOS();
40+
41+
Future<void> Initialize(AdParent parent) override;
42+
Future<QueryInfoResult> CreateQueryInfo(AdFormat format,
43+
const AdRequest& request) override;
44+
Future<QueryInfoResult> CreateQueryInfoWithAdUnit(
45+
AdFormat format, const AdRequest& request,
46+
const char* ad_unit_id) override;
47+
bool is_initialized() const override { return initialized_; }
48+
49+
#ifdef __OBJC__
50+
void CreateQueryInfoSucceeded(GADQueryInfo *query_info);
51+
void CreateQueryInfoFailedWithError(NSError *gad_error);
52+
#endif // __OBJC__
53+
54+
private:
55+
/// Prevents duplicate invocations of initialize on the Native Ad.
56+
bool initialized_;
57+
58+
/// Contains information to asynchronously complete the createQueryInfo
59+
/// Future.
60+
FutureCallbackData<QueryInfoResult>* query_info_callback_data_;
61+
62+
/// The publisher-provided view (UIView) that's the parent view of the ad.
63+
/// Declared as an "id" type to avoid referencing an Objective-C class in this
64+
/// header.
65+
id parent_view_;
66+
67+
// Mutex to guard against concurrent operations;
68+
Mutex mutex_;
69+
};
70+
71+
} // namespace internal
72+
} // namespace gma
73+
} // namespace firebase
74+
75+
#endif // FIREBASE_GMA_SRC_IOS_QUERY_INFO_INTERNAL_IOS_H_
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
extern "C" {
18+
#include <objc/objc.h>
19+
} // extern "C"
20+
21+
#include "gma/src/ios/query_info_internal_ios.h"
22+
23+
#import "gma/src/ios/FADRequest.h"
24+
#import "gma/src/ios/gma_ios.h"
25+
26+
#include "app/src/util_ios.h"
27+
#include "gma/src/ios/response_info_ios.h"
28+
29+
namespace firebase {
30+
namespace gma {
31+
namespace internal {
32+
33+
QueryInfoInternalIOS::QueryInfoInternalIOS(QueryInfo *base)
34+
: QueryInfoInternal(base),
35+
initialized_(false),
36+
query_info_callback_data_(nil),
37+
parent_view_(nil) {}
38+
39+
QueryInfoInternalIOS::~QueryInfoInternalIOS() {
40+
firebase::MutexLock lock(mutex_);
41+
if (query_info_callback_data_ != nil) {
42+
delete query_info_callback_data_;
43+
query_info_callback_data_ = nil;
44+
}
45+
}
46+
47+
Future<void> QueryInfoInternalIOS::Initialize(AdParent parent) {
48+
firebase::MutexLock lock(mutex_);
49+
const SafeFutureHandle<void> future_handle =
50+
future_data_.future_impl.SafeAlloc<void>(kQueryInfoFnInitialize);
51+
Future<void> future = MakeFuture(&future_data_.future_impl, future_handle);
52+
53+
if (initialized_) {
54+
CompleteFuture(kAdErrorCodeAlreadyInitialized, kAdAlreadyInitializedErrorMessage, future_handle,
55+
&future_data_);
56+
} else {
57+
initialized_ = true;
58+
parent_view_ = (UIView *)parent;
59+
CompleteFuture(kAdErrorCodeNone, nullptr, future_handle, &future_data_);
60+
}
61+
return future;
62+
}
63+
64+
Future<QueryInfoResult> QueryInfoInternalIOS::CreateQueryInfo(AdFormat format,
65+
const AdRequest &request) {
66+
firebase::MutexLock lock(mutex_);
67+
FutureCallbackData<QueryInfoResult> *callback_data =
68+
CreateQueryInfoResultFutureCallbackData(kQueryInfoFnCreateQueryInfo, &future_data_);
69+
Future<QueryInfoResult> future =
70+
MakeFuture(&future_data_.future_impl, callback_data->future_handle);
71+
72+
if (query_info_callback_data_ != nil) {
73+
CompleteQueryInfoInternalError(callback_data, kAdErrorCodeLoadInProgress,
74+
kAdLoadInProgressErrorMessage);
75+
return future;
76+
}
77+
78+
// Persist a pointer to the callback data so that we may use it after the iOS
79+
// SDK returns the QueryInfo.
80+
query_info_callback_data_ = callback_data;
81+
82+
// Guard against parameter object destruction before the async operation
83+
// executes (below).
84+
AdRequest local_ad_request = request;
85+
86+
dispatch_async(dispatch_get_main_queue(), ^{
87+
// Create a GADRequest from a gma::AdRequest.
88+
AdErrorCode error_code = kAdErrorCodeNone;
89+
std::string error_message;
90+
GADRequest *ad_request =
91+
GADRequestFromCppAdRequest(local_ad_request, &error_code, &error_message);
92+
if (ad_request == nullptr) {
93+
if (error_code == kAdErrorCodeNone) {
94+
error_code = kAdErrorCodeInternalError;
95+
error_message = kAdCouldNotParseAdRequestErrorMessage;
96+
}
97+
CompleteQueryInfoInternalError(query_info_callback_data_, error_code, error_message.c_str());
98+
query_info_callback_data_ = nil;
99+
} else {
100+
// Make the create query info request.
101+
[GADQueryInfo
102+
createQueryInfoWithRequest:ad_request
103+
adFormat:MapCPPAdFormatToGADAdformat(format)
104+
completionHandler:^(GADQueryInfo *query_info, NSError *error) // NO LINT
105+
{
106+
if (error) {
107+
CreateQueryInfoFailedWithError(error);
108+
} else {
109+
CreateQueryInfoSucceeded(query_info);
110+
}
111+
}];
112+
}
113+
});
114+
115+
return future;
116+
}
117+
118+
Future<QueryInfoResult> QueryInfoInternalIOS::CreateQueryInfoWithAdUnit(AdFormat format,
119+
const AdRequest &request,
120+
const char *ad_unit_id) {
121+
firebase::MutexLock lock(mutex_);
122+
FutureCallbackData<QueryInfoResult> *callback_data =
123+
CreateQueryInfoResultFutureCallbackData(kQueryInfoFnCreateQueryInfoWithAdUnit, &future_data_);
124+
Future<QueryInfoResult> future =
125+
MakeFuture(&future_data_.future_impl, callback_data->future_handle);
126+
127+
if (query_info_callback_data_ != nil) {
128+
CompleteQueryInfoInternalError(callback_data, kAdErrorCodeLoadInProgress,
129+
kAdLoadInProgressErrorMessage);
130+
return future;
131+
}
132+
133+
// Persist a pointer to the callback data so that we may use it after the iOS
134+
// SDK returns the QueryInfo.
135+
query_info_callback_data_ = callback_data;
136+
137+
// Guard against parameter object destruction before the async operation
138+
// executes (below).
139+
AdRequest local_ad_request = request;
140+
NSString *local_ad_unit_id = @(ad_unit_id);
141+
142+
dispatch_async(dispatch_get_main_queue(), ^{
143+
// Create a GADRequest from a gma::AdRequest.
144+
AdErrorCode error_code = kAdErrorCodeNone;
145+
std::string error_message;
146+
GADRequest *ad_request =
147+
GADRequestFromCppAdRequest(local_ad_request, &error_code, &error_message);
148+
if (ad_request == nullptr) {
149+
if (error_code == kAdErrorCodeNone) {
150+
error_code = kAdErrorCodeInternalError;
151+
error_message = kAdCouldNotParseAdRequestErrorMessage;
152+
}
153+
CompleteQueryInfoInternalError(query_info_callback_data_, error_code, error_message.c_str());
154+
query_info_callback_data_ = nil;
155+
} else {
156+
// Make the create query info request.
157+
[GADQueryInfo
158+
createQueryInfoWithRequest:ad_request
159+
adFormat:MapCPPAdFormatToGADAdformat(format)
160+
adUnitID:local_ad_unit_id
161+
completionHandler:^(GADQueryInfo *query_info, NSError *error) // NO LINT
162+
{
163+
if (error) {
164+
CreateQueryInfoFailedWithError(error);
165+
} else {
166+
CreateQueryInfoSucceeded(query_info);
167+
}
168+
}];
169+
}
170+
});
171+
172+
return future;
173+
}
174+
175+
void QueryInfoInternalIOS::CreateQueryInfoSucceeded(GADQueryInfo *query_info) {
176+
firebase::MutexLock lock(mutex_);
177+
178+
if (query_info_callback_data_ != nil) {
179+
CompleteQueryInfoInternalSuccess(query_info_callback_data_, query_info.query);
180+
query_info_callback_data_ = nil;
181+
}
182+
}
183+
184+
void QueryInfoInternalIOS::CreateQueryInfoFailedWithError(NSError *gad_error) {
185+
firebase::MutexLock lock(mutex_);
186+
FIREBASE_ASSERT(gad_error);
187+
if (query_info_callback_data_ != nil) {
188+
AdErrorCode error_code = MapAdRequestErrorCodeToCPPErrorCode((GADErrorCode)gad_error.code);
189+
CompleteQueryInfoInternalError(query_info_callback_data_, error_code,
190+
util::NSStringToString(gad_error.localizedDescription).c_str());
191+
query_info_callback_data_ = nil;
192+
}
193+
}
194+
195+
} // namespace internal
196+
} // namespace gma
197+
} // namespace firebase

0 commit comments

Comments
 (0)