diff --git a/melos.yaml b/melos.yaml index c87ba36f5ab7..55a69ea8c70a 100644 --- a/melos.yaml +++ b/melos.yaml @@ -141,6 +141,7 @@ scripts: dirExists: - test ignore: + - firebase_app_installations_platform_interface - '*web*' - '*example*' diff --git a/packages/firebase_app_installations/firebase_app_installations/android/src/main/java/io/flutter/plugins/firebase/installations/GeneratedAndroidFirebaseAppInstallations.java b/packages/firebase_app_installations/firebase_app_installations/android/src/main/java/io/flutter/plugins/firebase/installations/GeneratedAndroidFirebaseAppInstallations.java new file mode 100644 index 000000000000..992b01d2da92 --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations/android/src/main/java/io/flutter/plugins/firebase/installations/GeneratedAndroidFirebaseAppInstallations.java @@ -0,0 +1,650 @@ +// 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 + +package io.flutter.plugins.firebase.installations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.CLASS; + +import android.util.Log; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import io.flutter.plugin.common.BasicMessageChannel; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.MessageCodec; +import io.flutter.plugin.common.StandardMessageCodec; +import java.io.ByteArrayOutputStream; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** Generated class from Pigeon. */ +@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"}) +public class GeneratedAndroidFirebaseAppInstallations { + + /** Error class for passing custom error details to Flutter via a thrown PlatformException. */ + public static class FlutterError extends RuntimeException { + + /** The error code. */ + public final String code; + + /** The error details. Must be a datatype supported by the api codec. */ + public final Object details; + + public FlutterError(@NonNull String code, @Nullable String message, @Nullable Object details) { + super(message); + this.code = code; + this.details = details; + } + } + + @NonNull + protected static ArrayList wrapError(@NonNull Throwable exception) { + ArrayList errorList = new ArrayList<>(3); + if (exception instanceof FlutterError) { + FlutterError error = (FlutterError) exception; + errorList.add(error.code); + errorList.add(error.getMessage()); + errorList.add(error.details); + } else { + errorList.add(exception.toString()); + errorList.add(exception.getClass().getSimpleName()); + errorList.add( + "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception)); + } + return errorList; + } + + @NonNull + protected static FlutterError createConnectionError(@NonNull String channelName) { + return new FlutterError( + "channel-error", "Unable to establish connection on channel: " + channelName + ".", ""); + } + + @Target(METHOD) + @Retention(CLASS) + @interface CanIgnoreReturnValue {} + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class AppInstallationsPigeonSettings { + private @NonNull Boolean persistenceEnabled; + + public @NonNull Boolean getPersistenceEnabled() { + return persistenceEnabled; + } + + public void setPersistenceEnabled(@NonNull Boolean setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"persistenceEnabled\" is null."); + } + this.persistenceEnabled = setterArg; + } + + private @NonNull Boolean forceRefreshOnSignIn; + + public @NonNull Boolean getForceRefreshOnSignIn() { + return forceRefreshOnSignIn; + } + + public void setForceRefreshOnSignIn(@NonNull Boolean setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"forceRefreshOnSignIn\" is null."); + } + this.forceRefreshOnSignIn = setterArg; + } + + private @NonNull Boolean forceRefreshOnTokenChange; + + public @NonNull Boolean getForceRefreshOnTokenChange() { + return forceRefreshOnTokenChange; + } + + public void setForceRefreshOnTokenChange(@NonNull Boolean setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"forceRefreshOnTokenChange\" is null."); + } + this.forceRefreshOnTokenChange = setterArg; + } + + private @NonNull Boolean forceRefreshOnAppUpdate; + + public @NonNull Boolean getForceRefreshOnAppUpdate() { + return forceRefreshOnAppUpdate; + } + + public void setForceRefreshOnAppUpdate(@NonNull Boolean setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"forceRefreshOnAppUpdate\" is null."); + } + this.forceRefreshOnAppUpdate = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + AppInstallationsPigeonSettings() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AppInstallationsPigeonSettings that = (AppInstallationsPigeonSettings) o; + return persistenceEnabled.equals(that.persistenceEnabled) + && forceRefreshOnSignIn.equals(that.forceRefreshOnSignIn) + && forceRefreshOnTokenChange.equals(that.forceRefreshOnTokenChange) + && forceRefreshOnAppUpdate.equals(that.forceRefreshOnAppUpdate); + } + + @Override + public int hashCode() { + return Objects.hash( + persistenceEnabled, + forceRefreshOnSignIn, + forceRefreshOnTokenChange, + forceRefreshOnAppUpdate); + } + + public static final class Builder { + + private @Nullable Boolean persistenceEnabled; + + @CanIgnoreReturnValue + public @NonNull Builder setPersistenceEnabled(@NonNull Boolean setterArg) { + this.persistenceEnabled = setterArg; + return this; + } + + private @Nullable Boolean forceRefreshOnSignIn; + + @CanIgnoreReturnValue + public @NonNull Builder setForceRefreshOnSignIn(@NonNull Boolean setterArg) { + this.forceRefreshOnSignIn = setterArg; + return this; + } + + private @Nullable Boolean forceRefreshOnTokenChange; + + @CanIgnoreReturnValue + public @NonNull Builder setForceRefreshOnTokenChange(@NonNull Boolean setterArg) { + this.forceRefreshOnTokenChange = setterArg; + return this; + } + + private @Nullable Boolean forceRefreshOnAppUpdate; + + @CanIgnoreReturnValue + public @NonNull Builder setForceRefreshOnAppUpdate(@NonNull Boolean setterArg) { + this.forceRefreshOnAppUpdate = setterArg; + return this; + } + + public @NonNull AppInstallationsPigeonSettings build() { + AppInstallationsPigeonSettings pigeonReturn = new AppInstallationsPigeonSettings(); + pigeonReturn.setPersistenceEnabled(persistenceEnabled); + pigeonReturn.setForceRefreshOnSignIn(forceRefreshOnSignIn); + pigeonReturn.setForceRefreshOnTokenChange(forceRefreshOnTokenChange); + pigeonReturn.setForceRefreshOnAppUpdate(forceRefreshOnAppUpdate); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList<>(4); + toListResult.add(persistenceEnabled); + toListResult.add(forceRefreshOnSignIn); + toListResult.add(forceRefreshOnTokenChange); + toListResult.add(forceRefreshOnAppUpdate); + return toListResult; + } + + static @NonNull AppInstallationsPigeonSettings fromList( + @NonNull ArrayList pigeonVar_list) { + AppInstallationsPigeonSettings pigeonResult = new AppInstallationsPigeonSettings(); + Object persistenceEnabled = pigeonVar_list.get(0); + pigeonResult.setPersistenceEnabled((Boolean) persistenceEnabled); + Object forceRefreshOnSignIn = pigeonVar_list.get(1); + pigeonResult.setForceRefreshOnSignIn((Boolean) forceRefreshOnSignIn); + Object forceRefreshOnTokenChange = pigeonVar_list.get(2); + pigeonResult.setForceRefreshOnTokenChange((Boolean) forceRefreshOnTokenChange); + Object forceRefreshOnAppUpdate = pigeonVar_list.get(3); + pigeonResult.setForceRefreshOnAppUpdate((Boolean) forceRefreshOnAppUpdate); + return pigeonResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class AppInstallationsPigeonFirebaseApp { + private @NonNull String appName; + + public @NonNull String getAppName() { + return appName; + } + + public void setAppName(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"appName\" is null."); + } + this.appName = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + AppInstallationsPigeonFirebaseApp() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AppInstallationsPigeonFirebaseApp that = (AppInstallationsPigeonFirebaseApp) o; + return appName.equals(that.appName); + } + + @Override + public int hashCode() { + return Objects.hash(appName); + } + + public static final class Builder { + + private @Nullable String appName; + + @CanIgnoreReturnValue + public @NonNull Builder setAppName(@NonNull String setterArg) { + this.appName = setterArg; + return this; + } + + public @NonNull AppInstallationsPigeonFirebaseApp build() { + AppInstallationsPigeonFirebaseApp pigeonReturn = new AppInstallationsPigeonFirebaseApp(); + pigeonReturn.setAppName(appName); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList<>(1); + toListResult.add(appName); + return toListResult; + } + + static @NonNull AppInstallationsPigeonFirebaseApp fromList( + @NonNull ArrayList pigeonVar_list) { + AppInstallationsPigeonFirebaseApp pigeonResult = new AppInstallationsPigeonFirebaseApp(); + Object appName = pigeonVar_list.get(0); + pigeonResult.setAppName((String) appName); + return pigeonResult; + } + } + + private static class PigeonCodec extends StandardMessageCodec { + public static final PigeonCodec INSTANCE = new PigeonCodec(); + + private PigeonCodec() {} + + @Override + protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { + switch (type) { + case (byte) 129: + return AppInstallationsPigeonSettings.fromList((ArrayList) readValue(buffer)); + case (byte) 130: + return AppInstallationsPigeonFirebaseApp.fromList((ArrayList) readValue(buffer)); + default: + return super.readValueOfType(type, buffer); + } + } + + @Override + protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { + if (value instanceof AppInstallationsPigeonSettings) { + stream.write(129); + writeValue(stream, ((AppInstallationsPigeonSettings) value).toList()); + } else if (value instanceof AppInstallationsPigeonFirebaseApp) { + stream.write(130); + writeValue(stream, ((AppInstallationsPigeonFirebaseApp) value).toList()); + } else { + super.writeValue(stream, value); + } + } + } + + /** Asynchronous error handling return type for non-nullable API method returns. */ + public interface Result { + /** Success case callback method for handling returns. */ + void success(@NonNull T result); + + /** Failure case callback method for handling errors. */ + void error(@NonNull Throwable error); + } + /** Asynchronous error handling return type for nullable API method returns. */ + public interface NullableResult { + /** Success case callback method for handling returns. */ + void success(@Nullable T result); + + /** Failure case callback method for handling errors. */ + void error(@NonNull Throwable error); + } + /** Asynchronous error handling return type for void API method returns. */ + public interface VoidResult { + /** Success case callback method for handling returns. */ + void success(); + + /** Failure case callback method for handling errors. */ + void error(@NonNull Throwable error); + } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ + public interface FirebaseAppInstallationsHostApi { + + void initializeApp( + @NonNull AppInstallationsPigeonFirebaseApp app, + @NonNull AppInstallationsPigeonSettings settings, + @NonNull VoidResult result); + + void delete(@NonNull AppInstallationsPigeonFirebaseApp app, @NonNull VoidResult result); + + void getId(@NonNull AppInstallationsPigeonFirebaseApp app, @NonNull Result result); + + void getToken( + @NonNull AppInstallationsPigeonFirebaseApp app, + @NonNull Boolean forceRefresh, + @NonNull Result result); + + void onIdChange( + @NonNull AppInstallationsPigeonFirebaseApp app, + @NonNull String newId, + @NonNull VoidResult result); + + void registerIdChangeListener( + @NonNull AppInstallationsPigeonFirebaseApp app, + @NonNull Result result); + + /** The codec used by FirebaseAppInstallationsHostApi. */ + static @NonNull MessageCodec getCodec() { + return PigeonCodec.INSTANCE; + } + + /** + * Sets up an instance of `FirebaseAppInstallationsHostApi` to handle messages through the + * `binaryMessenger`. + */ + static void setUp( + @NonNull BinaryMessenger binaryMessenger, @Nullable FirebaseAppInstallationsHostApi api) { + setUp(binaryMessenger, "", api); + } + + static void setUp( + @NonNull BinaryMessenger binaryMessenger, + @NonNull String messageChannelSuffix, + @Nullable FirebaseAppInstallationsHostApi api) { + messageChannelSuffix = messageChannelSuffix.isEmpty() ? "" : "." + messageChannelSuffix; + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.initializeApp" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList<>(); + ArrayList args = (ArrayList) message; + AppInstallationsPigeonFirebaseApp appArg = + (AppInstallationsPigeonFirebaseApp) args.get(0); + AppInstallationsPigeonSettings settingsArg = + (AppInstallationsPigeonSettings) args.get(1); + VoidResult resultCallback = + new VoidResult() { + public void success() { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.initializeApp(appArg, settingsArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.delete" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList<>(); + ArrayList args = (ArrayList) message; + AppInstallationsPigeonFirebaseApp appArg = + (AppInstallationsPigeonFirebaseApp) args.get(0); + VoidResult resultCallback = + new VoidResult() { + public void success() { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.delete(appArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.getId" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList<>(); + ArrayList args = (ArrayList) message; + AppInstallationsPigeonFirebaseApp appArg = + (AppInstallationsPigeonFirebaseApp) args.get(0); + Result resultCallback = + new Result() { + public void success(String result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.getId(appArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.getToken" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList<>(); + ArrayList args = (ArrayList) message; + AppInstallationsPigeonFirebaseApp appArg = + (AppInstallationsPigeonFirebaseApp) args.get(0); + Boolean forceRefreshArg = (Boolean) args.get(1); + Result resultCallback = + new Result() { + public void success(String result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.getToken(appArg, forceRefreshArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.onIdChange" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList<>(); + ArrayList args = (ArrayList) message; + AppInstallationsPigeonFirebaseApp appArg = + (AppInstallationsPigeonFirebaseApp) args.get(0); + String newIdArg = (String) args.get(1); + VoidResult resultCallback = + new VoidResult() { + public void success() { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.onIdChange(appArg, newIdArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.registerIdChangeListener" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList<>(); + ArrayList args = (ArrayList) message; + AppInstallationsPigeonFirebaseApp appArg = + (AppInstallationsPigeonFirebaseApp) args.get(0); + Result resultCallback = + new Result() { + public void success(String result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.registerIdChangeListener(appArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + } + } + /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */ + public static class FirebaseAppInstallationsFlutterApi { + private final @NonNull BinaryMessenger binaryMessenger; + private final String messageChannelSuffix; + + public FirebaseAppInstallationsFlutterApi(@NonNull BinaryMessenger argBinaryMessenger) { + this(argBinaryMessenger, ""); + } + + public FirebaseAppInstallationsFlutterApi( + @NonNull BinaryMessenger argBinaryMessenger, @NonNull String messageChannelSuffix) { + this.binaryMessenger = argBinaryMessenger; + this.messageChannelSuffix = messageChannelSuffix.isEmpty() ? "" : "." + messageChannelSuffix; + } + + /** Public interface for sending reply. The codec used by FirebaseAppInstallationsFlutterApi. */ + static @NonNull MessageCodec getCodec() { + return PigeonCodec.INSTANCE; + } + + public void registerIdTokenListener( + @NonNull AppInstallationsPigeonFirebaseApp appArg, @NonNull Result result) { + final String channelName = + "dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsFlutterApi.registerIdTokenListener" + + messageChannelSuffix; + BasicMessageChannel channel = + new BasicMessageChannel<>(binaryMessenger, channelName, getCodec()); + channel.send( + new ArrayList<>(Collections.singletonList(appArg)), + channelReply -> { + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), (String) listReply.get(1), listReply.get(2))); + } else if (listReply.get(0) == null) { + result.error( + new FlutterError( + "null-error", + "Flutter api returned null value for non-null return value.", + "")); + } else { + @SuppressWarnings("ConstantConditions") + String output = (String) listReply.get(0); + result.success(output); + } + } else { + result.error(createConnectionError(channelName)); + } + }); + } + } +} diff --git a/packages/firebase_app_installations/firebase_app_installations/android/src/main/java/io/flutter/plugins/firebase/installations/firebase_app_installations/FirebaseInstallationsPlugin.java b/packages/firebase_app_installations/firebase_app_installations/android/src/main/java/io/flutter/plugins/firebase/installations/firebase_app_installations/FirebaseInstallationsPlugin.java index 2ddb5d1e54fd..6ba39a075f0a 100644 --- a/packages/firebase_app_installations/firebase_app_installations/android/src/main/java/io/flutter/plugins/firebase/installations/firebase_app_installations/FirebaseInstallationsPlugin.java +++ b/packages/firebase_app_installations/firebase_app_installations/android/src/main/java/io/flutter/plugins/firebase/installations/firebase_app_installations/FirebaseInstallationsPlugin.java @@ -15,98 +15,153 @@ 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.FlutterFirebasePluginRegistry; +import io.flutter.plugins.firebase.installations.GeneratedAndroidFirebaseAppInstallations; +import io.flutter.plugins.firebase.installations.GeneratedAndroidFirebaseAppInstallations.AppInstallationsPigeonFirebaseApp; +import io.flutter.plugins.firebase.installations.GeneratedAndroidFirebaseAppInstallations.AppInstallationsPigeonSettings; import java.util.HashMap; import java.util.Map; import java.util.Objects; /** FirebaseInstallationsPlugin */ public class FirebaseInstallationsPlugin - implements FlutterFirebasePlugin, FlutterPlugin, MethodCallHandler { - private MethodChannel channel; + implements FlutterFirebasePlugin, + FlutterPlugin, + GeneratedAndroidFirebaseAppInstallations.FirebaseAppInstallationsHostApi { private static final String METHOD_CHANNEL_NAME = "plugins.flutter.io/firebase_app_installations"; private final Map streamHandlers = new HashMap<>(); @Nullable private BinaryMessenger messenger; - private MethodChannel setup(BinaryMessenger binaryMessenger) { - final MethodChannel channel = new MethodChannel(binaryMessenger, METHOD_CHANNEL_NAME); - channel.setMethodCallHandler(this); + private void setup(BinaryMessenger binaryMessenger) { this.messenger = binaryMessenger; - return channel; + // Set up Pigeon host API handlers. + GeneratedAndroidFirebaseAppInstallations.FirebaseAppInstallationsHostApi.setUp( + binaryMessenger, this); } @Override public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { BinaryMessenger binaryMessenger = flutterPluginBinding.getBinaryMessenger(); - channel = setup(binaryMessenger); + setup(binaryMessenger); FlutterFirebasePluginRegistry.registerPlugin(METHOD_CHANNEL_NAME, this); } @Override public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { - channel.setMethodCallHandler(null); - channel = null; + if (messenger != null) { + GeneratedAndroidFirebaseAppInstallations.FirebaseAppInstallationsHostApi.setUp( + messenger, null); + } messenger = null; removeEventListeners(); } - private FirebaseInstallations getInstallations(Map arguments) { - @NonNull String appName = (String) Objects.requireNonNull(arguments.get("appName")); + private FirebaseInstallations getInstallations(AppInstallationsPigeonFirebaseApp appArg) { + @NonNull String appName = appArg.getAppName(); FirebaseApp app = FirebaseApp.getInstance(appName); return FirebaseInstallations.getInstance(app); } - private Task getId(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); + // Pigeon FirebaseAppInstallationsHostApi implementation. + @Override + public void initializeApp( + @NonNull AppInstallationsPigeonFirebaseApp app, + @NonNull AppInstallationsPigeonSettings settings, + @NonNull GeneratedAndroidFirebaseAppInstallations.VoidResult result) { + // Currently there is no per-app configurable behavior required on Android for these settings. + // We execute asynchronously to keep the threading model consistent. cachedThreadPool.execute( () -> { try { - taskCompletionSource.setResult(Tasks.await(getInstallations(arguments).getId())); + // Touch the instance to ensure it's initialized. + getInstallations(app); + result.success(); } catch (Exception e) { - taskCompletionSource.setException(e); + result.error( + new GeneratedAndroidFirebaseAppInstallations.FlutterError( + "firebase_app_installations", e.getMessage(), getExceptionDetails(e))); } }); + } - return taskCompletionSource.getTask(); + @Override + public void delete( + @NonNull AppInstallationsPigeonFirebaseApp app, + @NonNull GeneratedAndroidFirebaseAppInstallations.VoidResult result) { + cachedThreadPool.execute( + () -> { + try { + Tasks.await(getInstallations(app).delete()); + result.success(); + } catch (Exception e) { + result.error( + new GeneratedAndroidFirebaseAppInstallations.FlutterError( + "firebase_app_installations", e.getMessage(), getExceptionDetails(e))); + } + }); } - private Task getToken(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); + @Override + public void getId( + @NonNull AppInstallationsPigeonFirebaseApp app, + @NonNull GeneratedAndroidFirebaseAppInstallations.Result result) { + cachedThreadPool.execute( + () -> { + try { + String id = Tasks.await(getInstallations(app).getId()); + result.success(id); + } catch (Exception e) { + result.error( + new GeneratedAndroidFirebaseAppInstallations.FlutterError( + "firebase_app_installations", e.getMessage(), getExceptionDetails(e))); + } + }); + } + @Override + public void getToken( + @NonNull AppInstallationsPigeonFirebaseApp app, + @NonNull Boolean forceRefresh, + @NonNull GeneratedAndroidFirebaseAppInstallations.Result result) { cachedThreadPool.execute( () -> { try { - FirebaseInstallations firebaseInstallations = getInstallations(arguments); - Boolean forceRefresh = (Boolean) Objects.requireNonNull(arguments.get("forceRefresh")); + FirebaseInstallations firebaseInstallations = getInstallations(app); InstallationTokenResult tokenResult = Tasks.await(firebaseInstallations.getToken(forceRefresh)); - - taskCompletionSource.setResult(tokenResult.getToken()); + result.success(tokenResult.getToken()); } catch (Exception e) { - taskCompletionSource.setException(e); + result.error( + new GeneratedAndroidFirebaseAppInstallations.FlutterError( + "firebase_app_installations", e.getMessage(), getExceptionDetails(e))); } }); - - return taskCompletionSource.getTask(); } - private Task registerIdChangeListener(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); + @Override + public void onIdChange( + @NonNull AppInstallationsPigeonFirebaseApp app, + @NonNull String newId, + @NonNull GeneratedAndroidFirebaseAppInstallations.VoidResult result) { + // The Dart side currently uses an EventChannel-based listener, so this Pigeon hook + // is a no-op placeholder to satisfy the interface. + result.success(); + } + @Override + public void registerIdChangeListener( + @NonNull AppInstallationsPigeonFirebaseApp app, + @NonNull GeneratedAndroidFirebaseAppInstallations.Result result) { cachedThreadPool.execute( () -> { try { - String appName = (String) Objects.requireNonNull(arguments.get("appName")); - FirebaseInstallations firebaseInstallations = getInstallations(arguments); + FirebaseInstallations firebaseInstallations = getInstallations(app); + @NonNull String appName = app.getAppName(); io.flutter.plugins.firebase.installations.firebase_app_installations .TokenChannelStreamHandler @@ -119,65 +174,11 @@ private Task registerIdChangeListener(Map arguments) { channel.setStreamHandler(handler); streamHandlers.put(channel, handler); - taskCompletionSource.setResult(name); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task deleteId(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - Tasks.await(getInstallations(arguments).delete()); - - taskCompletionSource.setResult(null); + result.success(name); } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - @Override - public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { - Task methodCallTask; - - switch (call.method) { - case "FirebaseInstallations#getId": - methodCallTask = getId(call.arguments()); - break; - case "FirebaseInstallations#getToken": - methodCallTask = getToken(call.arguments()); - break; - case "FirebaseInstallations#delete": - methodCallTask = deleteId(call.arguments()); - break; - case "FirebaseInstallations#registerIdChangeListener": - methodCallTask = registerIdChangeListener(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_installations", - exception != null ? exception.getMessage() : null, - getExceptionDetails(exception)); + new GeneratedAndroidFirebaseAppInstallations.FlutterError( + "firebase_app_installations", e.getMessage(), getExceptionDetails(e))); } }); } diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations.podspec b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations.podspec index e99dea9b9010..3aafa63ca102 100644 --- a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations.podspec +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations.podspec @@ -24,7 +24,11 @@ Pod::Spec.new do |s| s.license = { :file => '../LICENSE' } s.authors = 'The Chromium Authors' s.source = { :path => '.' } - s.source_files = 'firebase_app_installations/Sources/**/*.swift' + s.source_files = 'firebase_app_installations/Sources/**/*.{swift,h,m}' + s.public_header_files = [ + 'firebase_app_installations/Sources/firebase_app_installations/firebase_app_installations.h', + 'firebase_app_installations/Sources/firebase_app_installations_objc/firebase_app_installations_messages.g.h', + ] s.ios.deployment_target = '15.0' diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift index 5f11fa8d659a..41e6d40eedbc 100644 --- a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift @@ -98,6 +98,14 @@ let package = Package( // Wrapper dependency .product(name: "firebase-core-shared", package: "flutterfire"), ], + // Exclude Objective-C sources that are used only for CocoaPods integration. + // The Swift Package Manager target is pure Swift and uses the Swift Pigeon + // types defined in FirebaseAppInstallationsMessages.g.swift instead. + exclude: [ + "Sources/firebase_app_installations/firebase_app_installations.h", + "Sources/firebase_app_installations/firebase_app_installations_messages.g.h", + "Sources/firebase_app_installations/firebase_app_installations_messages.g.m", + ], resources: [ .process("Resources"), ] diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/FirebaseAppInstallationsMessages.g.swift b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/FirebaseAppInstallationsMessages.g.swift new file mode 100644 index 000000000000..92048e1c4b6a --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/FirebaseAppInstallationsMessages.g.swift @@ -0,0 +1,465 @@ +// 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 { + "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" + } +} + +private func wrapResult(_ result: Any?) -> [Any?] { + [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 createConnectionError(withChannelName channelName: String) -> PigeonError { + PigeonError( + code: "channel-error", + message: "Unable to establish connection on channel: '\(channelName)'.", + details: "" + ) +} + +private func isNullish(_ value: Any?) -> Bool { + value is NSNull || value == nil +} + +private func nilOrValue(_ value: Any?) -> T? { + if value is NSNull { return nil } + return value as! T? +} + +func deepEqualsFirebaseAppInstallationsMessages(_ 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 !deepEqualsFirebaseAppInstallationsMessages(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 !deepEqualsFirebaseAppInstallationsMessages(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 deepHashFirebaseAppInstallationsMessages(value: Any?, hasher: inout Hasher) { + if let valueList = value as? [AnyHashable] { + for item in valueList { + deepHashFirebaseAppInstallationsMessages(value: item, hasher: &hasher) + } + return + } + + if let valueDict = value as? [AnyHashable: AnyHashable] { + for key in valueDict.keys { + hasher.combine(key) + deepHashFirebaseAppInstallationsMessages(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 AppInstallationsPigeonSettings: Hashable { + var persistenceEnabled: Bool + var forceRefreshOnSignIn: Bool + var forceRefreshOnTokenChange: Bool + var forceRefreshOnAppUpdate: Bool + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> AppInstallationsPigeonSettings? { + let persistenceEnabled = pigeonVar_list[0] as! Bool + let forceRefreshOnSignIn = pigeonVar_list[1] as! Bool + let forceRefreshOnTokenChange = pigeonVar_list[2] as! Bool + let forceRefreshOnAppUpdate = pigeonVar_list[3] as! Bool + + return AppInstallationsPigeonSettings( + persistenceEnabled: persistenceEnabled, + forceRefreshOnSignIn: forceRefreshOnSignIn, + forceRefreshOnTokenChange: forceRefreshOnTokenChange, + forceRefreshOnAppUpdate: forceRefreshOnAppUpdate + ) + } + + func toList() -> [Any?] { + [ + persistenceEnabled, + forceRefreshOnSignIn, + forceRefreshOnTokenChange, + forceRefreshOnAppUpdate, + ] + } + + static func == (lhs: AppInstallationsPigeonSettings, + rhs: AppInstallationsPigeonSettings) -> Bool { + deepEqualsFirebaseAppInstallationsMessages(lhs.toList(), rhs.toList()) + } + + func hash(into hasher: inout Hasher) { + deepHashFirebaseAppInstallationsMessages(value: toList(), hasher: &hasher) + } +} + +/// Generated class from Pigeon that represents data sent in messages. +struct AppInstallationsPigeonFirebaseApp: Hashable { + var appName: String + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> AppInstallationsPigeonFirebaseApp? { + let appName = pigeonVar_list[0] as! String + + return AppInstallationsPigeonFirebaseApp( + appName: appName + ) + } + + func toList() -> [Any?] { + [ + appName, + ] + } + + static func == (lhs: AppInstallationsPigeonFirebaseApp, + rhs: AppInstallationsPigeonFirebaseApp) -> Bool { + deepEqualsFirebaseAppInstallationsMessages(lhs.toList(), rhs.toList()) + } + + func hash(into hasher: inout Hasher) { + deepHashFirebaseAppInstallationsMessages(value: toList(), hasher: &hasher) + } +} + +private class FirebaseAppInstallationsMessagesPigeonCodecReader: FlutterStandardReader { + override func readValue(ofType type: UInt8) -> Any? { + switch type { + case 129: + return AppInstallationsPigeonSettings.fromList(readValue() as! [Any?]) + case 130: + return AppInstallationsPigeonFirebaseApp.fromList(readValue() as! [Any?]) + default: + return super.readValue(ofType: type) + } + } +} + +private class FirebaseAppInstallationsMessagesPigeonCodecWriter: FlutterStandardWriter { + override func writeValue(_ value: Any) { + if let value = value as? AppInstallationsPigeonSettings { + super.writeByte(129) + super.writeValue(value.toList()) + } else if let value = value as? AppInstallationsPigeonFirebaseApp { + super.writeByte(130) + super.writeValue(value.toList()) + } else { + super.writeValue(value) + } + } +} + +private class FirebaseAppInstallationsMessagesPigeonCodecReaderWriter: FlutterStandardReaderWriter { + override func reader(with data: Data) -> FlutterStandardReader { + FirebaseAppInstallationsMessagesPigeonCodecReader(data: data) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + FirebaseAppInstallationsMessagesPigeonCodecWriter(data: data) + } +} + +class FirebaseAppInstallationsMessagesPigeonCodec: FlutterStandardMessageCodec, + @unchecked Sendable { + static let shared = + FirebaseAppInstallationsMessagesPigeonCodec( + readerWriter: FirebaseAppInstallationsMessagesPigeonCodecReaderWriter() + ) +} + +/// Generated protocol from Pigeon that represents a handler of messages from Flutter. +protocol FirebaseAppInstallationsHostApi { + func initializeApp(app: AppInstallationsPigeonFirebaseApp, + settings: AppInstallationsPigeonSettings, + completion: @escaping (Result) -> Void) + func delete(app: AppInstallationsPigeonFirebaseApp, + completion: @escaping (Result) -> Void) + func getId(app: AppInstallationsPigeonFirebaseApp, + completion: @escaping (Result) -> Void) + func getToken(app: AppInstallationsPigeonFirebaseApp, forceRefresh: Bool, + completion: @escaping (Result) -> Void) + func onIdChange(app: AppInstallationsPigeonFirebaseApp, newId: String, + completion: @escaping (Result) -> Void) + func registerIdChangeListener(app: AppInstallationsPigeonFirebaseApp, + completion: @escaping (Result) -> Void) +} + +/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. +class FirebaseAppInstallationsHostApiSetup { + static var codec: FlutterStandardMessageCodec { + FirebaseAppInstallationsMessagesPigeonCodec.shared + } + + /// Sets up an instance of `FirebaseAppInstallationsHostApi` to handle messages through the + /// `binaryMessenger`. + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: FirebaseAppInstallationsHostApi?, + messageChannelSuffix: String = "") { + let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" + let initializeAppChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.initializeApp\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + initializeAppChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let appArg = args[0] as! AppInstallationsPigeonFirebaseApp + let settingsArg = args[1] as! AppInstallationsPigeonSettings + api.initializeApp(app: appArg, settings: settingsArg) { result in + switch result { + case .success: + reply(wrapResult(nil)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + initializeAppChannel.setMessageHandler(nil) + } + let deleteChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.delete\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + deleteChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let appArg = args[0] as! AppInstallationsPigeonFirebaseApp + api.delete(app: appArg) { result in + switch result { + case .success: + reply(wrapResult(nil)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + deleteChannel.setMessageHandler(nil) + } + let getIdChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.getId\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + getIdChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let appArg = args[0] as! AppInstallationsPigeonFirebaseApp + api.getId(app: appArg) { result in + switch result { + case let .success(res): + reply(wrapResult(res)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + getIdChannel.setMessageHandler(nil) + } + let getTokenChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.getToken\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + getTokenChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let appArg = args[0] as! AppInstallationsPigeonFirebaseApp + let forceRefreshArg = args[1] as! Bool + api.getToken(app: appArg, forceRefresh: forceRefreshArg) { result in + switch result { + case let .success(res): + reply(wrapResult(res)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + getTokenChannel.setMessageHandler(nil) + } + let onIdChangeChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.onIdChange\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + onIdChangeChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let appArg = args[0] as! AppInstallationsPigeonFirebaseApp + let newIdArg = args[1] as! String + api.onIdChange(app: appArg, newId: newIdArg) { result in + switch result { + case .success: + reply(wrapResult(nil)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + onIdChangeChannel.setMessageHandler(nil) + } + let registerIdChangeListenerChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.registerIdChangeListener\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + registerIdChangeListenerChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let appArg = args[0] as! AppInstallationsPigeonFirebaseApp + api.registerIdChangeListener(app: appArg) { result in + switch result { + case let .success(res): + reply(wrapResult(res)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + registerIdChangeListenerChannel.setMessageHandler(nil) + } + } +} + +/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift. +protocol FirebaseAppInstallationsFlutterApiProtocol { + func registerIdTokenListener(app appArg: AppInstallationsPigeonFirebaseApp, + completion: @escaping (Result) -> Void) +} + +class FirebaseAppInstallationsFlutterApi: FirebaseAppInstallationsFlutterApiProtocol { + private let binaryMessenger: FlutterBinaryMessenger + private let messageChannelSuffix: String + init(binaryMessenger: FlutterBinaryMessenger, messageChannelSuffix: String = "") { + self.binaryMessenger = binaryMessenger + self.messageChannelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" + } + + var codec: FirebaseAppInstallationsMessagesPigeonCodec { + FirebaseAppInstallationsMessagesPigeonCodec.shared + } + + func registerIdTokenListener(app appArg: AppInstallationsPigeonFirebaseApp, + completion: @escaping (Result) -> Void) { + let channelName = "dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsFlutterApi.registerIdTokenListener\(messageChannelSuffix)" + let channel = FlutterBasicMessageChannel( + name: channelName, + binaryMessenger: binaryMessenger, + codec: codec + ) + channel.sendMessage([appArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else if listResponse[0] == nil { + completion(.failure(PigeonError( + code: "null-error", + message: "Flutter api returned null value for non-null return value.", + details: "" + ))) + } else { + let result = listResponse[0] as! String + completion(.success(result)) + } + } + } +} diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/FirebaseInstallationsPlugin.swift b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/FirebaseInstallationsPlugin.swift index fb9ed2a06894..0c93ac65898d 100644 --- a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/FirebaseInstallationsPlugin.swift +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/FirebaseInstallationsPlugin.swift @@ -17,7 +17,8 @@ import FirebaseInstallations let kFLTFirebaseInstallationsChannelName = "plugins.flutter.io/firebase_app_installations" -public class FirebaseInstallationsPlugin: NSObject, FLTFirebasePluginProtocol, FlutterPlugin { +public class FirebaseInstallationsPlugin: NSObject, FLTFirebasePluginProtocol, + FlutterPlugin, FirebaseAppInstallationsHostApi { private var eventSink: FlutterEventSink? private var messenger: FlutterBinaryMessenger private var streamHandler = [String: IdChangedStreamHandler?]() @@ -42,6 +43,12 @@ public class FirebaseInstallationsPlugin: NSObject, FLTFirebasePluginProtocol, F let instance = FirebaseInstallationsPlugin(messenger: binaryMessenger) FLTFirebasePluginRegistry.sharedInstance().register(instance) registrar.addMethodCallDelegate(instance, channel: channel) + + // Set up Pigeon host API handlers for Dart-side FirebaseAppInstallationsHostApi. + FirebaseAppInstallationsHostApiSetup.setUp( + binaryMessenger: binaryMessenger, + api: instance + ) } public func firebaseLibraryVersion() -> String { @@ -71,6 +78,10 @@ public class FirebaseInstallationsPlugin: NSObject, FLTFirebasePluginProtocol, F return Installations.installations(app: app) } + private func getInstallations(app: AppInstallationsPigeonFirebaseApp) -> Installations { + getInstallations(appName: app.appName) + } + /// Gets Installations Id for an instance. /// - Parameter arguments: the arguments passed by the Dart calling method /// - Parameter result: the result instance used to send the result to Dart. @@ -122,6 +133,88 @@ public class FirebaseInstallationsPlugin: NSObject, FLTFirebasePluginProtocol, F } } + // MARK: - FirebaseAppInstallationsHostApi (Pigeon) + + func initializeApp(app: AppInstallationsPigeonFirebaseApp, + settings: AppInstallationsPigeonSettings, + completion: @escaping (Result) -> Void) { + // Currently no per-app settings are applied on iOS; ensure the instance is created. + _ = getInstallations(app: app) + completion(.success(())) + } + + func delete(app: AppInstallationsPigeonFirebaseApp, + completion: @escaping (Result) -> Void) { + let instance = getInstallations(app: app) + instance.delete { error in + if let error { + completion(.failure(error)) + } else { + completion(.success(())) + } + } + } + + func getId(app: AppInstallationsPigeonFirebaseApp, + completion: @escaping (Result) -> Void) { + let instance = getInstallations(app: app) + instance.installationID { id, error in + if let error { + completion(.failure(error)) + } else if let id { + completion(.success(id)) + } else { + completion(.failure(NSError(domain: "firebase_app_installations", + code: -1, + userInfo: [ + NSLocalizedDescriptionKey: "Installation ID is nil.", + ]))) + } + } + } + + func getToken(app: AppInstallationsPigeonFirebaseApp, + forceRefresh: Bool, + completion: @escaping (Result) -> Void) { + let instance = getInstallations(app: app) + instance.authTokenForcingRefresh(forceRefresh) { tokenResult, error in + if let error { + completion(.failure(error)) + } else if let token = tokenResult?.authToken { + completion(.success(token)) + } else { + completion(.failure(NSError(domain: "firebase_app_installations", + code: -1, + userInfo: [NSLocalizedDescriptionKey: "Auth token is nil."]))) + } + } + } + + func onIdChange(app: AppInstallationsPigeonFirebaseApp, + newId: String, + completion: @escaping (Result) -> Void) { + // The Dart side currently uses an EventChannel-based listener, so this Pigeon hook + // is a no-op placeholder to satisfy the interface. + completion(.success(())) + } + + func registerIdChangeListener(app: AppInstallationsPigeonFirebaseApp, + completion: @escaping (Result) -> Void) { + let instance = getInstallations(app: app) + let appName = app.appName + let eventChannelName = kFLTFirebaseInstallationsChannelName + "/token/" + appName + + let eventChannel = FlutterEventChannel(name: eventChannelName, binaryMessenger: messenger) + + if streamHandler[eventChannelName] == nil { + streamHandler[eventChannelName] = IdChangedStreamHandler(instance: instance) + } + + eventChannel.setStreamHandler(streamHandler[eventChannelName]!) + + completion(.success(eventChannelName)) + } + /// Registers a listener for changes in the Installations Id. /// - Parameter arguments: the arguments passed by the Dart calling method /// - Parameter result: the result instance used to send the result to Dart. diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/firebase_app_installations.h b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/firebase_app_installations.h new file mode 100644 index 000000000000..6fb82f462208 --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/firebase_app_installations.h @@ -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 +// found in the LICENSE file. +// +// Umbrella header for the firebase_app_installations iOS pod. +// Exposes the generated Pigeon APIs to Swift and ObjC consumers. + +#import +#import diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations_objc/firebase_app_installations_messages.g.h b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations_objc/firebase_app_installations_messages.g.h new file mode 100644 index 000000000000..9fb8284f2fef --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations_objc/firebase_app_installations_messages.g.h @@ -0,0 +1,75 @@ +// 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 + +@protocol FlutterBinaryMessenger; +@protocol FlutterMessageCodec; +@class FlutterError; +@class FlutterStandardTypedData; + +NS_ASSUME_NONNULL_BEGIN + +@class AppInstallationsPigeonSettings; +@class AppInstallationsPigeonFirebaseApp; + +@interface AppInstallationsPigeonSettings : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithPersistenceEnabled:(BOOL)persistenceEnabled + forceRefreshOnSignIn:(BOOL)forceRefreshOnSignIn + forceRefreshOnTokenChange:(BOOL)forceRefreshOnTokenChange + forceRefreshOnAppUpdate:(BOOL)forceRefreshOnAppUpdate; +@property(nonatomic, assign) BOOL persistenceEnabled; +@property(nonatomic, assign) BOOL forceRefreshOnSignIn; +@property(nonatomic, assign) BOOL forceRefreshOnTokenChange; +@property(nonatomic, assign) BOOL forceRefreshOnAppUpdate; +@end + +@interface AppInstallationsPigeonFirebaseApp : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithAppName:(NSString *)appName; +@property(nonatomic, copy) NSString *appName; +@end + +/// The codec used by all APIs. +NSObject *nullGetFirebaseAppInstallationsMessagesCodec(void); + +@protocol FirebaseAppInstallationsHostApi +- (void)initializeAppApp:(AppInstallationsPigeonFirebaseApp *)app + settings:(AppInstallationsPigeonSettings *)settings + completion:(void (^)(FlutterError *_Nullable))completion; +- (void)deleteApp:(AppInstallationsPigeonFirebaseApp *)app + completion:(void (^)(FlutterError *_Nullable))completion; +- (void)getIdApp:(AppInstallationsPigeonFirebaseApp *)app + completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; +- (void)getTokenApp:(AppInstallationsPigeonFirebaseApp *)app + forceRefresh:(BOOL)forceRefresh + completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; +- (void)onIdChangeApp:(AppInstallationsPigeonFirebaseApp *)app + newId:(NSString *)newId + completion:(void (^)(FlutterError *_Nullable))completion; +@end + +extern void SetUpFirebaseAppInstallationsHostApi( + id binaryMessenger, + NSObject *_Nullable api); + +extern void SetUpFirebaseAppInstallationsHostApiWithSuffix( + id binaryMessenger, + NSObject *_Nullable api, NSString *messageChannelSuffix); + +@interface FirebaseAppInstallationsFlutterApi : NSObject +- (instancetype)initWithBinaryMessenger:(id)binaryMessenger; +- (instancetype)initWithBinaryMessenger:(id)binaryMessenger + messageChannelSuffix:(nullable NSString *)messageChannelSuffix; +- (void)registerIdTokenListenerApp:(AppInstallationsPigeonFirebaseApp *)app + completion: + (void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations_objc/firebase_app_installations_messages.g.m b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations_objc/firebase_app_installations_messages.g.m new file mode 100644 index 000000000000..2ffd4f9f7bad --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations_objc/firebase_app_installations_messages.g.m @@ -0,0 +1,359 @@ +// 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 "firebase_app_installations_messages.g.h" + +#if TARGET_OS_OSX +#import +#else +#import +#endif + +#if !__has_feature(objc_arc) +#error File requires ARC to be enabled. +#endif + +static NSArray *wrapResult(id result, FlutterError *error) { + if (error) { + return @[ + error.code ?: [NSNull null], error.message ?: [NSNull null], error.details ?: [NSNull null] + ]; + } + return @[ result ?: [NSNull null] ]; +} + +static FlutterError *createConnectionError(NSString *channelName) { + return [FlutterError + errorWithCode:@"channel-error" + message:[NSString stringWithFormat:@"%@/%@/%@", + @"Unable to establish connection on channel: '", + channelName, @"'."] + details:@""]; +} + +static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { + id result = array[key]; + return (result == [NSNull null]) ? nil : result; +} + +@interface AppInstallationsPigeonSettings () ++ (AppInstallationsPigeonSettings *)fromList:(NSArray *)list; ++ (nullable AppInstallationsPigeonSettings *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface AppInstallationsPigeonFirebaseApp () ++ (AppInstallationsPigeonFirebaseApp *)fromList:(NSArray *)list; ++ (nullable AppInstallationsPigeonFirebaseApp *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@implementation AppInstallationsPigeonSettings ++ (instancetype)makeWithPersistenceEnabled:(BOOL)persistenceEnabled + forceRefreshOnSignIn:(BOOL)forceRefreshOnSignIn + forceRefreshOnTokenChange:(BOOL)forceRefreshOnTokenChange + forceRefreshOnAppUpdate:(BOOL)forceRefreshOnAppUpdate { + AppInstallationsPigeonSettings *pigeonResult = [[AppInstallationsPigeonSettings alloc] init]; + pigeonResult.persistenceEnabled = persistenceEnabled; + pigeonResult.forceRefreshOnSignIn = forceRefreshOnSignIn; + pigeonResult.forceRefreshOnTokenChange = forceRefreshOnTokenChange; + pigeonResult.forceRefreshOnAppUpdate = forceRefreshOnAppUpdate; + return pigeonResult; +} ++ (AppInstallationsPigeonSettings *)fromList:(NSArray *)list { + AppInstallationsPigeonSettings *pigeonResult = [[AppInstallationsPigeonSettings alloc] init]; + pigeonResult.persistenceEnabled = [GetNullableObjectAtIndex(list, 0) boolValue]; + pigeonResult.forceRefreshOnSignIn = [GetNullableObjectAtIndex(list, 1) boolValue]; + pigeonResult.forceRefreshOnTokenChange = [GetNullableObjectAtIndex(list, 2) boolValue]; + pigeonResult.forceRefreshOnAppUpdate = [GetNullableObjectAtIndex(list, 3) boolValue]; + return pigeonResult; +} ++ (nullable AppInstallationsPigeonSettings *)nullableFromList:(NSArray *)list { + return (list) ? [AppInstallationsPigeonSettings fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + @(self.persistenceEnabled), + @(self.forceRefreshOnSignIn), + @(self.forceRefreshOnTokenChange), + @(self.forceRefreshOnAppUpdate), + ]; +} +@end + +@implementation AppInstallationsPigeonFirebaseApp ++ (instancetype)makeWithAppName:(NSString *)appName { + AppInstallationsPigeonFirebaseApp *pigeonResult = + [[AppInstallationsPigeonFirebaseApp alloc] init]; + pigeonResult.appName = appName; + return pigeonResult; +} ++ (AppInstallationsPigeonFirebaseApp *)fromList:(NSArray *)list { + AppInstallationsPigeonFirebaseApp *pigeonResult = + [[AppInstallationsPigeonFirebaseApp alloc] init]; + pigeonResult.appName = GetNullableObjectAtIndex(list, 0); + return pigeonResult; +} ++ (nullable AppInstallationsPigeonFirebaseApp *)nullableFromList:(NSArray *)list { + return (list) ? [AppInstallationsPigeonFirebaseApp fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + self.appName ?: [NSNull null], + ]; +} +@end + +@interface nullFirebaseAppInstallationsMessagesPigeonCodecReader : FlutterStandardReader +@end +@implementation nullFirebaseAppInstallationsMessagesPigeonCodecReader +- (nullable id)readValueOfType:(UInt8)type { + switch (type) { + case 129: + return [AppInstallationsPigeonSettings fromList:[self readValue]]; + case 130: + return [AppInstallationsPigeonFirebaseApp fromList:[self readValue]]; + default: + return [super readValueOfType:type]; + } +} +@end + +@interface nullFirebaseAppInstallationsMessagesPigeonCodecWriter : FlutterStandardWriter +@end +@implementation nullFirebaseAppInstallationsMessagesPigeonCodecWriter +- (void)writeValue:(id)value { + if ([value isKindOfClass:[AppInstallationsPigeonSettings class]]) { + [self writeByte:129]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[AppInstallationsPigeonFirebaseApp class]]) { + [self writeByte:130]; + [self writeValue:[value toList]]; + } else { + [super writeValue:value]; + } +} +@end + +@interface nullFirebaseAppInstallationsMessagesPigeonCodecReaderWriter : FlutterStandardReaderWriter +@end +@implementation nullFirebaseAppInstallationsMessagesPigeonCodecReaderWriter +- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data { + return [[nullFirebaseAppInstallationsMessagesPigeonCodecWriter alloc] initWithData:data]; +} +- (FlutterStandardReader *)readerWithData:(NSData *)data { + return [[nullFirebaseAppInstallationsMessagesPigeonCodecReader alloc] initWithData:data]; +} +@end + +NSObject *nullGetFirebaseAppInstallationsMessagesCodec(void) { + static FlutterStandardMessageCodec *sSharedObject = nil; + static dispatch_once_t sPred = 0; + dispatch_once(&sPred, ^{ + nullFirebaseAppInstallationsMessagesPigeonCodecReaderWriter *readerWriter = + [[nullFirebaseAppInstallationsMessagesPigeonCodecReaderWriter alloc] init]; + sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; + }); + return sSharedObject; +} +void SetUpFirebaseAppInstallationsHostApi(id binaryMessenger, + NSObject *api) { + SetUpFirebaseAppInstallationsHostApiWithSuffix(binaryMessenger, api, @""); +} + +void SetUpFirebaseAppInstallationsHostApiWithSuffix(id binaryMessenger, + NSObject *api, + NSString *messageChannelSuffix) { + messageChannelSuffix = messageChannelSuffix.length > 0 + ? [NSString stringWithFormat:@".%@", messageChannelSuffix] + : @""; + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat: + @"%@%@", + @"dev.flutter.pigeon.firebase_app_installations_platform_" + @"interface.FirebaseAppInstallationsHostApi.initializeApp", + messageChannelSuffix] + binaryMessenger:binaryMessenger + codec:nullGetFirebaseAppInstallationsMessagesCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(initializeAppApp:settings:completion:)], + @"FirebaseAppInstallationsHostApi api (%@) doesn't respond to " + @"@selector(initializeAppApp:settings:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + AppInstallationsPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + AppInstallationsPigeonSettings *arg_settings = GetNullableObjectAtIndex(args, 1); + [api initializeAppApp:arg_app + settings:arg_settings + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName: + [NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.firebase_app_installations_platform_" + @"interface.FirebaseAppInstallationsHostApi.delete", + messageChannelSuffix] + binaryMessenger:binaryMessenger + codec:nullGetFirebaseAppInstallationsMessagesCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(deleteApp:completion:)], + @"FirebaseAppInstallationsHostApi api (%@) doesn't respond to " + @"@selector(deleteApp:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + AppInstallationsPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + [api deleteApp:arg_app + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName: + [NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.firebase_app_installations_platform_" + @"interface.FirebaseAppInstallationsHostApi.getId", + messageChannelSuffix] + binaryMessenger:binaryMessenger + codec:nullGetFirebaseAppInstallationsMessagesCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(getIdApp:completion:)], + @"FirebaseAppInstallationsHostApi api (%@) doesn't respond to " + @"@selector(getIdApp:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + AppInstallationsPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + [api getIdApp:arg_app + completion:^(NSString *_Nullable output, FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName: + [NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.firebase_app_installations_platform_" + @"interface.FirebaseAppInstallationsHostApi.getToken", + messageChannelSuffix] + binaryMessenger:binaryMessenger + codec:nullGetFirebaseAppInstallationsMessagesCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(getTokenApp:forceRefresh:completion:)], + @"FirebaseAppInstallationsHostApi api (%@) doesn't respond to " + @"@selector(getTokenApp:forceRefresh:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + AppInstallationsPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + BOOL arg_forceRefresh = [GetNullableObjectAtIndex(args, 1) boolValue]; + [api getTokenApp:arg_app + forceRefresh:arg_forceRefresh + completion:^(NSString *_Nullable output, FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName: + [NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.firebase_app_installations_platform_" + @"interface.FirebaseAppInstallationsHostApi.onIdChange", + messageChannelSuffix] + binaryMessenger:binaryMessenger + codec:nullGetFirebaseAppInstallationsMessagesCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(onIdChangeApp:newId:completion:)], + @"FirebaseAppInstallationsHostApi api (%@) doesn't respond to " + @"@selector(onIdChangeApp:newId:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + AppInstallationsPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_newId = GetNullableObjectAtIndex(args, 1); + [api onIdChangeApp:arg_app + newId:arg_newId + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } +} +@interface FirebaseAppInstallationsFlutterApi () +@property(nonatomic, strong) NSObject *binaryMessenger; +@property(nonatomic, strong) NSString *messageChannelSuffix; +@end + +@implementation FirebaseAppInstallationsFlutterApi + +- (instancetype)initWithBinaryMessenger:(NSObject *)binaryMessenger { + return [self initWithBinaryMessenger:binaryMessenger messageChannelSuffix:@""]; +} +- (instancetype)initWithBinaryMessenger:(NSObject *)binaryMessenger + messageChannelSuffix:(nullable NSString *)messageChannelSuffix { + self = [self init]; + if (self) { + _binaryMessenger = binaryMessenger; + _messageChannelSuffix = [messageChannelSuffix length] == 0 + ? @"" + : [NSString stringWithFormat:@".%@", messageChannelSuffix]; + } + return self; +} +- (void)registerIdTokenListenerApp:(AppInstallationsPigeonFirebaseApp *)arg_app + completion: + (void (^)(NSString *_Nullable, FlutterError *_Nullable))completion { + NSString *channelName = [NSString + stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.firebase_app_installations_platform_interface." + @"FirebaseAppInstallationsFlutterApi.registerIdTokenListener", + _messageChannelSuffix]; + FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel + messageChannelWithName:channelName + binaryMessenger:self.binaryMessenger + codec:nullGetFirebaseAppInstallationsMessagesCodec()]; + [channel sendMessage:@[ arg_app ?: [NSNull null] ] + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSString *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, createConnectionError(channelName)); + } + }]; +} +@end diff --git a/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift b/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift index 751edd05f9c4..75ebb249f6b4 100644 --- a/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift +++ b/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift @@ -100,6 +100,14 @@ let package = Package( // Wrapper dependency .product(name: "firebase-core-shared", package: "flutterfire"), ], + // Exclude Objective-C sources that are used only for CocoaPods/iOS integration. + // The macOS Swift Package target is pure Swift and uses the Swift Pigeon + // types defined in FirebaseAppInstallationsMessages.g.swift instead. + exclude: [ + "Sources/firebase_app_installations/firebase_app_installations.h", + "Sources/firebase_app_installations/firebase_app_installations_messages.g.h", + "Sources/firebase_app_installations/firebase_app_installations_messages.g.m", + ], resources: [ .process("Resources"), ] diff --git a/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Sources/firebase_app_installations/FirebaseAppInstallationsMessages.g.swift b/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Sources/firebase_app_installations/FirebaseAppInstallationsMessages.g.swift new file mode 120000 index 000000000000..3992a0860aab --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Sources/firebase_app_installations/FirebaseAppInstallationsMessages.g.swift @@ -0,0 +1 @@ +../../../../ios/firebase_app_installations/Sources/firebase_app_installations/FirebaseAppInstallationsMessages.g.swift \ No newline at end of file diff --git a/packages/firebase_app_installations/firebase_app_installations/windows/messages.g.cpp b/packages/firebase_app_installations/firebase_app_installations/windows/messages.g.cpp new file mode 100644 index 000000000000..cb19063581cd --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations/windows/messages.g.cpp @@ -0,0 +1,489 @@ +// 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_installations_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("")); +} + +// AppInstallationsPigeonSettings + +AppInstallationsPigeonSettings::AppInstallationsPigeonSettings( + bool persistence_enabled, bool force_refresh_on_sign_in, + bool force_refresh_on_token_change, bool force_refresh_on_app_update) + : persistence_enabled_(persistence_enabled), + force_refresh_on_sign_in_(force_refresh_on_sign_in), + force_refresh_on_token_change_(force_refresh_on_token_change), + force_refresh_on_app_update_(force_refresh_on_app_update) {} + +bool AppInstallationsPigeonSettings::persistence_enabled() const { + return persistence_enabled_; +} + +void AppInstallationsPigeonSettings::set_persistence_enabled(bool value_arg) { + persistence_enabled_ = value_arg; +} + +bool AppInstallationsPigeonSettings::force_refresh_on_sign_in() const { + return force_refresh_on_sign_in_; +} + +void AppInstallationsPigeonSettings::set_force_refresh_on_sign_in( + bool value_arg) { + force_refresh_on_sign_in_ = value_arg; +} + +bool AppInstallationsPigeonSettings::force_refresh_on_token_change() const { + return force_refresh_on_token_change_; +} + +void AppInstallationsPigeonSettings::set_force_refresh_on_token_change( + bool value_arg) { + force_refresh_on_token_change_ = value_arg; +} + +bool AppInstallationsPigeonSettings::force_refresh_on_app_update() const { + return force_refresh_on_app_update_; +} + +void AppInstallationsPigeonSettings::set_force_refresh_on_app_update( + bool value_arg) { + force_refresh_on_app_update_ = value_arg; +} + +EncodableList AppInstallationsPigeonSettings::ToEncodableList() const { + EncodableList list; + list.reserve(4); + list.push_back(EncodableValue(persistence_enabled_)); + list.push_back(EncodableValue(force_refresh_on_sign_in_)); + list.push_back(EncodableValue(force_refresh_on_token_change_)); + list.push_back(EncodableValue(force_refresh_on_app_update_)); + return list; +} + +AppInstallationsPigeonSettings +AppInstallationsPigeonSettings::FromEncodableList(const EncodableList& list) { + AppInstallationsPigeonSettings decoded( + std::get(list[0]), std::get(list[1]), std::get(list[2]), + std::get(list[3])); + return decoded; +} + +// AppInstallationsPigeonFirebaseApp + +AppInstallationsPigeonFirebaseApp::AppInstallationsPigeonFirebaseApp( + const std::string& app_name) + : app_name_(app_name) {} + +const std::string& AppInstallationsPigeonFirebaseApp::app_name() const { + return app_name_; +} + +void AppInstallationsPigeonFirebaseApp::set_app_name( + std::string_view value_arg) { + app_name_ = value_arg; +} + +EncodableList AppInstallationsPigeonFirebaseApp::ToEncodableList() const { + EncodableList list; + list.reserve(1); + list.push_back(EncodableValue(app_name_)); + return list; +} + +AppInstallationsPigeonFirebaseApp +AppInstallationsPigeonFirebaseApp::FromEncodableList( + const EncodableList& list) { + AppInstallationsPigeonFirebaseApp decoded(std::get(list[0])); + return decoded; +} + +PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} + +EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( + uint8_t type, flutter::ByteStreamReader* stream) const { + switch (type) { + case 129: { + return CustomEncodableValue( + AppInstallationsPigeonSettings::FromEncodableList( + std::get(ReadValue(stream)))); + } + case 130: { + return CustomEncodableValue( + AppInstallationsPigeonFirebaseApp::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(AppInstallationsPigeonSettings)) { + stream->WriteByte(129); + WriteValue(EncodableValue(std::any_cast( + *custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(AppInstallationsPigeonFirebaseApp)) { + stream->WriteByte(130); + WriteValue( + EncodableValue( + std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + } + flutter::StandardCodecSerializer::WriteValue(value, stream); +} + +/// The codec used by FirebaseAppInstallationsHostApi. +const flutter::StandardMessageCodec& +FirebaseAppInstallationsHostApi::GetCodec() { + return flutter::StandardMessageCodec::GetInstance( + &PigeonInternalCodecSerializer::GetInstance()); +} + +// Sets up an instance of `FirebaseAppInstallationsHostApi` to handle messages +// through the `binary_messenger`. +void FirebaseAppInstallationsHostApi::SetUp( + flutter::BinaryMessenger* binary_messenger, + FirebaseAppInstallationsHostApi* api) { + FirebaseAppInstallationsHostApi::SetUp(binary_messenger, api, ""); +} + +void FirebaseAppInstallationsHostApi::SetUp( + flutter::BinaryMessenger* binary_messenger, + FirebaseAppInstallationsHostApi* 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_installations_platform_interface." + "FirebaseAppInstallationsHostApi.initializeApp" + + 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_arg = args.at(0); + if (encodable_app_arg.IsNull()) { + reply(WrapError("app_arg unexpectedly null.")); + return; + } + const auto& app_arg = + std::any_cast( + std::get(encodable_app_arg)); + const auto& encodable_settings_arg = args.at(1); + if (encodable_settings_arg.IsNull()) { + reply(WrapError("settings_arg unexpectedly null.")); + return; + } + const auto& settings_arg = + std::any_cast( + std::get(encodable_settings_arg)); + api->InitializeApp(app_arg, settings_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_installations_platform_interface." + "FirebaseAppInstallationsHostApi.delete" + + 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_arg = args.at(0); + if (encodable_app_arg.IsNull()) { + reply(WrapError("app_arg unexpectedly null.")); + return; + } + const auto& app_arg = + std::any_cast( + std::get(encodable_app_arg)); + api->Delete(app_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_installations_platform_interface." + "FirebaseAppInstallationsHostApi.getId" + + 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_arg = args.at(0); + if (encodable_app_arg.IsNull()) { + reply(WrapError("app_arg unexpectedly null.")); + return; + } + const auto& app_arg = + std::any_cast( + std::get(encodable_app_arg)); + api->GetId(app_arg, [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.firebase_app_installations_platform_interface." + "FirebaseAppInstallationsHostApi.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_arg = args.at(0); + if (encodable_app_arg.IsNull()) { + reply(WrapError("app_arg unexpectedly null.")); + return; + } + const auto& app_arg = + std::any_cast( + std::get(encodable_app_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_arg, force_refresh_arg, + [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue( + std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.firebase_app_installations_platform_interface." + "FirebaseAppInstallationsHostApi.onIdChange" + + 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_arg = args.at(0); + if (encodable_app_arg.IsNull()) { + reply(WrapError("app_arg unexpectedly null.")); + return; + } + const auto& app_arg = + std::any_cast( + std::get(encodable_app_arg)); + const auto& encodable_new_id_arg = args.at(1); + if (encodable_new_id_arg.IsNull()) { + reply(WrapError("new_id_arg unexpectedly null.")); + return; + } + const auto& new_id_arg = + std::get(encodable_new_id_arg); + api->OnIdChange(app_arg, new_id_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); + } + } +} + +EncodableValue FirebaseAppInstallationsHostApi::WrapError( + std::string_view error_message) { + return EncodableValue( + EncodableList{EncodableValue(std::string(error_message)), + EncodableValue("Error"), EncodableValue()}); +} + +EncodableValue FirebaseAppInstallationsHostApi::WrapError( + const FlutterError& error) { + return EncodableValue(EncodableList{EncodableValue(error.code()), + EncodableValue(error.message()), + error.details()}); +} + +// Note: The concrete Windows plugin does not yet implement RegisterIdChangeListener; +// this stub keeps the generated HostApi interface in sync with Dart/iOS/Android. + +// Generated class from Pigeon that represents Flutter messages that can be +// called from C++. +FirebaseAppInstallationsFlutterApi::FirebaseAppInstallationsFlutterApi( + flutter::BinaryMessenger* binary_messenger) + : binary_messenger_(binary_messenger), message_channel_suffix_("") {} + +FirebaseAppInstallationsFlutterApi::FirebaseAppInstallationsFlutterApi( + flutter::BinaryMessenger* binary_messenger, + const std::string& message_channel_suffix) + : binary_messenger_(binary_messenger), + message_channel_suffix_(message_channel_suffix.length() > 0 + ? std::string(".") + message_channel_suffix + : "") {} + +const flutter::StandardMessageCodec& +FirebaseAppInstallationsFlutterApi::GetCodec() { + return flutter::StandardMessageCodec::GetInstance( + &PigeonInternalCodecSerializer::GetInstance()); +} + +void FirebaseAppInstallationsFlutterApi::RegisterIdTokenListener( + const AppInstallationsPigeonFirebaseApp& app_arg, + std::function&& on_success, + std::function&& on_error) { + const std::string channel_name = + "dev.flutter.pigeon.firebase_app_installations_platform_interface." + "FirebaseAppInstallationsFlutterApi.registerIdTokenListener" + + message_channel_suffix_; + BasicMessageChannel<> channel(binary_messenger_, channel_name, &GetCodec()); + EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ + CustomEncodableValue(app_arg), + }); + channel.Send( + encoded_api_arguments, [channel_name, on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error( + FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { + const auto& return_value = + std::get(list_return_value->at(0)); + on_success(return_value); + } + } else { + on_error(CreateConnectionError(channel_name)); + } + }); +} + +} // namespace firebase_app_installations_windows diff --git a/packages/firebase_app_installations/firebase_app_installations/windows/messages.g.h b/packages/firebase_app_installations/firebase_app_installations/windows/messages.g.h new file mode 100644 index 000000000000..2d7fe946797c --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations/windows/messages.g.h @@ -0,0 +1,195 @@ +// 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_installations_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 FirebaseAppInstallationsHostApi; + friend class FirebaseAppInstallationsFlutterApi; + ErrorOr() = default; + T TakeValue() && { return std::get(std::move(v_)); } + + std::variant v_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class AppInstallationsPigeonSettings { + public: + // Constructs an object setting all fields. + explicit AppInstallationsPigeonSettings(bool persistence_enabled, + bool force_refresh_on_sign_in, + bool force_refresh_on_token_change, + bool force_refresh_on_app_update); + + bool persistence_enabled() const; + void set_persistence_enabled(bool value_arg); + + bool force_refresh_on_sign_in() const; + void set_force_refresh_on_sign_in(bool value_arg); + + bool force_refresh_on_token_change() const; + void set_force_refresh_on_token_change(bool value_arg); + + bool force_refresh_on_app_update() const; + void set_force_refresh_on_app_update(bool value_arg); + + private: + static AppInstallationsPigeonSettings FromEncodableList( + const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class FirebaseAppInstallationsHostApi; + friend class FirebaseAppInstallationsFlutterApi; + friend class PigeonInternalCodecSerializer; + bool persistence_enabled_; + bool force_refresh_on_sign_in_; + bool force_refresh_on_token_change_; + bool force_refresh_on_app_update_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class AppInstallationsPigeonFirebaseApp { + public: + // Constructs an object setting all fields. + explicit AppInstallationsPigeonFirebaseApp(const std::string& app_name); + + const std::string& app_name() const; + void set_app_name(std::string_view value_arg); + + private: + static AppInstallationsPigeonFirebaseApp FromEncodableList( + const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class FirebaseAppInstallationsHostApi; + friend class FirebaseAppInstallationsFlutterApi; + friend class PigeonInternalCodecSerializer; + std::string app_name_; +}; + +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 FirebaseAppInstallationsHostApi { + public: + FirebaseAppInstallationsHostApi(const FirebaseAppInstallationsHostApi&) = + delete; + FirebaseAppInstallationsHostApi& operator=( + const FirebaseAppInstallationsHostApi&) = delete; + virtual ~FirebaseAppInstallationsHostApi() {} + virtual void InitializeApp( + const AppInstallationsPigeonFirebaseApp& app, + const AppInstallationsPigeonSettings& settings, + std::function reply)> result) = 0; + virtual void Delete( + const AppInstallationsPigeonFirebaseApp& app, + std::function reply)> result) = 0; + virtual void GetId( + const AppInstallationsPigeonFirebaseApp& app, + std::function reply)> result) = 0; + virtual void GetToken( + const AppInstallationsPigeonFirebaseApp& app, bool force_refresh, + std::function reply)> result) = 0; + virtual void OnIdChange( + const AppInstallationsPigeonFirebaseApp& app, const std::string& new_id, + std::function reply)> result) = 0; + virtual void RegisterIdChangeListener( + const AppInstallationsPigeonFirebaseApp& app, + std::function reply)> result) = 0; + + // The codec used by FirebaseAppInstallationsHostApi. + static const flutter::StandardMessageCodec& GetCodec(); + // Sets up an instance of `FirebaseAppInstallationsHostApi` to handle messages + // through the `binary_messenger`. + static void SetUp(flutter::BinaryMessenger* binary_messenger, + FirebaseAppInstallationsHostApi* api); + static void SetUp(flutter::BinaryMessenger* binary_messenger, + FirebaseAppInstallationsHostApi* api, + const std::string& message_channel_suffix); + static flutter::EncodableValue WrapError(std::string_view error_message); + static flutter::EncodableValue WrapError(const FlutterError& error); + + protected: + FirebaseAppInstallationsHostApi() = default; +}; +// Generated class from Pigeon that represents Flutter messages that can be +// called from C++. +class FirebaseAppInstallationsFlutterApi { + public: + FirebaseAppInstallationsFlutterApi( + flutter::BinaryMessenger* binary_messenger); + FirebaseAppInstallationsFlutterApi(flutter::BinaryMessenger* binary_messenger, + const std::string& message_channel_suffix); + static const flutter::StandardMessageCodec& GetCodec(); + void RegisterIdTokenListener( + const AppInstallationsPigeonFirebaseApp& app, + std::function&& on_success, + std::function&& on_error); + + private: + flutter::BinaryMessenger* binary_messenger_; + std::string message_channel_suffix_; +}; + +} // namespace firebase_app_installations_windows +#endif // PIGEON_MESSAGES_G_H_ diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/lib/src/method_channel/method_channel_firebase_app_installations.dart b/packages/firebase_app_installations/firebase_app_installations_platform_interface/lib/src/method_channel/method_channel_firebase_app_installations.dart index 8ab904811d42..544abcb3b951 100644 --- a/packages/firebase_app_installations/firebase_app_installations_platform_interface/lib/src/method_channel/method_channel_firebase_app_installations.dart +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/lib/src/method_channel/method_channel_firebase_app_installations.dart @@ -8,22 +8,21 @@ import 'package:_flutterfire_internals/_flutterfire_internals.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_app_installations_platform_interface/firebase_app_installations_platform_interface.dart'; import 'package:flutter/services.dart'; +import 'package:firebase_app_installations_platform_interface/src/pigeon/messages.pigeon.dart'; import 'utils/exception.dart'; class MethodChannelFirebaseAppInstallations extends FirebaseAppInstallationsPlatform { + final FirebaseAppInstallationsHostApi _api = + FirebaseAppInstallationsHostApi(); + /// Returns a stub instance to allow the platform interface to access /// the class instance statically. static MethodChannelFirebaseAppInstallations get instance { return MethodChannelFirebaseAppInstallations._(); } - /// The [MethodChannelFirebaseFunctions] method channel. - static const MethodChannel channel = MethodChannel( - 'plugins.flutter.io/firebase_app_installations', - ); - static final Map> _idTokenChangesListeners = >{}; @@ -33,11 +32,12 @@ class MethodChannelFirebaseAppInstallations final controller = _idTokenChangesListeners[app.name] = StreamController.broadcast(); - channel.invokeMethod( - 'FirebaseInstallations#registerIdChangeListener', { - 'appName': app.name, - }).then((channelName) { - final events = EventChannel(channelName!, channel.codec); + _api + .registerIdChangeListener( + AppInstallationsPigeonFirebaseApp(appName: app.name), + ) + .then((channelName) { + final events = EventChannel(channelName); events .receiveGuardedBroadcastStream(onError: convertPlatformException) @@ -62,9 +62,9 @@ class MethodChannelFirebaseAppInstallations @override Future delete() async { try { - await channel.invokeMethod('FirebaseInstallations#delete', { - 'appName': app!.name, - }); + await _api.delete( + AppInstallationsPigeonFirebaseApp(appName: app!.name), + ); } catch (e, s) { convertPlatformException(e, s); } @@ -73,12 +73,9 @@ class MethodChannelFirebaseAppInstallations @override Future getId() async { try { - final id = (await channel.invokeMethod( - 'FirebaseInstallations#getId', - {'appName': app!.name}, - ))!; - - return id; + return await _api.getId( + AppInstallationsPigeonFirebaseApp(appName: app!.name), + ); } catch (e, s) { convertPlatformException(e, s); } @@ -87,12 +84,10 @@ class MethodChannelFirebaseAppInstallations @override Future getToken(bool forceRefresh) async { try { - final id = (await channel.invokeMethod( - 'FirebaseInstallations#getToken', - {'appName': app!.name, 'forceRefresh': forceRefresh}, - ))!; - - return id; + return await _api.getToken( + AppInstallationsPigeonFirebaseApp(appName: app!.name), + forceRefresh, + ); } catch (e, s) { convertPlatformException(e, s); } diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/firebase_app_installations/firebase_app_installations_platform_interface/lib/src/pigeon/messages.pigeon.dart new file mode 100644 index 000000000000..11ab74e3ef60 --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -0,0 +1,411 @@ +// 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".', + ); +} + +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + +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 AppInstallationsPigeonSettings { + AppInstallationsPigeonSettings({ + required this.persistenceEnabled, + required this.forceRefreshOnSignIn, + required this.forceRefreshOnTokenChange, + required this.forceRefreshOnAppUpdate, + }); + + bool persistenceEnabled; + + bool forceRefreshOnSignIn; + + bool forceRefreshOnTokenChange; + + bool forceRefreshOnAppUpdate; + + List _toList() { + return [ + persistenceEnabled, + forceRefreshOnSignIn, + forceRefreshOnTokenChange, + forceRefreshOnAppUpdate, + ]; + } + + Object encode() { + return _toList(); + } + + static AppInstallationsPigeonSettings decode(Object result) { + result as List; + return AppInstallationsPigeonSettings( + persistenceEnabled: result[0]! as bool, + forceRefreshOnSignIn: result[1]! as bool, + forceRefreshOnTokenChange: result[2]! as bool, + forceRefreshOnAppUpdate: result[3]! as bool, + ); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! AppInstallationsPigeonSettings || + 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 AppInstallationsPigeonFirebaseApp { + AppInstallationsPigeonFirebaseApp({ + required this.appName, + }); + + String appName; + + List _toList() { + return [ + appName, + ]; + } + + Object encode() { + return _toList(); + } + + static AppInstallationsPigeonFirebaseApp decode(Object result) { + result as List; + return AppInstallationsPigeonFirebaseApp( + appName: result[0]! as String, + ); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! AppInstallationsPigeonFirebaseApp || + 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 AppInstallationsPigeonSettings) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); + } else if (value is AppInstallationsPigeonFirebaseApp) { + buffer.putUint8(130); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 129: + return AppInstallationsPigeonSettings.decode(readValue(buffer)!); + case 130: + return AppInstallationsPigeonFirebaseApp.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +class FirebaseAppInstallationsHostApi { + /// Constructor for [FirebaseAppInstallationsHostApi]. 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. + FirebaseAppInstallationsHostApi( + {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 initializeApp(AppInstallationsPigeonFirebaseApp app, + AppInstallationsPigeonSettings settings) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.initializeApp$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, settings]); + 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 delete(AppInstallationsPigeonFirebaseApp app) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.delete$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + 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 getId(AppInstallationsPigeonFirebaseApp app) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.getId$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + 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?)!; + } + } + + Future getToken( + AppInstallationsPigeonFirebaseApp app, bool forceRefresh) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.getToken$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, 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 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?)!; + } + } + + Future registerIdChangeListener( + AppInstallationsPigeonFirebaseApp app) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.registerIdChangeListener$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + 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?)!; + } + } + + Future onIdChange( + AppInstallationsPigeonFirebaseApp app, String newId) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.onIdChange$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, newId]); + 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; + } + } +} + +abstract class FirebaseAppInstallationsFlutterApi { + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); + + Future registerIdTokenListener(AppInstallationsPigeonFirebaseApp app); + + static void setUp( + FirebaseAppInstallationsFlutterApi? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + { + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsFlutterApi.registerIdTokenListener$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (api == null) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsFlutterApi.registerIdTokenListener was null.'); + final List args = (message as List?)!; + final AppInstallationsPigeonFirebaseApp? arg_app = + (args[0] as AppInstallationsPigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsFlutterApi.registerIdTokenListener was null, expected non-null AppInstallationsPigeonFirebaseApp.'); + try { + final String output = await api.registerIdTokenListener(arg_app!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } +} diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/pigeons/copyright.txt b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pigeons/copyright.txt new file mode 100644 index 000000000000..4e197781c6db --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations_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_installations/firebase_app_installations_platform_interface/pigeons/messages.dart b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pigeons/messages.dart new file mode 100644 index 000000000000..984a99938d1e --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pigeons/messages.dart @@ -0,0 +1,80 @@ +// 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'; + +@ConfigurePigeon( + PigeonOptions( + dartOut: 'lib/src/pigeon/messages.pigeon.dart', + dartTestOut: 'test/pigeon/test_api.dart', + dartPackageName: 'firebase_app_installations_platform_interface', + javaOut: + '../firebase_app_installations/android/src/main/java/io/flutter/plugins/firebase/installations/GeneratedAndroidFirebaseAppInstallations.java', + javaOptions: JavaOptions( + package: 'io.flutter.plugins.firebase.installations', + className: 'GeneratedAndroidFirebaseAppInstallations', + ), + objcHeaderOut: + '../firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/firebase_app_installations_messages.g.h', + objcSourceOut: + '../firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/firebase_app_installations_messages.g.m', + swiftOut: + '../firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/FirebaseAppInstallationsMessages.g.swift', + cppHeaderOut: '../firebase_app_installations/windows/messages.g.h', + cppSourceOut: '../firebase_app_installations/windows/messages.g.cpp', + cppOptions: CppOptions(namespace: 'firebase_app_installations_windows'), + copyrightHeader: 'pigeons/copyright.txt', + ), +) +class AppInstallationsPigeonSettings { + const AppInstallationsPigeonSettings({ + required this.persistenceEnabled, + required this.forceRefreshOnSignIn, + required this.forceRefreshOnTokenChange, + required this.forceRefreshOnAppUpdate, + }); + + final bool persistenceEnabled; + final bool forceRefreshOnSignIn; + final bool forceRefreshOnTokenChange; + final bool forceRefreshOnAppUpdate; +} + +class AppInstallationsPigeonFirebaseApp { + const AppInstallationsPigeonFirebaseApp({ + required this.appName, + }); + + final String appName; +} + +@HostApi(dartHostTestHandler: 'TestFirebaseAppInstallationsHostApi') +abstract class FirebaseAppInstallationsHostApi { + @async + void initializeApp(AppInstallationsPigeonFirebaseApp app, + AppInstallationsPigeonSettings settings); + + @async + void delete(AppInstallationsPigeonFirebaseApp app); + + @async + String getId(AppInstallationsPigeonFirebaseApp app); + + @async + String getToken(AppInstallationsPigeonFirebaseApp app, bool forceRefresh); + + @async + void onIdChange(AppInstallationsPigeonFirebaseApp app, String newId); + + /// Registers an ID change listener on the host and returns the EventChannel name + /// used to stream token changes for the given app. + @async + String registerIdChangeListener(AppInstallationsPigeonFirebaseApp app); +} + +@FlutterApi() +abstract class FirebaseAppInstallationsFlutterApi { + @async + String registerIdTokenListener(AppInstallationsPigeonFirebaseApp app); +} diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml index 15dcc6272874..55722ebfaf47 100644 --- a/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml @@ -21,3 +21,4 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^4.0.0 + pigeon: 25.3.2 \ No newline at end of file diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/test/pigeon/test_api.dart b/packages/firebase_app_installations/firebase_app_installations_platform_interface/test/pigeon/test_api.dart new file mode 100644 index 000000000000..f0779078db24 --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/test/pigeon/test_api.dart @@ -0,0 +1,248 @@ +// 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, unnecessary_import, no_leading_underscores_for_local_identifiers +// ignore_for_file: avoid_relative_lib_imports +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'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:firebase_app_installations_platform_interface/src/pigeon/messages.pigeon.dart'; + +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 AppInstallationsPigeonSettings) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); + } else if (value is AppInstallationsPigeonFirebaseApp) { + buffer.putUint8(130); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 129: + return AppInstallationsPigeonSettings.decode(readValue(buffer)!); + case 130: + return AppInstallationsPigeonFirebaseApp.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +abstract class TestFirebaseAppInstallationsHostApi { + static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => + TestDefaultBinaryMessengerBinding.instance; + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); + + Future initializeApp(AppInstallationsPigeonFirebaseApp app, + AppInstallationsPigeonSettings settings); + + Future delete(AppInstallationsPigeonFirebaseApp app); + + Future getId(AppInstallationsPigeonFirebaseApp app); + + Future getToken( + AppInstallationsPigeonFirebaseApp app, bool forceRefresh); + + Future onIdChange(AppInstallationsPigeonFirebaseApp app, String newId); + + static void setUp( + TestFirebaseAppInstallationsHostApi? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + { + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.initializeApp$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.initializeApp was null.'); + final List args = (message as List?)!; + final AppInstallationsPigeonFirebaseApp? arg_app = + (args[0] as AppInstallationsPigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.initializeApp was null, expected non-null AppInstallationsPigeonFirebaseApp.'); + final AppInstallationsPigeonSettings? arg_settings = + (args[1] as AppInstallationsPigeonSettings?); + assert(arg_settings != null, + 'Argument for dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.initializeApp was null, expected non-null AppInstallationsPigeonSettings.'); + try { + await api.initializeApp(arg_app!, arg_settings!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + { + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.delete$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.delete was null.'); + final List args = (message as List?)!; + final AppInstallationsPigeonFirebaseApp? arg_app = + (args[0] as AppInstallationsPigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.delete was null, expected non-null AppInstallationsPigeonFirebaseApp.'); + try { + await api.delete(arg_app!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + { + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.getId$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.getId was null.'); + final List args = (message as List?)!; + final AppInstallationsPigeonFirebaseApp? arg_app = + (args[0] as AppInstallationsPigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.getId was null, expected non-null AppInstallationsPigeonFirebaseApp.'); + try { + final String output = await api.getId(arg_app!); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + { + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.getToken$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.getToken was null.'); + final List args = (message as List?)!; + final AppInstallationsPigeonFirebaseApp? arg_app = + (args[0] as AppInstallationsPigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.getToken was null, expected non-null AppInstallationsPigeonFirebaseApp.'); + final bool? arg_forceRefresh = (args[1] as bool?); + assert(arg_forceRefresh != null, + 'Argument for dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.getToken was null, expected non-null bool.'); + try { + final String output = + await api.getToken(arg_app!, arg_forceRefresh!); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + { + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.onIdChange$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(pigeonVar_channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.onIdChange was null.'); + final List args = (message as List?)!; + final AppInstallationsPigeonFirebaseApp? arg_app = + (args[0] as AppInstallationsPigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.onIdChange was null, expected non-null AppInstallationsPigeonFirebaseApp.'); + final String? arg_newId = (args[1] as String?); + assert(arg_newId != null, + 'Argument for dev.flutter.pigeon.firebase_app_installations_platform_interface.FirebaseAppInstallationsHostApi.onIdChange was null, expected non-null String.'); + try { + await api.onIdChange(arg_app!, arg_newId!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } +}