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..3535e8dda82f --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations/android/src/main/java/io/flutter/plugins/firebase/installations/GeneratedAndroidFirebaseAppInstallations.java @@ -0,0 +1,553 @@ +// 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.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +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); + + /** 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); + } + } + } + } + /** 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..18abcbfb7f1a 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 @@ -21,13 +21,19 @@ 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 { + implements FlutterFirebasePlugin, + FlutterPlugin, + MethodCallHandler, + GeneratedAndroidFirebaseAppInstallations.FirebaseAppInstallationsHostApi { private MethodChannel channel; private static final String METHOD_CHANNEL_NAME = "plugins.flutter.io/firebase_app_installations"; private final Map streamHandlers = new HashMap<>(); @@ -38,6 +44,9 @@ private MethodChannel setup(BinaryMessenger binaryMessenger) { final MethodChannel channel = new MethodChannel(binaryMessenger, METHOD_CHANNEL_NAME); channel.setMethodCallHandler(this); this.messenger = binaryMessenger; + // Set up Pigeon host API handlers. + GeneratedAndroidFirebaseAppInstallations.FirebaseAppInstallationsHostApi.setUp( + binaryMessenger, this); return channel; } @@ -64,6 +73,12 @@ private FirebaseInstallations getInstallations(Map arguments) { return FirebaseInstallations.getInstance(app); } + 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<>(); @@ -145,6 +160,85 @@ private Task deleteId(Map arguments) { return taskCompletionSource.getTask(); } + // 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 { + // Touch the instance to ensure it's initialized. + getInstallations(app); + result.success(); + } catch (Exception e) { + result.error(e); + } + }); + } + + @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(e); + } + }); + } + + @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(e); + } + }); + } + + @Override + public void getToken( + @NonNull AppInstallationsPigeonFirebaseApp app, + @NonNull Boolean forceRefresh, + @NonNull GeneratedAndroidFirebaseAppInstallations.Result result) { + cachedThreadPool.execute( + () -> { + try { + FirebaseInstallations firebaseInstallations = getInstallations(app); + InstallationTokenResult tokenResult = + Tasks.await(firebaseInstallations.getToken(forceRefresh)); + result.success(tokenResult.getToken()); + } catch (Exception e) { + result.error(e); + } + }); + } + + @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 onMethodCall(@NonNull MethodCall call, @NonNull Result result) { Task methodCallTask; 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..610ce415e688 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/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/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..02c6767391e3 --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/FirebaseAppInstallationsMessages.g.swift @@ -0,0 +1,382 @@ +// Copyright 2025, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +import Foundation + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + +/// Error class for passing custom error details to Dart side. +final class PigeonError: Error { + let code: String + let message: String? + let details: Sendable? + + init(code: String, message: String?, details: Sendable?) { + self.code = code + self.message = message + self.details = details + } + + var localizedDescription: String { + return + "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" + } +} + +private func wrapResult(_ result: Any?) -> [Any?] { + return [result] +} + +private func wrapError(_ error: Any) -> [Any?] { + if let pigeonError = error as? PigeonError { + return [ + pigeonError.code, + pigeonError.message, + pigeonError.details, + ] + } + if let flutterError = error as? FlutterError { + return [ + flutterError.code, + flutterError.message, + flutterError.details, + ] + } + return [ + "\(error)", + "\(type(of: error))", + "Stacktrace: \(Thread.callStackSymbols)", + ] +} + +private func createConnectionError(withChannelName channelName: String) -> PigeonError { + return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") +} + +private func isNullish(_ value: Any?) -> Bool { + return value is NSNull || value == nil +} + +private func nilOrValue(_ value: Any?) -> T? { + if value is NSNull { return nil } + return value as! T? +} + +func 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?] { + return [ + persistenceEnabled, + forceRefreshOnSignIn, + forceRefreshOnTokenChange, + forceRefreshOnAppUpdate, + ] + } + static func == (lhs: AppInstallationsPigeonSettings, rhs: AppInstallationsPigeonSettings) -> Bool { + return 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?] { + return [ + appName + ] + } + static func == (lhs: AppInstallationsPigeonFirebaseApp, rhs: AppInstallationsPigeonFirebaseApp) -> Bool { + return 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(self.readValue() as! [Any?]) + case 130: + return AppInstallationsPigeonFirebaseApp.fromList(self.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 { + return FirebaseAppInstallationsMessagesPigeonCodecReader(data: data) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + return 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) +} + +/// 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 = 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 .failure(let 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 = 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 .failure(let 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 = 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 .success(let res): + reply(wrapResult(res)) + case .failure(let 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 = 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 .success(let res): + reply(wrapResult(res)) + case .failure(let 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 = 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 .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + onIdChangeChannel.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 { + return FirebaseAppInstallationsMessagesPigeonCodec.shared + } + func registerIdTokenListener(app appArg: AppInstallationsPigeonFirebaseApp, completion: @escaping (Result) -> Void) { + let channelName: String = "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..a9a56db1ae8c 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,9 @@ 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. + SetUpFirebaseAppInstallationsHostApi(binaryMessenger, instance) } public func firebaseLibraryVersion() -> String { @@ -71,6 +75,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 +130,79 @@ 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 = 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 = error { + completion(.failure(error)) + } else if let id = 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 = 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(())) + } + /// 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..82fa063d3df0 --- /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,7 @@ +// 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/firebase_app_installations_messages.g.h b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/firebase_app_installations_messages.g.h new file mode 100644 index 000000000000..45f075ab07ad --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/firebase_app_installations_messages.g.h @@ -0,0 +1,61 @@ +// 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/firebase_app_installations_messages.g.m b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/firebase_app_installations_messages.g.m new file mode 100644 index 000000000000..504ed4fef493 --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/firebase_app_installations_messages.g.m @@ -0,0 +1,298 @@ +// 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/windows/messages.g.cpp b/packages/firebase_app_installations/firebase_app_installations/windows/messages.g.cpp new file mode 100644 index 000000000000..d9ee0205e5ec --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations/windows/messages.g.cpp @@ -0,0 +1,403 @@ +// 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() + }); +} + +// 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..a64ac343c764 --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations/windows/messages.g.h @@ -0,0 +1,193 @@ +// 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; + + // 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..b9e37385dd00 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,11 +8,13 @@ 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 { @@ -62,9 +64,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 +75,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 +86,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..5f082a02172a --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -0,0 +1,346 @@ +// 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 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 pigeonVar_channel = BasicMessageChannel( + '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..4e1f9378583d --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pigeons/messages.dart @@ -0,0 +1,74 @@ +// 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); +} + +@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..fc63484a77a8 --- /dev/null +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/test/pigeon/test_api.dart @@ -0,0 +1,199 @@ +// 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 pigeonVar_channel = BasicMessageChannel( + '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 pigeonVar_channel = BasicMessageChannel( + '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 pigeonVar_channel = BasicMessageChannel( + '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 pigeonVar_channel = BasicMessageChannel( + '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 pigeonVar_channel = BasicMessageChannel( + '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())); + } + }); + } + } + } +}