diff --git a/packages/firebase_app_check/analysis_options.yaml b/packages/firebase_app_check/analysis_options.yaml new file mode 100644 index 000000000000..9eeae6b966d6 --- /dev/null +++ b/packages/firebase_app_check/analysis_options.yaml @@ -0,0 +1,9 @@ +# Copyright 2025 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# in the LICENSE file. + +include: ../../analysis_options.yaml + +analyzer: + exclude: + - firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart 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 099e28aab3c1..3f82e038fc4d 100644 --- a/packages/firebase_app_check/firebase_app_check/android/build.gradle +++ b/packages/firebase_app_check/firebase_app_check/android/build.gradle @@ -2,6 +2,7 @@ group 'io.flutter.plugins.firebase.appcheck' version '1.0-SNAPSHOT' apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' apply from: file("local-config.gradle") buildscript { @@ -12,6 +13,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:8.3.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10" } } @@ -53,6 +55,10 @@ android { targetCompatibility project.ext.javaVersion } + kotlinOptions { + jvmTarget = project.ext.javaVersion + } + buildFeatures { buildConfig true } @@ -67,7 +73,7 @@ android { implementation 'com.google.firebase:firebase-appcheck-debug' implementation 'com.google.firebase:firebase-appcheck-playintegrity' implementation 'androidx.annotation:annotation:1.7.0' - + implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.10" } } diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppCheckPlugin.java b/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppCheckPlugin.java deleted file mode 100644 index 2f49368edea1..000000000000 --- a/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppCheckPlugin.java +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.plugins.firebase.appcheck; - -import static io.flutter.plugins.firebase.core.FlutterFirebasePluginRegistry.registerPlugin; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import com.google.android.gms.tasks.Task; -import com.google.android.gms.tasks.TaskCompletionSource; -import com.google.android.gms.tasks.Tasks; -import com.google.firebase.FirebaseApp; -import com.google.firebase.appcheck.AppCheckToken; -import com.google.firebase.appcheck.FirebaseAppCheck; -import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory; -import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory; -import io.flutter.embedding.engine.plugins.FlutterPlugin; -import io.flutter.plugin.common.BinaryMessenger; -import io.flutter.plugin.common.EventChannel; -import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugin.common.MethodChannel.MethodCallHandler; -import io.flutter.plugin.common.MethodChannel.Result; -import io.flutter.plugins.firebase.core.FlutterFirebasePlugin; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -public class FlutterFirebaseAppCheckPlugin - implements FlutterFirebasePlugin, FlutterPlugin, MethodCallHandler { - - private static final String METHOD_CHANNEL_NAME = "plugins.flutter.io/firebase_app_check"; - private final Map streamHandlers = new HashMap<>(); - - private final String debugProvider = "debug"; - private final String playIntegrity = "playIntegrity"; - - @Nullable private BinaryMessenger messenger; - - private MethodChannel channel; - - private void initInstance(BinaryMessenger messenger) { - registerPlugin(METHOD_CHANNEL_NAME, this); - channel = new MethodChannel(messenger, METHOD_CHANNEL_NAME); - channel.setMethodCallHandler(this); - - this.messenger = messenger; - } - - @Override - public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { - initInstance(binding.getBinaryMessenger()); - } - - @Override - public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { - channel.setMethodCallHandler(null); - channel = null; - messenger = null; - - removeEventListeners(); - } - - private FirebaseAppCheck getAppCheck(Map arguments) { - String appName = (String) Objects.requireNonNull(arguments.get("appName")); - FirebaseApp app = FirebaseApp.getInstance(appName); - return FirebaseAppCheck.getInstance(app); - } - - private Task getLimitedUseAppCheckToken(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAppCheck firebaseAppCheck = getAppCheck(arguments); - AppCheckToken tokenResult = Tasks.await(firebaseAppCheck.getLimitedUseAppCheckToken()); - taskCompletionSource.setResult(tokenResult.getToken()); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task activate(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - String provider = (String) Objects.requireNonNull(arguments.get("androidProvider")); - - switch (provider) { - case debugProvider: - { - FirebaseAppCheck firebaseAppCheck = getAppCheck(arguments); - firebaseAppCheck.installAppCheckProviderFactory( - DebugAppCheckProviderFactory.getInstance()); - break; - } - case playIntegrity: - { - FirebaseAppCheck firebaseAppCheck = getAppCheck(arguments); - firebaseAppCheck.installAppCheckProviderFactory( - PlayIntegrityAppCheckProviderFactory.getInstance()); - break; - } - } - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task getToken(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAppCheck firebaseAppCheck = getAppCheck(arguments); - Boolean forceRefresh = (Boolean) Objects.requireNonNull(arguments.get("forceRefresh")); - AppCheckToken tokenResult = - Tasks.await(firebaseAppCheck.getAppCheckToken(forceRefresh)); - - taskCompletionSource.setResult(tokenResult.getToken()); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task setTokenAutoRefreshEnabled(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAppCheck firebaseAppCheck = getAppCheck(arguments); - Boolean isTokenAutoRefreshEnabled = - (Boolean) Objects.requireNonNull(arguments.get("isTokenAutoRefreshEnabled")); - firebaseAppCheck.setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled); - - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task registerTokenListener(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - String appName = (String) Objects.requireNonNull(arguments.get("appName")); - FirebaseAppCheck firebaseAppCheck = getAppCheck(arguments); - - final TokenChannelStreamHandler handler = - new TokenChannelStreamHandler(firebaseAppCheck); - final String name = METHOD_CHANNEL_NAME + "/token/" + appName; - final EventChannel channel = new EventChannel(messenger, name); - channel.setStreamHandler(handler); - streamHandlers.put(channel, handler); - - taskCompletionSource.setResult(name); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - @Override - public void onMethodCall(MethodCall call, @NonNull final Result result) { - Task methodCallTask; - - switch (call.method) { - case "FirebaseAppCheck#activate": - methodCallTask = activate(call.arguments()); - break; - case "FirebaseAppCheck#getToken": - methodCallTask = getToken(call.arguments()); - break; - case "FirebaseAppCheck#setTokenAutoRefreshEnabled": - methodCallTask = setTokenAutoRefreshEnabled(call.arguments()); - break; - case "FirebaseAppCheck#registerTokenListener": - methodCallTask = registerTokenListener(call.arguments()); - break; - case "FirebaseAppCheck#getLimitedUseAppCheckToken": - methodCallTask = getLimitedUseAppCheckToken(call.arguments()); - break; - default: - result.notImplemented(); - return; - } - - methodCallTask.addOnCompleteListener( - task -> { - if (task.isSuccessful()) { - result.success(task.getResult()); - } else { - Exception exception = task.getException(); - result.error( - "firebase_app_check", - exception != null ? exception.getMessage() : null, - getExceptionDetails(exception)); - } - }); - } - - private Map getExceptionDetails(@Nullable Exception exception) { - Map details = new HashMap<>(); - details.put("code", "unknown"); - if (exception != null) { - details.put("message", exception.getMessage()); - } else { - details.put("message", "An unknown error has occurred."); - } - return details; - } - - @Override - public Task> getPluginConstantsForFirebaseApp(FirebaseApp firebaseApp) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - @Override - public Task didReinitializeFirebaseCore() { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private void removeEventListeners() { - for (EventChannel eventChannel : streamHandlers.keySet()) { - EventChannel.StreamHandler streamHandler = streamHandlers.get(eventChannel); - assert streamHandler != null; - streamHandler.onCancel(null); - eventChannel.setStreamHandler(null); - } - streamHandlers.clear(); - } -} diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.java b/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.java deleted file mode 100644 index 69aaee5288c5..000000000000 --- a/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.java +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.plugins.firebase.appcheck; - -import androidx.annotation.Keep; -import com.google.firebase.components.Component; -import com.google.firebase.components.ComponentRegistrar; -import com.google.firebase.platforminfo.LibraryVersionComponent; -import java.util.Collections; -import java.util.List; - -@Keep -public class FlutterFirebaseAppRegistrar implements ComponentRegistrar { - @Override - public List> getComponents() { - return Collections.>singletonList( - LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION)); - } -} diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.java b/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.java deleted file mode 100644 index 3f1367002c70..000000000000 --- a/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2022, 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. - */ - -package io.flutter.plugins.firebase.appcheck; - -import com.google.firebase.appcheck.FirebaseAppCheck; -import io.flutter.plugin.common.EventChannel; -import java.util.HashMap; -import java.util.Map; - -public class TokenChannelStreamHandler implements EventChannel.StreamHandler { - - private final FirebaseAppCheck firebaseAppCheck; - private FirebaseAppCheck.AppCheckListener listener; - - public TokenChannelStreamHandler(FirebaseAppCheck firebaseAppCheck) { - this.firebaseAppCheck = firebaseAppCheck; - } - - @Override - public void onListen(Object arguments, EventChannel.EventSink events) { - - listener = - result -> { - Map event = new HashMap<>(); - event.put("token", result.getToken()); - events.success(event); - }; - - firebaseAppCheck.addAppCheckListener(listener); - } - - @Override - public void onCancel(Object arguments) { - if (listener != null) { - firebaseAppCheck.removeAppCheckListener(listener); - listener = null; - } - } -} diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppCheckPlugin.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppCheckPlugin.kt new file mode 100644 index 000000000000..de0d8de29176 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppCheckPlugin.kt @@ -0,0 +1,334 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.firebase.appcheck + +import androidx.annotation.NonNull +import androidx.annotation.Nullable +import com.google.android.gms.tasks.Task +import com.google.android.gms.tasks.TaskCompletionSource +import com.google.android.gms.tasks.Tasks +import com.google.firebase.FirebaseApp +import com.google.firebase.appcheck.AppCheckToken +import com.google.firebase.appcheck.FirebaseAppCheck +import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory +import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory +import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.EventChannel +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import io.flutter.plugin.common.MethodChannel.Result +import io.flutter.plugins.firebase.core.FlutterFirebasePlugin +import io.flutter.plugins.firebase.core.FlutterFirebasePlugin.cachedThreadPool +import io.flutter.plugins.firebase.core.FlutterFirebasePluginRegistry.registerPlugin +import io.flutter.plugins.firebase.firebaseappcheck.AppCheckWebProvider +import io.flutter.plugins.firebase.firebaseappcheck.AppCheckAndroidProvider +import io.flutter.plugins.firebase.firebaseappcheck.AppCheckAppleProvider +import io.flutter.plugins.firebase.firebaseappcheck.FirebaseAppCheckHostApi + +class FlutterFirebaseAppCheckPlugin : FlutterFirebasePlugin, FlutterPlugin, MethodCallHandler, FirebaseAppCheckHostApi { + + companion object { + private const val METHOD_CHANNEL_NAME = "plugins.flutter.io/firebase_app_check" + private const val DEBUG_PROVIDER = "debug" + private const val PLAY_INTEGRITY = "playIntegrity" + } + + private val streamHandlers = mutableMapOf() + + @Nullable + private var messenger: BinaryMessenger? = null + + private var channel: MethodChannel? = null + + private fun initInstance(messenger: BinaryMessenger) { + registerPlugin(METHOD_CHANNEL_NAME, this) + channel = MethodChannel(messenger, METHOD_CHANNEL_NAME) + channel?.setMethodCallHandler(this) + + // Set up Pigeon API + FirebaseAppCheckHostApi.setUp(messenger, this) + + this.messenger = messenger + } + + override fun onAttachedToEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { + initInstance(binding.binaryMessenger) + } + + override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { + channel?.setMethodCallHandler(null) + channel = null + + // Clean up Pigeon API + FirebaseAppCheckHostApi.setUp(binding.binaryMessenger, null) + + messenger = null + + removeEventListeners() + } + + private fun getAppCheck(arguments: Map): FirebaseAppCheck { + val appName = arguments["appName"] as String + val app = FirebaseApp.getInstance(appName) + return FirebaseAppCheck.getInstance(app) + } + + private fun getLimitedUseAppCheckToken(arguments: Map): Task { + val taskCompletionSource = TaskCompletionSource() + + cachedThreadPool.execute { + try { + val firebaseAppCheck = getAppCheck(arguments) + val tokenResult = Tasks.await(firebaseAppCheck.limitedUseAppCheckToken) + taskCompletionSource.setResult(tokenResult.token) + } catch (e: Exception) { + taskCompletionSource.setException(e) + } + } + + return taskCompletionSource.task + } + + private fun activate(arguments: Map): Task { + val taskCompletionSource = TaskCompletionSource() + + cachedThreadPool.execute { + try { + val provider = arguments["androidProvider"] as String + + when (provider) { + DEBUG_PROVIDER -> { + val firebaseAppCheck = getAppCheck(arguments) + firebaseAppCheck.installAppCheckProviderFactory( + DebugAppCheckProviderFactory.getInstance() + ) + } + PLAY_INTEGRITY -> { + val firebaseAppCheck = getAppCheck(arguments) + firebaseAppCheck.installAppCheckProviderFactory( + PlayIntegrityAppCheckProviderFactory.getInstance() + ) + } + } + taskCompletionSource.setResult(null) + } catch (e: Exception) { + taskCompletionSource.setException(e) + } + } + + return taskCompletionSource.task + } + + private fun getToken(arguments: Map): Task { + val taskCompletionSource = TaskCompletionSource() + + cachedThreadPool.execute { + try { + val firebaseAppCheck = getAppCheck(arguments) + val forceRefresh = arguments["forceRefresh"] as Boolean + val tokenResult = Tasks.await(firebaseAppCheck.getAppCheckToken(forceRefresh)) + + taskCompletionSource.setResult(tokenResult.token) + } catch (e: Exception) { + taskCompletionSource.setException(e) + } + } + + return taskCompletionSource.task + } + + private fun setTokenAutoRefreshEnabled(arguments: Map): Task { + val taskCompletionSource = TaskCompletionSource() + + cachedThreadPool.execute { + try { + val firebaseAppCheck = getAppCheck(arguments) + val isTokenAutoRefreshEnabled = arguments["isTokenAutoRefreshEnabled"] as Boolean + firebaseAppCheck.setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled) + + taskCompletionSource.setResult(null) + } catch (e: Exception) { + taskCompletionSource.setException(e) + } + } + + return taskCompletionSource.task + } + + private fun registerTokenListener(arguments: Map): Task { + val taskCompletionSource = TaskCompletionSource() + + cachedThreadPool.execute { + try { + val appName = arguments["appName"] as String + val firebaseAppCheck = getAppCheck(arguments) + + val handler = TokenChannelStreamHandler(firebaseAppCheck) + val name = "$METHOD_CHANNEL_NAME/token/$appName" + val eventChannel = EventChannel(messenger, name) + eventChannel.setStreamHandler(handler) + streamHandlers[eventChannel] = handler + + taskCompletionSource.setResult(name) + } catch (e: Exception) { + taskCompletionSource.setException(e) + } + } + + return taskCompletionSource.task + } + + override fun onMethodCall(call: MethodCall, @NonNull result: Result) { + val arguments = call.arguments>() ?: return + val methodCallTask: Task<*> = when (call.method) { + "FirebaseAppCheck#activate" -> activate(arguments) + "FirebaseAppCheck#getToken" -> getToken(arguments) + "FirebaseAppCheck#setTokenAutoRefreshEnabled" -> setTokenAutoRefreshEnabled(arguments) + "FirebaseAppCheck#registerTokenListener" -> registerTokenListener(arguments) + "FirebaseAppCheck#getLimitedUseAppCheckToken" -> getLimitedUseAppCheckToken(arguments) + else -> { + result.notImplemented() + return + } + } + + methodCallTask.addOnCompleteListener { task -> + if (task.isSuccessful) { + result.success(task.result) + } else { + val exception = task.exception + result.error( + "firebase_app_check", + exception?.message, + getExceptionDetails(exception) + ) + } + } + } + + private fun getExceptionDetails(@Nullable exception: Exception?): Map { + val details = mutableMapOf() + details["code"] = "unknown" + if (exception != null) { + details["message"] = exception.message ?: "An unknown error has occurred." + } else { + details["message"] = "An unknown error has occurred." + } + return details + } + + override fun getPluginConstantsForFirebaseApp(firebaseApp: FirebaseApp): Task?> { + val taskCompletionSource = TaskCompletionSource?>() + + cachedThreadPool.execute { + try { + taskCompletionSource.setResult(null) + } catch (e: Exception) { + taskCompletionSource.setException(e) + } + } + + return taskCompletionSource.task + } + + override fun didReinitializeFirebaseCore(): Task { + val taskCompletionSource = TaskCompletionSource() + + cachedThreadPool.execute { + try { + taskCompletionSource.setResult(null) + } catch (e: Exception) { + taskCompletionSource.setException(e) + } + } + + return taskCompletionSource.task + } + + private fun removeEventListeners() { + for ((eventChannel, streamHandler) in streamHandlers) { + streamHandler.onCancel(null) + eventChannel.setStreamHandler(null) + } + streamHandlers.clear() + } + + // Pigeon API implementation + override fun activate( + appName: String, + webProvider: AppCheckWebProvider, + androidProvider: AppCheckAndroidProvider, + appleProvider: AppCheckAppleProvider, + callback: (kotlin.Result) -> Unit + ) { + cachedThreadPool.execute { + try { + val app = FirebaseApp.getInstance(appName) + val firebaseAppCheck = FirebaseAppCheck.getInstance(app) + + when (androidProvider.providerName) { + DEBUG_PROVIDER -> { + firebaseAppCheck.installAppCheckProviderFactory( + DebugAppCheckProviderFactory.getInstance() + ) + } + PLAY_INTEGRITY -> { + firebaseAppCheck.installAppCheckProviderFactory( + PlayIntegrityAppCheckProviderFactory.getInstance() + ) + } + } + callback(kotlin.Result.success(Unit)) + } catch (e: Exception) { + callback(kotlin.Result.failure(e)) + } + } + } + + override fun getToken(appName: String, forceRefresh: Boolean, callback: (kotlin.Result) -> Unit) { + cachedThreadPool.execute { + try { + val app = FirebaseApp.getInstance(appName) + val firebaseAppCheck = FirebaseAppCheck.getInstance(app) + val tokenResult = Tasks.await(firebaseAppCheck.getAppCheckToken(forceRefresh)) + callback(kotlin.Result.success(tokenResult.token)) + } catch (e: Exception) { + callback(kotlin.Result.failure(e)) + } + } + } + + override fun setTokenAutoRefreshEnabled( + appName: String, + isTokenAutoRefreshEnabled: Boolean, + callback: (kotlin.Result) -> Unit + ) { + cachedThreadPool.execute { + try { + val app = FirebaseApp.getInstance(appName) + val firebaseAppCheck = FirebaseAppCheck.getInstance(app) + firebaseAppCheck.setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled) + callback(kotlin.Result.success(Unit)) + } catch (e: Exception) { + callback(kotlin.Result.failure(e)) + } + } + } + + override fun getLimitedUseToken(appName: String, callback: (kotlin.Result) -> Unit) { + cachedThreadPool.execute { + try { + val app = FirebaseApp.getInstance(appName) + val firebaseAppCheck = FirebaseAppCheck.getInstance(app) + val tokenResult = Tasks.await(firebaseAppCheck.limitedUseAppCheckToken) + callback(kotlin.Result.success(tokenResult.token)) + } catch (e: Exception) { + callback(kotlin.Result.failure(e)) + } + } + } +} \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.kt new file mode 100644 index 000000000000..354f86bdebca --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.kt @@ -0,0 +1,19 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.firebase.appcheck + +import androidx.annotation.Keep +import com.google.firebase.components.Component +import com.google.firebase.components.ComponentRegistrar +import com.google.firebase.platforminfo.LibraryVersionComponent + +@Keep +class FlutterFirebaseAppRegistrar : ComponentRegistrar { + override fun getComponents(): List> { + return listOf( + LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION) + ) + } +} \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.kt new file mode 100644 index 000000000000..a882445bc584 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2022, 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. + */ + +package io.flutter.plugins.firebase.appcheck + +import com.google.firebase.appcheck.FirebaseAppCheck +import io.flutter.plugin.common.EventChannel + +class TokenChannelStreamHandler(private val firebaseAppCheck: FirebaseAppCheck) : EventChannel.StreamHandler { + + private var listener: FirebaseAppCheck.AppCheckListener? = null + + override fun onListen(arguments: Any?, events: EventChannel.EventSink?) { + val newListener = FirebaseAppCheck.AppCheckListener { result -> + val event = mapOf("token" to result.token) + events?.success(event) + } + + listener = newListener + firebaseAppCheck.addAppCheckListener(newListener) + } + + override fun onCancel(arguments: Any?) { + val currentListener = listener + if (currentListener != null) { + firebaseAppCheck.removeAppCheckListener(currentListener) + listener = null + } + } +} \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseappcheck/GeneratedAndroidFirebaseAppCheck.g.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseappcheck/GeneratedAndroidFirebaseAppCheck.g.kt new file mode 100644 index 000000000000..10956eaa3eae --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseappcheck/GeneratedAndroidFirebaseAppCheck.g.kt @@ -0,0 +1,352 @@ +// 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. +// See also: https://pub.dev/packages/pigeon +@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") + +package io.flutter.plugins.firebase.firebaseappcheck + +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 { + return listOf(result) + } + + fun wrapError(exception: Throwable): List { + return if (exception is FlutterError) { + listOf( + exception.code, + exception.message, + exception.details + ) + } else { + listOf( + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) + ) + } + } + fun deepEquals(a: Any?, b: Any?): Boolean { + if (a is ByteArray && b is ByteArray) { + return a.contentEquals(b) + } + if (a is IntArray && b is IntArray) { + return a.contentEquals(b) + } + if (a is LongArray && b is LongArray) { + return a.contentEquals(b) + } + if (a is DoubleArray && b is DoubleArray) { + return a.contentEquals(b) + } + if (a is Array<*> && b is Array<*>) { + return a.size == b.size && + a.indices.all{ deepEquals(a[it], b[it]) } + } + if (a is List<*> && b is List<*>) { + return a.size == b.size && + a.indices.all{ deepEquals(a[it], b[it]) } + } + if (a is Map<*, *> && b is Map<*, *>) { + return a.size == b.size && a.all { + (b as Map).containsKey(it.key) && + deepEquals(it.value, b[it.key]) + } + } + return a == b + } + +} + +/** + * Error class for passing custom error details to Flutter via a thrown PlatformException. + * @property code The error code. + * @property message The error message. + * @property details The error details. Must be a datatype supported by the api codec. + */ +class FlutterError ( + val code: String, + override val message: String? = null, + val details: Any? = null +) : Throwable() + +/** Generated class from Pigeon that represents data sent in messages. */ +data class AppCheckWebProvider ( + val providerName: String +) + { + companion object { + fun fromList(pigeonVar_list: List): AppCheckWebProvider { + val providerName = pigeonVar_list[0] as String + return AppCheckWebProvider(providerName) + } + } + fun toList(): List { + return listOf( + providerName, + ) + } + override fun equals(other: Any?): Boolean { + if (other !is AppCheckWebProvider) { + return false + } + if (this === other) { + return true + } + return GeneratedAndroidFirebaseAppCheckPigeonUtils.deepEquals(toList(), other.toList()) } + + override fun hashCode(): Int = toList().hashCode() +} + +/** Generated class from Pigeon that represents data sent in messages. */ +data class AppCheckAndroidProvider ( + val providerName: String +) + { + companion object { + fun fromList(pigeonVar_list: List): AppCheckAndroidProvider { + val providerName = pigeonVar_list[0] as String + return AppCheckAndroidProvider(providerName) + } + } + fun toList(): List { + return listOf( + providerName, + ) + } + override fun equals(other: Any?): Boolean { + if (other !is AppCheckAndroidProvider) { + return false + } + if (this === other) { + return true + } + return GeneratedAndroidFirebaseAppCheckPigeonUtils.deepEquals(toList(), other.toList()) } + + override fun hashCode(): Int = toList().hashCode() +} + +/** Generated class from Pigeon that represents data sent in messages. */ +data class AppCheckAppleProvider ( + val providerName: String +) + { + companion object { + fun fromList(pigeonVar_list: List): AppCheckAppleProvider { + val providerName = pigeonVar_list[0] as String + return AppCheckAppleProvider(providerName) + } + } + fun toList(): List { + return listOf( + providerName, + ) + } + override fun equals(other: Any?): Boolean { + if (other !is AppCheckAppleProvider) { + return false + } + if (this === other) { + return true + } + return GeneratedAndroidFirebaseAppCheckPigeonUtils.deepEquals(toList(), other.toList()) } + + override fun hashCode(): Int = toList().hashCode() +} + +/** Generated class from Pigeon that represents data sent in messages. */ +data class AppCheckPigeonSettings ( + val webProvider: AppCheckWebProvider, + val androidProvider: AppCheckAndroidProvider, + val appleProvider: AppCheckAppleProvider +) + { + companion object { + fun fromList(pigeonVar_list: List): AppCheckPigeonSettings { + val webProvider = pigeonVar_list[0] as AppCheckWebProvider + val androidProvider = pigeonVar_list[1] as AppCheckAndroidProvider + val appleProvider = pigeonVar_list[2] as AppCheckAppleProvider + return AppCheckPigeonSettings(webProvider, androidProvider, appleProvider) + } + } + fun toList(): List { + return listOf( + webProvider, + androidProvider, + appleProvider, + ) + } + override fun equals(other: Any?): Boolean { + if (other !is AppCheckPigeonSettings) { + return false + } + if (this === other) { + return true + } + return GeneratedAndroidFirebaseAppCheckPigeonUtils.deepEquals(toList(), other.toList()) } + + override fun hashCode(): Int = toList().hashCode() +} +private open class GeneratedAndroidFirebaseAppCheckPigeonCodec : StandardMessageCodec() { + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return when (type) { + 129.toByte() -> { + return (readValue(buffer) as? List)?.let { + AppCheckWebProvider.fromList(it) + } + } + 130.toByte() -> { + return (readValue(buffer) as? List)?.let { + AppCheckAndroidProvider.fromList(it) + } + } + 131.toByte() -> { + return (readValue(buffer) as? List)?.let { + AppCheckAppleProvider.fromList(it) + } + } + 132.toByte() -> { + return (readValue(buffer) as? List)?.let { + AppCheckPigeonSettings.fromList(it) + } + } + else -> super.readValueOfType(type, buffer) + } + } + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + when (value) { + is AppCheckWebProvider -> { + stream.write(129) + writeValue(stream, value.toList()) + } + is AppCheckAndroidProvider -> { + stream.write(130) + writeValue(stream, value.toList()) + } + is AppCheckAppleProvider -> { + stream.write(131) + writeValue(stream, value.toList()) + } + is AppCheckPigeonSettings -> { + stream.write(132) + writeValue(stream, value.toList()) + } + else -> super.writeValue(stream, value) + } + } +} + + +/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ +interface FirebaseAppCheckHostApi { + fun activate(appName: String, webProvider: AppCheckWebProvider, androidProvider: AppCheckAndroidProvider, appleProvider: AppCheckAppleProvider, callback: (Result) -> Unit) + fun getToken(appName: String, forceRefresh: Boolean, callback: (Result) -> Unit) + fun setTokenAutoRefreshEnabled(appName: String, isTokenAutoRefreshEnabled: Boolean, callback: (Result) -> Unit) + fun getLimitedUseToken(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`. */ + @JvmOverloads + 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) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val appNameArg = args[0] as String + val webProviderArg = args[1] as AppCheckWebProvider + val androidProviderArg = args[2] as AppCheckAndroidProvider + val appleProviderArg = args[3] as AppCheckAppleProvider + api.activate(appNameArg, webProviderArg, androidProviderArg, appleProviderArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapError(error)) + } else { + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapResult(null)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + 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 + val appNameArg = args[0] as String + val forceRefreshArg = args[1] as Boolean + api.getToken(appNameArg, forceRefreshArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(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 -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapError(error)) + } else { + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapResult(null)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseToken$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val appNameArg = args[0] as String + api.getLimitedUseToken(appNameArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + } + } +} diff --git a/packages/firebase_app_check/firebase_app_check/example/ios/Runner.xcodeproj/project.pbxproj b/packages/firebase_app_check/firebase_app_check/example/ios/Runner.xcodeproj/project.pbxproj index 7d86b897a846..72031d6550d0 100644 --- a/packages/firebase_app_check/firebase_app_check/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/firebase_app_check/firebase_app_check/example/ios/Runner.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 14C7769AAE6B32133AA5CD0C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 89D2B16D9A434347D5972425 /* Pods_Runner.framework */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 4627F94B299406540090DA25 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = BBE2A093D0D5DFBA7CE858E4 /* GoogleService-Info.plist */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; @@ -40,6 +41,7 @@ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 89D2B16D9A434347D5972425 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -48,7 +50,10 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A0D98577EA5F91F62EFA6154 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + BBDE97449FE5A7D57A5899FC /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; BBE2A093D0D5DFBA7CE858E4 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; + D77D1E6A1B0B238106A314B8 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -57,12 +62,21 @@ buildActionMask = 2147483647; files = ( 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, + 14C7769AAE6B32133AA5CD0C /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 12AA3CE588BAE31BEE665D65 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 89D2B16D9A434347D5972425 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -82,6 +96,7 @@ 97C146EF1CF9000F007C117D /* Products */, F919868105D7CB93D33CAD83 /* Pods */, BBE2A093D0D5DFBA7CE858E4 /* GoogleService-Info.plist */, + 12AA3CE588BAE31BEE665D65 /* Frameworks */, ); sourceTree = ""; }; @@ -122,6 +137,9 @@ F919868105D7CB93D33CAD83 /* Pods */ = { isa = PBXGroup; children = ( + A0D98577EA5F91F62EFA6154 /* Pods-Runner.debug.xcconfig */, + BBDE97449FE5A7D57A5899FC /* Pods-Runner.release.xcconfig */, + D77D1E6A1B0B238106A314B8 /* Pods-Runner.profile.xcconfig */, ); path = Pods; sourceTree = ""; @@ -133,6 +151,7 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + C37AD95B42832F6A68E334D2 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, @@ -140,6 +159,7 @@ 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 46A64A04299681F5003FC4F3 /* ShellScript */, + AFB7A6C16FE39E97CCC45D78 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -252,6 +272,45 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; }; + AFB7A6C16FE39E97CCC45D78 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + C37AD95B42832F6A68E334D2 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/packages/firebase_app_check/firebase_app_check/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_app_check/firebase_app_check/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 6f83bdc750b0..8a6c683e3d89 100644 --- a/packages/firebase_app_check/firebase_app_check/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/firebase_app_check/firebase_app_check/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -44,6 +44,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" shouldUseLaunchSchemeArgsEnv = "YES"> diff --git a/packages/firebase_app_check/firebase_app_check/example/macos/Runner.xcodeproj/project.pbxproj b/packages/firebase_app_check/firebase_app_check/example/macos/Runner.xcodeproj/project.pbxproj index 7c41affca666..895f6401ebca 100644 --- a/packages/firebase_app_check/firebase_app_check/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/firebase_app_check/firebase_app_check/example/macos/Runner.xcodeproj/project.pbxproj @@ -190,6 +190,7 @@ 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + 8802B691B91E1D7A84DAF775 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -304,6 +305,23 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; + 8802B691B91E1D7A84DAF775 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 8FAF6BECF1FF5E1A559C7452 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/packages/firebase_app_check/firebase_app_check/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_app_check/firebase_app_check/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 92a5c6f961f3..0b52b918e3a9 100644 --- a/packages/firebase_app_check/firebase_app_check/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/firebase_app_check/firebase_app_check/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -66,6 +66,7 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" + enableGPUValidationMode = "1" allowLocationSimulation = "YES"> diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check.podspec b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check.podspec index a1a5161f0e7f..1fd34c67a6d7 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check.podspec +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check.podspec @@ -24,8 +24,8 @@ Pod::Spec.new do |s| s.license = { :file => '../LICENSE' } s.authors = 'The Chromium Authors' s.source = { :path => '.' } - s.source_files = 'firebase_app_check/Sources/firebase_app_check/**/*.{h,m}' - s.public_header_files = 'firebase_app_check/Sources/firebase_app_check/include/*.h' + s.source_files = 'firebase_app_check/Sources/firebase_app_check/**/*.{swift}' + s.swift_version = '5.0' s.ios.deployment_target = '15.0' # Flutter dependencies diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.m b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.m deleted file mode 100644 index 09d966017e20..000000000000 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.m +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "FLTAppCheckProvider.h" - -@implementation FLTAppCheckProvider - -- (id)initWithApp:app { - self = [super init]; - if (self) { - self.app = app; - } - return self; -} - -- (void)configure:(FIRApp *)app providerName:(NSString *)providerName { - if ([providerName isEqualToString:@"debug"]) { - FIRAppCheckDebugProvider *provider = [[FIRAppCheckDebugProvider alloc] initWithApp:app]; - NSLog(@"Firebase App Check Debug Token: %@", [provider localDebugToken]); - self.delegateProvider = provider; - } - - if ([providerName isEqualToString:@"deviceCheck"]) { - self.delegateProvider = [[FIRDeviceCheckProvider alloc] initWithApp:app]; - } - - if ([providerName isEqualToString:@"appAttest"]) { - if (@available(iOS 14.0, macCatalyst 14.0, tvOS 15.0, watchOS 9.0, *)) { - self.delegateProvider = [[FIRAppAttestProvider alloc] initWithApp:app]; - } else { - // This is not a valid environment, setup debug provider. - self.delegateProvider = [[FIRAppCheckDebugProvider alloc] initWithApp:app]; - } - } - - if ([providerName isEqualToString:@"appAttestWithDeviceCheckFallback"]) { - if (@available(iOS 14.0, *)) { - self.delegateProvider = [[FIRAppAttestProvider alloc] initWithApp:app]; - } else { - self.delegateProvider = [[FIRDeviceCheckProvider alloc] initWithApp:app]; - } - } -} - -- (void)getTokenWithCompletion:(nonnull void (^)(FIRAppCheckToken *_Nullable, - NSError *_Nullable))handler { - // Proxying to delegateProvider - [self.delegateProvider getTokenWithCompletion:handler]; -} - -@end diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.swift new file mode 100644 index 000000000000..a99cd0ab8987 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.swift @@ -0,0 +1,54 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import FirebaseAppCheck +import FirebaseCore + +class FLTAppCheckProvider: NSObject, AppCheckProvider { + var app: FirebaseApp? + var delegateProvider: AppCheckProvider? + + init(app: FirebaseApp) { + super.init() + self.app = app + } + + func configure(app: FirebaseApp, providerName: String) { + switch providerName { + case "debug": + let provider: AppCheckDebugProvider? = AppCheckDebugProvider(app: app) + if let debugToken = provider?.localDebugToken() { + print("Firebase App Check Debug Token: \(debugToken)") + } + self.delegateProvider = provider + + case "deviceCheck": + self.delegateProvider = DeviceCheckProvider(app: app) + + case "appAttest": + if #available(iOS 14.0, macOS 11.3, macCatalyst 14.0, tvOS 15.0, watchOS 9.0, *) { + self.delegateProvider = AppAttestProvider(app: app) + } else { + // This is not a valid environment, setup debug provider. + self.delegateProvider = AppCheckDebugProvider(app: app) + } + + case "appAttestWithDeviceCheckFallback": + if #available(iOS 14.0, macOS 11.3, *) { + self.delegateProvider = AppAttestProvider(app: app) + } else { + self.delegateProvider = DeviceCheckProvider(app: app) + } + + default: + break + } + } + + func getToken(completion: @escaping (AppCheckToken?, Error?) -> Void) { + // Proxying to delegateProvider + delegateProvider?.getToken(completion: completion) + } +} \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.m b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.m deleted file mode 100644 index f6566f299321..000000000000 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.m +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import - -@import FirebaseAppCheck; -@import FirebaseCore; - -#import "FLTAppCheckProviderFactory.h" - -#import "FLTAppCheckProvider.h" - -@implementation FLTAppCheckProviderFactory - -- (nullable id)createProviderWithApp:(FIRApp *)app { - // The SDK may try to call this before we have been configured, - // so we will configure ourselves and set the provider up as a default to start - // pre-configure - if (self.providers == nil) { - self.providers = [NSMutableDictionary new]; - } - - if (self.providers[app.name] == nil) { - self.providers[app.name] = [FLTAppCheckProvider new]; - FLTAppCheckProvider *provider = self.providers[app.name]; - // We set "deviceCheck" as this is currently what is default. Backward compatible. - [provider configure:app providerName:@"deviceCheck"]; - } - - return self.providers[app.name]; -} - -- (void)configure:(FIRApp *)app providerName:(NSString *)providerName { - if (self.providers == nil) { - self.providers = [NSMutableDictionary new]; - } - - if (self.providers[app.name] == nil) { - self.providers[app.name] = [FLTAppCheckProvider new]; - } - - FLTAppCheckProvider *provider = self.providers[app.name]; - [provider configure:app providerName:providerName]; -} - -@end diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.swift new file mode 100644 index 000000000000..9fe0e3d23d56 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.swift @@ -0,0 +1,44 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import FirebaseAppCheck +import FirebaseCore + +class FLTAppCheckProviderFactory: NSObject, AppCheckProviderFactory { + var providers: [String: FLTAppCheckProvider]? + + func createProvider(with app: FirebaseApp) -> AppCheckProvider? { + // The SDK may try to call this before we have been configured, + // so we will configure ourselves and set the provider up as a default to start + // pre-configure + if providers == nil { + providers = [:] + } + + if providers?[app.name] == nil { + providers?[app.name] = FLTAppCheckProvider(app: app) + if let provider = providers?[app.name] { + // We set "deviceCheck" as this is currently what is default. Backward compatible. + provider.configure(app: app, providerName: "deviceCheck") + } + } + + return providers?[app.name] + } + + func configure(app: FirebaseApp, providerName: String) { + if providers == nil { + providers = [:] + } + + if providers?[app.name] == nil { + providers?[app.name] = FLTAppCheckProvider(app: app) + } + + if let provider = providers?[app.name] { + provider.configure(app: app, providerName: providerName) + } + } +} \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.m b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.m deleted file mode 100644 index 124486037ad9..000000000000 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.m +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "FLTFirebaseAppCheckPlugin.h" -#import "FLTTokenRefreshStreamHandler.h" - -@import FirebaseAppCheck; - -#if __has_include() -#import -#else -#import -#endif - -#import "FLTAppCheckProviderFactory.h" - -NSString *const kFLTFirebaseAppCheckChannelName = @"plugins.flutter.io/firebase_app_check"; - -@interface FLTFirebaseAppCheckPlugin () -@end - -@implementation FLTFirebaseAppCheckPlugin { - NSMutableDictionary *_eventChannels; - NSMutableDictionary *> *_streamHandlers; - NSObject *_binaryMessenger; - FLTAppCheckProviderFactory *_Nullable providerFactory; -} - -#pragma mark - FlutterPlugin - -- (instancetype)init:(NSObject *)messenger { - self = [super init]; - if (self) { - self->providerFactory = [[FLTAppCheckProviderFactory alloc] init]; - [FIRAppCheck setAppCheckProviderFactory:self->providerFactory]; - - [[FLTFirebasePluginRegistry sharedInstance] registerFirebasePlugin:self]; - _binaryMessenger = messenger; - _eventChannels = [NSMutableDictionary dictionary]; - _streamHandlers = [NSMutableDictionary dictionary]; - } - return self; -} - -+ (void)registerWithRegistrar:(NSObject *)registrar { - FlutterMethodChannel *channel = - [FlutterMethodChannel methodChannelWithName:kFLTFirebaseAppCheckChannelName - binaryMessenger:[registrar messenger]]; - FLTFirebaseAppCheckPlugin *instance = - [[FLTFirebaseAppCheckPlugin alloc] init:registrar.messenger]; - [registrar addMethodCallDelegate:instance channel:channel]; -} - -- (void)cleanupWithCompletion:(void (^)(void))completion { - for (FlutterEventChannel *channel in self->_eventChannels.allValues) { - [channel setStreamHandler:nil]; - } - [self->_eventChannels removeAllObjects]; - for (NSObject *handler in self->_streamHandlers.allValues) { - [handler onCancelWithArguments:nil]; - } - [self->_streamHandlers removeAllObjects]; - - if (completion != nil) completion(); -} - -- (void)detachFromEngineForRegistrar:(NSObject *)registrar { - [self cleanupWithCompletion:nil]; -} - -- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)flutterResult { - FLTFirebaseMethodCallErrorBlock errorBlock = ^( - NSString *_Nullable code, NSString *_Nullable message, NSDictionary *_Nullable details, - NSError *_Nullable error) { - NSMutableDictionary *errorDetails = [NSMutableDictionary dictionary]; - NSString *errorCode; - - switch (error.code) { - case FIRAppCheckErrorCodeServerUnreachable: - errorCode = @"server-unreachable"; - break; - case FIRAppCheckErrorCodeInvalidConfiguration: - errorCode = @"invalid-configuration"; - break; - case FIRAppCheckErrorCodeKeychain: - errorCode = @"code-keychain"; - break; - case FIRAppCheckErrorCodeUnsupported: - errorCode = @"code-unsupported"; - break; - case FIRAppCheckErrorCodeUnknown: - default: - errorCode = @"unknown"; - } - - NSString *errorMessage = error.localizedDescription; - errorDetails[@"code"] = errorCode; - errorDetails[@"message"] = errorMessage; - flutterResult([FlutterError errorWithCode:errorCode message:errorMessage details:errorDetails]); - }; - - FLTFirebaseMethodCallResult *methodCallResult = - [FLTFirebaseMethodCallResult createWithSuccess:flutterResult andErrorBlock:errorBlock]; - - if ([@"FirebaseAppCheck#activate" isEqualToString:call.method]) { - [self activate:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"FirebaseAppCheck#getToken" isEqualToString:call.method]) { - [self getToken:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"FirebaseAppCheck#setTokenAutoRefreshEnabled" isEqualToString:call.method]) { - [self setTokenAutoRefreshEnabled:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"FirebaseAppCheck#registerTokenListener" isEqualToString:call.method]) { - [self registerTokenListener:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"FirebaseAppCheck#getLimitedUseAppCheckToken" isEqualToString:call.method]) { - [self getLimitedUseAppCheckToken:call.arguments withMethodCallResult:methodCallResult]; - } else { - flutterResult(FlutterMethodNotImplemented); - } -} - -#pragma mark - Firebase App Check API - -- (void)activate:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - NSString *appNameDart = arguments[@"appName"]; - NSString *providerName = arguments[@"appleProvider"]; - - FIRApp *app = [FLTFirebasePlugin firebaseAppNamed:appNameDart]; - [self->providerFactory configure:app providerName:providerName]; - result.success(nil); -} - -- (void)registerTokenListener:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - NSString *appName = arguments[@"appName"]; - NSString *name = - [NSString stringWithFormat:@"%@/token/%@", kFLTFirebaseAppCheckChannelName, appName]; - - FlutterEventChannel *channel = [FlutterEventChannel eventChannelWithName:name - binaryMessenger:_binaryMessenger]; - - FLTTokenRefreshStreamHandler *handler = [[FLTTokenRefreshStreamHandler alloc] init]; - [channel setStreamHandler:handler]; - - [_eventChannels setObject:channel forKey:name]; - [_streamHandlers setObject:handler forKey:name]; - result.success(name); -} - -- (void)getToken:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAppCheck *appCheck = [self getFIRAppCheckFromArguments:arguments]; - bool forceRefresh = [arguments[@"forceRefresh"] boolValue]; - - [appCheck tokenForcingRefresh:forceRefresh - completion:^(FIRAppCheckToken *_Nullable token, NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - result.success(token.token); - } - }]; -} - -- (void)getLimitedUseAppCheckToken:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAppCheck *appCheck = [self getFIRAppCheckFromArguments:arguments]; - [appCheck - limitedUseTokenWithCompletion:^(FIRAppCheckToken *_Nullable token, NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - result.success(token.token); - } - }]; -} - -- (void)setTokenAutoRefreshEnabled:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAppCheck *appCheck = [self getFIRAppCheckFromArguments:arguments]; - bool isTokenAutoRefreshEnabled = arguments[@"isTokenAutoRefreshEnabled"]; - appCheck.isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabled; - result.success(nil); -} - -#pragma mark - FLTFirebasePlugin - -- (void)didReinitializeFirebaseCore:(void (^)(void))completion { - [self cleanupWithCompletion:completion]; -} - -- (NSDictionary *_Nonnull)pluginConstantsForFIRApp:(FIRApp *)firebase_app { - return @{}; -} - -- (NSString *_Nonnull)firebaseLibraryName { - return @LIBRARY_NAME; -} - -- (NSString *_Nonnull)firebaseLibraryVersion { - return @LIBRARY_VERSION; -} - -- (NSString *_Nonnull)flutterChannelName { - return kFLTFirebaseAppCheckChannelName; -} - -#pragma mark - Utilities - -- (FIRAppCheck *_Nullable)getFIRAppCheckFromArguments:(NSDictionary *)arguments { - NSString *appNameDart = arguments[@"appName"]; - FIRApp *app = [FLTFirebasePlugin firebaseAppNamed:appNameDart]; - FIRAppCheck *appCheck = [FIRAppCheck appCheckWithApp:app]; - - return appCheck; -} - -@end diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.swift new file mode 100644 index 000000000000..6ace2a221a87 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.swift @@ -0,0 +1,322 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation + +#if os(macOS) +import FlutterMacOS +#else +import Flutter +#endif + +import FirebaseAppCheck + +#if canImport(firebase_core) +import firebase_core +#endif + +private let kFLTFirebaseAppCheckChannelName = "plugins.flutter.io/firebase_app_check" + +public class FLTFirebaseAppCheckPlugin: NSObject, FLTFirebasePluginProtocol, FlutterPlugin, FirebaseAppCheckHostApi { + private var eventChannels: [String: FlutterEventChannel] = [:] + private var streamHandlers: [String: FlutterStreamHandler] = [:] + private var binaryMessenger: FlutterBinaryMessenger? + private var providerFactory: FLTAppCheckProviderFactory? + + public static func register(with registrar: FlutterPluginRegistrar) { + let binaryMessenger: FlutterBinaryMessenger + + #if os(macOS) + binaryMessenger = registrar.messenger + #elseif os(iOS) + binaryMessenger = registrar.messenger() + #endif + + let channel = FlutterMethodChannel( + name: kFLTFirebaseAppCheckChannelName, + binaryMessenger: binaryMessenger + ) + let instance = FLTFirebaseAppCheckPlugin() + instance.binaryMessenger = binaryMessenger + instance.providerFactory = FLTAppCheckProviderFactory() + AppCheck.setAppCheckProviderFactory(instance.providerFactory) + + // Set up Pigeon API + FirebaseAppCheckHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: instance) + + FLTFirebasePluginRegistry.sharedInstance().register(instance) + registrar.addMethodCallDelegate(instance, channel: channel) + } + + func cleanup(completion: (() -> Void)?) { + for channel in eventChannels.values { + channel.setStreamHandler(nil) + } + eventChannels.removeAll() + + for handler in streamHandlers.values { + handler.onCancel(withArguments: nil) + } + streamHandlers.removeAll() + + // Clean up Pigeon API + if let messenger = binaryMessenger { + FirebaseAppCheckHostApiSetup.setUp(binaryMessenger: messenger, api: nil) + } + + completion?() + } + + public func detachFromEngine(for registrar: FlutterPluginRegistrar) { + cleanup(completion: nil) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + let errorBlock: FLTFirebaseMethodCallErrorBlock = { code, message, details, error in + var errorDetails: [String: Any] = [:] + let errorCode: String + + if let appCheckError = error as? NSError { + switch AppCheckErrorCode.Code(rawValue: appCheckError.code) { + case .serverUnreachable: + errorCode = "server-unreachable" + case .invalidConfiguration: + errorCode = "invalid-configuration" + case .keychain: + errorCode = "code-keychain" + case .unsupported: + errorCode = "code-unsupported" + case .unknown: + fallthrough + default: + errorCode = "unknown" + } + } else { + errorCode = "unknown" + } + + let errorMessage = error?.localizedDescription ?? "" + errorDetails["code"] = errorCode + errorDetails["message"] = errorMessage + result(FlutterError(code: errorCode, message: errorMessage, details: errorDetails)) + } + + let methodCallResult = FLTFirebaseMethodCallResult.create( + success: result, + andErrorBlock: errorBlock + ) + + switch call.method { + case "FirebaseAppCheck#activate": + activate(call.arguments, withMethodCallResult: methodCallResult) + case "FirebaseAppCheck#getToken": + getToken(call.arguments, withMethodCallResult: methodCallResult) + case "FirebaseAppCheck#setTokenAutoRefreshEnabled": + setTokenAutoRefreshEnabled(call.arguments, withMethodCallResult: methodCallResult) + case "FirebaseAppCheck#registerTokenListener": + registerTokenListener(call.arguments, withMethodCallResult: methodCallResult) + case "FirebaseAppCheck#getLimitedUseAppCheckToken": + getLimitedUseAppCheckToken(call.arguments, withMethodCallResult: methodCallResult) + default: + result(FlutterMethodNotImplemented) + } + } + + // MARK: - Firebase App Check API + + private func activate(_ arguments: Any?, withMethodCallResult result: FLTFirebaseMethodCallResult) { + guard let args = arguments as? [String: Any], + let appNameDart = args["appName"] as? String, + let providerName = args["appleProvider"] as? String else { + result.error(nil, nil, nil, NSError(domain: "FLTFirebaseAppCheck", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid arguments"])) + return + } + + guard let app = FLTFirebasePlugin.firebaseAppNamed(appNameDart) else { + result.error(nil, nil, nil, NSError(domain: "FLTFirebaseAppCheck", code: -1, userInfo: [NSLocalizedDescriptionKey: "Firebase app not found"])) + return + } + providerFactory?.configure(app: app, providerName: providerName) + result.success(nil) + } + + private func registerTokenListener(_ arguments: Any?, withMethodCallResult result: FLTFirebaseMethodCallResult) { + guard let args = arguments as? [String: Any], + let appName = args["appName"] as? String else { + result.error(nil, nil, nil, NSError(domain: "FLTFirebaseAppCheck", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid arguments"])) + return + } + + let name = "\(kFLTFirebaseAppCheckChannelName)/token/\(appName)" + + guard let messenger = binaryMessenger else { + result.error(nil, nil, nil, NSError(domain: "FLTFirebaseAppCheck", code: -1, userInfo: [NSLocalizedDescriptionKey: "Binary messenger not available"])) + return + } + + let channel = FlutterEventChannel(name: name, binaryMessenger: messenger) + let handler = FLTTokenRefreshStreamHandler() + channel.setStreamHandler(handler) + + eventChannels[name] = channel + streamHandlers[name] = handler + result.success(name) + } + + private func getToken(_ arguments: Any?, withMethodCallResult result: FLTFirebaseMethodCallResult) { + guard let appCheck = getAppCheck(fromArguments: arguments) else { + result.error(nil, nil, nil, NSError(domain: "FLTFirebaseAppCheck", code: -1, userInfo: [NSLocalizedDescriptionKey: "Could not get AppCheck instance"])) + return + } + + let forceRefresh = (arguments as? [String: Any])?["forceRefresh"] as? Bool ?? false + + appCheck.token(forcingRefresh: forceRefresh) { token, error in + if let error = error { + result.error(nil, nil, nil, error) + } else { + result.success(token?.token) + } + } + } + + private func getLimitedUseAppCheckToken(_ arguments: Any?, withMethodCallResult result: FLTFirebaseMethodCallResult) { + guard let appCheck = getAppCheck(fromArguments: arguments) else { + result.error(nil, nil, nil, NSError(domain: "FLTFirebaseAppCheck", code: -1, userInfo: [NSLocalizedDescriptionKey: "Could not get AppCheck instance"])) + return + } + + appCheck.limitedUseToken { token, error in + if let error = error { + result.error(nil, nil, nil, error) + } else { + result.success(token?.token) + } + } + } + + private func setTokenAutoRefreshEnabled(_ arguments: Any?, withMethodCallResult result: FLTFirebaseMethodCallResult) { + guard let appCheck = getAppCheck(fromArguments: arguments), + let args = arguments as? [String: Any], + let isEnabled = args["isTokenAutoRefreshEnabled"] as? Bool else { + result.error(nil, nil, nil, NSError(domain: "FLTFirebaseAppCheck", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid arguments"])) + return + } + + appCheck.isTokenAutoRefreshEnabled = isEnabled + result.success(nil) + } + + // MARK: - FLTFirebasePluginProtocol + + public func didReinitializeFirebaseCore(_ completion: @escaping () -> Void) { + cleanup(completion: completion) + } + + public func pluginConstants(for firebaseApp: FirebaseApp) -> [AnyHashable: Any] { + return [:] + } + + public func firebaseLibraryVersion() -> String { + return "LIBRARY_VERSION" + } + + @objc public func firebaseLibraryName() -> String { + return "flutter-fire-appcheck" + } + + @objc public func flutterChannelName() -> String { + return kFLTFirebaseAppCheckChannelName + } + + // MARK: - Utilities + + private func getAppCheck(fromArguments arguments: Any?) -> AppCheck? { + guard let args = arguments as? [String: Any], + let appNameDart = args["appName"] as? String, + let app = FLTFirebasePlugin.firebaseAppNamed(appNameDart) else { + return nil + } + + return AppCheck.appCheck(app: app) + } + + // MARK: - FirebaseAppCheckHostApi implementation + + func activate( + appName: String, + webProvider: AppCheckWebProvider, + androidProvider: AppCheckAndroidProvider, + appleProvider: AppCheckAppleProvider, + completion: @escaping (Result) -> Void + ) { + guard let app = FLTFirebasePlugin.firebaseAppNamed(appName) else { + completion(.failure(NSError(domain: "firebase_app_check", code: 1, userInfo: [NSLocalizedDescriptionKey: "Firebase app not found"]))) + return + } + + let factory = FLTAppCheckProviderFactory() + factory.configure(app: app, providerName: appleProvider.providerName) + + AppCheck.setAppCheckProviderFactory(factory) + completion(.success(())) + } + + func getToken(appName: String, forceRefresh: Bool, completion: @escaping (Result) -> Void) { + guard let app = FLTFirebasePlugin.firebaseAppNamed(appName) else { + completion(.failure(NSError(domain: "firebase_app_check", code: 1, userInfo: [NSLocalizedDescriptionKey: "Firebase app not found"]))) + return + } + + guard let appCheck = AppCheck.appCheck(app: app) else { + completion(.failure(NSError(domain: "firebase_app_check", code: 1, userInfo: [NSLocalizedDescriptionKey: "AppCheck instance not available"]))) + return + } + + appCheck.token(forcingRefresh: forceRefresh) { token, error in + if let error = error { + completion(.failure(error)) + } else { + completion(.success(token?.token)) + } + } + } + + func setTokenAutoRefreshEnabled(appName: String, isTokenAutoRefreshEnabled: Bool, completion: @escaping (Result) -> Void) { + guard let app = FLTFirebasePlugin.firebaseAppNamed(appName) else { + completion(.failure(NSError(domain: "firebase_app_check", code: 1, userInfo: [NSLocalizedDescriptionKey: "Firebase app not found"]))) + return + } + + guard let appCheck = AppCheck.appCheck(app: app) else { + completion(.failure(NSError(domain: "firebase_app_check", code: 1, userInfo: [NSLocalizedDescriptionKey: "AppCheck instance not available"]))) + return + } + + appCheck.isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabled + completion(.success(())) + } + + func getLimitedUseToken(appName: String, completion: @escaping (Result) -> Void) { + guard let app = FLTFirebasePlugin.firebaseAppNamed(appName) else { + completion(.failure(NSError(domain: "firebase_app_check", code: 1, userInfo: [NSLocalizedDescriptionKey: "Firebase app not found"]))) + return + } + + guard let appCheck = AppCheck.appCheck(app: app) else { + completion(.failure(NSError(domain: "firebase_app_check", code: 1, userInfo: [NSLocalizedDescriptionKey: "AppCheck instance not available"]))) + return + } + + appCheck.limitedUseToken { token, error in + if let error = error { + completion(.failure(error)) + } else if let token = token?.token { + completion(.success(token)) + } else { + completion(.failure(NSError(domain: "firebase_app_check", code: 2, userInfo: [NSLocalizedDescriptionKey: "Token is nil"]))) + } + } + } +} \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.m b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.m deleted file mode 100644 index 4b411926d616..000000000000 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.m +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "FLTTokenRefreshStreamHandler.h" -#import "FLTFirebaseAppCheckPlugin.h" - -const NSNotificationName kNotififactionEvent = @"FIRAppCheckAppCheckTokenDidChangeNotification"; - -NSString *const kTokenKey = @"FIRAppCheckTokenNotificationKey"; - -@implementation FLTTokenRefreshStreamHandler { - id _observer; -} - -- (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)events { - _observer = - [NSNotificationCenter.defaultCenter addObserverForName:kNotififactionEvent - object:nil - queue:nil - usingBlock:^(NSNotification *_Nonnull note) { - NSString *token = note.userInfo[kTokenKey]; - - events(@{@"token" : token}); - }]; - - return nil; -} - -- (FlutterError *)onCancelWithArguments:(id)arguments { - [NSNotificationCenter.defaultCenter removeObserver:_observer]; - return nil; -} - -@end diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.swift new file mode 100644 index 000000000000..6bc9b28453ba --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.swift @@ -0,0 +1,40 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation + +#if os(macOS) +import FlutterMacOS +#else +import Flutter +#endif + +private let kNotificationEvent = NSNotification.Name("FIRAppCheckAppCheckTokenDidChangeNotification") +private let kTokenKey = "FIRAppCheckTokenNotificationKey" + +class FLTTokenRefreshStreamHandler: NSObject, FlutterStreamHandler { + private var observer: NSObjectProtocol? + + func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { + observer = NotificationCenter.default.addObserver( + forName: kNotificationEvent, + object: nil, + queue: nil + ) { notification in + if let token = notification.userInfo?[kTokenKey] as? String { + events(["token": token]) + } + } + + return nil + } + + func onCancel(withArguments arguments: Any?) -> FlutterError? { + if let observer = observer { + NotificationCenter.default.removeObserver(observer) + self.observer = nil + } + return nil + } +} \ No newline at end of file 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 new file mode 100644 index 000000000000..2467c44da15a --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift @@ -0,0 +1,382 @@ +// 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. +// See also: https://pub.dev/packages/pigeon + +import Foundation + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + +/// Error class for passing custom error details to Dart side. +final class PigeonError: Error { + let code: String + let message: String? + let details: Sendable? + + init(code: String, message: String?, details: Sendable?) { + self.code = code + self.message = message + self.details = details + } + + var localizedDescription: String { + return + "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" + } +} + +private func wrapResult(_ result: Any?) -> [Any?] { + return [result] +} + +private func wrapError(_ error: Any) -> [Any?] { + if let pigeonError = error as? PigeonError { + return [ + pigeonError.code, + pigeonError.message, + pigeonError.details, + ] + } + if let flutterError = error as? FlutterError { + return [ + flutterError.code, + flutterError.message, + flutterError.details, + ] + } + return [ + "\(error)", + "\(type(of: error))", + "Stacktrace: \(Thread.callStackSymbols)", + ] +} + +private func isNullish(_ value: Any?) -> Bool { + return value is NSNull || value == nil +} + +private func nilOrValue(_ value: Any?) -> T? { + if value is NSNull { return nil } + return value as! T? +} + +func deepEqualsFirebaseAppCheckMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { + let cleanLhs = nilOrValue(lhs) as Any? + let cleanRhs = nilOrValue(rhs) as Any? + switch (cleanLhs, cleanRhs) { + case (nil, nil): + return true + + case (nil, _), (_, nil): + return false + + case is (Void, Void): + return true + + case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable): + return cleanLhsHashable == cleanRhsHashable + + case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]): + guard cleanLhsArray.count == cleanRhsArray.count else { return false } + for (index, element) in cleanLhsArray.enumerated() { + if !deepEqualsFirebaseAppCheckMessages(element, cleanRhsArray[index]) { + return false + } + } + return true + + case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): + guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false } + for (key, cleanLhsValue) in cleanLhsDictionary { + guard cleanRhsDictionary.index(forKey: key) != nil else { return false } + if !deepEqualsFirebaseAppCheckMessages(cleanLhsValue, cleanRhsDictionary[key]!) { + return false + } + } + return true + + default: + // Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be untrue. + return false + } +} + +func deepHashFirebaseAppCheckMessages(value: Any?, hasher: inout Hasher) { + if let valueList = value as? [AnyHashable] { + for item in valueList { deepHashFirebaseAppCheckMessages(value: item, hasher: &hasher) } + return + } + + if let valueDict = value as? [AnyHashable: AnyHashable] { + for key in valueDict.keys { + hasher.combine(key) + deepHashFirebaseAppCheckMessages(value: valueDict[key]!, hasher: &hasher) + } + return + } + + if let hashableValue = value as? AnyHashable { + hasher.combine(hashableValue.hashValue) + } + + return hasher.combine(String(describing: value)) +} + + + +/// Generated class from Pigeon that represents data sent in messages. +struct AppCheckWebProvider: Hashable { + var providerName: String + + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> AppCheckWebProvider? { + let providerName = pigeonVar_list[0] as! String + + return AppCheckWebProvider( + providerName: providerName + ) + } + func toList() -> [Any?] { + return [ + providerName + ] + } + static func == (lhs: AppCheckWebProvider, rhs: AppCheckWebProvider) -> Bool { + return deepEqualsFirebaseAppCheckMessages(lhs.toList(), rhs.toList()) } + func hash(into hasher: inout Hasher) { + deepHashFirebaseAppCheckMessages(value: toList(), hasher: &hasher) + } +} + +/// Generated class from Pigeon that represents data sent in messages. +struct AppCheckAndroidProvider: Hashable { + var providerName: String + + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> AppCheckAndroidProvider? { + let providerName = pigeonVar_list[0] as! String + + return AppCheckAndroidProvider( + providerName: providerName + ) + } + func toList() -> [Any?] { + return [ + providerName + ] + } + static func == (lhs: AppCheckAndroidProvider, rhs: AppCheckAndroidProvider) -> Bool { + return deepEqualsFirebaseAppCheckMessages(lhs.toList(), rhs.toList()) } + func hash(into hasher: inout Hasher) { + deepHashFirebaseAppCheckMessages(value: toList(), hasher: &hasher) + } +} + +/// Generated class from Pigeon that represents data sent in messages. +struct AppCheckAppleProvider: Hashable { + var providerName: String + + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> AppCheckAppleProvider? { + let providerName = pigeonVar_list[0] as! String + + return AppCheckAppleProvider( + providerName: providerName + ) + } + func toList() -> [Any?] { + return [ + providerName + ] + } + static func == (lhs: AppCheckAppleProvider, rhs: AppCheckAppleProvider) -> Bool { + return deepEqualsFirebaseAppCheckMessages(lhs.toList(), rhs.toList()) } + func hash(into hasher: inout Hasher) { + deepHashFirebaseAppCheckMessages(value: toList(), hasher: &hasher) + } +} + +/// Generated class from Pigeon that represents data sent in messages. +struct AppCheckPigeonSettings: Hashable { + var webProvider: AppCheckWebProvider + var androidProvider: AppCheckAndroidProvider + var appleProvider: AppCheckAppleProvider + + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> AppCheckPigeonSettings? { + let webProvider = pigeonVar_list[0] as! AppCheckWebProvider + let androidProvider = pigeonVar_list[1] as! AppCheckAndroidProvider + let appleProvider = pigeonVar_list[2] as! AppCheckAppleProvider + + return AppCheckPigeonSettings( + webProvider: webProvider, + androidProvider: androidProvider, + appleProvider: appleProvider + ) + } + func toList() -> [Any?] { + return [ + webProvider, + androidProvider, + appleProvider, + ] + } + static func == (lhs: AppCheckPigeonSettings, rhs: AppCheckPigeonSettings) -> Bool { + return deepEqualsFirebaseAppCheckMessages(lhs.toList(), rhs.toList()) } + func hash(into hasher: inout Hasher) { + deepHashFirebaseAppCheckMessages(value: toList(), hasher: &hasher) + } +} + +private class FirebaseAppCheckMessagesPigeonCodecReader: FlutterStandardReader { + override func readValue(ofType type: UInt8) -> Any? { + switch type { + case 129: + return AppCheckWebProvider.fromList(self.readValue() as! [Any?]) + case 130: + return AppCheckAndroidProvider.fromList(self.readValue() as! [Any?]) + case 131: + return AppCheckAppleProvider.fromList(self.readValue() as! [Any?]) + case 132: + return AppCheckPigeonSettings.fromList(self.readValue() as! [Any?]) + default: + return super.readValue(ofType: type) + } + } +} + +private class FirebaseAppCheckMessagesPigeonCodecWriter: FlutterStandardWriter { + override func writeValue(_ value: Any) { + if let value = value as? AppCheckWebProvider { + super.writeByte(129) + super.writeValue(value.toList()) + } else if let value = value as? AppCheckAndroidProvider { + super.writeByte(130) + super.writeValue(value.toList()) + } else if let value = value as? AppCheckAppleProvider { + super.writeByte(131) + super.writeValue(value.toList()) + } else if let value = value as? AppCheckPigeonSettings { + super.writeByte(132) + super.writeValue(value.toList()) + } else { + super.writeValue(value) + } + } +} + +private class FirebaseAppCheckMessagesPigeonCodecReaderWriter: FlutterStandardReaderWriter { + override func reader(with data: Data) -> FlutterStandardReader { + return FirebaseAppCheckMessagesPigeonCodecReader(data: data) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + return FirebaseAppCheckMessagesPigeonCodecWriter(data: data) + } +} + +class FirebaseAppCheckMessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { + static let shared = FirebaseAppCheckMessagesPigeonCodec(readerWriter: FirebaseAppCheckMessagesPigeonCodecReaderWriter()) +} + + +/// Generated protocol from Pigeon that represents a handler of messages from Flutter. +protocol FirebaseAppCheckHostApi { + func activate(appName: String, webProvider: AppCheckWebProvider, androidProvider: AppCheckAndroidProvider, appleProvider: AppCheckAppleProvider, 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 getLimitedUseToken(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 = "") { + 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 = api { + activateChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let appNameArg = args[0] as! String + let webProviderArg = args[1] as! AppCheckWebProvider + let androidProviderArg = args[2] as! AppCheckAndroidProvider + let appleProviderArg = args[3] as! AppCheckAppleProvider + api.activate(appName: appNameArg, webProvider: webProviderArg, androidProvider: androidProviderArg, appleProvider: appleProviderArg) { result in + switch result { + case .success: + reply(wrapResult(nil)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } 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 = 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 .success(let res): + reply(wrapResult(res)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } 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 = 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 + switch result { + case .success: + reply(wrapResult(nil)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + setTokenAutoRefreshEnabledChannel.setMessageHandler(nil) + } + let getLimitedUseTokenChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseToken\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + getLimitedUseTokenChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let appNameArg = args[0] as! String + api.getLimitedUseToken(appName: appNameArg) { result in + switch result { + case .success(let res): + reply(wrapResult(res)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + getLimitedUseTokenChannel.setMessageHandler(nil) + } + } +} diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProvider.h b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProvider.h deleted file mode 100644 index 87797e53def0..000000000000 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProvider.h +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import FirebaseAppCheck; - -@interface FLTAppCheckProvider : NSObject - -@property FIRApp *app; - -@property id delegateProvider; - -- (void)configure:(FIRApp *)app providerName:(NSString *)providerName; - -- (id)initWithApp:(FIRApp *)app; - -@end diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProviderFactory.h b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProviderFactory.h deleted file mode 100644 index b98d5a823626..000000000000 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProviderFactory.h +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -#import - -@interface FLTAppCheckProviderFactory : NSObject - -@property NSMutableDictionary *_Nullable providers; - -- (void)configure:(FIRApp *_Nonnull)app providerName:(NSString *_Nonnull)providerName; - -@end diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTFirebaseAppCheckPlugin.h b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTFirebaseAppCheckPlugin.h deleted file mode 100644 index 9d07d0ebc671..000000000000 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTFirebaseAppCheckPlugin.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -#import - -#if TARGET_OS_OSX -#import -#else -#import -#endif - -#import -#if __has_include() -#import -#else -#import -#endif -#import "FLTAppCheckProviderFactory.h" - -@interface FLTFirebaseAppCheckPlugin : FLTFirebasePlugin -@end diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTTokenRefreshStreamHandler.h b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTTokenRefreshStreamHandler.h deleted file mode 100644 index acd570bc3b75..000000000000 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTTokenRefreshStreamHandler.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import - -#if TARGET_OS_OSX -#import -#else -#import -#endif - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface FLTTokenRefreshStreamHandler : NSObject -@end - -NS_ASSUME_NONNULL_END diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check.podspec b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check.podspec index d1b3b7eb6fe8..d8b2e3a331a5 100644 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check.podspec +++ b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check.podspec @@ -43,8 +43,8 @@ Pod::Spec.new do |s| s.authors = 'The Chromium Authors' s.source = { :path => '.' } - s.source_files = 'firebase_app_check/Sources/firebase_app_check/**/*.{h,m}' - s.public_header_files = 'firebase_app_check/Sources/firebase_app_check/include/*.h' + s.source_files = 'firebase_app_check/Sources/firebase_app_check/**/*.{swift}' + s.swift_version = '5.0' s.platform = :osx, '10.13' diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.m b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.m deleted file mode 120000 index 57fc55914ef1..000000000000 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.m +++ /dev/null @@ -1 +0,0 @@ -../../../../ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.m \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.swift b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.swift new file mode 120000 index 000000000000..c21d676bfee7 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.swift @@ -0,0 +1 @@ +../../../../ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.swift \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.m b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.m deleted file mode 120000 index 90899e731380..000000000000 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.m +++ /dev/null @@ -1 +0,0 @@ -../../../../ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.m \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.swift b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.swift new file mode 120000 index 000000000000..041f0f6c5864 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.swift @@ -0,0 +1 @@ +../../../../ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.swift \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.m b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.m deleted file mode 120000 index 3bef267bc202..000000000000 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.m +++ /dev/null @@ -1 +0,0 @@ -../../../../ios/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.m \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.swift b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.swift new file mode 120000 index 000000000000..cdca58a42c28 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.swift @@ -0,0 +1 @@ +../../../../ios/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.swift \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.m b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.m deleted file mode 120000 index 93cf7946f352..000000000000 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.m +++ /dev/null @@ -1 +0,0 @@ -../../../../ios/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.m \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.swift b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.swift new file mode 120000 index 000000000000..3fb0fb5b827e --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.swift @@ -0,0 +1 @@ +../../../../ios/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.swift \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/Resources b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/Resources new file mode 120000 index 000000000000..07d25e35fd91 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/Resources @@ -0,0 +1 @@ +../../../../ios/firebase_app_check/Sources/firebase_app_check/Resources \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/Resources/.gitkeep b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/Resources/.gitkeep deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProvider.h b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProvider.h deleted file mode 120000 index 62bc70731543..000000000000 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProvider.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProvider.h \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProviderFactory.h b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProviderFactory.h deleted file mode 120000 index 5638882c87c2..000000000000 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProviderFactory.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProviderFactory.h \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTFirebaseAppCheckPlugin.h b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTFirebaseAppCheckPlugin.h deleted file mode 120000 index e64b79a492b6..000000000000 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTFirebaseAppCheckPlugin.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../ios/firebase_app_check/Sources/firebase_app_check/include/FLTFirebaseAppCheckPlugin.h \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTTokenRefreshStreamHandler.h b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTTokenRefreshStreamHandler.h deleted file mode 120000 index f4b967d7d5b3..000000000000 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTTokenRefreshStreamHandler.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../ios/firebase_app_check/Sources/firebase_app_check/include/FLTTokenRefreshStreamHandler.h \ No newline at end of file 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 new file mode 100644 index 000000000000..7f91d36cc3cf --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/windows/messages.g.cpp @@ -0,0 +1,419 @@ +// 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. +// See also: https://pub.dev/packages/pigeon + +#undef _HAS_EXCEPTIONS + +#include "messages.g.h" + +#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; + +FlutterError CreateConnectionError(const std::string channel_name) { + return FlutterError( + "channel-error", + "Unable to establish connection on channel: '" + channel_name + "'.", + EncodableValue("")); +} + +// AppCheckWebProvider + +AppCheckWebProvider::AppCheckWebProvider(const std::string& provider_name) + : provider_name_(provider_name) {} + +const std::string& AppCheckWebProvider::provider_name() const { + return provider_name_; +} + +void AppCheckWebProvider::set_provider_name(std::string_view value_arg) { + provider_name_ = value_arg; +} + + +EncodableList AppCheckWebProvider::ToEncodableList() const { + EncodableList list; + list.reserve(1); + list.push_back(EncodableValue(provider_name_)); + return list; +} + +AppCheckWebProvider AppCheckWebProvider::FromEncodableList(const EncodableList& list) { + AppCheckWebProvider decoded( + std::get(list[0])); + return decoded; +} + +// AppCheckAndroidProvider + +AppCheckAndroidProvider::AppCheckAndroidProvider(const std::string& provider_name) + : provider_name_(provider_name) {} + +const std::string& AppCheckAndroidProvider::provider_name() const { + return provider_name_; +} + +void AppCheckAndroidProvider::set_provider_name(std::string_view value_arg) { + provider_name_ = value_arg; +} + + +EncodableList AppCheckAndroidProvider::ToEncodableList() const { + EncodableList list; + list.reserve(1); + list.push_back(EncodableValue(provider_name_)); + return list; +} + +AppCheckAndroidProvider AppCheckAndroidProvider::FromEncodableList(const EncodableList& list) { + AppCheckAndroidProvider decoded( + std::get(list[0])); + return decoded; +} + +// AppCheckAppleProvider + +AppCheckAppleProvider::AppCheckAppleProvider(const std::string& provider_name) + : provider_name_(provider_name) {} + +const std::string& AppCheckAppleProvider::provider_name() const { + return provider_name_; +} + +void AppCheckAppleProvider::set_provider_name(std::string_view value_arg) { + provider_name_ = value_arg; +} + + +EncodableList AppCheckAppleProvider::ToEncodableList() const { + EncodableList list; + list.reserve(1); + list.push_back(EncodableValue(provider_name_)); + return list; +} + +AppCheckAppleProvider AppCheckAppleProvider::FromEncodableList(const EncodableList& list) { + AppCheckAppleProvider decoded( + std::get(list[0])); + return decoded; +} + +// AppCheckPigeonSettings + +AppCheckPigeonSettings::AppCheckPigeonSettings( + const AppCheckWebProvider& web_provider, + const AppCheckAndroidProvider& android_provider, + const AppCheckAppleProvider& apple_provider) + : web_provider_(std::make_unique(web_provider)), + android_provider_(std::make_unique(android_provider)), + apple_provider_(std::make_unique(apple_provider)) {} + +AppCheckPigeonSettings::AppCheckPigeonSettings(const AppCheckPigeonSettings& other) + : web_provider_(std::make_unique(*other.web_provider_)), + android_provider_(std::make_unique(*other.android_provider_)), + apple_provider_(std::make_unique(*other.apple_provider_)) {} + +AppCheckPigeonSettings& AppCheckPigeonSettings::operator=(const AppCheckPigeonSettings& other) { + web_provider_ = std::make_unique(*other.web_provider_); + android_provider_ = std::make_unique(*other.android_provider_); + apple_provider_ = std::make_unique(*other.apple_provider_); + return *this; +} + +const AppCheckWebProvider& AppCheckPigeonSettings::web_provider() const { + return *web_provider_; +} + +void AppCheckPigeonSettings::set_web_provider(const AppCheckWebProvider& value_arg) { + web_provider_ = std::make_unique(value_arg); +} + + +const AppCheckAndroidProvider& AppCheckPigeonSettings::android_provider() const { + return *android_provider_; +} + +void AppCheckPigeonSettings::set_android_provider(const AppCheckAndroidProvider& value_arg) { + android_provider_ = std::make_unique(value_arg); +} + + +const AppCheckAppleProvider& AppCheckPigeonSettings::apple_provider() const { + return *apple_provider_; +} + +void AppCheckPigeonSettings::set_apple_provider(const AppCheckAppleProvider& value_arg) { + apple_provider_ = std::make_unique(value_arg); +} + + +EncodableList AppCheckPigeonSettings::ToEncodableList() const { + EncodableList list; + list.reserve(3); + list.push_back(CustomEncodableValue(*web_provider_)); + list.push_back(CustomEncodableValue(*android_provider_)); + list.push_back(CustomEncodableValue(*apple_provider_)); + return list; +} + +AppCheckPigeonSettings AppCheckPigeonSettings::FromEncodableList(const EncodableList& list) { + AppCheckPigeonSettings decoded( + std::any_cast(std::get(list[0])), + std::any_cast(std::get(list[1])), + std::any_cast(std::get(list[2]))); + return decoded; +} + + +PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} + +EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( + uint8_t type, + flutter::ByteStreamReader* stream) const { + switch (type) { + case 129: { + return CustomEncodableValue(AppCheckWebProvider::FromEncodableList(std::get(ReadValue(stream)))); + } + case 130: { + return CustomEncodableValue(AppCheckAndroidProvider::FromEncodableList(std::get(ReadValue(stream)))); + } + case 131: { + return CustomEncodableValue(AppCheckAppleProvider::FromEncodableList(std::get(ReadValue(stream)))); + } + case 132: { + return CustomEncodableValue(AppCheckPigeonSettings::FromEncodableList(std::get(ReadValue(stream)))); + } + default: + return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); + } +} + +void PigeonInternalCodecSerializer::WriteValue( + const EncodableValue& value, + flutter::ByteStreamWriter* stream) const { + if (const CustomEncodableValue* custom_value = std::get_if(&value)) { + if (custom_value->type() == typeid(AppCheckWebProvider)) { + stream->WriteByte(129); + WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); + return; + } + if (custom_value->type() == typeid(AppCheckAndroidProvider)) { + stream->WriteByte(130); + WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); + return; + } + if (custom_value->type() == typeid(AppCheckAppleProvider)) { + stream->WriteByte(131); + WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); + return; + } + if (custom_value->type() == typeid(AppCheckPigeonSettings)) { + stream->WriteByte(132); + WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); + return; + } + } + flutter::StandardCodecSerializer::WriteValue(value, stream); +} + +/// The codec used by FirebaseAppCheckHostApi. +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) { + 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 : ""; + { + 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_web_provider_arg = args.at(1); + if (encodable_web_provider_arg.IsNull()) { + reply(WrapError("web_provider_arg unexpectedly null.")); + return; + } + const auto& web_provider_arg = std::any_cast(std::get(encodable_web_provider_arg)); + const auto& encodable_android_provider_arg = args.at(2); + if (encodable_android_provider_arg.IsNull()) { + reply(WrapError("android_provider_arg unexpectedly null.")); + return; + } + const auto& android_provider_arg = std::any_cast(std::get(encodable_android_provider_arg)); + const auto& encodable_apple_provider_arg = args.at(3); + if (encodable_apple_provider_arg.IsNull()) { + reply(WrapError("apple_provider_arg unexpectedly null.")); + return; + } + const auto& apple_provider_arg = std::any_cast(std::get(encodable_apple_provider_arg)); + api->Activate(app_name_arg, web_provider_arg, android_provider_arg, apple_provider_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()); + 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())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + 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())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseToken" + 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->GetLimitedUseToken(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(const FlutterError& error) { + 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 new file mode 100644 index 000000000000..379161de1df7 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/windows/messages.g.h @@ -0,0 +1,211 @@ +// 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. +// See also: https://pub.dev/packages/pigeon + +#ifndef PIGEON_MESSAGES_G_H_ +#define PIGEON_MESSAGES_G_H_ +#include +#include +#include +#include + +#include +#include +#include + +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, 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) {} + + const std::string& code() const { return code_; } + const std::string& message() const { return message_; } + const flutter::EncodableValue& details() const { return details_; } + + private: + std::string code_; + std::string message_; + flutter::EncodableValue details_; +}; + +template class ErrorOr { + public: + ErrorOr(const T& rhs) : v_(rhs) {} + ErrorOr(const T&& rhs) : v_(std::move(rhs)) {} + ErrorOr(const FlutterError& rhs) : v_(rhs) {} + ErrorOr(const FlutterError&& rhs) : v_(std::move(rhs)) {} + + bool has_error() const { return std::holds_alternative(v_); } + const T& value() const { return std::get(v_); }; + const FlutterError& error() const { return std::get(v_); }; + + private: + friend class FirebaseAppCheckHostApi; + ErrorOr() = default; + T TakeValue() && { return std::get(std::move(v_)); } + + std::variant v_; +}; + + + +// Generated class from Pigeon that represents data sent in messages. +class AppCheckWebProvider { + public: + // Constructs an object setting all fields. + explicit AppCheckWebProvider(const std::string& provider_name); + + const std::string& provider_name() const; + void set_provider_name(std::string_view value_arg); + + private: + static AppCheckWebProvider FromEncodableList(const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class AppCheckPigeonSettings; + friend class FirebaseAppCheckHostApi; + friend class PigeonInternalCodecSerializer; + std::string provider_name_; +}; + + +// Generated class from Pigeon that represents data sent in messages. +class AppCheckAndroidProvider { + public: + // Constructs an object setting all fields. + explicit AppCheckAndroidProvider(const std::string& provider_name); + + const std::string& provider_name() const; + void set_provider_name(std::string_view value_arg); + + private: + static AppCheckAndroidProvider FromEncodableList(const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class AppCheckPigeonSettings; + friend class FirebaseAppCheckHostApi; + friend class PigeonInternalCodecSerializer; + std::string provider_name_; +}; + + +// Generated class from Pigeon that represents data sent in messages. +class AppCheckAppleProvider { + public: + // Constructs an object setting all fields. + explicit AppCheckAppleProvider(const std::string& provider_name); + + const std::string& provider_name() const; + void set_provider_name(std::string_view value_arg); + + private: + static AppCheckAppleProvider FromEncodableList(const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class AppCheckPigeonSettings; + friend class FirebaseAppCheckHostApi; + friend class PigeonInternalCodecSerializer; + std::string provider_name_; +}; + + +// Generated class from Pigeon that represents data sent in messages. +class AppCheckPigeonSettings { + public: + // Constructs an object setting all fields. + explicit AppCheckPigeonSettings( + const AppCheckWebProvider& web_provider, + const AppCheckAndroidProvider& android_provider, + const AppCheckAppleProvider& apple_provider); + + ~AppCheckPigeonSettings() = default; + AppCheckPigeonSettings(const AppCheckPigeonSettings& other); + AppCheckPigeonSettings& operator=(const AppCheckPigeonSettings& other); + AppCheckPigeonSettings(AppCheckPigeonSettings&& other) = default; + AppCheckPigeonSettings& operator=(AppCheckPigeonSettings&& other) noexcept = default; + const AppCheckWebProvider& web_provider() const; + void set_web_provider(const AppCheckWebProvider& value_arg); + + const AppCheckAndroidProvider& android_provider() const; + void set_android_provider(const AppCheckAndroidProvider& value_arg); + + const AppCheckAppleProvider& apple_provider() const; + void set_apple_provider(const AppCheckAppleProvider& value_arg); + + private: + static AppCheckPigeonSettings FromEncodableList(const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class FirebaseAppCheckHostApi; + friend class PigeonInternalCodecSerializer; + std::unique_ptr web_provider_; + std::unique_ptr android_provider_; + std::unique_ptr apple_provider_; +}; + + +class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { + public: + PigeonInternalCodecSerializer(); + inline static PigeonInternalCodecSerializer& GetInstance() { + static PigeonInternalCodecSerializer sInstance; + return sInstance; + } + + void WriteValue( + const flutter::EncodableValue& value, + flutter::ByteStreamWriter* stream) const override; + protected: + flutter::EncodableValue ReadValueOfType( + uint8_t type, + flutter::ByteStreamReader* stream) const override; +}; + +// 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 AppCheckWebProvider& web_provider, + const AppCheckAndroidProvider& android_provider, + const AppCheckAppleProvider& apple_provider, + std::function reply)> result) = 0; + virtual void GetToken( + 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; + virtual void GetLimitedUseToken( + 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); + protected: + FirebaseAppCheckHostApi() = default; +}; +} // namespace firebase_app_check_windows +#endif // PIGEON_MESSAGES_G_H_ 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 edee4fbe09d0..21ef85a895b4 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 @@ -7,6 +7,7 @@ import 'dart:async'; import 'package:_flutterfire_internals/_flutterfire_internals.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/foundation.dart'; +import 'package:firebase_app_check_platform_interface/src/pigeon/messages.pigeon.dart'; import 'package:flutter/services.dart'; import '../../firebase_app_check_platform_interface.dart'; @@ -73,6 +74,8 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { return this; } + final _hostApi = FirebaseAppCheckHostApi(); + @override Future activate({ WebProvider? webProvider, @@ -80,30 +83,38 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { AppleProvider? appleProvider, }) async { try { - await channel.invokeMethod('FirebaseAppCheck#activate', { - 'appName': app.name, - // Allow value to pass for debug mode for unit testing - if (defaultTargetPlatform == TargetPlatform.android || kDebugMode) - 'androidProvider': getAndroidProviderString(androidProvider), - if (defaultTargetPlatform == TargetPlatform.iOS || - defaultTargetPlatform == TargetPlatform.macOS || - kDebugMode) - 'appleProvider': getAppleProviderString(appleProvider), - }); + // Convert platform interface types to Pigeon types + AppCheckWebProvider pigeonWebProvider = AppCheckWebProvider( + providerName: webProvider != null ? _getWebProviderString(webProvider) : 'debug' + ); + AppCheckAndroidProvider pigeonAndroidProvider = AppCheckAndroidProvider( + providerName: getAndroidProviderString(androidProvider) + ); + AppCheckAppleProvider pigeonAppleProvider = AppCheckAppleProvider( + providerName: getAppleProviderString(appleProvider) + ); + + await _hostApi.activate(app.name, pigeonWebProvider, pigeonAndroidProvider, pigeonAppleProvider); } on PlatformException catch (e, s) { convertPlatformException(e, s); } } + /// Converts [WebProvider] to [String] + String _getWebProviderString(WebProvider? provider) { + if (provider is ReCaptchaV3Provider) { + return 'reCAPTCHA'; + } else if (provider is ReCaptchaEnterpriseProvider) { + return 'reCAPTCHA'; + } else { + return 'debug'; + } + } + @override Future getToken(bool forceRefresh) async { try { - final result = await channel.invokeMethod( - 'FirebaseAppCheck#getToken', - {'appName': app.name, 'forceRefresh': forceRefresh}, - ); - - return result; + return await _hostApi.getToken(app.name, forceRefresh); } on PlatformException catch (e, s) { convertPlatformException(e, s); } @@ -114,13 +125,7 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { bool isTokenAutoRefreshEnabled, ) async { try { - await channel.invokeMethod( - 'FirebaseAppCheck#setTokenAutoRefreshEnabled', - { - 'appName': app.name, - 'isTokenAutoRefreshEnabled': isTokenAutoRefreshEnabled, - }, - ); + await _hostApi.setTokenAutoRefreshEnabled(app.name, isTokenAutoRefreshEnabled); } on PlatformException catch (e, s) { convertPlatformException(e, s); } @@ -134,14 +139,7 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { @override Future getLimitedUseToken() async { try { - final result = await channel.invokeMethod( - 'FirebaseAppCheck#getLimitedUseAppCheckToken', - { - 'appName': app.name, - }, - ); - - return result; + return await _hostApi.getLimitedUseToken(app.name); } 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 new file mode 100644 index 000000000000..559698cc0c69 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -0,0 +1,360 @@ +// 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. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers + +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; + +PlatformException _createConnectionError(String channelName) { + return PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); +} +bool _deepEquals(Object? a, Object? b) { + if (a is List && b is List) { + return a.length == b.length && + a.indexed + .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); + } + if (a is Map && b is Map) { + return a.length == b.length && a.entries.every((MapEntry entry) => + (b as Map).containsKey(entry.key) && + _deepEquals(entry.value, b[entry.key])); + } + return a == b; +} + + +class AppCheckWebProvider { + AppCheckWebProvider({ + required this.providerName, + }); + + String providerName; + + List _toList() { + return [ + providerName, + ]; + } + + Object encode() { + return _toList(); } + + static AppCheckWebProvider decode(Object result) { + result as List; + return AppCheckWebProvider( + providerName: result[0]! as String, + ); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! AppCheckWebProvider || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(encode(), other.encode()); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => Object.hashAll(_toList()) +; +} + +class AppCheckAndroidProvider { + AppCheckAndroidProvider({ + required this.providerName, + }); + + String providerName; + + List _toList() { + return [ + providerName, + ]; + } + + Object encode() { + return _toList(); } + + static AppCheckAndroidProvider decode(Object result) { + result as List; + return AppCheckAndroidProvider( + providerName: result[0]! as String, + ); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! AppCheckAndroidProvider || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(encode(), other.encode()); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => Object.hashAll(_toList()) +; +} + +class AppCheckAppleProvider { + AppCheckAppleProvider({ + required this.providerName, + }); + + String providerName; + + List _toList() { + return [ + providerName, + ]; + } + + Object encode() { + return _toList(); } + + static AppCheckAppleProvider decode(Object result) { + result as List; + return AppCheckAppleProvider( + providerName: result[0]! as String, + ); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! AppCheckAppleProvider || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(encode(), other.encode()); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => Object.hashAll(_toList()) +; +} + +class AppCheckPigeonSettings { + AppCheckPigeonSettings({ + required this.webProvider, + required this.androidProvider, + required this.appleProvider, + }); + + AppCheckWebProvider webProvider; + + AppCheckAndroidProvider androidProvider; + + AppCheckAppleProvider appleProvider; + + List _toList() { + return [ + webProvider, + androidProvider, + appleProvider, + ]; + } + + Object encode() { + return _toList(); } + + static AppCheckPigeonSettings decode(Object result) { + result as List; + return AppCheckPigeonSettings( + webProvider: result[0]! as AppCheckWebProvider, + androidProvider: result[1]! as AppCheckAndroidProvider, + appleProvider: result[2]! as AppCheckAppleProvider, + ); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! AppCheckPigeonSettings || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(encode(), other.encode()); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => Object.hashAll(_toList()) +; +} + + +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else if (value is AppCheckWebProvider) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); + } else if (value is AppCheckAndroidProvider) { + buffer.putUint8(130); + writeValue(buffer, value.encode()); + } else if (value is AppCheckAppleProvider) { + buffer.putUint8(131); + writeValue(buffer, value.encode()); + } else if (value is AppCheckPigeonSettings) { + buffer.putUint8(132); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 129: + return AppCheckWebProvider.decode(readValue(buffer)!); + case 130: + return AppCheckAndroidProvider.decode(readValue(buffer)!); + case 131: + return AppCheckAppleProvider.decode(readValue(buffer)!); + case 132: + return AppCheckPigeonSettings.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +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 = ''}) + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + final BinaryMessenger? pigeonVar_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); + + final String pigeonVar_messageChannelSuffix; + + Future activate(String appName, AppCheckWebProvider webProvider, AppCheckAndroidProvider androidProvider, AppCheckAppleProvider appleProvider) async { + final String pigeonVar_channelName = 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName, webProvider, androidProvider, appleProvider]); + 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; + } + } + + 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( + 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?); + } + } + + 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( + 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; + } + } + + Future getLimitedUseToken(String appName) async { + final String pigeonVar_channelName = 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseToken$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel 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?)!; + } + } +} diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/copyright.txt b/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/copyright.txt new file mode 100644 index 000000000000..4e197781c6db --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/copyright.txt @@ -0,0 +1,3 @@ +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. \ No newline at end of file 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 new file mode 100644 index 000000000000..35dc6df7ac8e --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/messages.dart @@ -0,0 +1,67 @@ +// Copyright 2025 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:pigeon/pigeon.dart'; + +class AppCheckWebProvider { + AppCheckWebProvider({required this.providerName}); + + String providerName; // 'reCAPTCHA' or 'debug' +} + +class AppCheckAndroidProvider { + AppCheckAndroidProvider({required this.providerName}); + + String providerName; // 'safetyNet', 'playIntegrity', or 'debug' +} + +class AppCheckAppleProvider { + AppCheckAppleProvider({required this.providerName}); + + String providerName; // 'deviceCheck', 'appAttest', 'debug', or 'appAttestWithDeviceCheckFallback' +} + +@ConfigurePigeon( + PigeonOptions( + dartOut: 'lib/src/pigeon/messages.pigeon.dart', + dartPackageName: 'firebase_app_check_platform_interface', + kotlinOut: + '../firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseappcheck/GeneratedAndroidFirebaseAppCheck.g.kt', + kotlinOptions: KotlinOptions( + package: 'io.flutter.plugins.firebase.firebaseappcheck', + ), + swiftOut: + '../firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift', + cppHeaderOut: '../firebase_app_check/windows/messages.g.h', + cppSourceOut: '../firebase_app_check/windows/messages.g.cpp', + cppOptions: CppOptions(namespace: 'firebase_app_check_windows'), + copyrightHeader: 'pigeons/copyright.txt', + ), +) +class AppCheckPigeonSettings { + AppCheckPigeonSettings({ + required this.webProvider, + required this.androidProvider, + required this.appleProvider, + }); + + AppCheckWebProvider webProvider; + AppCheckAndroidProvider androidProvider; + AppCheckAppleProvider appleProvider; +} + +@HostApi(dartHostTestHandler: 'TestFirebaseAppCheckHostApi') +abstract class FirebaseAppCheckHostApi { + @async + void activate(String appName, AppCheckWebProvider webProvider, AppCheckAndroidProvider androidProvider, AppCheckAppleProvider appleProvider); + + @async + String? getToken(String appName, bool forceRefresh); + + @async + void setTokenAutoRefreshEnabled(String appName, bool isTokenAutoRefreshEnabled); + + @async + String getLimitedUseToken(String appName); +} \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml index d36e052d584b..40e5963afa50 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml @@ -20,3 +20,4 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.0.0 + pigeon: 25.3.2