Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,24 @@ class FirebaseAppCheckPlugin : FlutterFirebasePlugin, FlutterPlugin, FirebaseApp
}
}

override fun getTokenResult(
appName: String,
forceRefresh: Boolean,
callback: (Result<InternalAppCheckTokenResult?>) -> Unit
) {
val firebaseAppCheck = getAppCheck(appName)
firebaseAppCheck.getAppCheckToken(forceRefresh).addOnCompleteListener { task ->
if (task.isSuccessful) {
val token = task.result
callback(
Result.success(
token?.let { InternalAppCheckTokenResult(it.token, it.expireTimeMillis) }))
} else {
callback(Result.failure(FlutterError("firebase_app_check", task.exception?.message, null)))
}
}
}

override fun setTokenAutoRefreshEnabled(
appName: String,
isTokenAutoRefreshEnabled: Boolean,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,150 @@ private object GeneratedAndroidFirebaseAppCheckPigeonUtils {
"Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception))
}
}

fun doubleEquals(a: Double, b: Double): Boolean {
// Normalize -0.0 to 0.0 and handle NaN equality.
return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN())
}

fun floatEquals(a: Float, b: Float): Boolean {
// Normalize -0.0 to 0.0 and handle NaN equality.
return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN())
}

fun doubleHash(d: Double): Int {
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
val normalized = if (d == 0.0) 0.0 else d
val bits = java.lang.Double.doubleToLongBits(normalized)
return (bits xor (bits ushr 32)).toInt()
}

fun floatHash(f: Float): Int {
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
val normalized = if (f == 0.0f) 0.0f else f
return java.lang.Float.floatToIntBits(normalized)
}

fun deepEquals(a: Any?, b: Any?): Boolean {
if (a === b) {
return true
}
if (a == null || b == null) {
return false
}
if (a is ByteArray && b is ByteArray) {
return a.contentEquals(b)
}
if (a is IntArray && b is IntArray) {
return a.contentEquals(b)
}
if (a is LongArray && b is LongArray) {
return a.contentEquals(b)
}
if (a is DoubleArray && b is DoubleArray) {
if (a.size != b.size) return false
for (i in a.indices) {
if (!doubleEquals(a[i], b[i])) return false
}
return true
}
if (a is FloatArray && b is FloatArray) {
if (a.size != b.size) return false
for (i in a.indices) {
if (!floatEquals(a[i], b[i])) return false
}
return true
}
if (a is Array<*> && b is Array<*>) {
if (a.size != b.size) return false
for (i in a.indices) {
if (!deepEquals(a[i], b[i])) return false
}
return true
}
if (a is List<*> && b is List<*>) {
if (a.size != b.size) return false
val iterA = a.iterator()
val iterB = b.iterator()
while (iterA.hasNext() && iterB.hasNext()) {
if (!deepEquals(iterA.next(), iterB.next())) return false
}
return true
}
if (a is Map<*, *> && b is Map<*, *>) {
if (a.size != b.size) return false
for (entry in a) {
val key = entry.key
var found = false
for (bEntry in b) {
if (deepEquals(key, bEntry.key)) {
if (deepEquals(entry.value, bEntry.value)) {
found = true
break
} else {
return false
}
}
}
if (!found) return false
}
return true
}
if (a is Double && b is Double) {
return doubleEquals(a, b)
}
if (a is Float && b is Float) {
return floatEquals(a, b)
}
return a == b
}

fun deepHash(value: Any?): Int {
return when (value) {
null -> 0
is ByteArray -> value.contentHashCode()
is IntArray -> value.contentHashCode()
is LongArray -> value.contentHashCode()
is DoubleArray -> {
var result = 1
for (item in value) {
result = 31 * result + doubleHash(item)
}
result
}
is FloatArray -> {
var result = 1
for (item in value) {
result = 31 * result + floatHash(item)
}
result
}
is Array<*> -> {
var result = 1
for (item in value) {
result = 31 * result + deepHash(item)
}
result
}
is List<*> -> {
var result = 1
for (item in value) {
result = 31 * result + deepHash(item)
}
result
}
is Map<*, *> -> {
var result = 0
for (entry in value) {
result += ((deepHash(entry.key) * 31) xor deepHash(entry.value))
}
result
}
is Double -> doubleHash(value)
is Float -> floatHash(value)
else -> value.hashCode()
}
}
}

/**
Expand All @@ -46,13 +190,63 @@ class FlutterError(
val details: Any? = null
) : RuntimeException()

/** Generated class from Pigeon that represents data sent in messages. */
data class InternalAppCheckTokenResult(val token: String, val expirationTimestamp: Long? = null) {
companion object {
fun fromList(pigeonVar_list: List<Any?>): InternalAppCheckTokenResult {
val token = pigeonVar_list[0] as String
val expirationTimestamp = pigeonVar_list[1] as Long?
return InternalAppCheckTokenResult(token, expirationTimestamp)
}
}

fun toList(): List<Any?> {
return listOf(
token,
expirationTimestamp,
)
}

override fun equals(other: Any?): Boolean {
if (other == null || other.javaClass != javaClass) {
return false
}
if (this === other) {
return true
}
val other = other as InternalAppCheckTokenResult
return GeneratedAndroidFirebaseAppCheckPigeonUtils.deepEquals(this.token, other.token) &&
GeneratedAndroidFirebaseAppCheckPigeonUtils.deepEquals(
this.expirationTimestamp, other.expirationTimestamp)
}

override fun hashCode(): Int {
var result = javaClass.hashCode()
result = 31 * result + GeneratedAndroidFirebaseAppCheckPigeonUtils.deepHash(this.token)
result =
31 * result + GeneratedAndroidFirebaseAppCheckPigeonUtils.deepHash(this.expirationTimestamp)
return result
}
}

private open class GeneratedAndroidFirebaseAppCheckPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return super.readValueOfType(type, buffer)
return when (type) {
129.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let { InternalAppCheckTokenResult.fromList(it) }
}
else -> super.readValueOfType(type, buffer)
}
}

override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
super.writeValue(stream, value)
when (value) {
is InternalAppCheckTokenResult -> {
stream.write(129)
writeValue(stream, value.toList())
}
else -> super.writeValue(stream, value)
}
}
}

Expand All @@ -68,6 +262,12 @@ interface FirebaseAppCheckHostApi {

fun getToken(appName: String, forceRefresh: Boolean, callback: (Result<String?>) -> Unit)

fun getTokenResult(
appName: String,
forceRefresh: Boolean,
callback: (Result<InternalAppCheckTokenResult?>) -> Unit
)

fun setTokenAutoRefreshEnabled(
appName: String,
isTokenAutoRefreshEnabled: Boolean,
Expand Down Expand Up @@ -145,6 +345,32 @@ interface FirebaseAppCheckHostApi {
channel.setMessageHandler(null)
}
}
run {
val channel =
BasicMessageChannel<Any?>(
binaryMessenger,
"dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getTokenResult$separatedMessageChannelSuffix",
codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val appNameArg = args[0] as String
val forceRefreshArg = args[1] as Boolean
api.getTokenResult(appNameArg, forceRefreshArg) {
result: Result<InternalAppCheckTokenResult?> ->
val error = result.exceptionOrNull()
if (error != null) {
reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapError(error))
} else {
val data = result.getOrNull()
reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapResult(data))
}
}
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel =
BasicMessageChannel<Any?>(
Expand Down
Loading
Loading