Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
22 changes: 16 additions & 6 deletions packages/mediation/gma_mediation_chartboost/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// 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<Any?> {
return listOf(result)
}

private fun wrapError(exception: Throwable): List<Any?> {
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()

enum class ChartboostPrivacyStandard(val raw: Int) {
GDPR(0),
CCPA(1);

companion object {
fun ofRaw(raw: Int): ChartboostPrivacyStandard? {
return values().firstOrNull { it.raw == raw }
}
}
}

private open class ChartboostSDKApiPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return when (type) {
129.toByte() -> {
return (readValue(buffer) as Long?)?.let { ChartboostPrivacyStandard.ofRaw(it.toInt()) }
}
else -> super.readValueOfType(type, buffer)
}
}

override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
when (value) {
is ChartboostPrivacyStandard -> {
stream.write(129)
writeValue(stream, value.raw)
}
else -> 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)

/** Used to clear any of the privacy data use consent above. */
fun clearDataUseConsent(privacyStandard: ChartboostPrivacyStandard)

companion object {
/** The codec used by ChartboostSDKApi. */
val codec: MessageCodec<Any?> 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<Any?>(
binaryMessenger,
"dev.flutter.pigeon.gma_mediation_chartboost.ChartboostSDKApi.setGDPRConsent$separatedMessageChannelSuffix",
codec,
)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val userConsentArg = args[0] as Boolean
val wrapped: List<Any?> =
try {
api.setGDPRConsent(userConsentArg)
listOf(null)
} catch (exception: Throwable) {
wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel =
BasicMessageChannel<Any?>(
binaryMessenger,
"dev.flutter.pigeon.gma_mediation_chartboost.ChartboostSDKApi.setCCPAConsent$separatedMessageChannelSuffix",
codec,
)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val userOptInArg = args[0] as Boolean
val wrapped: List<Any?> =
try {
api.setCCPAConsent(userOptInArg)
listOf(null)
} catch (exception: Throwable) {
wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel =
BasicMessageChannel<Any?>(
binaryMessenger,
"dev.flutter.pigeon.gma_mediation_chartboost.ChartboostSDKApi.clearDataUseConsent$separatedMessageChannelSuffix",
codec,
)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val privacyStandardArg = args[0] as ChartboostPrivacyStandard
val wrapped: List<Any?> =
try {
api.clearDataUseConsent(privacyStandardArg)
listOf(null)
} catch (exception: Throwable) {
wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,54 @@

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 clearDataUseConsent(privacyStandard: ChartboostPrivacyStandard) {
val dataUseConsent =
when (privacyStandard) {
ChartboostPrivacyStandard.GDPR -> GDPR(GDPR.GDPR_CONSENT.BEHAVIORAL)
ChartboostPrivacyStandard.CCPA -> CCPA(CCPA.CCPA_CONSENT.OPT_IN_SALE)
}
Chartboost.clearDataUseConsent(context, dataUseConsent.privacyStandard)
}

override fun onDetachedFromActivity() {}

override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {}

override fun onAttachedToActivity(binding: ActivityPluginBinding) {}

override fun onDetachedFromActivityForConfigChanges() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,118 @@

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<Context>()
private val mockBinaryMessenger = mock<BinaryMessenger>()
private val mockFlutterPluginBinding =
mock<FlutterPlugin.FlutterPluginBinding> {
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))
}
}
}

@Test
fun clearDataUseConsent_usesGDPRPrivacyStandard() {
val plugin = GmaMediationChartboostPlugin()
mockStatic(ChartboostSDKApi::class.java).use { mockedchartboostSDKApi ->
plugin.onAttachedToEngine(mockFlutterPluginBinding)
val expectedPrivacyStandard = GDPR(GDPR.GDPR_CONSENT.NON_BEHAVIORAL).privacyStandard

plugin.clearDataUseConsent(ChartboostPrivacyStandard.GDPR)

mockedchartboostSDKApi.verify {
Chartboost.clearDataUseConsent(eq(context), eq(expectedPrivacyStandard))
}
}
}

@Test
fun clearDataUseConsent_usesCCPAPrivacyStandard() {
val plugin = GmaMediationChartboostPlugin()
mockStatic(ChartboostSDKApi::class.java).use { mockedchartboostSDKApi ->
plugin.onAttachedToEngine(mockFlutterPluginBinding)
val expectedPrivacyStandard = CCPA(CCPA.CCPA_CONSENT.OPT_OUT_SALE).privacyStandard

plugin.clearDataUseConsent(ChartboostPrivacyStandard.CCPA)

mockedchartboostSDKApi.verify {
Chartboost.clearDataUseConsent(eq(context), eq(expectedPrivacyStandard))
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
Loading
Loading