From 5735a6c0c082a36adad437eefdc4b4186a15bacc Mon Sep 17 00:00:00 2001 From: Aldo Becerril Date: Tue, 3 Dec 2024 08:42:12 -0800 Subject: [PATCH] Add GDPR and CCPA consent APIs to Chartboost Flutter Adapter Plugin PiperOrigin-RevId: 702353803 --- .../gma_mediation_chartboost/CHANGELOG.md | 7 +- .../android/build.gradle | 22 ++- .../ChartboostSDKApi.g.kt | 132 ++++++++++++++++ .../GmaMediationChartboostPlugin.kt | 40 ++++- .../GmaMediationChartboostPluginTest.kt | 86 +++++++++- .../GmaMediationChartboostPluginTest.swift | 20 --- .../GmaMediationChartboostPluginTests.swift | 49 ++++++ .../ios/Classes/ChartboostSDKApi.g.swift | 148 ++++++++++++++++++ .../GmaMediationChartboostPlugin.swift | 55 ++++++- .../lib/chartboost_sdk_api.g.dart | 107 +++++++++++++ .../lib/gma_mediation_chartboost.dart | 14 +- .../pigeons/chartboost_sdk_api.dart | 12 +- 12 files changed, 651 insertions(+), 41 deletions(-) create mode 100644 packages/mediation/gma_mediation_chartboost/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_chartboost/ChartboostSDKApi.g.kt delete mode 100644 packages/mediation/gma_mediation_chartboost/example/ios/RunnerTests/GmaMediationChartboostPluginTest.swift create mode 100644 packages/mediation/gma_mediation_chartboost/example/ios/RunnerTests/GmaMediationChartboostPluginTests.swift create mode 100644 packages/mediation/gma_mediation_chartboost/ios/Classes/ChartboostSDKApi.g.swift create mode 100644 packages/mediation/gma_mediation_chartboost/lib/chartboost_sdk_api.g.dart diff --git a/packages/mediation/gma_mediation_chartboost/CHANGELOG.md b/packages/mediation/gma_mediation_chartboost/CHANGELOG.md index f9e4f3893..6002bb854 100644 --- a/packages/mediation/gma_mediation_chartboost/CHANGELOG.md +++ b/packages/mediation/gma_mediation_chartboost/CHANGELOG.md @@ -2,8 +2,7 @@ #### 1.0.0 -TODO: Add version numbers * Initial release. -* Verified compatibility with Chartboost Android adapter version a.b.c.d -* Verified compatibility with Chartboost iOS adapter version a.b.c.d -* Built and tested with the Google Mobile Ads Flutter Plugin version X.Y.Z. +* Verified compatibility with Chartboost Android adapter version 9.8.1.0 +* Verified compatibility with Chartboost iOS adapter version 9.8.0.0 +* Built and tested with the Google Mobile Ads Flutter Plugin version 5.2.0. diff --git a/packages/mediation/gma_mediation_chartboost/android/build.gradle b/packages/mediation/gma_mediation_chartboost/android/build.gradle index 550e3b429..ea07b830a 100644 --- a/packages/mediation/gma_mediation_chartboost/android/build.gradle +++ b/packages/mediation/gma_mediation_chartboost/android/build.gradle @@ -54,19 +54,29 @@ android { dependencies { implementation("com.google.ads.mediation:chartboost:9.8.1.0") - testImplementation("org.jetbrains.kotlin:kotlin-test") - testImplementation("org.mockito:mockito-core:5.0.0") + testImplementation 'junit:junit:4.13.2' + testImplementation 'androidx.test:core:1.6.1' + testImplementation 'androidx.test:core-ktx:1.6.1' + testImplementation 'androidx.test.ext:junit:1.2.1' + testImplementation 'org.jetbrains.kotlin:kotlin-stdlib:2.0.21' + testImplementation 'org.mockito:mockito-core:5.5.0' + testImplementation 'org.mockito.kotlin:mockito-kotlin:5.1.0' + testImplementation 'org.robolectric:robolectric:4.10.3' } testOptions { unitTests.all { - useJUnitPlatform() + useJUnit() testLogging { - events "passed", "skipped", "failed", "standardOut", "standardError" - outputs.upToDateWhen {false} - showStandardStreams = true + events "passed", "skipped", "failed", "standardOut", "standardError" + outputs.upToDateWhen {false} + showStandardStreams = true } } + unitTests { + includeAndroidResources = true + unitTests.returnDefaultValues = true + } } } diff --git a/packages/mediation/gma_mediation_chartboost/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_chartboost/ChartboostSDKApi.g.kt b/packages/mediation/gma_mediation_chartboost/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_chartboost/ChartboostSDKApi.g.kt new file mode 100644 index 000000000..69d2fe058 --- /dev/null +++ b/packages/mediation/gma_mediation_chartboost/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_chartboost/ChartboostSDKApi.g.kt @@ -0,0 +1,132 @@ +// Autogenerated from Pigeon (v22.6.2), do not edit directly. +// See also: https://pub.dev/packages/pigeon +@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") + +package io.flutter.plugins.googlemobileads.mediation.gma_mediation_chartboost + +import android.util.Log +import io.flutter.plugin.common.BasicMessageChannel +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.MessageCodec +import io.flutter.plugin.common.StandardMessageCodec +import java.io.ByteArrayOutputStream +import java.nio.ByteBuffer + +private fun wrapResult(result: Any?): List { + return listOf(result) +} + +private fun wrapError(exception: Throwable): List { + return if (exception is FlutterError) { + listOf(exception.code, exception.message, exception.details) + } else { + listOf( + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception), + ) + } +} + +/** + * Error class for passing custom error details to Flutter via a thrown PlatformException. + * + * @property code The error code. + * @property message The error message. + * @property details The error details. Must be a datatype supported by the api codec. + */ +class FlutterError( + val code: String, + override val message: String? = null, + val details: Any? = null, +) : Throwable() + +private open class ChartboostSDKApiPigeonCodec : StandardMessageCodec() { + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return super.readValueOfType(type, buffer) + } + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + super.writeValue(stream, value) + } +} + +/** + * The generated classes set the channels to call the methods in the corresponding kotlin + * ChartboostSDKApi interface and swift ChartboostSDKApi protocol from the dart layer. + * + * Generated interface from Pigeon that represents a handler of messages from Flutter. + */ +interface ChartboostSDKApi { + /** Used to configure GDPR consent on the Android or iOS Chartboost SDK */ + fun setGDPRConsent(userConsent: Boolean) + + /** Used to opt out of the sale of personal information in Chartboost SDK. */ + fun setCCPAConsent(userOptIn: Boolean) + + companion object { + /** The codec used by ChartboostSDKApi. */ + val codec: MessageCodec by lazy { ChartboostSDKApiPigeonCodec() } + + /** + * Sets up an instance of `ChartboostSDKApi` to handle messages through the `binaryMessenger`. + */ + @JvmOverloads + fun setUp( + binaryMessenger: BinaryMessenger, + api: ChartboostSDKApi?, + messageChannelSuffix: String = "", + ) { + val separatedMessageChannelSuffix = + if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.gma_mediation_chartboost.ChartboostSDKApi.setGDPRConsent$separatedMessageChannelSuffix", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val userConsentArg = args[0] as Boolean + val wrapped: List = + try { + api.setGDPRConsent(userConsentArg) + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.gma_mediation_chartboost.ChartboostSDKApi.setCCPAConsent$separatedMessageChannelSuffix", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val userOptInArg = args[0] as Boolean + val wrapped: List = + try { + api.setCCPAConsent(userOptInArg) + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } +} diff --git a/packages/mediation/gma_mediation_chartboost/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_chartboost/GmaMediationChartboostPlugin.kt b/packages/mediation/gma_mediation_chartboost/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_chartboost/GmaMediationChartboostPlugin.kt index 4c4b35124..7863b916d 100644 --- a/packages/mediation/gma_mediation_chartboost/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_chartboost/GmaMediationChartboostPlugin.kt +++ b/packages/mediation/gma_mediation_chartboost/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_chartboost/GmaMediationChartboostPlugin.kt @@ -14,11 +14,45 @@ package io.flutter.plugins.googlemobileads.mediation.gma_mediation_chartboost +import android.content.Context +import com.chartboost.sdk.Chartboost +import com.chartboost.sdk.privacy.model.CCPA +import com.chartboost.sdk.privacy.model.GDPR import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.embedding.engine.plugins.activity.ActivityAware +import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding /** Required to link the Android dependency of the Chartboost Adapter. */ -class GmaMediationChartboostPlugin: FlutterPlugin { - override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { } +class GmaMediationChartboostPlugin : FlutterPlugin, ActivityAware, ChartboostSDKApi { + private lateinit var context: Context - override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { } + override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { + context = flutterPluginBinding.applicationContext + ChartboostSDKApi.setUp(flutterPluginBinding.binaryMessenger, this) + } + + override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { + ChartboostSDKApi.setUp(binding.binaryMessenger, null) + } + + override fun setGDPRConsent(userConsent: Boolean) { + val dataUserConsent = + if (userConsent) GDPR(GDPR.GDPR_CONSENT.BEHAVIORAL) + else GDPR(GDPR.GDPR_CONSENT.NON_BEHAVIORAL) + Chartboost.addDataUseConsent(context, dataUserConsent) + } + + override fun setCCPAConsent(userOptIn: Boolean) { + val dataUseConsent = + if (userOptIn) CCPA(CCPA.CCPA_CONSENT.OPT_IN_SALE) else CCPA(CCPA.CCPA_CONSENT.OPT_OUT_SALE) + Chartboost.addDataUseConsent(context, dataUseConsent) + } + + override fun onDetachedFromActivity() {} + + override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {} + + override fun onAttachedToActivity(binding: ActivityPluginBinding) {} + + override fun onDetachedFromActivityForConfigChanges() {} } diff --git a/packages/mediation/gma_mediation_chartboost/android/src/test/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_chartboost/GmaMediationChartboostPluginTest.kt b/packages/mediation/gma_mediation_chartboost/android/src/test/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_chartboost/GmaMediationChartboostPluginTest.kt index d929f89a2..42010b1d2 100644 --- a/packages/mediation/gma_mediation_chartboost/android/src/test/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_chartboost/GmaMediationChartboostPluginTest.kt +++ b/packages/mediation/gma_mediation_chartboost/android/src/test/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_chartboost/GmaMediationChartboostPluginTest.kt @@ -14,4 +14,88 @@ package io.flutter.plugins.googlemobileads.mediation.gma_mediation_chartboost -internal class GmaMediationChartboostPluginTest {} +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.chartboost.sdk.Chartboost +import com.chartboost.sdk.privacy.model.CCPA +import com.chartboost.sdk.privacy.model.GDPR +import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.plugin.common.BinaryMessenger +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.mockStatic +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.eq +import org.mockito.kotlin.mock + +@RunWith(AndroidJUnit4::class) +internal class GmaMediationChartboostPluginTest { + private val context = ApplicationProvider.getApplicationContext() + private val mockBinaryMessenger = mock() + private val mockFlutterPluginBinding = + mock { + on { applicationContext } doReturn context + on { binaryMessenger } doReturn mockBinaryMessenger + } + + @Test + fun setGDPRConsent_withTrueValue_addsDataUserConsentAsBehavioral() { + val plugin = GmaMediationChartboostPlugin() + mockStatic(ChartboostSDKApi::class.java).use { mockedchartboostSDKApi -> + plugin.onAttachedToEngine(mockFlutterPluginBinding) + val expectedDataUserConsent = GDPR(GDPR.GDPR_CONSENT.BEHAVIORAL) + + plugin.setGDPRConsent(true) + + mockedchartboostSDKApi.verify { + Chartboost.addDataUseConsent(eq(context), eq(expectedDataUserConsent)) + } + } + } + + @Test + fun setGDPRConsent_withFalseValue_addsDataUserConsentAsNonBehavioral() { + val plugin = GmaMediationChartboostPlugin() + mockStatic(ChartboostSDKApi::class.java).use { mockedchartboostSDKApi -> + plugin.onAttachedToEngine(mockFlutterPluginBinding) + val expectedDataUserConsent = GDPR(GDPR.GDPR_CONSENT.NON_BEHAVIORAL) + + plugin.setGDPRConsent(false) + + mockedchartboostSDKApi.verify { + Chartboost.addDataUseConsent(eq(context), eq(expectedDataUserConsent)) + } + } + } + + @Test + fun setCCPAConsent_withTrueValue_addsDataUserConsentAsOptInSale() { + val plugin = GmaMediationChartboostPlugin() + mockStatic(ChartboostSDKApi::class.java).use { mockedchartboostSDKApi -> + plugin.onAttachedToEngine(mockFlutterPluginBinding) + val expectedDataUserConsent = CCPA(CCPA.CCPA_CONSENT.OPT_IN_SALE) + + plugin.setCCPAConsent(true) + + mockedchartboostSDKApi.verify { + Chartboost.addDataUseConsent(eq(context), eq(expectedDataUserConsent)) + } + } + } + + @Test + fun setCCPAConsent_withFalseValue_addsDataUserConsentAsOptOutSale() { + val plugin = GmaMediationChartboostPlugin() + mockStatic(ChartboostSDKApi::class.java).use { mockedchartboostSDKApi -> + plugin.onAttachedToEngine(mockFlutterPluginBinding) + val expectedDataUserConsent = CCPA(CCPA.CCPA_CONSENT.OPT_OUT_SALE) + + plugin.setCCPAConsent(false) + + mockedchartboostSDKApi.verify { + Chartboost.addDataUseConsent(eq(context), eq(expectedDataUserConsent)) + } + } + } +} diff --git a/packages/mediation/gma_mediation_chartboost/example/ios/RunnerTests/GmaMediationChartboostPluginTest.swift b/packages/mediation/gma_mediation_chartboost/example/ios/RunnerTests/GmaMediationChartboostPluginTest.swift deleted file mode 100644 index ccc66805e..000000000 --- a/packages/mediation/gma_mediation_chartboost/example/ios/RunnerTests/GmaMediationChartboostPluginTest.swift +++ /dev/null @@ -1,20 +0,0 @@ -// 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 -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import UIKit -import XCTest - -@testable import gma_mediation_chartboost - -class GmaMediationChartboostPluginTests: XCTestCase { } diff --git a/packages/mediation/gma_mediation_chartboost/example/ios/RunnerTests/GmaMediationChartboostPluginTests.swift b/packages/mediation/gma_mediation_chartboost/example/ios/RunnerTests/GmaMediationChartboostPluginTests.swift new file mode 100644 index 000000000..ce3092f75 --- /dev/null +++ b/packages/mediation/gma_mediation_chartboost/example/ios/RunnerTests/GmaMediationChartboostPluginTests.swift @@ -0,0 +1,49 @@ +// 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 +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import UIKit +import XCTest + +@testable import gma_mediation_chartboost + +class GmaMediationChartboostPluginTests: XCTestCase { + func testSetGDPRConsent() { + let chartboostApiFake = ChartboostApiFake() + + GmaMediationChartboostPlugin(chartboostApi: chartboostApiFake).setGDPRConsent(gdprConsent: true) + + XCTAssertTrue(chartboostApiFake.gdprConsent) + } + + func testSetCCPAConsent() { + let chartboostApiFake = ChartboostApiFake() + + GmaMediationChartboostPlugin(chartboostApi: chartboostApiFake).setCCPAConsent(ccpaConsent: true) + + XCTAssertTrue(chartboostApiFake.ccpaConsent) + } +} + +class ChartboostApiFake: ChartboostApiProtocol { + var gdprConsent: Bool = false + var ccpaConsent: Bool = false + + func setGDPRConsent(gdprConsent: Bool) { + self.gdprConsent = gdprConsent + } + + func setCCPAConsent(ccpaConsent: Bool) { + self.ccpaConsent = ccpaConsent + } +} diff --git a/packages/mediation/gma_mediation_chartboost/ios/Classes/ChartboostSDKApi.g.swift b/packages/mediation/gma_mediation_chartboost/ios/Classes/ChartboostSDKApi.g.swift new file mode 100644 index 000000000..e93e23bdd --- /dev/null +++ b/packages/mediation/gma_mediation_chartboost/ios/Classes/ChartboostSDKApi.g.swift @@ -0,0 +1,148 @@ +// Autogenerated from Pigeon (v22.6.2), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +import Foundation + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + +/// Error class for passing custom error details to Dart side. +final class PigeonError: Error { + let code: String + let message: String? + let details: Any? + + init(code: String, message: String?, details: Any?) { + self.code = code + self.message = message + self.details = details + } + + var localizedDescription: String { + return + "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" + } +} + +private func wrapResult(_ result: Any?) -> [Any?] { + return [result] +} + +private func wrapError(_ error: Any) -> [Any?] { + if let pigeonError = error as? PigeonError { + return [ + pigeonError.code, + pigeonError.message, + pigeonError.details, + ] + } + if let flutterError = error as? FlutterError { + return [ + flutterError.code, + flutterError.message, + flutterError.details, + ] + } + return [ + "\(error)", + "\(type(of: error))", + "Stacktrace: \(Thread.callStackSymbols)", + ] +} + +private func isNullish(_ value: Any?) -> Bool { + return value is NSNull || value == nil +} + +private func nilOrValue(_ value: Any?) -> T? { + if value is NSNull { return nil } + return value as! T? +} + +private class ChartboostSDKApiPigeonCodecReader: FlutterStandardReader { +} + +private class ChartboostSDKApiPigeonCodecWriter: FlutterStandardWriter { +} + +private class ChartboostSDKApiPigeonCodecReaderWriter: FlutterStandardReaderWriter { + override func reader(with data: Data) -> FlutterStandardReader { + return ChartboostSDKApiPigeonCodecReader(data: data) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + return ChartboostSDKApiPigeonCodecWriter(data: data) + } +} + +class ChartboostSDKApiPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { + static let shared = ChartboostSDKApiPigeonCodec( + readerWriter: ChartboostSDKApiPigeonCodecReaderWriter()) +} + +/// The generated classes set the channels to call the methods in the +/// corresponding kotlin ChartboostSDKApi interface and swift ChartboostSDKApi +/// protocol from the dart layer. +/// +/// Generated protocol from Pigeon that represents a handler of messages from Flutter. +protocol ChartboostSDKApi { + /// Used to configure GDPR consent on the Android or iOS Chartboost SDK + func setGDPRConsent(userConsent: Bool) throws + /// Used to opt out of the sale of personal information in Chartboost SDK. + func setCCPAConsent(userOptIn: Bool) throws +} + +/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. +class ChartboostSDKApiSetup { + static var codec: FlutterStandardMessageCodec { ChartboostSDKApiPigeonCodec.shared } + /// Sets up an instance of `ChartboostSDKApi` to handle messages through the `binaryMessenger`. + static func setUp( + binaryMessenger: FlutterBinaryMessenger, api: ChartboostSDKApi?, + messageChannelSuffix: String = "" + ) { + let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" + /// Used to configure GDPR consent on the Android or iOS Chartboost SDK + let setGDPRConsentChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.gma_mediation_chartboost.ChartboostSDKApi.setGDPRConsent\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + setGDPRConsentChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let userConsentArg = args[0] as! Bool + do { + try api.setGDPRConsent(userConsent: userConsentArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setGDPRConsentChannel.setMessageHandler(nil) + } + /// Used to opt out of the sale of personal information in Chartboost SDK. + let setCCPAConsentChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.gma_mediation_chartboost.ChartboostSDKApi.setCCPAConsent\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + setCCPAConsentChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let userOptInArg = args[0] as! Bool + do { + try api.setCCPAConsent(userOptIn: userOptInArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setCCPAConsentChannel.setMessageHandler(nil) + } + } +} diff --git a/packages/mediation/gma_mediation_chartboost/ios/Classes/GmaMediationChartboostPlugin.swift b/packages/mediation/gma_mediation_chartboost/ios/Classes/GmaMediationChartboostPlugin.swift index ef294f815..0df3d19ff 100644 --- a/packages/mediation/gma_mediation_chartboost/ios/Classes/GmaMediationChartboostPlugin.swift +++ b/packages/mediation/gma_mediation_chartboost/ios/Classes/GmaMediationChartboostPlugin.swift @@ -15,7 +15,56 @@ import Flutter import UIKit -/** Required to link the iOS dependency of the Chartboost Adapter. */ -public class GmaMediationChartboostPlugin: NSObject, FlutterPlugin { - public static func register(with registrar: FlutterPluginRegistrar) { } +/// Required to link the iOS dependency of the Chartboost Adapter. +public class GmaMediationChartboostPlugin: NSObject, FlutterPlugin, ChartboostSDKApi { + let chartboostApi: ChartboostApiProtocol + + init(chartboostApi: ChartboostApiProtocol) { + self.chartboostApi = chartboostApi + } + + public static func register(with registrar: FlutterPluginRegistrar) { + let messenger: FlutterBinaryMessenger = registrar.messenger() + let api: ChartboostSDKApi & NSObjectProtocol = GmaMediationChartboostPlugin( + chartboostApi: ChartboostApiImpl()) + ChartboostSDKApiSetup.setUp(binaryMessenger: messenger, api: api) + } + + public func detachFromEngine(for registrar: FlutterPluginRegistrar) { + let messenger: FlutterBinaryMessenger = registrar.messenger() + ChartboostSDKApiSetup.setUp(binaryMessenger: messenger, api: nil) + } + + func setGDPRConsent(userConsent: Bool) { + chartboostApi.setGDPRConsent(gdprConsent: userConsent) + } + + func setCCPAConsent(userConsent: Bool) { + chartboostApi.setCCPAConsent(ccpaConsent: userConsent) + } +} + +protocol ChartboostApiProtocol { + func setGDPRConsent(gdprConsent: Bool) + func setCCPAConsent(ccpaConsent: Bool) +} + +class ChartboostApiImpl: ChartboostApiProtocol { + + func setGDPRConsent(gdprConsent: Bool) { + Chartboost.addDataUseConsent( + CHBDataUseConsent.GDPR( + gdprConsent + ? CHBDataUseConsent.GDPR.Consent.behavioral : CHBDataUseConsent.GDPR.Consent.nonbehavioral + ) + ) + } + + func setCCPAConsent(ccpaConsent: Bool) { + Chartboost.addDataUseConsent( + CHBDataUseConsent.CCPA( + ccpaConsent + ? CHBDataUseConsent.CCPA.Consent.optInSale : CHBDataUseConsent.CCPA.Consent.optOutSale) + ) + } } diff --git a/packages/mediation/gma_mediation_chartboost/lib/chartboost_sdk_api.g.dart b/packages/mediation/gma_mediation_chartboost/lib/chartboost_sdk_api.g.dart new file mode 100644 index 000000000..cbb7164cf --- /dev/null +++ b/packages/mediation/gma_mediation_chartboost/lib/chartboost_sdk_api.g.dart @@ -0,0 +1,107 @@ +// Autogenerated from Pigeon (v22.6.2), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers + +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; + +PlatformException _createConnectionError(String channelName) { + return PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); +} + +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + default: + return super.readValueOfType(type, buffer); + } + } +} + +/// The generated classes set the channels to call the methods in the +/// corresponding kotlin ChartboostSDKApi interface and swift ChartboostSDKApi +/// protocol from the dart layer. +class ChartboostSDKApi { + /// Constructor for [ChartboostSDKApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + ChartboostSDKApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + final BinaryMessenger? pigeonVar_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); + + final String pigeonVar_messageChannelSuffix; + + /// Used to configure GDPR consent on the Android or iOS Chartboost SDK + Future setGDPRConsent(bool userConsent) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.gma_mediation_chartboost.ChartboostSDKApi.setGDPRConsent$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final List? pigeonVar_replyList = + await pigeonVar_channel.send([userConsent]) as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } + + /// Used to opt out of the sale of personal information in Chartboost SDK. + Future setCCPAConsent(bool userOptIn) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.gma_mediation_chartboost.ChartboostSDKApi.setCCPAConsent$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final List? pigeonVar_replyList = + await pigeonVar_channel.send([userOptIn]) as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } +} diff --git a/packages/mediation/gma_mediation_chartboost/lib/gma_mediation_chartboost.dart b/packages/mediation/gma_mediation_chartboost/lib/gma_mediation_chartboost.dart index 666426317..03f9c4984 100644 --- a/packages/mediation/gma_mediation_chartboost/lib/gma_mediation_chartboost.dart +++ b/packages/mediation/gma_mediation_chartboost/lib/gma_mediation_chartboost.dart @@ -12,5 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -/// This empty class is needed to allow correct compatibility analysis with host platforms. -class GmaMediationChartboost {} +import 'package:gma_mediation_chartboost/chartboost_sdk_api.g.dart'; + +/// This class has entrypoint to call Chartboost SDK APIs. +class GmaMediationChartboost { + Future setGDPRConsent(bool userConsent) async { + ChartboostSDKApi().setGDPRConsent(userConsent); + } + + Future setCCPAConsent(bool userOptIn) async { + ChartboostSDKApi().setCCPAConsent(userOptIn); + } +} diff --git a/packages/mediation/gma_mediation_chartboost/pigeons/chartboost_sdk_api.dart b/packages/mediation/gma_mediation_chartboost/pigeons/chartboost_sdk_api.dart index 97411b562..9dd17269a 100644 --- a/packages/mediation/gma_mediation_chartboost/pigeons/chartboost_sdk_api.dart +++ b/packages/mediation/gma_mediation_chartboost/pigeons/chartboost_sdk_api.dart @@ -31,5 +31,13 @@ import 'package:pigeon/pigeon.dart'; ) @HostApi() -/// The generated classes set the channels to call the methods in the corresponding kotlin ChartboostSDKApi interface and swift ChartboostSDKApi protocol from the dart layer. -abstract class ChartboostSDKApi { } +/// The generated classes set the channels to call the methods in the +/// corresponding kotlin ChartboostSDKApi interface and swift ChartboostSDKApi +/// protocol from the dart layer. +abstract class ChartboostSDKApi { + /// Used to configure GDPR consent on the Android or iOS Chartboost SDK + void setGDPRConsent(bool userConsent); + + /// Used to opt out of the sale of personal information in Chartboost SDK. + void setCCPAConsent(bool userOptIn); +}