From 359fec804abcd90340bf66f1f3fd3bbeb3e703b0 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Wed, 6 May 2026 21:36:26 -0700 Subject: [PATCH 1/9] first commit for appcheck recaptcha support --- .../firebase_app_check/android/build.gradle | 1 + .../appcheck/FirebaseAppCheckPlugin.kt | 12 + .../GeneratedAndroidFirebaseAppCheck.g.kt | 9 +- .../FirebaseAppCheckMessages.g.swift | 120 ++-- .../firebase_app_check/windows/messages.g.cpp | 580 +++++++++++------- .../firebase_app_check/windows/messages.g.h | 88 +-- .../lib/src/android_providers.dart | 12 + .../method_channel_firebase_app_check.dart | 6 + .../lib/src/pigeon/messages.pigeon.dart | 214 +++---- .../pigeons/messages.dart | 2 + ...ethod_channel_firebase_app_check_test.dart | 28 + 11 files changed, 610 insertions(+), 462 deletions(-) diff --git a/packages/firebase_app_check/firebase_app_check/android/build.gradle b/packages/firebase_app_check/firebase_app_check/android/build.gradle index 45c2fa4d6345..920e8e906e00 100644 --- a/packages/firebase_app_check/firebase_app_check/android/build.gradle +++ b/packages/firebase_app_check/firebase_app_check/android/build.gradle @@ -80,6 +80,7 @@ android { implementation platform("com.google.firebase:firebase-bom:${getRootProjectExtOrCoreProperty("FirebaseSDKVersion", firebaseCoreProject)}") implementation 'com.google.firebase:firebase-appcheck-debug' implementation 'com.google.firebase:firebase-appcheck-playintegrity' + implementation 'com.google.firebase:firebase-appcheck-recaptchaenterprise' implementation 'androidx.annotation:annotation:1.7.0' } } diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt index 0dc0ce26dc7e..f9908dee54bc 100644 --- a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt @@ -9,6 +9,7 @@ import com.google.firebase.FirebaseApp import com.google.firebase.appcheck.FirebaseAppCheck import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory +import com.google.firebase.appcheck.recaptchaenterprise.ReCaptchaEnterpriseProviderFactory import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding import io.flutter.plugin.common.BinaryMessenger @@ -55,6 +56,7 @@ class FirebaseAppCheckPlugin : androidProvider: String?, appleProvider: String?, debugToken: String?, + recaptchaEnterpriseSiteKey: String?, callback: (Result) -> Unit ) { try { @@ -66,6 +68,16 @@ class FirebaseAppCheckPlugin : DebugAppCheckProviderFactory.getInstance() ) } + "recaptchaEnterprise" -> { + if (recaptchaEnterpriseSiteKey != null) { + firebaseAppCheck.installAppCheckProviderFactory( + ReCaptchaEnterpriseProviderFactory.getInstance(recaptchaEnterpriseSiteKey) + ) + } else { + callback(Result.failure(FlutterError("invalid-argument", "Site key is required for reCAPTCHA Enterprise", null))) + return + } + } else -> { firebaseAppCheck.installAppCheckProviderFactory( PlayIntegrityAppCheckProviderFactory.getInstance() diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt index 0a046dd5aa47..099f8514464d 100644 --- a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon @file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") @@ -49,7 +49,7 @@ class FlutterError ( val code: String, override val message: String? = null, val details: Any? = null -) : Throwable() +) : RuntimeException() private open class GeneratedAndroidFirebaseAppCheckPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return super.readValueOfType(type, buffer) @@ -62,7 +62,7 @@ private open class GeneratedAndroidFirebaseAppCheckPigeonCodec : StandardMessage /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface FirebaseAppCheckHostApi { - fun activate(appName: String, androidProvider: String?, appleProvider: String?, debugToken: String?, callback: (Result) -> Unit) + fun activate(appName: String, androidProvider: String?, appleProvider: String?, debugToken: String?, recaptchaEnterpriseSiteKey: String?, callback: (Result) -> Unit) fun getToken(appName: String, forceRefresh: Boolean, callback: (Result) -> Unit) fun setTokenAutoRefreshEnabled(appName: String, isTokenAutoRefreshEnabled: Boolean, callback: (Result) -> Unit) fun registerTokenListener(appName: String, callback: (Result) -> Unit) @@ -86,7 +86,8 @@ interface FirebaseAppCheckHostApi { val androidProviderArg = args[1] as String? val appleProviderArg = args[2] as String? val debugTokenArg = args[3] as String? - api.activate(appNameArg, androidProviderArg, appleProviderArg, debugTokenArg) { result: Result -> + val recaptchaEnterpriseSiteKeyArg = args[4] as String? + api.activate(appNameArg, androidProviderArg, appleProviderArg, debugTokenArg, recaptchaEnterpriseSiteKeyArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapError(error)) diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift index 1842cfe9c240..bc76bee940f7 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon import Foundation @@ -27,12 +27,13 @@ final class PigeonError: Error { } var localizedDescription: String { - "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" + return + "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" } } private func wrapResult(_ result: Any?) -> [Any?] { - [result] + return [result] } private func wrapError(_ error: Any) -> [Any?] { @@ -52,13 +53,13 @@ private func wrapError(_ error: Any) -> [Any?] { } return [ "\(error)", - "\(type(of: error))", + "\(Swift.type(of: error))", "Stacktrace: \(Thread.callStackSymbols)", ] } private func isNullish(_ value: Any?) -> Bool { - value is NSNull || value == nil + return value is NSNull || value == nil } private func nilOrValue(_ value: Any?) -> T? { @@ -66,73 +67,57 @@ private func nilOrValue(_ value: Any?) -> T? { return value as! T? } -private class FirebaseAppCheckMessagesPigeonCodecReader: FlutterStandardReader {} -private class FirebaseAppCheckMessagesPigeonCodecWriter: FlutterStandardWriter {} +private class FirebaseAppCheckMessagesPigeonCodecReader: FlutterStandardReader { +} + +private class FirebaseAppCheckMessagesPigeonCodecWriter: FlutterStandardWriter { +} private class FirebaseAppCheckMessagesPigeonCodecReaderWriter: FlutterStandardReaderWriter { override func reader(with data: Data) -> FlutterStandardReader { - FirebaseAppCheckMessagesPigeonCodecReader(data: data) + return FirebaseAppCheckMessagesPigeonCodecReader(data: data) } override func writer(with data: NSMutableData) -> FlutterStandardWriter { - FirebaseAppCheckMessagesPigeonCodecWriter(data: data) + return FirebaseAppCheckMessagesPigeonCodecWriter(data: data) } } class FirebaseAppCheckMessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = - FirebaseAppCheckMessagesPigeonCodec( - readerWriter: FirebaseAppCheckMessagesPigeonCodecReaderWriter() - ) + static let shared = FirebaseAppCheckMessagesPigeonCodec(readerWriter: FirebaseAppCheckMessagesPigeonCodecReaderWriter()) } + /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol FirebaseAppCheckHostApi { - func activate(appName: String, androidProvider: String?, appleProvider: String?, - debugToken: String?, completion: @escaping (Result) -> Void) - func getToken(appName: String, forceRefresh: Bool, - completion: @escaping (Result) -> Void) - func setTokenAutoRefreshEnabled(appName: String, isTokenAutoRefreshEnabled: Bool, - completion: @escaping (Result) -> Void) + func activate(appName: String, androidProvider: String?, appleProvider: String?, debugToken: String?, recaptchaEnterpriseSiteKey: String?, completion: @escaping (Result) -> Void) + func getToken(appName: String, forceRefresh: Bool, completion: @escaping (Result) -> Void) + func setTokenAutoRefreshEnabled(appName: String, isTokenAutoRefreshEnabled: Bool, completion: @escaping (Result) -> Void) func registerTokenListener(appName: String, completion: @escaping (Result) -> Void) - func getLimitedUseAppCheckToken(appName: String, - completion: @escaping (Result) -> Void) + func getLimitedUseAppCheckToken(appName: String, completion: @escaping (Result) -> Void) } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. class FirebaseAppCheckHostApiSetup { - static var codec: FlutterStandardMessageCodec { - FirebaseAppCheckMessagesPigeonCodec.shared - } - - /// Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through the - /// `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: FirebaseAppCheckHostApi?, - messageChannelSuffix: String = "") { + static var codec: FlutterStandardMessageCodec { FirebaseAppCheckMessagesPigeonCodec.shared } + /// Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through the `binaryMessenger`. + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: FirebaseAppCheckHostApi?, messageChannelSuffix: String = "") { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - let activateChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate\(channelSuffix)", - binaryMessenger: binaryMessenger, - codec: codec - ) - if let api { + let activateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { activateChannel.setMessageHandler { message, reply in let args = message as! [Any?] let appNameArg = args[0] as! String let androidProviderArg: String? = nilOrValue(args[1]) let appleProviderArg: String? = nilOrValue(args[2]) let debugTokenArg: String? = nilOrValue(args[3]) - api.activate( - appName: appNameArg, - androidProvider: androidProviderArg, - appleProvider: appleProviderArg, - debugToken: debugTokenArg - ) { result in + let recaptchaEnterpriseSiteKeyArg: String? = nilOrValue(args[4]) + api.activate(appName: appNameArg, androidProvider: androidProviderArg, appleProvider: appleProviderArg, debugToken: debugTokenArg, recaptchaEnterpriseSiteKey: recaptchaEnterpriseSiteKeyArg) { result in switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -140,21 +125,17 @@ class FirebaseAppCheckHostApiSetup { } else { activateChannel.setMessageHandler(nil) } - let getTokenChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken\(channelSuffix)", - binaryMessenger: binaryMessenger, - codec: codec - ) - if let api { + let getTokenChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { getTokenChannel.setMessageHandler { message, reply in let args = message as! [Any?] let appNameArg = args[0] as! String let forceRefreshArg = args[1] as! Bool api.getToken(appName: appNameArg, forceRefresh: forceRefreshArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -162,24 +143,17 @@ class FirebaseAppCheckHostApiSetup { } else { getTokenChannel.setMessageHandler(nil) } - let setTokenAutoRefreshEnabledChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled\(channelSuffix)", - binaryMessenger: binaryMessenger, - codec: codec - ) - if let api { + let setTokenAutoRefreshEnabledChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { setTokenAutoRefreshEnabledChannel.setMessageHandler { message, reply in let args = message as! [Any?] let appNameArg = args[0] as! String let isTokenAutoRefreshEnabledArg = args[1] as! Bool - api.setTokenAutoRefreshEnabled( - appName: appNameArg, - isTokenAutoRefreshEnabled: isTokenAutoRefreshEnabledArg - ) { result in + api.setTokenAutoRefreshEnabled(appName: appNameArg, isTokenAutoRefreshEnabled: isTokenAutoRefreshEnabledArg) { result in switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -187,20 +161,16 @@ class FirebaseAppCheckHostApiSetup { } else { setTokenAutoRefreshEnabledChannel.setMessageHandler(nil) } - let registerTokenListenerChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener\(channelSuffix)", - binaryMessenger: binaryMessenger, - codec: codec - ) - if let api { + let registerTokenListenerChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { registerTokenListenerChannel.setMessageHandler { message, reply in let args = message as! [Any?] let appNameArg = args[0] as! String api.registerTokenListener(appName: appNameArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -208,20 +178,16 @@ class FirebaseAppCheckHostApiSetup { } else { registerTokenListenerChannel.setMessageHandler(nil) } - let getLimitedUseAppCheckTokenChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken\(channelSuffix)", - binaryMessenger: binaryMessenger, - codec: codec - ) - if let api { + let getLimitedUseAppCheckTokenChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { getLimitedUseAppCheckTokenChannel.setMessageHandler { message, reply in let args = message as! [Any?] let appNameArg = args[0] as! String api.getLimitedUseAppCheckToken(appName: appNameArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } diff --git a/packages/firebase_app_check/firebase_app_check/windows/messages.g.cpp b/packages/firebase_app_check/firebase_app_check/windows/messages.g.cpp index 0343b73ea815..d46886ee294e 100644 --- a/packages/firebase_app_check/firebase_app_check/windows/messages.g.cpp +++ b/packages/firebase_app_check/firebase_app_check/windows/messages.g.cpp @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #undef _HAS_EXCEPTIONS @@ -13,16 +13,18 @@ #include #include +#include +#include #include #include #include namespace firebase_app_check_windows { -using flutter::BasicMessageChannel; -using flutter::CustomEncodableValue; -using flutter::EncodableList; -using flutter::EncodableMap; -using flutter::EncodableValue; +using ::flutter::BasicMessageChannel; +using ::flutter::CustomEncodableValue; +using ::flutter::EncodableList; +using ::flutter::EncodableMap; +using ::flutter::EncodableValue; FlutterError CreateConnectionError(const std::string channel_name) { return FlutterError( @@ -31,277 +33,419 @@ FlutterError CreateConnectionError(const std::string channel_name) { EncodableValue("")); } +namespace { +template +bool PigeonInternalDeepEquals(const T& a, const T& b); + +bool PigeonInternalDeepEquals(const double& a, const double& b); + +template +bool PigeonInternalDeepEquals(const std::vector& a, const std::vector& b); + +template +bool PigeonInternalDeepEquals(const std::map& a, const std::map& b); + +template +bool PigeonInternalDeepEquals(const std::optional& a, const std::optional& b); + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, const std::unique_ptr& b); + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, const ::flutter::EncodableValue& b); + +template +bool PigeonInternalDeepEquals(const T& a, const T& b) { + return a == b; +} + +template +bool PigeonInternalDeepEquals(const std::vector& a, const std::vector& b) { + if (a.size() != b.size()) { + return false; + } + for (size_t i = 0; i < a.size(); ++i) { + if (!PigeonInternalDeepEquals(a[i], b[i])) { + return false; + } + } + return true; +} + +template +bool PigeonInternalDeepEquals(const std::map& a, const std::map& b) { + if (a.size() != b.size()) { + return false; + } + for (const auto& kv : a) { + bool found = false; + for (const auto& b_kv : b) { + if (PigeonInternalDeepEquals(kv.first, b_kv.first)) { + if (PigeonInternalDeepEquals(kv.second, b_kv.second)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; +} + +bool PigeonInternalDeepEquals(const double& a, const double& b) { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (a == b) || (std::isnan(a) && std::isnan(b)); +} + +template +bool PigeonInternalDeepEquals(const std::optional& a, const std::optional& b) { + if (!a && !b) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, const std::unique_ptr& b) { + if (a.get() == b.get()) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, const ::flutter::EncodableValue& b) { + if (a.index() != b.index()) { + return false; + } + if (const double* da = std::get_if(&a)) { + return PigeonInternalDeepEquals(*da, std::get(b)); + } else if (const ::flutter::EncodableList* la = std::get_if<::flutter::EncodableList>(&a)) { + return PigeonInternalDeepEquals(*la, std::get<::flutter::EncodableList>(b)); + } else if (const ::flutter::EncodableMap* ma = std::get_if<::flutter::EncodableMap>(&a)) { + return PigeonInternalDeepEquals(*ma, std::get<::flutter::EncodableMap>(b)); + } + return a == b; +} + +template +size_t PigeonInternalDeepHash(const T& v); + +size_t PigeonInternalDeepHash(const double& v); + +template +size_t PigeonInternalDeepHash(const std::vector& v); + +template +size_t PigeonInternalDeepHash(const std::map& v); + +template +size_t PigeonInternalDeepHash(const std::optional& v); + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v); + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v); + +template +size_t PigeonInternalDeepHash(const T& v) { + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::vector& v) { + size_t result = 1; + for (const auto& item : v) { + result = result * 31 + PigeonInternalDeepHash(item); + } + return result; +} + +template +size_t PigeonInternalDeepHash(const std::map& v) { + size_t result = 0; + for (const auto& kv : v) { + result += ((PigeonInternalDeepHash(kv.first) * 31) ^ PigeonInternalDeepHash(kv.second)); + } + return result; +} + +size_t PigeonInternalDeepHash(const double& v) { + if (std::isnan(v)) { + // Normalize NaN to a consistent hash. + return std::hash()(std::numeric_limits::quiet_NaN()); + } + if (v == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return std::hash()(0.0); + } + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::optional& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v) { + size_t result = v.index(); + if (const double* dv = std::get_if(&v)) { + result = result * 31 + PigeonInternalDeepHash(*dv); + } else if (const ::flutter::EncodableList* lv = + std::get_if<::flutter::EncodableList>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*lv); + } else if (const ::flutter::EncodableMap* mv = + std::get_if<::flutter::EncodableMap>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*mv); + } else { + std::visit( + [&result](const auto& val) { + using T = std::decay_t; + if constexpr (!std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v) { + result = result * 31 + PigeonInternalDeepHash(val); + } + }, + v); + } + return result; +} + +} // namespace + PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const { - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); + uint8_t type, + ::flutter::ByteStreamReader* stream) const { + return ::flutter::StandardCodecSerializer::ReadValueOfType(type, stream); } void PigeonInternalCodecSerializer::WriteValue( - const EncodableValue& value, flutter::ByteStreamWriter* stream) const { - flutter::StandardCodecSerializer::WriteValue(value, stream); + const EncodableValue& value, + ::flutter::ByteStreamWriter* stream) const { + ::flutter::StandardCodecSerializer::WriteValue(value, stream); } /// The codec used by FirebaseAppCheckHostApi. -const flutter::StandardMessageCodec& FirebaseAppCheckHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( - &PigeonInternalCodecSerializer::GetInstance()); +const ::flutter::StandardMessageCodec& FirebaseAppCheckHostApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance(&PigeonInternalCodecSerializer::GetInstance()); } -// Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through -// the `binary_messenger`. -void FirebaseAppCheckHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, - FirebaseAppCheckHostApi* api) { +// Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through the `binary_messenger`. +void FirebaseAppCheckHostApi::SetUp( + ::flutter::BinaryMessenger* binary_messenger, + FirebaseAppCheckHostApi* api) { FirebaseAppCheckHostApi::SetUp(binary_messenger, api, ""); } -void FirebaseAppCheckHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, - FirebaseAppCheckHostApi* api, - const std::string& message_channel_suffix) { - const std::string prepended_suffix = - message_channel_suffix.length() > 0 - ? std::string(".") + message_channel_suffix - : ""; +void FirebaseAppCheckHostApi::SetUp( + ::flutter::BinaryMessenger* binary_messenger, + FirebaseAppCheckHostApi* api, + const std::string& message_channel_suffix) { + const std::string prepended_suffix = message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix : ""; { - BasicMessageChannel<> channel( - binary_messenger, - "dev.flutter.pigeon.firebase_app_check_platform_interface." - "FirebaseAppCheckHostApi.activate" + - prepended_suffix, - &GetCodec()); + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate" + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler( - [api](const EncodableValue& message, - const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_app_name_arg = args.at(0); - if (encodable_app_name_arg.IsNull()) { - reply(WrapError("app_name_arg unexpectedly null.")); - return; - } - const auto& app_name_arg = - std::get(encodable_app_name_arg); - const auto& encodable_android_provider_arg = args.at(1); - const auto* android_provider_arg = - std::get_if(&encodable_android_provider_arg); - const auto& encodable_apple_provider_arg = args.at(2); - const auto* apple_provider_arg = - std::get_if(&encodable_apple_provider_arg); - const auto& encodable_debug_token_arg = args.at(3); - const auto* debug_token_arg = - std::get_if(&encodable_debug_token_arg); - api->Activate(app_name_arg, android_provider_arg, - apple_provider_arg, debug_token_arg, - [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); + channel.SetMessageHandler([api](const EncodableValue& message, const ::flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_name_arg = args.at(0); + if (encodable_app_name_arg.IsNull()) { + reply(WrapError("app_name_arg unexpectedly null.")); + return; + } + const auto& app_name_arg = std::get(encodable_app_name_arg); + const auto& encodable_android_provider_arg = args.at(1); + const auto* android_provider_arg = std::get_if(&encodable_android_provider_arg); + const auto& encodable_apple_provider_arg = args.at(2); + const auto* apple_provider_arg = std::get_if(&encodable_apple_provider_arg); + const auto& encodable_debug_token_arg = args.at(3); + const auto* debug_token_arg = std::get_if(&encodable_debug_token_arg); + const auto& encodable_recaptcha_enterprise_site_key_arg = args.at(4); + const auto* recaptcha_enterprise_site_key_arg = std::get_if(&encodable_recaptcha_enterprise_site_key_arg); + api->Activate(app_name_arg, android_provider_arg, apple_provider_arg, debug_token_arg, recaptcha_enterprise_site_key_arg, [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel( - binary_messenger, - "dev.flutter.pigeon.firebase_app_check_platform_interface." - "FirebaseAppCheckHostApi.getToken" + - prepended_suffix, - &GetCodec()); + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken" + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler( - [api](const EncodableValue& message, - const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_app_name_arg = args.at(0); - if (encodable_app_name_arg.IsNull()) { - reply(WrapError("app_name_arg unexpectedly null.")); - return; - } - const auto& app_name_arg = - std::get(encodable_app_name_arg); - const auto& encodable_force_refresh_arg = args.at(1); - if (encodable_force_refresh_arg.IsNull()) { - reply(WrapError("force_refresh_arg unexpectedly null.")); - return; - } - const auto& force_refresh_arg = - std::get(encodable_force_refresh_arg); - api->GetToken( - app_name_arg, force_refresh_arg, - [reply](ErrorOr>&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - auto output_optional = std::move(output).TakeValue(); - if (output_optional) { - wrapped.push_back( - EncodableValue(std::move(output_optional).value())); - } else { - wrapped.push_back(EncodableValue()); - } - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); + channel.SetMessageHandler([api](const EncodableValue& message, const ::flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_name_arg = args.at(0); + if (encodable_app_name_arg.IsNull()) { + reply(WrapError("app_name_arg unexpectedly null.")); + return; + } + const auto& app_name_arg = std::get(encodable_app_name_arg); + const auto& encodable_force_refresh_arg = args.at(1); + if (encodable_force_refresh_arg.IsNull()) { + reply(WrapError("force_refresh_arg unexpectedly null.")); + return; + } + const auto& force_refresh_arg = std::get(encodable_force_refresh_arg); + api->GetToken(app_name_arg, force_refresh_arg, [reply](ErrorOr>&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + auto output_optional = std::move(output).TakeValue(); + if (output_optional) { + wrapped.push_back(EncodableValue(std::move(output_optional).value())); + } else { + wrapped.push_back(EncodableValue()); } + reply(EncodableValue(std::move(wrapped))); }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel( - binary_messenger, - "dev.flutter.pigeon.firebase_app_check_platform_interface." - "FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled" + - prepended_suffix, - &GetCodec()); + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled" + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler( - [api](const EncodableValue& message, - const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_app_name_arg = args.at(0); - if (encodable_app_name_arg.IsNull()) { - reply(WrapError("app_name_arg unexpectedly null.")); - return; - } - const auto& app_name_arg = - std::get(encodable_app_name_arg); - const auto& encodable_is_token_auto_refresh_enabled_arg = - args.at(1); - if (encodable_is_token_auto_refresh_enabled_arg.IsNull()) { - reply(WrapError( - "is_token_auto_refresh_enabled_arg unexpectedly null.")); - return; - } - const auto& is_token_auto_refresh_enabled_arg = - std::get(encodable_is_token_auto_refresh_enabled_arg); - api->SetTokenAutoRefreshEnabled( - app_name_arg, is_token_auto_refresh_enabled_arg, - [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); + channel.SetMessageHandler([api](const EncodableValue& message, const ::flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_name_arg = args.at(0); + if (encodable_app_name_arg.IsNull()) { + reply(WrapError("app_name_arg unexpectedly null.")); + return; + } + const auto& app_name_arg = std::get(encodable_app_name_arg); + const auto& encodable_is_token_auto_refresh_enabled_arg = args.at(1); + if (encodable_is_token_auto_refresh_enabled_arg.IsNull()) { + reply(WrapError("is_token_auto_refresh_enabled_arg unexpectedly null.")); + return; + } + const auto& is_token_auto_refresh_enabled_arg = std::get(encodable_is_token_auto_refresh_enabled_arg); + api->SetTokenAutoRefreshEnabled(app_name_arg, is_token_auto_refresh_enabled_arg, [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel( - binary_messenger, - "dev.flutter.pigeon.firebase_app_check_platform_interface." - "FirebaseAppCheckHostApi.registerTokenListener" + - prepended_suffix, - &GetCodec()); + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener" + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler( - [api](const EncodableValue& message, - const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_app_name_arg = args.at(0); - if (encodable_app_name_arg.IsNull()) { - reply(WrapError("app_name_arg unexpectedly null.")); - return; - } - const auto& app_name_arg = - std::get(encodable_app_name_arg); - api->RegisterTokenListener( - app_name_arg, [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back( - EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); + channel.SetMessageHandler([api](const EncodableValue& message, const ::flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_name_arg = args.at(0); + if (encodable_app_name_arg.IsNull()) { + reply(WrapError("app_name_arg unexpectedly null.")); + return; + } + const auto& app_name_arg = std::get(encodable_app_name_arg); + api->RegisterTokenListener(app_name_arg, [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; } + EncodableList wrapped; + wrapped.push_back(EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel( - binary_messenger, - "dev.flutter.pigeon.firebase_app_check_platform_interface." - "FirebaseAppCheckHostApi.getLimitedUseAppCheckToken" + - prepended_suffix, - &GetCodec()); + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken" + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler( - [api](const EncodableValue& message, - const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_app_name_arg = args.at(0); - if (encodable_app_name_arg.IsNull()) { - reply(WrapError("app_name_arg unexpectedly null.")); - return; - } - const auto& app_name_arg = - std::get(encodable_app_name_arg); - api->GetLimitedUseAppCheckToken( - app_name_arg, [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back( - EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); + channel.SetMessageHandler([api](const EncodableValue& message, const ::flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_name_arg = args.at(0); + if (encodable_app_name_arg.IsNull()) { + reply(WrapError("app_name_arg unexpectedly null.")); + return; + } + const auto& app_name_arg = std::get(encodable_app_name_arg); + api->GetLimitedUseAppCheckToken(app_name_arg, [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; } + EncodableList wrapped; + wrapped.push_back(EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } } } -EncodableValue FirebaseAppCheckHostApi::WrapError( - std::string_view error_message) { - return EncodableValue( - EncodableList{EncodableValue(std::string(error_message)), - EncodableValue("Error"), EncodableValue()}); +EncodableValue FirebaseAppCheckHostApi::WrapError(std::string_view error_message) { + return EncodableValue(EncodableList{ + EncodableValue(std::string(error_message)), + EncodableValue("Error"), + EncodableValue() + }); } EncodableValue FirebaseAppCheckHostApi::WrapError(const FlutterError& error) { - return EncodableValue(EncodableList{EncodableValue(error.code()), - EncodableValue(error.message()), - error.details()}); + return EncodableValue(EncodableList{ + EncodableValue(error.code()), + EncodableValue(error.message()), + error.details() + }); } } // namespace firebase_app_check_windows diff --git a/packages/firebase_app_check/firebase_app_check/windows/messages.g.h b/packages/firebase_app_check/firebase_app_check/windows/messages.g.h index c56d71862604..4d13d5ff3fe4 100644 --- a/packages/firebase_app_check/firebase_app_check/windows/messages.g.h +++ b/packages/firebase_app_check/firebase_app_check/windows/messages.g.h @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #ifndef PIGEON_MESSAGES_G_H_ @@ -17,29 +17,29 @@ namespace firebase_app_check_windows { + // Generated class from Pigeon. class FlutterError { public: - explicit FlutterError(const std::string& code) : code_(code) {} + explicit FlutterError(const std::string& code) + : code_(code) {} explicit FlutterError(const std::string& code, const std::string& message) - : code_(code), message_(message) {} - explicit FlutterError(const std::string& code, const std::string& message, - const flutter::EncodableValue& details) - : code_(code), message_(message), details_(details) {} + : code_(code), message_(message) {} + explicit FlutterError(const std::string& code, const std::string& message, const ::flutter::EncodableValue& details) + : code_(code), message_(message), details_(details) {} const std::string& code() const { return code_; } const std::string& message() const { return message_; } - const flutter::EncodableValue& details() const { return details_; } + const ::flutter::EncodableValue& details() const { return details_; } private: std::string code_; std::string message_; - flutter::EncodableValue details_; + ::flutter::EncodableValue details_; }; -template -class ErrorOr { +template class ErrorOr { public: ErrorOr(const T& rhs) : v_(rhs) {} ErrorOr(const T&& rhs) : v_(std::move(rhs)) {} @@ -58,7 +58,9 @@ class ErrorOr { std::variant v_; }; -class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { + + +class PigeonInternalCodecSerializer : public ::flutter::StandardCodecSerializer { public: PigeonInternalCodecSerializer(); inline static PigeonInternalCodecSerializer& GetInstance() { @@ -66,51 +68,55 @@ class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { return sInstance; } - void WriteValue(const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; - + void WriteValue( + const ::flutter::EncodableValue& value, + ::flutter::ByteStreamWriter* stream) const override; protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const override; + ::flutter::EncodableValue ReadValueOfType( + uint8_t type, + ::flutter::ByteStreamReader* stream) const override; }; -// Generated interface from Pigeon that represents a handler of messages from -// Flutter. +// Generated interface from Pigeon that represents a handler of messages from Flutter. class FirebaseAppCheckHostApi { public: FirebaseAppCheckHostApi(const FirebaseAppCheckHostApi&) = delete; FirebaseAppCheckHostApi& operator=(const FirebaseAppCheckHostApi&) = delete; virtual ~FirebaseAppCheckHostApi() {} virtual void Activate( - const std::string& app_name, const std::string* android_provider, - const std::string* apple_provider, const std::string* debug_token, - std::function reply)> result) = 0; + const std::string& app_name, + const std::string* android_provider, + const std::string* apple_provider, + const std::string* debug_token, + const std::string* recaptcha_enterprise_site_key, + std::function reply)> result) = 0; virtual void GetToken( - const std::string& app_name, bool force_refresh, - std::function> reply)> - result) = 0; + const std::string& app_name, + bool force_refresh, + std::function> reply)> result) = 0; virtual void SetTokenAutoRefreshEnabled( - const std::string& app_name, bool is_token_auto_refresh_enabled, - std::function reply)> result) = 0; + const std::string& app_name, + bool is_token_auto_refresh_enabled, + std::function reply)> result) = 0; virtual void RegisterTokenListener( - const std::string& app_name, - std::function reply)> result) = 0; + const std::string& app_name, + std::function reply)> result) = 0; virtual void GetLimitedUseAppCheckToken( - const std::string& app_name, - std::function reply)> result) = 0; + const std::string& app_name, + std::function reply)> result) = 0; // The codec used by FirebaseAppCheckHostApi. - static const flutter::StandardMessageCodec& GetCodec(); - // Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through - // the `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, - FirebaseAppCheckHostApi* api); - static void SetUp(flutter::BinaryMessenger* binary_messenger, - FirebaseAppCheckHostApi* api, - const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); - + static const ::flutter::StandardMessageCodec& GetCodec(); + // Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through the `binary_messenger`. + static void SetUp( + ::flutter::BinaryMessenger* binary_messenger, + FirebaseAppCheckHostApi* api); + static void SetUp( + ::flutter::BinaryMessenger* binary_messenger, + FirebaseAppCheckHostApi* api, + const std::string& message_channel_suffix); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: FirebaseAppCheckHostApi() = default; }; diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/android_providers.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/android_providers.dart index c827b3184022..76ce5b389981 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/android_providers.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/android_providers.dart @@ -32,3 +32,15 @@ class AndroidDebugProvider extends AndroidAppCheckProvider { class AndroidPlayIntegrityProvider extends AndroidAppCheckProvider { const AndroidPlayIntegrityProvider() : super('playIntegrity'); } + +/// reCAPTCHA Enterprise provider for Android. +/// +/// See documentation: https://firebase.google.com/docs/app-check/android/recaptcha-enterprise-provider +class AndroidReCaptchaEnterpriseProvider extends AndroidAppCheckProvider { + /// Creates an Android reCAPTCHA Enterprise provider with a site key. + const AndroidReCaptchaEnterpriseProvider({required this.siteKey}) : super('recaptchaEnterprise'); + + /// The reCAPTCHA Enterprise site key. + final String siteKey; +} + diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart index 96afb6f2c999..062bae9a10ac 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart @@ -104,6 +104,11 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { debugToken = providerWindows.debugToken; } + String? recaptchaEnterpriseSiteKey; + if (providerAndroid is AndroidReCaptchaEnterpriseProvider) { + recaptchaEnterpriseSiteKey = providerAndroid.siteKey; + } + await _pigeonApi.activate( app.name, defaultTargetPlatform == TargetPlatform.android || kDebugMode @@ -121,6 +126,7 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { ) : null, debugToken, + recaptchaEnterpriseSiteKey, ); } on PlatformException catch (e, s) { convertPlatformException(e, s); diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart index 8916928599ce..8fb14b67fa11 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -1,23 +1,44 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), 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 +// ignore_for_file: unused_import, unused_shown_name +// ignore_for_file: type=lint import 'dart:async'; -import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; +import 'dart:typed_data' show Float64List, Int32List, Int64List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; -PlatformException _createConnectionError(String channelName) { - return PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel: "$channelName".', - ); +Object? _extractReplyValueOrThrow( + List? replyList, + String channelName, { + required bool isNullValid, +}) { + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } + return replyList.firstOrNull; } + + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -43,156 +64,105 @@ class FirebaseAppCheckHostApi { /// Constructor for [FirebaseAppCheckHostApi]. 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. - FirebaseAppCheckHostApi( - {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + FirebaseAppCheckHostApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = - messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); final String pigeonVar_messageChannelSuffix; - Future activate(String appName, String? androidProvider, - String? appleProvider, String? debugToken) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + Future activate(String appName, String? androidProvider, String? appleProvider, String? debugToken, String? recaptchaEnterpriseSiteKey) async { + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel - .send([appName, androidProvider, appleProvider, debugToken]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture 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; - } + final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName, androidProvider, appleProvider, debugToken, recaptchaEnterpriseSiteKey]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ) + ; } Future getToken(String appName, bool forceRefresh) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([appName, forceRefresh]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture 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 (pigeonVar_replyList[0] as String?); - } + final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName, forceRefresh]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ) + ; + return pigeonVar_replyValue as String?; } - Future setTokenAutoRefreshEnabled( - String appName, bool isTokenAutoRefreshEnabled) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + Future setTokenAutoRefreshEnabled(String appName, bool isTokenAutoRefreshEnabled) async { + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([appName, isTokenAutoRefreshEnabled]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture 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; - } + final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName, isTokenAutoRefreshEnabled]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ) + ; } Future registerTokenListener(String appName) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([appName]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture 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 if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as String?)!; - } + final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ) + ; + return pigeonVar_replyValue! as String; } Future getLimitedUseAppCheckToken(String appName) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([appName]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture 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 if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as String?)!; - } + final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ) + ; + return pigeonVar_replyValue! as String; } } diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/messages.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/messages.dart index e84ff78ab5f4..e20e1bdfba0e 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/messages.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/messages.dart @@ -29,8 +29,10 @@ abstract class FirebaseAppCheckHostApi { String? androidProvider, String? appleProvider, String? debugToken, + String? recaptchaEnterpriseSiteKey, ); + @async String? getToken(String appName, bool forceRefresh); diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart index 5f215cec19fc..45cf6427c0d7 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart @@ -5,6 +5,7 @@ import 'package:firebase_app_check_platform_interface/firebase_app_check_platform_interface.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter/services.dart'; import '../mock.dart'; @@ -44,5 +45,32 @@ void main() { expect(appCheck.setInitialValues(), appCheck); }); }); + + group('activate()', () { + test('passes recaptchaEnterpriseSiteKey on Android', () async { + final appCheck = MethodChannelFirebaseAppCheck(app: Firebase.app()); + + final List log = []; + + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMessageHandler( + 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate', + (message) async { + final list = const StandardMessageCodec().decodeMessage(message) as List; + log.add(list); + return const StandardMessageCodec().encodeMessage([null]); // Return success + }, + ); + + await appCheck.activate( + providerAndroid: const AndroidReCaptchaEnterpriseProvider(siteKey: 'my-site-key'), + ); + + expect(log.length, 1); + expect(log[0][0], '[DEFAULT]'); // appName + expect(log[0][1], 'recaptchaEnterprise'); // androidProvider + expect(log[0][4], 'my-site-key'); // recaptchaEnterpriseSiteKey + }); + }); }); } From 6c44526072de3b24539e9341e141d21bf9be725f Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Wed, 6 May 2026 22:14:30 -0700 Subject: [PATCH 2/9] update example --- .../firebase_app_check/android/build.gradle | 2 +- .../appcheck/FirebaseAppCheckPlugin.kt | 4 +- .../example/android/build.gradle | 1 + .../example/android/settings.gradle | 2 +- .../firebase_app_check/example/lib/main.dart | 40 ++++++++++++++++++- .../lib/firebase_app_check.dart | 1 + 6 files changed, 45 insertions(+), 5 deletions(-) diff --git a/packages/firebase_app_check/firebase_app_check/android/build.gradle b/packages/firebase_app_check/firebase_app_check/android/build.gradle index 920e8e906e00..81e347abd98e 100644 --- a/packages/firebase_app_check/firebase_app_check/android/build.gradle +++ b/packages/firebase_app_check/firebase_app_check/android/build.gradle @@ -80,7 +80,7 @@ android { implementation platform("com.google.firebase:firebase-bom:${getRootProjectExtOrCoreProperty("FirebaseSDKVersion", firebaseCoreProject)}") implementation 'com.google.firebase:firebase-appcheck-debug' implementation 'com.google.firebase:firebase-appcheck-playintegrity' - implementation 'com.google.firebase:firebase-appcheck-recaptchaenterprise' + implementation 'com.google.firebase:firebase-appcheck-recaptchaenterprise:16.0.0-beta01' implementation 'androidx.annotation:annotation:1.7.0' } } diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt index f9908dee54bc..4bb063508300 100644 --- a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt @@ -9,7 +9,7 @@ import com.google.firebase.FirebaseApp import com.google.firebase.appcheck.FirebaseAppCheck import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory -import com.google.firebase.appcheck.recaptchaenterprise.ReCaptchaEnterpriseProviderFactory +import com.google.firebase.appcheck.recaptchaenterprise.RecaptchaEnterpriseAppCheckProviderFactory import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding import io.flutter.plugin.common.BinaryMessenger @@ -71,7 +71,7 @@ class FirebaseAppCheckPlugin : "recaptchaEnterprise" -> { if (recaptchaEnterpriseSiteKey != null) { firebaseAppCheck.installAppCheckProviderFactory( - ReCaptchaEnterpriseProviderFactory.getInstance(recaptchaEnterpriseSiteKey) + RecaptchaEnterpriseAppCheckProviderFactory.getInstance(recaptchaEnterpriseSiteKey) ) } else { callback(Result.failure(FlutterError("invalid-argument", "Site key is required for reCAPTCHA Enterprise", null))) diff --git a/packages/firebase_app_check/firebase_app_check/example/android/build.gradle b/packages/firebase_app_check/firebase_app_check/example/android/build.gradle index d2ffbffa4cd2..c63004eaacea 100644 --- a/packages/firebase_app_check/firebase_app_check/example/android/build.gradle +++ b/packages/firebase_app_check/firebase_app_check/example/android/build.gradle @@ -1,5 +1,6 @@ allprojects { repositories { + mavenLocal() google() mavenCentral() } diff --git a/packages/firebase_app_check/firebase_app_check/example/android/settings.gradle b/packages/firebase_app_check/firebase_app_check/example/android/settings.gradle index 30463c1cf2f2..4fb566e9929e 100644 --- a/packages/firebase_app_check/firebase_app_check/example/android/settings.gradle +++ b/packages/firebase_app_check/firebase_app_check/example/android/settings.gradle @@ -22,7 +22,7 @@ plugins { // START: FlutterFire Configuration id "com.google.gms.google-services" version "4.3.15" apply false // END: FlutterFire Configuration - id "org.jetbrains.kotlin.android" version "1.9.22" apply false + id "org.jetbrains.kotlin.android" version "2.1.0" apply false } include ":app" diff --git a/packages/firebase_app_check/firebase_app_check/example/lib/main.dart b/packages/firebase_app_check/firebase_app_check/example/lib/main.dart index 8f26c6439a83..415cda451750 100644 --- a/packages/firebase_app_check/firebase_app_check/example/lib/main.dart +++ b/packages/firebase_app_check/firebase_app_check/example/lib/main.dart @@ -79,13 +79,21 @@ class _FirebaseAppCheck extends State { final appCheck = FirebaseAppCheck.instance; String _message = ''; String _eventToken = 'not yet'; + late final TextEditingController _siteKeyController; @override void initState() { + _siteKeyController = TextEditingController(text: kWebRecaptchaSiteKey); appCheck.onTokenChange.listen(setEventToken); super.initState(); } + @override + void dispose() { + _siteKeyController.dispose(); + super.dispose(); + } + void setMessage(String message) { setState(() { _message = message; @@ -101,16 +109,25 @@ class _FirebaseAppCheck extends State { Future _activate({ AndroidAppCheckProvider? android, AppleAppCheckProvider? apple, + String? webProviderType, WindowsAppCheckProvider? windows, }) async { try { + dynamic providerWeb; + if (webProviderType == 'enterprise') { + providerWeb = ReCaptchaEnterpriseProvider(_siteKeyController.text); + } else if (webProviderType == 'v3') { + providerWeb = ReCaptchaV3Provider(_siteKeyController.text); + } + await appCheck.activate( providerAndroid: android ?? const AndroidPlayIntegrityProvider(), providerApple: apple ?? const AppleDeviceCheckProvider(), - providerWeb: ReCaptchaV3Provider(kWebRecaptchaSiteKey), + providerWeb: providerWeb, providerWindows: windows ?? const WindowsDebugProvider(), ); final providerName = windows?.runtimeType.toString() ?? + webProviderType ?? apple?.runtimeType.toString() ?? android?.runtimeType.toString() ?? 'default'; @@ -170,6 +187,27 @@ class _FirebaseAppCheck extends State { 'activate(AppAttest + DeviceCheck fallback)', ), ), + const SizedBox(height: 8), + TextField( + controller: _siteKeyController, + decoration: const InputDecoration( + labelText: 'reCAPTCHA Site Key', + border: OutlineInputBorder(), + ), + ), + const SizedBox(height: 8), + ElevatedButton( + onPressed: () => _activate( + android: AndroidReCaptchaEnterpriseProvider(siteKey: _siteKeyController.text), + ), + child: const Text('activate(Android reCAPTCHA Enterprise)'), + ), + ElevatedButton( + onPressed: () => _activate( + webProviderType: 'enterprise', + ), + child: const Text('activate(Web reCAPTCHA Enterprise)'), + ), const SizedBox(height: 16), const Text( 'Actions', diff --git a/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart index cd569468c12c..7c6afa311651 100644 --- a/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart @@ -13,6 +13,7 @@ export 'package:firebase_app_check_platform_interface/firebase_app_check_platfor AndroidAppCheckProvider, AndroidDebugProvider, AndroidPlayIntegrityProvider, + AndroidReCaptchaEnterpriseProvider, AppleProvider, AppleAppCheckProvider, AppleDebugProvider, From 94e013139cdee07fdc01423a8bb0275b7c22eb74 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Thu, 21 May 2026 22:30:11 -0700 Subject: [PATCH 3/9] apple tentative implementation --- .../firebase_app_check/example/lib/main.dart | 7 +++++ .../lib/firebase_app_check.dart | 1 + .../lib/src/apple_providers.dart | 14 ++++++++++ .../method_channel_firebase_app_check.dart | 2 ++ ...ethod_channel_firebase_app_check_test.dart | 26 +++++++++++++++++++ 5 files changed, 50 insertions(+) diff --git a/packages/firebase_app_check/firebase_app_check/example/lib/main.dart b/packages/firebase_app_check/firebase_app_check/example/lib/main.dart index 415cda451750..a7dbb872eaa7 100644 --- a/packages/firebase_app_check/firebase_app_check/example/lib/main.dart +++ b/packages/firebase_app_check/firebase_app_check/example/lib/main.dart @@ -202,6 +202,13 @@ class _FirebaseAppCheck extends State { ), child: const Text('activate(Android reCAPTCHA Enterprise)'), ), + if (!kIsWeb && defaultTargetPlatform == TargetPlatform.iOS) + ElevatedButton( + onPressed: () => _activate( + apple: AppleReCaptchaEnterpriseProvider(siteKey: _siteKeyController.text), + ), + child: const Text('activate(Apple reCAPTCHA Enterprise)'), + ), ElevatedButton( onPressed: () => _activate( webProviderType: 'enterprise', diff --git a/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart index 7c6afa311651..0c91314550cf 100644 --- a/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart @@ -20,6 +20,7 @@ export 'package:firebase_app_check_platform_interface/firebase_app_check_platfor AppleDeviceCheckProvider, AppleAppAttestProvider, AppleAppAttestWithDeviceCheckFallbackProvider, + AppleReCaptchaEnterpriseProvider, ReCaptchaEnterpriseProvider, ReCaptchaV3Provider, WebDebugProvider, diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/apple_providers.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/apple_providers.dart index 5e6af1ce2359..50d79ba946af 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/apple_providers.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/apple_providers.dart @@ -54,3 +54,17 @@ class AppleAppAttestWithDeviceCheckFallbackProvider const AppleAppAttestWithDeviceCheckFallbackProvider() : super('appAttestWithDeviceCheckFallback'); } + +/// reCAPTCHA Enterprise provider for Apple platforms. +/// +/// See documentation: https://firebase.google.com/docs/app-check/ios/recaptcha-enterprise-provider +class AppleReCaptchaEnterpriseProvider extends AppleAppCheckProvider { + /// Creates an Apple reCAPTCHA Enterprise provider with a site key. + const AppleReCaptchaEnterpriseProvider({required this.siteKey}) + : super('recaptchaEnterprise'); + + /// The reCAPTCHA Enterprise site key. + final String siteKey; +} + + diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart index 10382eba09c4..966559a5520c 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart @@ -127,6 +127,8 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { String? recaptchaEnterpriseSiteKey; if (providerAndroid is AndroidReCaptchaEnterpriseProvider) { recaptchaEnterpriseSiteKey = providerAndroid.siteKey; + } else if (providerApple is AppleReCaptchaEnterpriseProvider) { + recaptchaEnterpriseSiteKey = providerApple.siteKey; } await _pigeonApi.activate( diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart index 73199cf51c58..395e96ef5134 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart @@ -148,6 +148,32 @@ void main() { expect(log[0][1], 'recaptchaEnterprise'); // androidProvider expect(log[0][4], 'my-site-key'); // recaptchaEnterpriseSiteKey }); + + test('passes recaptchaEnterpriseSiteKey on iOS', () async { + debugDefaultTargetPlatformOverride = TargetPlatform.iOS; + final appCheck = MethodChannelFirebaseAppCheck(app: Firebase.app()); + + final List log = []; + + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMessageHandler( + 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate', + (message) async { + final list = const StandardMessageCodec().decodeMessage(message) as List; + log.add(list); + return const StandardMessageCodec().encodeMessage([null]); // Return success + }, + ); + + await appCheck.activate( + providerApple: const AppleReCaptchaEnterpriseProvider(siteKey: 'my-apple-site-key'), + ); + + expect(log.length, 1); + expect(log[0][0], '[DEFAULT]'); // appName + expect(log[0][2], 'recaptchaEnterprise'); // appleProvider + expect(log[0][4], 'my-apple-site-key'); // recaptchaEnterpriseSiteKey + }); }); }); } From 8842bb4ddb85be455c2438cc9d1b288565343855 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Tue, 26 May 2026 20:41:13 -0700 Subject: [PATCH 4/9] add recaptcha in the plugin swift --- .../FirebaseAppCheckPlugin.swift | 47 ++++++++++++++++--- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift index 5aec32b1ad2c..7b9089edaba2 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift @@ -60,7 +60,7 @@ public class FirebaseAppCheckPlugin: NSObject, FlutterPlugin, private var binaryMessenger: FlutterBinaryMessenger? func activate(appName: String, androidProvider: String?, appleProvider: String?, - debugToken: String?, + debugToken: String?, recaptchaEnterpriseSiteKey: String?, completion: @escaping (Result) -> Void) { guard let app = FLTFirebasePlugin.firebaseAppNamed(appName) else { completion(.failure(FlutterError( @@ -70,7 +70,12 @@ public class FirebaseAppCheckPlugin: NSObject, FlutterPlugin, } let provider = appleProvider ?? "deviceCheck" - providerFactory?.configure(app: app, providerName: provider, debugToken: debugToken) + providerFactory?.configure( + app: app, + providerName: provider, + debugToken: debugToken, + recaptchaEnterpriseSiteKey: recaptchaEnterpriseSiteKey + ) completion(.success(())) } @@ -242,24 +247,44 @@ class FlutterAppCheckProviderFactory: NSObject, AppCheckProviderFactory { if providers[app.name] == nil { let wrapper = AppCheckProviderWrapper() // Default to deviceCheck. activate() will reconfigure with the correct provider. - wrapper.configure(app: app, providerName: "deviceCheck", debugToken: nil) + wrapper.configure( + app: app, + providerName: "deviceCheck", + debugToken: nil, + recaptchaEnterpriseSiteKey: nil + ) providers[app.name] = wrapper } return providers[app.name] } - func configure(app: FirebaseApp, providerName: String, debugToken: String?) { + func configure( + app: FirebaseApp, + providerName: String, + debugToken: String?, + recaptchaEnterpriseSiteKey: String? + ) { if providers[app.name] == nil { providers[app.name] = AppCheckProviderWrapper() } - providers[app.name]?.configure(app: app, providerName: providerName, debugToken: debugToken) + providers[app.name]?.configure( + app: app, + providerName: providerName, + debugToken: debugToken, + recaptchaEnterpriseSiteKey: recaptchaEnterpriseSiteKey + ) } } class AppCheckProviderWrapper: NSObject, AppCheckProvider { private var delegateProvider: (any AppCheckProvider)? - func configure(app: FirebaseApp, providerName: String, debugToken: String?) { + func configure( + app: FirebaseApp, + providerName: String, + debugToken: String?, + recaptchaEnterpriseSiteKey: String? + ) { switch providerName { case "debug": if let debugToken { @@ -281,6 +306,16 @@ class AppCheckProviderWrapper: NSObject, AppCheckProvider { } else { delegateProvider = DeviceCheckProvider(app: app) } + case "recaptchaEnterprise": + #if os(iOS) + if let siteKey = recaptchaEnterpriseSiteKey { + delegateProvider = RecaptchaEnterpriseProvider(app: app, siteKey: siteKey) + } else { + print("Firebase App Check: siteKey is missing for reCAPTCHA Enterprise provider.") + } + #else + print("Firebase App Check: reCAPTCHA Enterprise is only supported on iOS.") + #endif default: // deviceCheck delegateProvider = DeviceCheckProvider(app: app) From 57db3e5126ea8a04504483fe4561e3442b49bc65 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Tue, 26 May 2026 20:42:42 -0700 Subject: [PATCH 5/9] minor fix --- .../lib/src/apple_providers.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/apple_providers.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/apple_providers.dart index 50d79ba946af..f2ca2f6e548f 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/apple_providers.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/apple_providers.dart @@ -66,5 +66,3 @@ class AppleReCaptchaEnterpriseProvider extends AppleAppCheckProvider { /// The reCAPTCHA Enterprise site key. final String siteKey; } - - From 5a8f598c6107d4fcc5630c90f3da7b91194e0377 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Tue, 26 May 2026 21:13:05 -0700 Subject: [PATCH 6/9] some dart fix --- .../lib/src/android_providers.dart | 4 ++-- .../method_channel_firebase_app_check.dart | 12 ------------ 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/android_providers.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/android_providers.dart index 76ce5b389981..98337af759c6 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/android_providers.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/android_providers.dart @@ -38,9 +38,9 @@ class AndroidPlayIntegrityProvider extends AndroidAppCheckProvider { /// See documentation: https://firebase.google.com/docs/app-check/android/recaptcha-enterprise-provider class AndroidReCaptchaEnterpriseProvider extends AndroidAppCheckProvider { /// Creates an Android reCAPTCHA Enterprise provider with a site key. - const AndroidReCaptchaEnterpriseProvider({required this.siteKey}) : super('recaptchaEnterprise'); + const AndroidReCaptchaEnterpriseProvider({required this.siteKey}) + : super('recaptchaEnterprise'); /// The reCAPTCHA Enterprise site key. final String siteKey; } - diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart index 966559a5520c..5d157aea948e 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart @@ -112,18 +112,6 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { WindowsAppCheckProvider? providerWindows, }) async { try { - String? debugToken; - if (providerAndroid is AndroidDebugProvider && - providerAndroid.debugToken != null) { - debugToken = providerAndroid.debugToken; - } else if (providerApple is AppleDebugProvider && - providerApple.debugToken != null) { - debugToken = providerApple.debugToken; - } else if (providerWindows is WindowsDebugProvider && - providerWindows.debugToken != null) { - debugToken = providerWindows.debugToken; - } - String? recaptchaEnterpriseSiteKey; if (providerAndroid is AndroidReCaptchaEnterpriseProvider) { recaptchaEnterpriseSiteKey = providerAndroid.siteKey; From a2acf79d765a54c28fdc80f43d44d9d7a9810c58 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Wed, 27 May 2026 22:29:03 -0700 Subject: [PATCH 7/9] updated sample app UI --- .../firebase_app_check/example/lib/main.dart | 163 ++++++++++++------ 1 file changed, 113 insertions(+), 50 deletions(-) diff --git a/packages/firebase_app_check/firebase_app_check/example/lib/main.dart b/packages/firebase_app_check/firebase_app_check/example/lib/main.dart index a7dbb872eaa7..8045706d9add 100644 --- a/packages/firebase_app_check/firebase_app_check/example/lib/main.dart +++ b/packages/firebase_app_check/firebase_app_check/example/lib/main.dart @@ -13,6 +13,8 @@ import 'package:flutter/material.dart'; import 'firebase_options.dart'; const kWebRecaptchaSiteKey = '6Lemcn0dAAAAABLkf6aiiHvpGD6x-zF3nOSDU2M8'; +const kAndroidRecaptchaSiteKey = '6LfQpf4sAAAAAJnxnEmtVMpjkwuLpDZnxxcLbjxb'; +const kAppleRecaptchaSiteKey = '6LeJev4sAAAAADbZGhkk_kkxSEzxRjzzZRC4R1R-'; // Windows: create a debug token in the Firebase Console // (App Check > Apps > Manage debug tokens), then paste it here @@ -79,18 +81,26 @@ class _FirebaseAppCheck extends State { final appCheck = FirebaseAppCheck.instance; String _message = ''; String _eventToken = 'not yet'; - late final TextEditingController _siteKeyController; + late final TextEditingController _webSiteKeyController; + late final TextEditingController _androidSiteKeyController; + late final TextEditingController _appleSiteKeyController; @override void initState() { - _siteKeyController = TextEditingController(text: kWebRecaptchaSiteKey); + _webSiteKeyController = TextEditingController(text: kWebRecaptchaSiteKey); + _androidSiteKeyController = + TextEditingController(text: kAndroidRecaptchaSiteKey); + _appleSiteKeyController = + TextEditingController(text: kAppleRecaptchaSiteKey); appCheck.onTokenChange.listen(setEventToken); super.initState(); } @override void dispose() { - _siteKeyController.dispose(); + _webSiteKeyController.dispose(); + _androidSiteKeyController.dispose(); + _appleSiteKeyController.dispose(); super.dispose(); } @@ -115,9 +125,9 @@ class _FirebaseAppCheck extends State { try { dynamic providerWeb; if (webProviderType == 'enterprise') { - providerWeb = ReCaptchaEnterpriseProvider(_siteKeyController.text); + providerWeb = ReCaptchaEnterpriseProvider(_webSiteKeyController.text); } else if (webProviderType == 'v3') { - providerWeb = ReCaptchaV3Provider(_siteKeyController.text); + providerWeb = ReCaptchaV3Provider(_webSiteKeyController.text); } await appCheck.activate( @@ -153,68 +163,121 @@ class _FirebaseAppCheck extends State { style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 8), - ElevatedButton( - onPressed: () => _activate( - android: const AndroidDebugProvider(), - apple: const AppleDebugProvider(), - windows: WindowsDebugProvider( - debugToken: - kWindowsDebugToken.isNotEmpty ? kWindowsDebugToken : null, + if (kIsWeb) ...[ + ElevatedButton( + onPressed: () => _activate( + webProviderType: 'v3', ), + child: const Text('activate(Web reCAPTCHA v3)'), ), - child: const Text('activate(Debug)'), - ), - ElevatedButton( - onPressed: () => _activate( - android: const AndroidPlayIntegrityProvider(), - apple: const AppleDeviceCheckProvider(), + const SizedBox(height: 8), + TextField( + controller: _webSiteKeyController, + decoration: const InputDecoration( + labelText: 'Web reCAPTCHA Site Key', + border: OutlineInputBorder(), + ), ), - child: const Text('activate(PlayIntegrity / DeviceCheck)'), - ), - if (!kIsWeb) + const SizedBox(height: 8), ElevatedButton( onPressed: () => _activate( - apple: const AppleAppAttestProvider(), + webProviderType: 'enterprise', ), - child: const Text('activate(AppAttest)'), + child: const Text('activate(Web reCAPTCHA Enterprise)'), ), - if (!kIsWeb) + ], + if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) ...[ ElevatedButton( onPressed: () => _activate( - apple: const AppleAppAttestWithDeviceCheckFallbackProvider(), + android: const AndroidDebugProvider(), ), - child: const Text( - 'activate(AppAttest + DeviceCheck fallback)', + child: const Text('activate(Android Debug)'), + ), + ElevatedButton( + onPressed: () => _activate( + android: const AndroidPlayIntegrityProvider(), ), + child: const Text('activate(Android Play Integrity)'), ), - const SizedBox(height: 8), - TextField( - controller: _siteKeyController, - decoration: const InputDecoration( - labelText: 'reCAPTCHA Site Key', - border: OutlineInputBorder(), + const SizedBox(height: 8), + TextField( + controller: _androidSiteKeyController, + decoration: const InputDecoration( + labelText: 'Android reCAPTCHA Site Key', + border: OutlineInputBorder(), + ), ), - ), - const SizedBox(height: 8), - ElevatedButton( - onPressed: () => _activate( - android: AndroidReCaptchaEnterpriseProvider(siteKey: _siteKeyController.text), + const SizedBox(height: 8), + ElevatedButton( + onPressed: () => _activate( + android: AndroidReCaptchaEnterpriseProvider( + siteKey: _androidSiteKeyController.text, + ), + ), + child: const Text('activate(Android reCAPTCHA Enterprise)'), ), - child: const Text('activate(Android reCAPTCHA Enterprise)'), - ), - if (!kIsWeb && defaultTargetPlatform == TargetPlatform.iOS) + ], + if (!kIsWeb && + (defaultTargetPlatform == TargetPlatform.iOS || + defaultTargetPlatform == TargetPlatform.macOS)) ...[ ElevatedButton( onPressed: () => _activate( - apple: AppleReCaptchaEnterpriseProvider(siteKey: _siteKeyController.text), + apple: const AppleDebugProvider(), ), - child: const Text('activate(Apple reCAPTCHA Enterprise)'), + child: const Text('activate(Apple Debug)'), ), - ElevatedButton( - onPressed: () => _activate( - webProviderType: 'enterprise', + ElevatedButton( + onPressed: () => _activate( + apple: const AppleDeviceCheckProvider(), + ), + child: const Text('activate(Apple DeviceCheck)'), ), - child: const Text('activate(Web reCAPTCHA Enterprise)'), - ), + ElevatedButton( + onPressed: () => _activate( + apple: const AppleAppAttestProvider(), + ), + child: const Text('activate(Apple AppAttest)'), + ), + ElevatedButton( + onPressed: () => _activate( + apple: const AppleAppAttestWithDeviceCheckFallbackProvider(), + ), + child: const Text( + 'activate(Apple AppAttest + DeviceCheck fallback)', + ), + ), + if (defaultTargetPlatform == TargetPlatform.iOS) ...[ + const SizedBox(height: 8), + TextField( + controller: _appleSiteKeyController, + decoration: const InputDecoration( + labelText: 'Apple reCAPTCHA Site Key', + border: OutlineInputBorder(), + ), + ), + const SizedBox(height: 8), + ElevatedButton( + onPressed: () => _activate( + apple: AppleReCaptchaEnterpriseProvider( + siteKey: _appleSiteKeyController.text, + ), + ), + child: const Text('activate(Apple reCAPTCHA Enterprise)'), + ), + ], + ], + if (!kIsWeb && defaultTargetPlatform == TargetPlatform.windows) ...[ + ElevatedButton( + onPressed: () => _activate( + windows: WindowsDebugProvider( + debugToken: kWindowsDebugToken.isNotEmpty + ? kWindowsDebugToken + : null, + ), + ), + child: const Text('activate(Windows Debug)'), + ), + ], const SizedBox(height: 16), const Text( 'Actions', @@ -271,7 +334,7 @@ class _FirebaseAppCheck extends State { child: const Text('Test Firestore with App Check'), ), const SizedBox(height: 20), - Text( + SelectableText( _message, style: const TextStyle( color: Color.fromRGBO(47, 79, 79, 1), @@ -279,7 +342,7 @@ class _FirebaseAppCheck extends State { ), ), const SizedBox(height: 20), - Text( + SelectableText( 'Token from onTokenChange: $_eventToken', style: const TextStyle( color: Color.fromRGBO(128, 0, 128, 1), From 4ab506794d2d0d087f64bf18a2434c8af30d711a Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Fri, 29 May 2026 13:27:38 -0700 Subject: [PATCH 8/9] update api name and parameter --- .../firebase_app_check/android/build.gradle | 4 +- .../appcheck/FirebaseAppCheckPlugin.kt | 16 +- .../GeneratedAndroidFirebaseAppCheck.g.kt | 5 +- .../firebase_app_check/example/lib/main.dart | 40 +- .../FirebaseAppCheckMessages.g.swift | 5 +- .../FirebaseAppCheckPlugin.swift | 30 +- .../lib/firebase_app_check.dart | 4 +- .../firebase_app_check/windows/messages.g.cpp | 412 ++++++++++-------- .../firebase_app_check/windows/messages.g.h | 75 ++-- .../lib/src/android_providers.dart | 13 +- .../lib/src/apple_providers.dart | 13 +- .../method_channel_firebase_app_check.dart | 8 - .../lib/src/pigeon/messages.pigeon.dart | 95 ++-- .../pigeons/messages.dart | 2 - ...ethod_channel_firebase_app_check_test.dart | 28 +- 15 files changed, 380 insertions(+), 370 deletions(-) diff --git a/packages/firebase_app_check/firebase_app_check/android/build.gradle b/packages/firebase_app_check/firebase_app_check/android/build.gradle index 81e347abd98e..dbd33ee3aef3 100644 --- a/packages/firebase_app_check/firebase_app_check/android/build.gradle +++ b/packages/firebase_app_check/firebase_app_check/android/build.gradle @@ -7,6 +7,7 @@ apply from: file("local-config.gradle") buildscript { ext.kotlin_version = "1.8.22" repositories { + mavenLocal() google() mavenCentral() } @@ -14,6 +15,7 @@ buildscript { rootProject.allprojects { repositories { + mavenLocal() google() mavenCentral() } @@ -80,7 +82,7 @@ android { implementation platform("com.google.firebase:firebase-bom:${getRootProjectExtOrCoreProperty("FirebaseSDKVersion", firebaseCoreProject)}") implementation 'com.google.firebase:firebase-appcheck-debug' implementation 'com.google.firebase:firebase-appcheck-playintegrity' - implementation 'com.google.firebase:firebase-appcheck-recaptchaenterprise:16.0.0-beta01' + implementation 'com.google.firebase:firebase-appcheck-recaptcha:16.0.0-beta01' implementation 'androidx.annotation:annotation:1.7.0' } } diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt index 4bb063508300..be5abd29d32e 100644 --- a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt @@ -9,7 +9,7 @@ import com.google.firebase.FirebaseApp import com.google.firebase.appcheck.FirebaseAppCheck import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory -import com.google.firebase.appcheck.recaptchaenterprise.RecaptchaEnterpriseAppCheckProviderFactory +import com.google.firebase.appcheck.recaptcha.RecaptchaAppCheckProviderFactory import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding import io.flutter.plugin.common.BinaryMessenger @@ -56,7 +56,6 @@ class FirebaseAppCheckPlugin : androidProvider: String?, appleProvider: String?, debugToken: String?, - recaptchaEnterpriseSiteKey: String?, callback: (Result) -> Unit ) { try { @@ -68,15 +67,10 @@ class FirebaseAppCheckPlugin : DebugAppCheckProviderFactory.getInstance() ) } - "recaptchaEnterprise" -> { - if (recaptchaEnterpriseSiteKey != null) { - firebaseAppCheck.installAppCheckProviderFactory( - RecaptchaEnterpriseAppCheckProviderFactory.getInstance(recaptchaEnterpriseSiteKey) - ) - } else { - callback(Result.failure(FlutterError("invalid-argument", "Site key is required for reCAPTCHA Enterprise", null))) - return - } + "recaptcha" -> { + firebaseAppCheck.installAppCheckProviderFactory( + RecaptchaAppCheckProviderFactory.getInstance() + ) } else -> { firebaseAppCheck.installAppCheckProviderFactory( diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt index 099f8514464d..97f6635352ad 100644 --- a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt @@ -62,7 +62,7 @@ private open class GeneratedAndroidFirebaseAppCheckPigeonCodec : StandardMessage /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface FirebaseAppCheckHostApi { - fun activate(appName: String, androidProvider: String?, appleProvider: String?, debugToken: String?, recaptchaEnterpriseSiteKey: String?, callback: (Result) -> Unit) + fun activate(appName: String, androidProvider: String?, appleProvider: String?, debugToken: String?, callback: (Result) -> Unit) fun getToken(appName: String, forceRefresh: Boolean, callback: (Result) -> Unit) fun setTokenAutoRefreshEnabled(appName: String, isTokenAutoRefreshEnabled: Boolean, callback: (Result) -> Unit) fun registerTokenListener(appName: String, callback: (Result) -> Unit) @@ -86,8 +86,7 @@ interface FirebaseAppCheckHostApi { val androidProviderArg = args[1] as String? val appleProviderArg = args[2] as String? val debugTokenArg = args[3] as String? - val recaptchaEnterpriseSiteKeyArg = args[4] as String? - api.activate(appNameArg, androidProviderArg, appleProviderArg, debugTokenArg, recaptchaEnterpriseSiteKeyArg) { result: Result -> + api.activate(appNameArg, androidProviderArg, appleProviderArg, debugTokenArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapError(error)) diff --git a/packages/firebase_app_check/firebase_app_check/example/lib/main.dart b/packages/firebase_app_check/firebase_app_check/example/lib/main.dart index 8045706d9add..e400ad08fbeb 100644 --- a/packages/firebase_app_check/firebase_app_check/example/lib/main.dart +++ b/packages/firebase_app_check/firebase_app_check/example/lib/main.dart @@ -13,8 +13,6 @@ import 'package:flutter/material.dart'; import 'firebase_options.dart'; const kWebRecaptchaSiteKey = '6Lemcn0dAAAAABLkf6aiiHvpGD6x-zF3nOSDU2M8'; -const kAndroidRecaptchaSiteKey = '6LfQpf4sAAAAAJnxnEmtVMpjkwuLpDZnxxcLbjxb'; -const kAppleRecaptchaSiteKey = '6LeJev4sAAAAADbZGhkk_kkxSEzxRjzzZRC4R1R-'; // Windows: create a debug token in the Firebase Console // (App Check > Apps > Manage debug tokens), then paste it here @@ -82,16 +80,10 @@ class _FirebaseAppCheck extends State { String _message = ''; String _eventToken = 'not yet'; late final TextEditingController _webSiteKeyController; - late final TextEditingController _androidSiteKeyController; - late final TextEditingController _appleSiteKeyController; @override void initState() { _webSiteKeyController = TextEditingController(text: kWebRecaptchaSiteKey); - _androidSiteKeyController = - TextEditingController(text: kAndroidRecaptchaSiteKey); - _appleSiteKeyController = - TextEditingController(text: kAppleRecaptchaSiteKey); appCheck.onTokenChange.listen(setEventToken); super.initState(); } @@ -99,8 +91,6 @@ class _FirebaseAppCheck extends State { @override void dispose() { _webSiteKeyController.dispose(); - _androidSiteKeyController.dispose(); - _appleSiteKeyController.dispose(); super.dispose(); } @@ -199,22 +189,13 @@ class _FirebaseAppCheck extends State { ), child: const Text('activate(Android Play Integrity)'), ), - const SizedBox(height: 8), - TextField( - controller: _androidSiteKeyController, - decoration: const InputDecoration( - labelText: 'Android reCAPTCHA Site Key', - border: OutlineInputBorder(), - ), - ), + const SizedBox(height: 8), ElevatedButton( onPressed: () => _activate( - android: AndroidReCaptchaEnterpriseProvider( - siteKey: _androidSiteKeyController.text, - ), + android: const AndroidReCaptchaProvider(), ), - child: const Text('activate(Android reCAPTCHA Enterprise)'), + child: const Text('activate(Android reCAPTCHA)'), ), ], if (!kIsWeb && @@ -247,22 +228,13 @@ class _FirebaseAppCheck extends State { ), ), if (defaultTargetPlatform == TargetPlatform.iOS) ...[ - const SizedBox(height: 8), - TextField( - controller: _appleSiteKeyController, - decoration: const InputDecoration( - labelText: 'Apple reCAPTCHA Site Key', - border: OutlineInputBorder(), - ), - ), + const SizedBox(height: 8), ElevatedButton( onPressed: () => _activate( - apple: AppleReCaptchaEnterpriseProvider( - siteKey: _appleSiteKeyController.text, - ), + apple: const AppleReCaptchaProvider(), ), - child: const Text('activate(Apple reCAPTCHA Enterprise)'), + child: const Text('activate(Apple reCAPTCHA)'), ), ], ], diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift index bc76bee940f7..ac93fc9c338f 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift @@ -91,7 +91,7 @@ class FirebaseAppCheckMessagesPigeonCodec: FlutterStandardMessageCodec, @uncheck /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol FirebaseAppCheckHostApi { - func activate(appName: String, androidProvider: String?, appleProvider: String?, debugToken: String?, recaptchaEnterpriseSiteKey: String?, completion: @escaping (Result) -> Void) + func activate(appName: String, androidProvider: String?, appleProvider: String?, debugToken: String?, completion: @escaping (Result) -> Void) func getToken(appName: String, forceRefresh: Bool, completion: @escaping (Result) -> Void) func setTokenAutoRefreshEnabled(appName: String, isTokenAutoRefreshEnabled: Bool, completion: @escaping (Result) -> Void) func registerTokenListener(appName: String, completion: @escaping (Result) -> Void) @@ -112,8 +112,7 @@ class FirebaseAppCheckHostApiSetup { let androidProviderArg: String? = nilOrValue(args[1]) let appleProviderArg: String? = nilOrValue(args[2]) let debugTokenArg: String? = nilOrValue(args[3]) - let recaptchaEnterpriseSiteKeyArg: String? = nilOrValue(args[4]) - api.activate(appName: appNameArg, androidProvider: androidProviderArg, appleProvider: appleProviderArg, debugToken: debugTokenArg, recaptchaEnterpriseSiteKey: recaptchaEnterpriseSiteKeyArg) { result in + api.activate(appName: appNameArg, androidProvider: androidProviderArg, appleProvider: appleProviderArg, debugToken: debugTokenArg) { result in switch result { case .success: reply(wrapResult(nil)) diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift index 7b9089edaba2..75ec36791e97 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift @@ -60,7 +60,7 @@ public class FirebaseAppCheckPlugin: NSObject, FlutterPlugin, private var binaryMessenger: FlutterBinaryMessenger? func activate(appName: String, androidProvider: String?, appleProvider: String?, - debugToken: String?, recaptchaEnterpriseSiteKey: String?, + debugToken: String?, completion: @escaping (Result) -> Void) { guard let app = FLTFirebasePlugin.firebaseAppNamed(appName) else { completion(.failure(FlutterError( @@ -73,8 +73,7 @@ public class FirebaseAppCheckPlugin: NSObject, FlutterPlugin, providerFactory?.configure( app: app, providerName: provider, - debugToken: debugToken, - recaptchaEnterpriseSiteKey: recaptchaEnterpriseSiteKey + debugToken: debugToken ) completion(.success(())) @@ -164,7 +163,7 @@ public class FirebaseAppCheckPlugin: NSObject, FlutterPlugin, channel.setStreamHandler(nil) } for (_, handler) in streamHandlers { - handler.onCancel(withArguments: nil) + _ = handler.onCancel(withArguments: nil) } eventChannels.removeAll() streamHandlers.removeAll() @@ -250,8 +249,7 @@ class FlutterAppCheckProviderFactory: NSObject, AppCheckProviderFactory { wrapper.configure( app: app, providerName: "deviceCheck", - debugToken: nil, - recaptchaEnterpriseSiteKey: nil + debugToken: nil ) providers[app.name] = wrapper } @@ -261,8 +259,7 @@ class FlutterAppCheckProviderFactory: NSObject, AppCheckProviderFactory { func configure( app: FirebaseApp, providerName: String, - debugToken: String?, - recaptchaEnterpriseSiteKey: String? + debugToken: String? ) { if providers[app.name] == nil { providers[app.name] = AppCheckProviderWrapper() @@ -270,8 +267,7 @@ class FlutterAppCheckProviderFactory: NSObject, AppCheckProviderFactory { providers[app.name]?.configure( app: app, providerName: providerName, - debugToken: debugToken, - recaptchaEnterpriseSiteKey: recaptchaEnterpriseSiteKey + debugToken: debugToken ) } } @@ -282,8 +278,7 @@ class AppCheckProviderWrapper: NSObject, AppCheckProvider { func configure( app: FirebaseApp, providerName: String, - debugToken: String?, - recaptchaEnterpriseSiteKey: String? + debugToken: String? ) { switch providerName { case "debug": @@ -306,15 +301,14 @@ class AppCheckProviderWrapper: NSObject, AppCheckProvider { } else { delegateProvider = DeviceCheckProvider(app: app) } - case "recaptchaEnterprise": + case "recaptcha": #if os(iOS) - if let siteKey = recaptchaEnterpriseSiteKey { - delegateProvider = RecaptchaEnterpriseProvider(app: app, siteKey: siteKey) - } else { - print("Firebase App Check: siteKey is missing for reCAPTCHA Enterprise provider.") + delegateProvider = RecaptchaProvider(app: app) + if delegateProvider == nil { + print("Firebase App Check: failed to initialize RecaptchaProvider. Ensure site key is in GoogleService-Info.plist.") } #else - print("Firebase App Check: reCAPTCHA Enterprise is only supported on iOS.") + print("Firebase App Check: reCAPTCHA is only supported on iOS.") #endif default: // deviceCheck diff --git a/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart index 0c91314550cf..88dcb0f16064 100644 --- a/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart @@ -13,14 +13,14 @@ export 'package:firebase_app_check_platform_interface/firebase_app_check_platfor AndroidAppCheckProvider, AndroidDebugProvider, AndroidPlayIntegrityProvider, - AndroidReCaptchaEnterpriseProvider, + AndroidReCaptchaProvider, AppleProvider, AppleAppCheckProvider, AppleDebugProvider, AppleDeviceCheckProvider, AppleAppAttestProvider, AppleAppAttestWithDeviceCheckFallbackProvider, - AppleReCaptchaEnterpriseProvider, + AppleReCaptchaProvider, ReCaptchaEnterpriseProvider, ReCaptchaV3Provider, WebDebugProvider, diff --git a/packages/firebase_app_check/firebase_app_check/windows/messages.g.cpp b/packages/firebase_app_check/firebase_app_check/windows/messages.g.cpp index d46886ee294e..0da3e3c1ded5 100644 --- a/packages/firebase_app_check/firebase_app_check/windows/messages.g.cpp +++ b/packages/firebase_app_check/firebase_app_check/windows/messages.g.cpp @@ -34,32 +34,36 @@ FlutterError CreateConnectionError(const std::string channel_name) { } namespace { -template +template bool PigeonInternalDeepEquals(const T& a, const T& b); bool PigeonInternalDeepEquals(const double& a, const double& b); -template +template bool PigeonInternalDeepEquals(const std::vector& a, const std::vector& b); -template +template bool PigeonInternalDeepEquals(const std::map& a, const std::map& b); -template -bool PigeonInternalDeepEquals(const std::optional& a, const std::optional& b); +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b); -template -bool PigeonInternalDeepEquals(const std::unique_ptr& a, const std::unique_ptr& b); +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b); -bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, const ::flutter::EncodableValue& b); +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b); -template +template bool PigeonInternalDeepEquals(const T& a, const T& b) { return a == b; } -template -bool PigeonInternalDeepEquals(const std::vector& a, const std::vector& b) { +template +bool PigeonInternalDeepEquals(const std::vector& a, + const std::vector& b) { if (a.size() != b.size()) { return false; } @@ -72,7 +76,8 @@ bool PigeonInternalDeepEquals(const std::vector& a, const std::vector& b) } template -bool PigeonInternalDeepEquals(const std::map& a, const std::map& b) { +bool PigeonInternalDeepEquals(const std::map& a, + const std::map& b) { if (a.size() != b.size()) { return false; } @@ -100,8 +105,9 @@ bool PigeonInternalDeepEquals(const double& a, const double& b) { return (a == b) || (std::isnan(a) && std::isnan(b)); } -template -bool PigeonInternalDeepEquals(const std::optional& a, const std::optional& b) { +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b) { if (!a && !b) { return true; } @@ -111,8 +117,9 @@ bool PigeonInternalDeepEquals(const std::optional& a, const std::optional& return PigeonInternalDeepEquals(*a, *b); } -template -bool PigeonInternalDeepEquals(const std::unique_ptr& a, const std::unique_ptr& b) { +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b) { if (a.get() == b.get()) { return true; } @@ -122,15 +129,18 @@ bool PigeonInternalDeepEquals(const std::unique_ptr& a, const std::unique_ptr return PigeonInternalDeepEquals(*a, *b); } -bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, const ::flutter::EncodableValue& b) { +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b) { if (a.index() != b.index()) { return false; } if (const double* da = std::get_if(&a)) { return PigeonInternalDeepEquals(*da, std::get(b)); - } else if (const ::flutter::EncodableList* la = std::get_if<::flutter::EncodableList>(&a)) { + } else if (const ::flutter::EncodableList* la = + std::get_if<::flutter::EncodableList>(&a)) { return PigeonInternalDeepEquals(*la, std::get<::flutter::EncodableList>(b)); - } else if (const ::flutter::EncodableMap* ma = std::get_if<::flutter::EncodableMap>(&a)) { + } else if (const ::flutter::EncodableMap* ma = + std::get_if<::flutter::EncodableMap>(&a)) { return PigeonInternalDeepEquals(*ma, std::get<::flutter::EncodableMap>(b)); } return a == b; @@ -173,7 +183,8 @@ template size_t PigeonInternalDeepHash(const std::map& v) { size_t result = 0; for (const auto& kv : v) { - result += ((PigeonInternalDeepHash(kv.first) * 31) ^ PigeonInternalDeepHash(kv.second)); + result += ((PigeonInternalDeepHash(kv.first) * 31) ^ + PigeonInternalDeepHash(kv.second)); } return result; } @@ -232,220 +243,275 @@ size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v) { PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( - uint8_t type, - ::flutter::ByteStreamReader* stream) const { + uint8_t type, ::flutter::ByteStreamReader* stream) const { return ::flutter::StandardCodecSerializer::ReadValueOfType(type, stream); } void PigeonInternalCodecSerializer::WriteValue( - const EncodableValue& value, - ::flutter::ByteStreamWriter* stream) const { + const EncodableValue& value, ::flutter::ByteStreamWriter* stream) const { ::flutter::StandardCodecSerializer::WriteValue(value, stream); } /// The codec used by FirebaseAppCheckHostApi. const ::flutter::StandardMessageCodec& FirebaseAppCheckHostApi::GetCodec() { - return ::flutter::StandardMessageCodec::GetInstance(&PigeonInternalCodecSerializer::GetInstance()); + return ::flutter::StandardMessageCodec::GetInstance( + &PigeonInternalCodecSerializer::GetInstance()); } -// Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through the `binary_messenger`. +// Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through +// the `binary_messenger`. void FirebaseAppCheckHostApi::SetUp( - ::flutter::BinaryMessenger* binary_messenger, - FirebaseAppCheckHostApi* api) { + ::flutter::BinaryMessenger* binary_messenger, + FirebaseAppCheckHostApi* api) { FirebaseAppCheckHostApi::SetUp(binary_messenger, api, ""); } void FirebaseAppCheckHostApi::SetUp( - ::flutter::BinaryMessenger* binary_messenger, - FirebaseAppCheckHostApi* api, - const std::string& message_channel_suffix) { - const std::string prepended_suffix = message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix : ""; + ::flutter::BinaryMessenger* binary_messenger, FirebaseAppCheckHostApi* api, + const std::string& message_channel_suffix) { + const std::string prepended_suffix = + message_channel_suffix.length() > 0 + ? std::string(".") + message_channel_suffix + : ""; { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.firebase_app_check_platform_interface." + "FirebaseAppCheckHostApi.activate" + + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const ::flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_app_name_arg = args.at(0); - if (encodable_app_name_arg.IsNull()) { - reply(WrapError("app_name_arg unexpectedly null.")); - return; - } - const auto& app_name_arg = std::get(encodable_app_name_arg); - const auto& encodable_android_provider_arg = args.at(1); - const auto* android_provider_arg = std::get_if(&encodable_android_provider_arg); - const auto& encodable_apple_provider_arg = args.at(2); - const auto* apple_provider_arg = std::get_if(&encodable_apple_provider_arg); - const auto& encodable_debug_token_arg = args.at(3); - const auto* debug_token_arg = std::get_if(&encodable_debug_token_arg); - const auto& encodable_recaptcha_enterprise_site_key_arg = args.at(4); - const auto* recaptcha_enterprise_site_key_arg = std::get_if(&encodable_recaptcha_enterprise_site_key_arg); - api->Activate(app_name_arg, android_provider_arg, apple_provider_arg, debug_token_arg, recaptcha_enterprise_site_key_arg, [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; + channel.SetMessageHandler( + [api](const EncodableValue& message, + const ::flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_name_arg = args.at(0); + if (encodable_app_name_arg.IsNull()) { + reply(WrapError("app_name_arg unexpectedly null.")); + return; + } + const auto& app_name_arg = + std::get(encodable_app_name_arg); + const auto& encodable_android_provider_arg = args.at(1); + const auto* android_provider_arg = + std::get_if(&encodable_android_provider_arg); + const auto& encodable_apple_provider_arg = args.at(2); + const auto* apple_provider_arg = + std::get_if(&encodable_apple_provider_arg); + const auto& encodable_debug_token_arg = args.at(3); + const auto* debug_token_arg = + std::get_if(&encodable_debug_token_arg); + api->Activate(app_name_arg, android_provider_arg, + apple_provider_arg, debug_token_arg, + [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.firebase_app_check_platform_interface." + "FirebaseAppCheckHostApi.getToken" + + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const ::flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_app_name_arg = args.at(0); - if (encodable_app_name_arg.IsNull()) { - reply(WrapError("app_name_arg unexpectedly null.")); - return; - } - const auto& app_name_arg = std::get(encodable_app_name_arg); - const auto& encodable_force_refresh_arg = args.at(1); - if (encodable_force_refresh_arg.IsNull()) { - reply(WrapError("force_refresh_arg unexpectedly null.")); - return; - } - const auto& force_refresh_arg = std::get(encodable_force_refresh_arg); - api->GetToken(app_name_arg, force_refresh_arg, [reply](ErrorOr>&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - auto output_optional = std::move(output).TakeValue(); - if (output_optional) { - wrapped.push_back(EncodableValue(std::move(output_optional).value())); - } else { - wrapped.push_back(EncodableValue()); + channel.SetMessageHandler( + [api](const EncodableValue& message, + const ::flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_name_arg = args.at(0); + if (encodable_app_name_arg.IsNull()) { + reply(WrapError("app_name_arg unexpectedly null.")); + return; + } + const auto& app_name_arg = + std::get(encodable_app_name_arg); + const auto& encodable_force_refresh_arg = args.at(1); + if (encodable_force_refresh_arg.IsNull()) { + reply(WrapError("force_refresh_arg unexpectedly null.")); + return; + } + const auto& force_refresh_arg = + std::get(encodable_force_refresh_arg); + api->GetToken( + app_name_arg, force_refresh_arg, + [reply](ErrorOr>&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + auto output_optional = std::move(output).TakeValue(); + if (output_optional) { + wrapped.push_back( + EncodableValue(std::move(output_optional).value())); + } else { + wrapped.push_back(EncodableValue()); + } + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); } - reply(EncodableValue(std::move(wrapped))); }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.firebase_app_check_platform_interface." + "FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled" + + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const ::flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_app_name_arg = args.at(0); - if (encodable_app_name_arg.IsNull()) { - reply(WrapError("app_name_arg unexpectedly null.")); - return; - } - const auto& app_name_arg = std::get(encodable_app_name_arg); - const auto& encodable_is_token_auto_refresh_enabled_arg = args.at(1); - if (encodable_is_token_auto_refresh_enabled_arg.IsNull()) { - reply(WrapError("is_token_auto_refresh_enabled_arg unexpectedly null.")); - return; - } - const auto& is_token_auto_refresh_enabled_arg = std::get(encodable_is_token_auto_refresh_enabled_arg); - api->SetTokenAutoRefreshEnabled(app_name_arg, is_token_auto_refresh_enabled_arg, [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; + channel.SetMessageHandler( + [api](const EncodableValue& message, + const ::flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_name_arg = args.at(0); + if (encodable_app_name_arg.IsNull()) { + reply(WrapError("app_name_arg unexpectedly null.")); + return; + } + const auto& app_name_arg = + std::get(encodable_app_name_arg); + const auto& encodable_is_token_auto_refresh_enabled_arg = + args.at(1); + if (encodable_is_token_auto_refresh_enabled_arg.IsNull()) { + reply(WrapError( + "is_token_auto_refresh_enabled_arg unexpectedly null.")); + return; + } + const auto& is_token_auto_refresh_enabled_arg = + std::get(encodable_is_token_auto_refresh_enabled_arg); + api->SetTokenAutoRefreshEnabled( + app_name_arg, is_token_auto_refresh_enabled_arg, + [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.firebase_app_check_platform_interface." + "FirebaseAppCheckHostApi.registerTokenListener" + + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const ::flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_app_name_arg = args.at(0); - if (encodable_app_name_arg.IsNull()) { - reply(WrapError("app_name_arg unexpectedly null.")); - return; - } - const auto& app_name_arg = std::get(encodable_app_name_arg); - api->RegisterTokenListener(app_name_arg, [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; + channel.SetMessageHandler( + [api](const EncodableValue& message, + const ::flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_name_arg = args.at(0); + if (encodable_app_name_arg.IsNull()) { + reply(WrapError("app_name_arg unexpectedly null.")); + return; + } + const auto& app_name_arg = + std::get(encodable_app_name_arg); + api->RegisterTokenListener( + app_name_arg, [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.firebase_app_check_platform_interface." + "FirebaseAppCheckHostApi.getLimitedUseAppCheckToken" + + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const ::flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_app_name_arg = args.at(0); - if (encodable_app_name_arg.IsNull()) { - reply(WrapError("app_name_arg unexpectedly null.")); - return; - } - const auto& app_name_arg = std::get(encodable_app_name_arg); - api->GetLimitedUseAppCheckToken(app_name_arg, [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; + channel.SetMessageHandler( + [api](const EncodableValue& message, + const ::flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_name_arg = args.at(0); + if (encodable_app_name_arg.IsNull()) { + reply(WrapError("app_name_arg unexpectedly null.")); + return; + } + const auto& app_name_arg = + std::get(encodable_app_name_arg); + api->GetLimitedUseAppCheckToken( + app_name_arg, [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); } else { channel.SetMessageHandler(nullptr); } } } -EncodableValue FirebaseAppCheckHostApi::WrapError(std::string_view error_message) { - return EncodableValue(EncodableList{ - EncodableValue(std::string(error_message)), - EncodableValue("Error"), - EncodableValue() - }); +EncodableValue FirebaseAppCheckHostApi::WrapError( + std::string_view error_message) { + return EncodableValue( + EncodableList{EncodableValue(std::string(error_message)), + EncodableValue("Error"), EncodableValue()}); } EncodableValue FirebaseAppCheckHostApi::WrapError(const FlutterError& error) { - return EncodableValue(EncodableList{ - EncodableValue(error.code()), - EncodableValue(error.message()), - error.details() - }); + return EncodableValue(EncodableList{EncodableValue(error.code()), + EncodableValue(error.message()), + error.details()}); } } // namespace firebase_app_check_windows diff --git a/packages/firebase_app_check/firebase_app_check/windows/messages.g.h b/packages/firebase_app_check/firebase_app_check/windows/messages.g.h index 4d13d5ff3fe4..50ae482963dc 100644 --- a/packages/firebase_app_check/firebase_app_check/windows/messages.g.h +++ b/packages/firebase_app_check/firebase_app_check/windows/messages.g.h @@ -17,17 +17,16 @@ namespace firebase_app_check_windows { - // Generated class from Pigeon. class FlutterError { public: - explicit FlutterError(const std::string& code) - : code_(code) {} + explicit FlutterError(const std::string& code) : code_(code) {} explicit FlutterError(const std::string& code, const std::string& message) - : code_(code), message_(message) {} - explicit FlutterError(const std::string& code, const std::string& message, const ::flutter::EncodableValue& details) - : code_(code), message_(message), details_(details) {} + : code_(code), message_(message) {} + explicit FlutterError(const std::string& code, const std::string& message, + const ::flutter::EncodableValue& details) + : code_(code), message_(message), details_(details) {} const std::string& code() const { return code_; } const std::string& message() const { return message_; } @@ -39,7 +38,8 @@ class FlutterError { ::flutter::EncodableValue details_; }; -template class ErrorOr { +template +class ErrorOr { public: ErrorOr(const T& rhs) : v_(rhs) {} ErrorOr(const T&& rhs) : v_(std::move(rhs)) {} @@ -58,9 +58,8 @@ template class ErrorOr { std::variant v_; }; - - -class PigeonInternalCodecSerializer : public ::flutter::StandardCodecSerializer { +class PigeonInternalCodecSerializer + : public ::flutter::StandardCodecSerializer { public: PigeonInternalCodecSerializer(); inline static PigeonInternalCodecSerializer& GetInstance() { @@ -68,55 +67,51 @@ class PigeonInternalCodecSerializer : public ::flutter::StandardCodecSerializer return sInstance; } - void WriteValue( - const ::flutter::EncodableValue& value, - ::flutter::ByteStreamWriter* stream) const override; + void WriteValue(const ::flutter::EncodableValue& value, + ::flutter::ByteStreamWriter* stream) const override; + protected: ::flutter::EncodableValue ReadValueOfType( - uint8_t type, - ::flutter::ByteStreamReader* stream) const override; + uint8_t type, ::flutter::ByteStreamReader* stream) const override; }; -// Generated interface from Pigeon that represents a handler of messages from Flutter. +// Generated interface from Pigeon that represents a handler of messages from +// Flutter. class FirebaseAppCheckHostApi { public: FirebaseAppCheckHostApi(const FirebaseAppCheckHostApi&) = delete; FirebaseAppCheckHostApi& operator=(const FirebaseAppCheckHostApi&) = delete; virtual ~FirebaseAppCheckHostApi() {} virtual void Activate( - const std::string& app_name, - const std::string* android_provider, - const std::string* apple_provider, - const std::string* debug_token, - const std::string* recaptcha_enterprise_site_key, - std::function reply)> result) = 0; + const std::string& app_name, const std::string* android_provider, + const std::string* apple_provider, const std::string* debug_token, + std::function reply)> result) = 0; virtual void GetToken( - const std::string& app_name, - bool force_refresh, - std::function> reply)> result) = 0; + const std::string& app_name, bool force_refresh, + std::function> reply)> + result) = 0; virtual void SetTokenAutoRefreshEnabled( - const std::string& app_name, - bool is_token_auto_refresh_enabled, - std::function reply)> result) = 0; + const std::string& app_name, bool is_token_auto_refresh_enabled, + std::function reply)> result) = 0; virtual void RegisterTokenListener( - const std::string& app_name, - std::function reply)> result) = 0; + const std::string& app_name, + std::function reply)> result) = 0; virtual void GetLimitedUseAppCheckToken( - const std::string& app_name, - std::function reply)> result) = 0; + const std::string& app_name, + std::function reply)> result) = 0; // The codec used by FirebaseAppCheckHostApi. static const ::flutter::StandardMessageCodec& GetCodec(); - // Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through the `binary_messenger`. - static void SetUp( - ::flutter::BinaryMessenger* binary_messenger, - FirebaseAppCheckHostApi* api); - static void SetUp( - ::flutter::BinaryMessenger* binary_messenger, - FirebaseAppCheckHostApi* api, - const std::string& message_channel_suffix); + // Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through + // the `binary_messenger`. + static void SetUp(::flutter::BinaryMessenger* binary_messenger, + FirebaseAppCheckHostApi* api); + static void SetUp(::flutter::BinaryMessenger* binary_messenger, + FirebaseAppCheckHostApi* api, + const std::string& message_channel_suffix); static ::flutter::EncodableValue WrapError(std::string_view error_message); static ::flutter::EncodableValue WrapError(const FlutterError& error); + protected: FirebaseAppCheckHostApi() = default; }; diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/android_providers.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/android_providers.dart index 98337af759c6..47640028475a 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/android_providers.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/android_providers.dart @@ -33,14 +33,9 @@ class AndroidPlayIntegrityProvider extends AndroidAppCheckProvider { const AndroidPlayIntegrityProvider() : super('playIntegrity'); } -/// reCAPTCHA Enterprise provider for Android. +/// reCAPTCHA provider for Android. /// -/// See documentation: https://firebase.google.com/docs/app-check/android/recaptcha-enterprise-provider -class AndroidReCaptchaEnterpriseProvider extends AndroidAppCheckProvider { - /// Creates an Android reCAPTCHA Enterprise provider with a site key. - const AndroidReCaptchaEnterpriseProvider({required this.siteKey}) - : super('recaptchaEnterprise'); - - /// The reCAPTCHA Enterprise site key. - final String siteKey; +/// The site key is retrieved automatically from google-services.json. +class AndroidReCaptchaProvider extends AndroidAppCheckProvider { + const AndroidReCaptchaProvider() : super('recaptcha'); } diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/apple_providers.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/apple_providers.dart index f2ca2f6e548f..e768fca29477 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/apple_providers.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/apple_providers.dart @@ -55,14 +55,9 @@ class AppleAppAttestWithDeviceCheckFallbackProvider : super('appAttestWithDeviceCheckFallback'); } -/// reCAPTCHA Enterprise provider for Apple platforms. +/// reCAPTCHA provider for Apple platforms. /// -/// See documentation: https://firebase.google.com/docs/app-check/ios/recaptcha-enterprise-provider -class AppleReCaptchaEnterpriseProvider extends AppleAppCheckProvider { - /// Creates an Apple reCAPTCHA Enterprise provider with a site key. - const AppleReCaptchaEnterpriseProvider({required this.siteKey}) - : super('recaptchaEnterprise'); - - /// The reCAPTCHA Enterprise site key. - final String siteKey; +/// The site key is retrieved automatically from GoogleService-Info.plist. +class AppleReCaptchaProvider extends AppleAppCheckProvider { + const AppleReCaptchaProvider() : super('recaptcha'); } diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart index 5d157aea948e..b7f2d035d212 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart @@ -112,13 +112,6 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { WindowsAppCheckProvider? providerWindows, }) async { try { - String? recaptchaEnterpriseSiteKey; - if (providerAndroid is AndroidReCaptchaEnterpriseProvider) { - recaptchaEnterpriseSiteKey = providerAndroid.siteKey; - } else if (providerApple is AppleReCaptchaEnterpriseProvider) { - recaptchaEnterpriseSiteKey = providerApple.siteKey; - } - await _pigeonApi.activate( app.name, defaultTargetPlatform == TargetPlatform.android || kDebugMode @@ -140,7 +133,6 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { providerApple: providerApple, providerWindows: providerWindows, ), - recaptchaEnterpriseSiteKey, ); } on PlatformException catch (e, s) { convertPlatformException(e, s); diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart index 8fb14b67fa11..ca154bea1029 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -13,9 +13,9 @@ import 'package:flutter/services.dart'; import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; Object? _extractReplyValueOrThrow( - List? replyList, - String channelName, { - required bool isNullValid, + List? replyList, + String channelName, { + required bool isNullValid, }) { if (replyList == null) { throw PlatformException( @@ -37,8 +37,6 @@ Object? _extractReplyValueOrThrow( return replyList.firstOrNull; } - - class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -64,105 +62,114 @@ class FirebaseAppCheckHostApi { /// Constructor for [FirebaseAppCheckHostApi]. 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. - FirebaseAppCheckHostApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + FirebaseAppCheckHostApi( + {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + pigeonVar_messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); final String pigeonVar_messageChannelSuffix; - Future activate(String appName, String? androidProvider, String? appleProvider, String? debugToken, String? recaptchaEnterpriseSiteKey) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate$pigeonVar_messageChannelSuffix'; + Future activate(String appName, String? androidProvider, + String? appleProvider, String? debugToken) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName, androidProvider, appleProvider, debugToken, recaptchaEnterpriseSiteKey]); + final Future pigeonVar_sendFuture = pigeonVar_channel + .send([appName, androidProvider, appleProvider, debugToken]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future getToken(String appName, bool forceRefresh) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName, forceRefresh]); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([appName, forceRefresh]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); return pigeonVar_replyValue as String?; } - Future setTokenAutoRefreshEnabled(String appName, bool isTokenAutoRefreshEnabled) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled$pigeonVar_messageChannelSuffix'; + Future setTokenAutoRefreshEnabled( + String appName, bool isTokenAutoRefreshEnabled) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName, isTokenAutoRefreshEnabled]); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([appName, isTokenAutoRefreshEnabled]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future registerTokenListener(String appName) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName]); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([appName]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as String; } Future getLimitedUseAppCheckToken(String appName) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName]); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([appName]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as String; } } diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/messages.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/messages.dart index e20e1bdfba0e..e84ff78ab5f4 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/messages.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/messages.dart @@ -29,10 +29,8 @@ abstract class FirebaseAppCheckHostApi { String? androidProvider, String? appleProvider, String? debugToken, - String? recaptchaEnterpriseSiteKey, ); - @async String? getToken(String appName, bool forceRefresh); diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart index 395e96ef5134..7c60c253ff3d 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart @@ -123,8 +123,8 @@ void main() { }); }); - group('activate()', () { - test('passes recaptchaEnterpriseSiteKey on Android', () async { + group('activate() with Recaptcha', () { + test('passes recaptcha on Android', () async { final appCheck = MethodChannelFirebaseAppCheck(app: Firebase.app()); final List log = []; @@ -133,23 +133,24 @@ void main() { .setMockMessageHandler( 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate', (message) async { - final list = const StandardMessageCodec().decodeMessage(message) as List; + final list = const StandardMessageCodec().decodeMessage(message) + as List; log.add(list); - return const StandardMessageCodec().encodeMessage([null]); // Return success + return const StandardMessageCodec() + .encodeMessage([null]); // Return success }, ); await appCheck.activate( - providerAndroid: const AndroidReCaptchaEnterpriseProvider(siteKey: 'my-site-key'), + providerAndroid: const AndroidReCaptchaProvider(), ); expect(log.length, 1); expect(log[0][0], '[DEFAULT]'); // appName - expect(log[0][1], 'recaptchaEnterprise'); // androidProvider - expect(log[0][4], 'my-site-key'); // recaptchaEnterpriseSiteKey + expect(log[0][1], 'recaptcha'); // androidProvider }); - test('passes recaptchaEnterpriseSiteKey on iOS', () async { + test('passes recaptcha on iOS', () async { debugDefaultTargetPlatformOverride = TargetPlatform.iOS; final appCheck = MethodChannelFirebaseAppCheck(app: Firebase.app()); @@ -159,20 +160,21 @@ void main() { .setMockMessageHandler( 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate', (message) async { - final list = const StandardMessageCodec().decodeMessage(message) as List; + final list = const StandardMessageCodec().decodeMessage(message) + as List; log.add(list); - return const StandardMessageCodec().encodeMessage([null]); // Return success + return const StandardMessageCodec() + .encodeMessage([null]); // Return success }, ); await appCheck.activate( - providerApple: const AppleReCaptchaEnterpriseProvider(siteKey: 'my-apple-site-key'), + providerApple: const AppleReCaptchaProvider(), ); expect(log.length, 1); expect(log[0][0], '[DEFAULT]'); // appName - expect(log[0][2], 'recaptchaEnterprise'); // appleProvider - expect(log[0][4], 'my-apple-site-key'); // recaptchaEnterpriseSiteKey + expect(log[0][2], 'recaptcha'); // appleProvider }); }); }); From d1c4187320dde0ecf27cf7236580a4fac2c2cf7e Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Fri, 29 May 2026 13:53:01 -0700 Subject: [PATCH 9/9] pigeon update --- .../GeneratedAndroidFirebaseAppCheck.g.kt | 95 ++++++------------- .../FirebaseAppCheckMessages.g.swift | 7 -- 2 files changed, 29 insertions(+), 73 deletions(-) diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt index 5890bbd641be..97f6635352ad 100644 --- a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt @@ -10,11 +10,12 @@ package io.flutter.plugins.firebase.appcheck import android.util.Log import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MessageCodec +import io.flutter.plugin.common.StandardMethodCodec import io.flutter.plugin.common.StandardMessageCodec import java.io.ByteArrayOutputStream import java.nio.ByteBuffer - private object GeneratedAndroidFirebaseAppCheckPigeonUtils { fun wrapResult(result: Any?): List { @@ -23,19 +24,23 @@ private object GeneratedAndroidFirebaseAppCheckPigeonUtils { fun wrapError(exception: Throwable): List { return if (exception is FlutterError) { - listOf(exception.code, exception.message, exception.details) + listOf( + exception.code, + exception.message, + exception.details + ) } else { listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)) + 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. @@ -47,57 +52,33 @@ class FlutterError ( ) : RuntimeException() private open class GeneratedAndroidFirebaseAppCheckPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { - return super.readValueOfType(type, buffer) + return super.readValueOfType(type, buffer) } - - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { super.writeValue(stream, value) } } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface FirebaseAppCheckHostApi { - fun activate( - appName: String, - androidProvider: String?, - appleProvider: String?, - debugToken: String?, - callback: (Result) -> Unit - ) - + fun activate(appName: String, androidProvider: String?, appleProvider: String?, debugToken: String?, callback: (Result) -> Unit) fun getToken(appName: String, forceRefresh: Boolean, callback: (Result) -> Unit) - - fun setTokenAutoRefreshEnabled( - appName: String, - isTokenAutoRefreshEnabled: Boolean, - callback: (Result) -> Unit - ) - + fun setTokenAutoRefreshEnabled(appName: String, isTokenAutoRefreshEnabled: Boolean, callback: (Result) -> Unit) fun registerTokenListener(appName: String, callback: (Result) -> Unit) - fun getLimitedUseAppCheckToken(appName: String, callback: (Result) -> Unit) companion object { /** The codec used by FirebaseAppCheckHostApi. */ - val codec: MessageCodec by lazy { GeneratedAndroidFirebaseAppCheckPigeonCodec() } - /** - * Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through the - * `binaryMessenger`. - */ + val codec: MessageCodec by lazy { + GeneratedAndroidFirebaseAppCheckPigeonCodec() + } + /** Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through the `binaryMessenger`. */ @JvmOverloads - fun setUp( - binaryMessenger: BinaryMessenger, - api: FirebaseAppCheckHostApi?, - messageChannelSuffix: String = "" - ) { - val separatedMessageChannelSuffix = - if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + fun setUp(binaryMessenger: BinaryMessenger, api: FirebaseAppCheckHostApi?, messageChannelSuffix: String = "") { + val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate$separatedMessageChannelSuffix", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -105,8 +86,7 @@ interface FirebaseAppCheckHostApi { val androidProviderArg = args[1] as String? val appleProviderArg = args[2] as String? val debugTokenArg = args[3] as String? - api.activate(appNameArg, androidProviderArg, appleProviderArg, debugTokenArg) { - result: Result -> + api.activate(appNameArg, androidProviderArg, appleProviderArg, debugTokenArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapError(error)) @@ -120,11 +100,7 @@ interface FirebaseAppCheckHostApi { } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken$separatedMessageChannelSuffix", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -145,18 +121,13 @@ interface FirebaseAppCheckHostApi { } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled$separatedMessageChannelSuffix", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val appNameArg = args[0] as String val isTokenAutoRefreshEnabledArg = args[1] as Boolean - api.setTokenAutoRefreshEnabled(appNameArg, isTokenAutoRefreshEnabledArg) { - result: Result -> + api.setTokenAutoRefreshEnabled(appNameArg, isTokenAutoRefreshEnabledArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapError(error)) @@ -170,11 +141,7 @@ interface FirebaseAppCheckHostApi { } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener$separatedMessageChannelSuffix", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -194,11 +161,7 @@ interface FirebaseAppCheckHostApi { } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken$separatedMessageChannelSuffix", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift index cdf5bae0a709..ac93fc9c338f 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift @@ -132,10 +132,8 @@ class FirebaseAppCheckHostApiSetup { let forceRefreshArg = args[1] as! Bool api.getToken(appName: appNameArg, forceRefresh: forceRefreshArg) { result in switch result { - case .success(let res): case .success(let res): reply(wrapResult(res)) - case .failure(let error): case .failure(let error): reply(wrapError(error)) } @@ -154,7 +152,6 @@ class FirebaseAppCheckHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case .failure(let error): case .failure(let error): reply(wrapError(error)) } @@ -170,10 +167,8 @@ class FirebaseAppCheckHostApiSetup { let appNameArg = args[0] as! String api.registerTokenListener(appName: appNameArg) { result in switch result { - case .success(let res): case .success(let res): reply(wrapResult(res)) - case .failure(let error): case .failure(let error): reply(wrapError(error)) } @@ -189,10 +184,8 @@ class FirebaseAppCheckHostApiSetup { let appNameArg = args[0] as! String api.getLimitedUseAppCheckToken(appName: appNameArg) { result in switch result { - case .success(let res): case .success(let res): reply(wrapResult(res)) - case .failure(let error): case .failure(let error): reply(wrapError(error)) }