diff --git a/.github/workflows/windows.yaml b/.github/workflows/windows.yaml index ff82836a8a18..1783aa967913 100644 --- a/.github/workflows/windows.yaml +++ b/.github/workflows/windows.yaml @@ -56,7 +56,7 @@ jobs: - name: "Build Windows (Release)" run: cd tests && flutter build windows --release - name: Start Firebase Emulator and run tests - run: cd ./.github/workflows/scripts && firebase emulators:exec --project flutterfire-e2e-tests "cd ../../../tests && flutter test .\integration_test\e2e_test.dart -d windows" + run: cd ./.github/workflows/scripts && firebase emulators:exec --project flutterfire-e2e-tests "cd ../../../tests && flutter test .\integration_test\e2e_test.dart -d windows --verbose" # We cannot run the tests but we can still try to build the app because of https://github.com/flutter/flutter/issues/79213 windows-firestore: diff --git a/packages/firebase_core/firebase_core/windows/CMakeLists.txt b/packages/firebase_core/firebase_core/windows/CMakeLists.txt index b5d1fce438e1..d944944c8c8a 100644 --- a/packages/firebase_core/firebase_core/windows/CMakeLists.txt +++ b/packages/firebase_core/firebase_core/windows/CMakeLists.txt @@ -122,7 +122,7 @@ add_subdirectory(${FIREBASE_CPP_SDK_DIR} bin/ EXCLUDE_FROM_ALL) target_include_directories(${PLUGIN_NAME} INTERFACE "${FIREBASE_CPP_SDK_DIR}/include") -set(FIREBASE_RELEASE_PATH_LIBS firebase_app firebase_auth firebase_remote_config firebase_storage firebase_firestore) +set(FIREBASE_RELEASE_PATH_LIBS firebase_app firebase_auth firebase_remote_config firebase_storage firebase_firestore firebase_database) foreach(firebase_lib IN ITEMS ${FIREBASE_RELEASE_PATH_LIBS}) get_target_property(firebase_lib_path ${firebase_lib} IMPORTED_LOCATION) string(REPLACE "Debug" "Release" firebase_lib_release_path ${firebase_lib_path}) diff --git a/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FirebaseDatabaseMessages.g.swift b/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FirebaseDatabaseMessages.g.swift index 174bb8cfc69b..e91097627f7e 100644 --- a/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FirebaseDatabaseMessages.g.swift +++ b/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FirebaseDatabaseMessages.g.swift @@ -59,7 +59,8 @@ private func wrapError(_ error: Any) -> [Any?] { private func createConnectionError(withChannelName channelName: String) -> PigeonError { PigeonError( - code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", + code: "channel-error", + message: "Unable to establish connection on channel: '\(channelName)'.", details: "" ) } @@ -490,9 +491,10 @@ private class FirebaseDatabaseMessagesPigeonCodecReaderWriter: FlutterStandardRe } class FirebaseDatabaseMessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = FirebaseDatabaseMessagesPigeonCodec( - readerWriter: FirebaseDatabaseMessagesPigeonCodecReaderWriter() - ) + static let shared = + FirebaseDatabaseMessagesPigeonCodec( + readerWriter: FirebaseDatabaseMessagesPigeonCodecReaderWriter() + ) } /// Generated protocol from Pigeon that represents a handler of messages from Flutter. @@ -558,9 +560,9 @@ class FirebaseDatabaseHostApiSetup { messageChannelSuffix: String = "") { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" let goOnlineChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOnline\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOnline\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { goOnlineChannel.setMessageHandler { message, reply in @@ -579,9 +581,9 @@ class FirebaseDatabaseHostApiSetup { goOnlineChannel.setMessageHandler(nil) } let goOfflineChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOffline\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOffline\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { goOfflineChannel.setMessageHandler { message, reply in @@ -600,9 +602,9 @@ class FirebaseDatabaseHostApiSetup { goOfflineChannel.setMessageHandler(nil) } let setPersistenceEnabledChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceEnabled\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceEnabled\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { setPersistenceEnabledChannel.setMessageHandler { message, reply in @@ -622,9 +624,9 @@ class FirebaseDatabaseHostApiSetup { setPersistenceEnabledChannel.setMessageHandler(nil) } let setPersistenceCacheSizeBytesChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceCacheSizeBytes\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceCacheSizeBytes\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { setPersistenceCacheSizeBytesChannel.setMessageHandler { message, reply in @@ -644,9 +646,9 @@ class FirebaseDatabaseHostApiSetup { setPersistenceCacheSizeBytesChannel.setMessageHandler(nil) } let setLoggingEnabledChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setLoggingEnabled\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setLoggingEnabled\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { setLoggingEnabledChannel.setMessageHandler { message, reply in @@ -666,9 +668,9 @@ class FirebaseDatabaseHostApiSetup { setLoggingEnabledChannel.setMessageHandler(nil) } let useDatabaseEmulatorChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.useDatabaseEmulator\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.useDatabaseEmulator\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { useDatabaseEmulatorChannel.setMessageHandler { message, reply in @@ -689,9 +691,9 @@ class FirebaseDatabaseHostApiSetup { useDatabaseEmulatorChannel.setMessageHandler(nil) } let refChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.ref\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.ref\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { refChannel.setMessageHandler { message, reply in @@ -711,9 +713,9 @@ class FirebaseDatabaseHostApiSetup { refChannel.setMessageHandler(nil) } let refFromURLChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.refFromURL\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.refFromURL\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { refFromURLChannel.setMessageHandler { message, reply in @@ -733,9 +735,9 @@ class FirebaseDatabaseHostApiSetup { refFromURLChannel.setMessageHandler(nil) } let purgeOutstandingWritesChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.purgeOutstandingWrites\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.purgeOutstandingWrites\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { purgeOutstandingWritesChannel.setMessageHandler { message, reply in @@ -754,9 +756,9 @@ class FirebaseDatabaseHostApiSetup { purgeOutstandingWritesChannel.setMessageHandler(nil) } let databaseReferenceSetChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSet\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSet\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { databaseReferenceSetChannel.setMessageHandler { message, reply in @@ -776,9 +778,9 @@ class FirebaseDatabaseHostApiSetup { databaseReferenceSetChannel.setMessageHandler(nil) } let databaseReferenceSetWithPriorityChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetWithPriority\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetWithPriority\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { databaseReferenceSetWithPriorityChannel.setMessageHandler { message, reply in @@ -798,9 +800,9 @@ class FirebaseDatabaseHostApiSetup { databaseReferenceSetWithPriorityChannel.setMessageHandler(nil) } let databaseReferenceUpdateChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceUpdate\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceUpdate\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { databaseReferenceUpdateChannel.setMessageHandler { message, reply in @@ -820,9 +822,9 @@ class FirebaseDatabaseHostApiSetup { databaseReferenceUpdateChannel.setMessageHandler(nil) } let databaseReferenceSetPriorityChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetPriority\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetPriority\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { databaseReferenceSetPriorityChannel.setMessageHandler { message, reply in @@ -842,9 +844,9 @@ class FirebaseDatabaseHostApiSetup { databaseReferenceSetPriorityChannel.setMessageHandler(nil) } let databaseReferenceRunTransactionChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceRunTransaction\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceRunTransaction\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { databaseReferenceRunTransactionChannel.setMessageHandler { message, reply in @@ -864,32 +866,33 @@ class FirebaseDatabaseHostApiSetup { databaseReferenceRunTransactionChannel.setMessageHandler(nil) } let databaseReferenceGetTransactionResultChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceGetTransactionResult\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceGetTransactionResult\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { databaseReferenceGetTransactionResultChannel.setMessageHandler { message, reply in let args = message as! [Any?] let appArg = args[0] as! DatabasePigeonFirebaseApp let transactionKeyArg = args[1] as! Int64 - api.databaseReferenceGetTransactionResult(app: appArg, transactionKey: transactionKeyArg) { - result in - switch result { - case let .success(res): - reply(wrapResult(res)) - case let .failure(error): - reply(wrapError(error)) + api + .databaseReferenceGetTransactionResult(app: appArg, + transactionKey: transactionKeyArg) { result in + switch result { + case let .success(res): + reply(wrapResult(res)) + case let .failure(error): + reply(wrapError(error)) + } } - } } } else { databaseReferenceGetTransactionResultChannel.setMessageHandler(nil) } let onDisconnectSetChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSet\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSet\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { onDisconnectSetChannel.setMessageHandler { message, reply in @@ -909,9 +912,9 @@ class FirebaseDatabaseHostApiSetup { onDisconnectSetChannel.setMessageHandler(nil) } let onDisconnectSetWithPriorityChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSetWithPriority\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSetWithPriority\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { onDisconnectSetWithPriorityChannel.setMessageHandler { message, reply in @@ -931,9 +934,9 @@ class FirebaseDatabaseHostApiSetup { onDisconnectSetWithPriorityChannel.setMessageHandler(nil) } let onDisconnectUpdateChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectUpdate\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectUpdate\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { onDisconnectUpdateChannel.setMessageHandler { message, reply in @@ -953,9 +956,9 @@ class FirebaseDatabaseHostApiSetup { onDisconnectUpdateChannel.setMessageHandler(nil) } let onDisconnectCancelChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectCancel\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectCancel\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { onDisconnectCancelChannel.setMessageHandler { message, reply in @@ -975,9 +978,9 @@ class FirebaseDatabaseHostApiSetup { onDisconnectCancelChannel.setMessageHandler(nil) } let queryObserveChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryObserve\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryObserve\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { queryObserveChannel.setMessageHandler { message, reply in @@ -997,9 +1000,9 @@ class FirebaseDatabaseHostApiSetup { queryObserveChannel.setMessageHandler(nil) } let queryKeepSyncedChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryKeepSynced\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryKeepSynced\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { queryKeepSyncedChannel.setMessageHandler { message, reply in @@ -1019,9 +1022,9 @@ class FirebaseDatabaseHostApiSetup { queryKeepSyncedChannel.setMessageHandler(nil) } let queryGetChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryGet\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec + name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryGet\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec ) if let api { queryGetChannel.setMessageHandler { message, reply in @@ -1067,10 +1070,11 @@ class FirebaseDatabaseFlutterApi: FirebaseDatabaseFlutterApiProtocol { snapshotValue snapshotValueArg: Any?, completion: @escaping (Result) -> Void) { - let channelName = - "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseFlutterApi.callTransactionHandler\(messageChannelSuffix)" + let channelName = "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseFlutterApi.callTransactionHandler\(messageChannelSuffix)" let channel = FlutterBasicMessageChannel( - name: channelName, binaryMessenger: binaryMessenger, codec: codec + name: channelName, + binaryMessenger: binaryMessenger, + codec: codec ) channel.sendMessage([transactionKeyArg, snapshotValueArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { @@ -1083,14 +1087,11 @@ class FirebaseDatabaseFlutterApi: FirebaseDatabaseFlutterApiProtocol { 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: "" - ) - ) - ) + completion(.failure(PigeonError( + code: "null-error", + message: "Flutter api returned null value for non-null return value.", + details: "" + ))) } else { let result = listResponse[0] as! TransactionHandlerResult completion(.success(result)) diff --git a/packages/firebase_database/firebase_database/pubspec.yaml b/packages/firebase_database/firebase_database/pubspec.yaml index 708d05cfe5ac..abbe7eb8e522 100755 --- a/packages/firebase_database/firebase_database/pubspec.yaml +++ b/packages/firebase_database/firebase_database/pubspec.yaml @@ -39,5 +39,7 @@ flutter: pluginClass: FLTFirebaseDatabasePlugin macos: pluginClass: FLTFirebaseDatabasePlugin + windows: + pluginClass: FirebaseDatabasePluginCApi web: default_package: firebase_database_web diff --git a/packages/firebase_database/firebase_database/windows/CMakeLists.txt b/packages/firebase_database/firebase_database/windows/CMakeLists.txt new file mode 100644 index 000000000000..b85c61d20594 --- /dev/null +++ b/packages/firebase_database/firebase_database/windows/CMakeLists.txt @@ -0,0 +1,60 @@ +cmake_minimum_required(VERSION 3.14) + +set(PROJECT_NAME "flutterfire_database") +project(${PROJECT_NAME} LANGUAGES CXX) + +set(PLUGIN_NAME "firebase_database_plugin") + +list(APPEND PLUGIN_SOURCES + "firebase_database_plugin.cpp" + "firebase_database_plugin.h" + "messages.g.cpp" + "messages.g.h" +) + +# Read version from pubspec.yaml +file(STRINGS "../pubspec.yaml" pubspec_content) +foreach(line ${pubspec_content}) + string(FIND ${line} "version: " has_version) + + if("${has_version}" STREQUAL "0") + string(FIND ${line} ": " version_start_pos) + math(EXPR version_start_pos "${version_start_pos} + 2") + string(LENGTH ${line} version_end_pos) + math(EXPR len "${version_end_pos} - ${version_start_pos}") + string(SUBSTRING ${line} ${version_start_pos} ${len} PLUGIN_VERSION) + break() + endif() +endforeach(line) + +configure_file(plugin_version.h.in ${CMAKE_BINARY_DIR}/generated/firebase_database/plugin_version.h) +include_directories(${CMAKE_BINARY_DIR}/generated/) + +add_library(${PLUGIN_NAME} STATIC + "include/firebase_database/firebase_database_plugin_c_api.h" + "firebase_database_plugin_c_api.cpp" + ${PLUGIN_SOURCES} + ${CMAKE_BINARY_DIR}/generated/firebase_database/plugin_version.h +) + +apply_standard_settings(${PLUGIN_NAME}) + +set_target_properties(${PLUGIN_NAME} PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_compile_definitions(${PLUGIN_NAME} PUBLIC FLUTTER_PLUGIN_IMPL) +target_compile_definitions(${PLUGIN_NAME} PRIVATE -DINTERNAL_EXPERIMENTAL=1) + +set(MSVC_RUNTIME_MODE MD) +set(firebase_libs firebase_core_plugin firebase_database) +set(ADDITIONAL_LIBS advapi32 ws2_32 crypt32 rpcrt4 ole32 shell32 Bcrypt.lib DbgHelp.lib) +set(RTDB_ADDITIONAL_LIBS iphlpapi psapi userenv) +target_link_libraries(${PLUGIN_NAME} PRIVATE "${firebase_libs}" "${ADDITIONAL_LIBS}" "${RTDB_ADDITIONAL_LIBS}") + +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin) + +set(firebase_database_bundled_libraries + "" + PARENT_SCOPE +) diff --git a/packages/firebase_database/firebase_database/windows/firebase_database_plugin.cpp b/packages/firebase_database/firebase_database/windows/firebase_database_plugin.cpp new file mode 100644 index 000000000000..f523a86ffe59 --- /dev/null +++ b/packages/firebase_database/firebase_database/windows/firebase_database_plugin.cpp @@ -0,0 +1,1123 @@ +// 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. + +#include "firebase_database_plugin.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "firebase/app.h" +#include "firebase/database.h" +#include "firebase/database/common.h" +#include "firebase/database/data_snapshot.h" +#include "firebase/database/database_reference.h" +#include "firebase/database/disconnection.h" +#include "firebase/database/listener.h" +#include "firebase/database/mutable_data.h" +#include "firebase/database/query.h" +#include "firebase/future.h" +#include "firebase/log.h" +#include "firebase/variant.h" +#include "firebase_database/plugin_version.h" +#include "messages.g.h" + +using firebase::App; +using firebase::Future; +using firebase::Variant; +using firebase::database::Database; +using firebase::database::DatabaseReference; +using firebase::database::DataSnapshot; +using firebase::database::Error; +using firebase::database::MutableData; +using firebase::database::TransactionResult; +using flutter::EncodableList; +using flutter::EncodableMap; +using flutter::EncodableValue; + +namespace firebase_database_windows { + +static const std::string kLibraryName = "flutter-fire-db"; + +// Static member initialization +flutter::BinaryMessenger* FirebaseDatabasePlugin::messenger_ = nullptr; +std::map>> + FirebaseDatabasePlugin::event_channels_; +std::map>> + FirebaseDatabasePlugin::stream_handlers_; +std::map + FirebaseDatabasePlugin::database_instances_; + +// atexit handler: clean up Database resources before static destruction. +// 1. Clear event channels to trigger StreamHandler destruction, which +// unregisters listeners from the Database while it's still alive. +// 2. Call GoOffline() to close WebSocket connections so thread joins +// during App::~App() → Database::DeleteInternal() complete quickly. +static void CleanupBeforeStaticDestruction() { + // Destroy event channels and stream handlers first. This triggers + // StreamHandler destructors which call RemoveValueListener / + // RemoveChildListener while the Database is still valid. + FirebaseDatabasePlugin::event_channels_.clear(); + FirebaseDatabasePlugin::stream_handlers_.clear(); + + // Disconnect all Database instances to close WebSocket connections. + for (auto& pair : FirebaseDatabasePlugin::database_instances_) { + if (pair.second) { + pair.second->GoOffline(); + } + } + // Give the scheduler thread time to process GoOffline callbacks. + std::this_thread::sleep_for(std::chrono::milliseconds(100)); +} + +// --- Helper: Register an EventChannel with a generated name --- +static std::string RegisterEventChannel( + const std::string& prefix, + std::unique_ptr> handler) { + static int channel_counter = 0; + std::string channelName = + prefix + std::to_string(channel_counter++) + "_" + + std::to_string( + std::chrono::system_clock::now().time_since_epoch().count()); + + FirebaseDatabasePlugin::event_channels_[channelName] = + std::make_unique>( + FirebaseDatabasePlugin::messenger_, channelName, + &flutter::StandardMethodCodec::GetInstance()); + FirebaseDatabasePlugin::stream_handlers_[channelName] = std::move(handler); + FirebaseDatabasePlugin::event_channels_[channelName]->SetStreamHandler( + std::move(FirebaseDatabasePlugin::stream_handlers_[channelName])); + return channelName; +} + +// --- Helper: Convert firebase::Variant to flutter::EncodableValue --- +EncodableValue FirebaseDatabasePlugin::VariantToEncodableValue( + const Variant& variant) { + switch (variant.type()) { + case Variant::kTypeNull: + return EncodableValue(); + case Variant::kTypeInt64: + return EncodableValue(variant.int64_value()); + case Variant::kTypeDouble: + return EncodableValue(variant.double_value()); + case Variant::kTypeBool: + return EncodableValue(variant.bool_value()); + case Variant::kTypeStaticString: + return EncodableValue(std::string(variant.string_value())); + case Variant::kTypeMutableString: + return EncodableValue(variant.mutable_string()); + case Variant::kTypeVector: { + EncodableList list; + for (const auto& item : variant.vector()) { + list.push_back(VariantToEncodableValue(item)); + } + return EncodableValue(list); + } + case Variant::kTypeMap: { + EncodableMap map; + for (const auto& kv : variant.map()) { + EncodableValue key = VariantToEncodableValue(kv.first); + EncodableValue value = VariantToEncodableValue(kv.second); + map[key] = value; + } + return EncodableValue(map); + } + case Variant::kTypeStaticBlob: { + std::vector blob(variant.blob_data(), + variant.blob_data() + variant.blob_size()); + return EncodableValue(blob); + } + case Variant::kTypeMutableBlob: { + std::vector blob( + variant.mutable_blob_data(), + variant.mutable_blob_data() + variant.blob_size()); + return EncodableValue(blob); + } + default: + return EncodableValue(); + } +} + +// --- Helper: Convert flutter::EncodableValue to firebase::Variant --- +Variant FirebaseDatabasePlugin::EncodableValueToVariant( + const EncodableValue& value) { + if (std::holds_alternative(value)) { + return Variant::Null(); + } else if (std::holds_alternative(value)) { + return Variant(std::get(value)); + } else if (std::holds_alternative(value)) { + return Variant(static_cast(std::get(value))); + } else if (std::holds_alternative(value)) { + return Variant(std::get(value)); + } else if (std::holds_alternative(value)) { + return Variant(std::get(value)); + } else if (std::holds_alternative(value)) { + return Variant(std::get(value)); + } else if (std::holds_alternative>(value)) { + const auto& blob = std::get>(value); + return Variant::FromMutableBlob(blob.data(), blob.size()); + } else if (std::holds_alternative(value)) { + const auto& list = std::get(value); + std::vector vec; + vec.reserve(list.size()); + for (const auto& item : list) { + vec.push_back(EncodableValueToVariant(item)); + } + return Variant(vec); + } else if (std::holds_alternative(value)) { + const auto& map = std::get(value); + std::map variant_map; + for (const auto& kv : map) { + variant_map[EncodableValueToVariant(kv.first)] = + EncodableValueToVariant(kv.second); + } + return Variant(variant_map); + } + return Variant::Null(); +} + +// --- Helper: Error code string from C++ SDK Error enum --- +std::string FirebaseDatabasePlugin::GetDatabaseErrorCode(Error error) { + switch (error) { + case Error::kErrorNone: + return "none"; + case Error::kErrorDisconnected: + return "disconnected"; + case Error::kErrorExpiredToken: + return "expired-token"; + case Error::kErrorInvalidToken: + return "invalid-token"; + case Error::kErrorMaxRetries: + return "max-retries"; + case Error::kErrorNetworkError: + return "network-error"; + case Error::kErrorOperationFailed: + return "operation-failed"; + case Error::kErrorOverriddenBySet: + return "overridden-by-set"; + case Error::kErrorPermissionDenied: + return "permission-denied"; + case Error::kErrorUnavailable: + return "unavailable"; + case Error::kErrorWriteCanceled: + return "write-canceled"; + case Error::kErrorInvalidVariantType: + return "invalid-variant-type"; + case Error::kErrorConflictingOperationInProgress: + return "conflicting-operation-in-progress"; + case Error::kErrorTransactionAbortedByUser: + return "transaction-aborted-by-user"; + default: + return "unknown"; + } +} + +std::string FirebaseDatabasePlugin::GetDatabaseErrorMessage(Error error) { + const char* msg = firebase::database::GetErrorMessage(error); + return msg ? std::string(msg) : "Unknown error"; +} + +FlutterError FirebaseDatabasePlugin::ParseError( + const firebase::FutureBase& future) { + Error error = static_cast(future.error()); + std::string code = GetDatabaseErrorCode(error); + std::string message = + future.error_message() ? future.error_message() : "Unknown error"; + return FlutterError(code, message); +} + +// --- Helper: Convert DataSnapshot to EncodableMap --- +EncodableMap FirebaseDatabasePlugin::DataSnapshotToEncodableMap( + const DataSnapshot& snapshot) { + EncodableMap result; + result[EncodableValue("key")] = + snapshot.key() ? EncodableValue(std::string(snapshot.key())) + : EncodableValue(); + result[EncodableValue("value")] = VariantToEncodableValue(snapshot.value()); + result[EncodableValue("priority")] = + VariantToEncodableValue(snapshot.priority()); + + EncodableList childKeys; + std::vector children = snapshot.children(); + for (const auto& child : children) { + if (child.key()) { + childKeys.push_back(EncodableValue(std::string(child.key()))); + } + } + result[EncodableValue("childKeys")] = EncodableValue(childKeys); + + return result; +} + +// --- Helper: Apply query modifiers --- +firebase::database::Query FirebaseDatabasePlugin::ApplyQueryModifiers( + firebase::database::Query query, const EncodableList& modifiers) { + for (const auto& mod_value : modifiers) { + const auto& mod = std::get(mod_value); + + auto type_it = mod.find(EncodableValue("type")); + if (type_it == mod.end()) continue; + std::string type = std::get(type_it->second); + + auto name_it = mod.find(EncodableValue("name")); + if (name_it == mod.end()) continue; + std::string name = std::get(name_it->second); + + if (type == "orderBy") { + if (name == "orderByChild") { + auto path_it = mod.find(EncodableValue("path")); + if (path_it != mod.end()) { + query = query.OrderByChild( + std::get(path_it->second).c_str()); + } + } else if (name == "orderByKey") { + query = query.OrderByKey(); + } else if (name == "orderByValue") { + query = query.OrderByValue(); + } else if (name == "orderByPriority") { + query = query.OrderByPriority(); + } + } else if (type == "cursor") { + auto value_it = mod.find(EncodableValue("value")); + Variant cursor_value = Variant::Null(); + if (value_it != mod.end()) { + cursor_value = EncodableValueToVariant(value_it->second); + } + + auto key_it = mod.find(EncodableValue("key")); + const char* child_key = nullptr; + std::string key_str; + if (key_it != mod.end() && + std::holds_alternative(key_it->second)) { + key_str = std::get(key_it->second); + child_key = key_str.c_str(); + } + + if (name == "startAt") { + query = child_key ? query.StartAt(cursor_value, child_key) + : query.StartAt(cursor_value); + } else if (name == "startAfter") { + // C++ SDK doesn't have StartAfter; use StartAt workaround + query = child_key ? query.StartAt(cursor_value, child_key) + : query.StartAt(cursor_value); + } else if (name == "endAt") { + query = child_key ? query.EndAt(cursor_value, child_key) + : query.EndAt(cursor_value); + } else if (name == "endBefore") { + // C++ SDK doesn't have EndBefore; use EndAt workaround + query = child_key ? query.EndAt(cursor_value, child_key) + : query.EndAt(cursor_value); + } + } else if (type == "limit") { + auto limit_it = mod.find(EncodableValue("limit")); + if (limit_it != mod.end()) { + int limit = 0; + if (std::holds_alternative(limit_it->second)) { + limit = std::get(limit_it->second); + } else if (std::holds_alternative(limit_it->second)) { + limit = static_cast(std::get(limit_it->second)); + } + if (name == "limitToFirst") { + query = query.LimitToFirst(static_cast(limit)); + } else if (name == "limitToLast") { + query = query.LimitToLast(static_cast(limit)); + } + } + } + } + return query; +} + +// ===== Plugin Implementation ===== + +FirebaseDatabasePlugin::FirebaseDatabasePlugin() {} + +FirebaseDatabasePlugin::~FirebaseDatabasePlugin() {} + +void FirebaseDatabasePlugin::RegisterWithRegistrar( + flutter::PluginRegistrarWindows* registrar) { + auto plugin = std::make_unique(); + messenger_ = registrar->messenger(); + FirebaseDatabaseHostApi::SetUp(registrar->messenger(), plugin.get()); + registrar->AddPlugin(std::move(plugin)); + App::RegisterLibrary(kLibraryName.c_str(), getPluginVersion().c_str(), + nullptr); + + // Register atexit handler to clean up listeners and disconnect + // before static destruction triggers thread joins in the C++ SDK. + std::atexit(CleanupBeforeStaticDestruction); +} + +// --- Helper: Get Database instance from Pigeon app --- +Database* FirebaseDatabasePlugin::GetDatabaseFromPigeon( + const DatabasePigeonFirebaseApp& app) { + App* firebase_app = App::GetInstance(app.app_name().c_str()); + if (!firebase_app) { + return nullptr; + } + + const auto& settings = app.settings(); + const std::string* url = app.database_u_r_l(); + + // Build a cache key from app name + effective URL (like Firestore does) + std::string effective_url; + if (url && !url->empty()) { + effective_url = *url; + } + + std::string cache_key = app.app_name() + "-" + effective_url; + + // Return cached instance if available (raw pointer, not owned). + // The C++ SDK manages Database instance lifetime internally. + // App::~App() triggers Database::DeleteInternal() during static destruction. + auto it = database_instances_.find(cache_key); + if (it != database_instances_.end()) { + return it->second; + } + + // Create new instance + // Always pass the URL explicitly - the C++ SDK on desktop may not + // properly read database_url from app options without it. + const char* app_db_url = firebase_app->options().database_url(); + if (effective_url.empty() && app_db_url && strlen(app_db_url) > 0) { + effective_url = app_db_url; + } + Database* database = nullptr; + if (!effective_url.empty()) { + database = Database::GetInstance(firebase_app, effective_url.c_str()); + } else { + database = Database::GetInstance(firebase_app); + } + + if (!database) return nullptr; + + if (settings.persistence_enabled()) { + database->set_persistence_enabled(*settings.persistence_enabled()); + } + if (settings.logging_enabled() && *settings.logging_enabled()) { + database->set_log_level(firebase::kLogLevelDebug); + } + + // Cache raw pointer. We do NOT take ownership — the C++ SDK manages + // the Database lifetime via App's CleanupNotifier. This matches the + // pattern used by firebase_auth and firebase_storage. + database_instances_[cache_key] = database; + + return database; +} + +// ===== Database methods ===== + +void FirebaseDatabasePlugin::GoOnline( + const DatabasePigeonFirebaseApp& app, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + database->GoOnline(); + result(std::nullopt); +} + +void FirebaseDatabasePlugin::GoOffline( + const DatabasePigeonFirebaseApp& app, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + database->GoOffline(); + result(std::nullopt); +} + +void FirebaseDatabasePlugin::SetPersistenceEnabled( + const DatabasePigeonFirebaseApp& app, bool enabled, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + database->set_persistence_enabled(enabled); + result(std::nullopt); +} + +void FirebaseDatabasePlugin::SetPersistenceCacheSizeBytes( + const DatabasePigeonFirebaseApp& app, int64_t cache_size, + std::function reply)> result) { + // C++ SDK doesn't directly support setting cache size + result(std::nullopt); +} + +void FirebaseDatabasePlugin::SetLoggingEnabled( + const DatabasePigeonFirebaseApp& app, bool enabled, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + database->set_log_level(enabled ? firebase::kLogLevelDebug + : firebase::kLogLevelInfo); + result(std::nullopt); +} + +void FirebaseDatabasePlugin::UseDatabaseEmulator( + const DatabasePigeonFirebaseApp& app, const std::string& host, int64_t port, + std::function reply)> result) { + // The C++ SDK for Realtime Database does not have a UseEmulator API. + // On Windows, tests run against the live Firebase instance. + result(std::nullopt); +} + +void FirebaseDatabasePlugin::Ref( + const DatabasePigeonFirebaseApp& app, const std::string* path, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + + DatabaseReference ref; + if (path && !path->empty()) { + ref = database->GetReference(path->c_str()); + } else { + ref = database->GetReference(); + } + + std::string ref_path; + if (ref.key()) { + // Build path from the URL + std::string url = ref.url(); + // Extract path from URL (after the host) + auto pos = url.find(".com/"); + if (pos != std::string::npos) { + ref_path = url.substr(pos + 4); + } else { + ref_path = path ? *path : "/"; + } + } else { + ref_path = path ? *path : "/"; + } + + result(DatabaseReferencePlatform(ref_path)); +} + +void FirebaseDatabasePlugin::RefFromURL( + const DatabasePigeonFirebaseApp& app, const std::string& url, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + + DatabaseReference ref = database->GetReferenceFromUrl(url.c_str()); + + std::string ref_path; + std::string ref_url = ref.url(); + auto pos = ref_url.find(".com/"); + if (pos != std::string::npos) { + ref_path = ref_url.substr(pos + 4); + } else { + ref_path = "/"; + } + + result(DatabaseReferencePlatform(ref_path)); +} + +void FirebaseDatabasePlugin::PurgeOutstandingWrites( + const DatabasePigeonFirebaseApp& app, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + database->PurgeOutstandingWrites(); + result(std::nullopt); +} + +// ===== DatabaseReference methods ===== + +void FirebaseDatabasePlugin::DatabaseReferenceSet( + const DatabasePigeonFirebaseApp& app, + const DatabaseReferenceRequest& request, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + + DatabaseReference ref = database->GetReference(request.path().c_str()); + Variant value = request.value() ? EncodableValueToVariant(*request.value()) + : Variant::Null(); + + ref.SetValue(value).OnCompletion([result](const Future& future) { + if (future.error() == Error::kErrorNone) { + result(std::nullopt); + } else { + result(FirebaseDatabasePlugin::ParseError(future)); + } + }); +} + +void FirebaseDatabasePlugin::DatabaseReferenceSetWithPriority( + const DatabasePigeonFirebaseApp& app, + const DatabaseReferenceRequest& request, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + + DatabaseReference ref = database->GetReference(request.path().c_str()); + Variant value = request.value() ? EncodableValueToVariant(*request.value()) + : Variant::Null(); + Variant priority = request.priority() + ? EncodableValueToVariant(*request.priority()) + : Variant::Null(); + + ref.SetValueAndPriority(value, priority) + .OnCompletion([result](const Future& future) { + if (future.error() == Error::kErrorNone) { + result(std::nullopt); + } else { + result(FirebaseDatabasePlugin::ParseError(future)); + } + }); +} + +void FirebaseDatabasePlugin::DatabaseReferenceUpdate( + const DatabasePigeonFirebaseApp& app, const UpdateRequest& request, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + + DatabaseReference ref = database->GetReference(request.path().c_str()); + Variant values = EncodableValueToVariant(EncodableValue(request.value())); + + ref.UpdateChildren(values).OnCompletion([result](const Future& future) { + if (future.error() == Error::kErrorNone) { + result(std::nullopt); + } else { + result(FirebaseDatabasePlugin::ParseError(future)); + } + }); +} + +void FirebaseDatabasePlugin::DatabaseReferenceSetPriority( + const DatabasePigeonFirebaseApp& app, + const DatabaseReferenceRequest& request, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + + DatabaseReference ref = database->GetReference(request.path().c_str()); + Variant priority = request.priority() + ? EncodableValueToVariant(*request.priority()) + : Variant::Null(); + + ref.SetPriority(priority).OnCompletion([result](const Future& future) { + if (future.error() == Error::kErrorNone) { + result(std::nullopt); + } else { + result(FirebaseDatabasePlugin::ParseError(future)); + } + }); +} + +void FirebaseDatabasePlugin::DatabaseReferenceRunTransaction( + const DatabasePigeonFirebaseApp& app, const TransactionRequest& request, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + + DatabaseReference ref = database->GetReference(request.path().c_str()); + int64_t transaction_key = request.transaction_key(); + bool apply_locally = request.apply_locally(); + + struct TransactionContext { + flutter::BinaryMessenger* messenger; + int64_t transaction_key; + std::map* transaction_results; + std::function reply)> result; + }; + + auto* ctx = new TransactionContext{messenger_, transaction_key, + &transaction_results_, result}; + + ref.RunTransaction( + [](MutableData* data, + void* context) -> firebase::database::TransactionResult { + auto* ctx = static_cast(context); + + // Convert current data to EncodableValue + Variant current_value = data->value(); + EncodableValue snapshot_value = + FirebaseDatabasePlugin::VariantToEncodableValue(current_value); + + // Call the Flutter transaction handler synchronously using a semaphore + std::mutex mtx; + std::condition_variable cv; + bool handler_complete = false; + TransactionHandlerResult* handler_result = nullptr; + + auto flutter_api = + std::make_unique(ctx->messenger); + + const EncodableValue* snapshot_ptr = + std::holds_alternative(snapshot_value) + ? nullptr + : &snapshot_value; + + flutter_api->CallTransactionHandler( + ctx->transaction_key, snapshot_ptr, + [&](const TransactionHandlerResult& result) { + handler_result = new TransactionHandlerResult( + result.value(), result.aborted(), result.exception()); + std::lock_guard lock(mtx); + handler_complete = true; + cv.notify_one(); + }, + [&](const FlutterError& error) { + handler_result = new TransactionHandlerResult(true, true); + std::lock_guard lock(mtx); + handler_complete = true; + cv.notify_one(); + }); + + // Wait for the Flutter callback to complete + { + std::unique_lock lock(mtx); + cv.wait(lock, [&] { return handler_complete; }); + } + + if (!handler_result || handler_result->aborted() || + handler_result->exception()) { + delete handler_result; + return firebase::database::kTransactionResultAbort; + } + + // Apply the result value + if (handler_result->value()) { + Variant new_value = FirebaseDatabasePlugin::EncodableValueToVariant( + *handler_result->value()); + data->set_value(new_value); + } else { + data->set_value(Variant::Null()); + } + + delete handler_result; + return firebase::database::kTransactionResultSuccess; + }, + ctx, apply_locally); + + // Wait for the transaction to complete + ref.RunTransactionLastResult().OnCompletion( + [ctx](const Future& future) { + if (future.error() == Error::kErrorNone) { + const DataSnapshot* snapshot = future.result(); + EncodableMap result_map; + result_map[EncodableValue("committed")] = EncodableValue(true); + if (snapshot) { + result_map[EncodableValue("snapshot")] = EncodableValue( + FirebaseDatabasePlugin::DataSnapshotToEncodableMap(*snapshot)); + } else { + result_map[EncodableValue("snapshot")] = EncodableValue(); + } + (*ctx->transaction_results)[ctx->transaction_key] = result_map; + ctx->result(std::nullopt); + } else { + // Transaction failed but may have been aborted + EncodableMap result_map; + result_map[EncodableValue("committed")] = EncodableValue(false); + result_map[EncodableValue("snapshot")] = EncodableValue(EncodableMap{ + {EncodableValue("key"), EncodableValue()}, + {EncodableValue("value"), EncodableValue()}, + {EncodableValue("priority"), EncodableValue()}, + {EncodableValue("childKeys"), EncodableValue(EncodableList{})}, + }); + (*ctx->transaction_results)[ctx->transaction_key] = result_map; + + if (static_cast(future.error()) == + Error::kErrorTransactionAbortedByUser) { + // Aborted by user is not an error condition + ctx->result(std::nullopt); + } else { + ctx->result(FirebaseDatabasePlugin::ParseError(future)); + } + } + delete ctx; + }); +} + +void FirebaseDatabasePlugin::DatabaseReferenceGetTransactionResult( + const DatabasePigeonFirebaseApp& app, int64_t transaction_key, + std::function reply)> result) { + auto it = transaction_results_.find(transaction_key); + if (it != transaction_results_.end()) { + result(it->second); + transaction_results_.erase(it); + } else { + // Return default result + EncodableMap default_result; + default_result[EncodableValue("committed")] = EncodableValue(false); + default_result[EncodableValue("snapshot")] = EncodableValue(EncodableMap{ + {EncodableValue("key"), EncodableValue()}, + {EncodableValue("value"), EncodableValue()}, + {EncodableValue("priority"), EncodableValue()}, + {EncodableValue("childKeys"), EncodableValue(EncodableList{})}, + }); + result(default_result); + } +} + +// ===== OnDisconnect methods ===== + +void FirebaseDatabasePlugin::OnDisconnectSet( + const DatabasePigeonFirebaseApp& app, + const DatabaseReferenceRequest& request, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + + DatabaseReference ref = database->GetReference(request.path().c_str()); + Variant value = request.value() ? EncodableValueToVariant(*request.value()) + : Variant::Null(); + + ref.OnDisconnect()->SetValue(value).OnCompletion( + [result](const Future& future) { + if (future.error() == Error::kErrorNone) { + result(std::nullopt); + } else { + result(FirebaseDatabasePlugin::ParseError(future)); + } + }); +} + +void FirebaseDatabasePlugin::OnDisconnectSetWithPriority( + const DatabasePigeonFirebaseApp& app, + const DatabaseReferenceRequest& request, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + + DatabaseReference ref = database->GetReference(request.path().c_str()); + Variant value = request.value() ? EncodableValueToVariant(*request.value()) + : Variant::Null(); + Variant priority = request.priority() + ? EncodableValueToVariant(*request.priority()) + : Variant::Null(); + + ref.OnDisconnect() + ->SetValueAndPriority(value, priority) + .OnCompletion([result](const Future& future) { + if (future.error() == Error::kErrorNone) { + result(std::nullopt); + } else { + result(FirebaseDatabasePlugin::ParseError(future)); + } + }); +} + +void FirebaseDatabasePlugin::OnDisconnectUpdate( + const DatabasePigeonFirebaseApp& app, const UpdateRequest& request, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + + DatabaseReference ref = database->GetReference(request.path().c_str()); + Variant values = EncodableValueToVariant(EncodableValue(request.value())); + + ref.OnDisconnect()->UpdateChildren(values).OnCompletion( + [result](const Future& future) { + if (future.error() == Error::kErrorNone) { + result(std::nullopt); + } else { + result(FirebaseDatabasePlugin::ParseError(future)); + } + }); +} + +void FirebaseDatabasePlugin::OnDisconnectCancel( + const DatabasePigeonFirebaseApp& app, const std::string& path, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + + DatabaseReference ref = database->GetReference(path.c_str()); + + ref.OnDisconnect()->Cancel().OnCompletion( + [result](const Future& future) { + if (future.error() == Error::kErrorNone) { + result(std::nullopt); + } else { + result(FirebaseDatabasePlugin::ParseError(future)); + } + }); +} + +// ===== Query methods ===== + +void FirebaseDatabasePlugin::QueryObserve( + const DatabasePigeonFirebaseApp& app, const QueryRequest& request, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + + DatabaseReference ref = database->GetReference(request.path().c_str()); + firebase::database::Query query = + ApplyQueryModifiers(ref, request.modifiers()); + + // The event type will be passed as an argument when the Dart side calls + // listen on the EventChannel. We need to create the appropriate handler. + // Since we don't know the event type here, we create both a value and child + // handler based on a shared approach: the Dart side passes eventType as an + // argument to the EventChannel's listen call. + + // We use a generic approach: create one handler that reads the eventType + // from the listen arguments. + class DatabaseGenericStreamHandler + : public flutter::StreamHandler { + public: + DatabaseGenericStreamHandler(firebase::database::Query query) + : query_(query), value_listener_(nullptr), child_listener_(nullptr) {} + + ~DatabaseGenericStreamHandler() override { + // Remove listeners before deleting to avoid dangling pointers in the + // Database's internal listener list. Query::RemoveXxxListener() checks + // if (internal_) first, so this is a safe no-op if the Database was + // already destroyed (the cleanup mechanism nullifies internal_). + if (value_listener_) { + query_.RemoveValueListener(value_listener_); + delete value_listener_; + value_listener_ = nullptr; + } + if (child_listener_) { + query_.RemoveChildListener(child_listener_); + delete child_listener_; + child_listener_ = nullptr; + } + } + + protected: + std::unique_ptr> + OnListenInternal( + const flutter::EncodableValue* arguments, + std::unique_ptr>&& events) + override { + events_ = std::move(events); + + // Extract eventType from arguments + std::string event_type = "value"; + if (arguments && std::holds_alternative(*arguments)) { + const auto& args_map = std::get(*arguments); + auto it = args_map.find(EncodableValue("eventType")); + if (it != args_map.end() && + std::holds_alternative(it->second)) { + event_type = std::get(it->second); + } + } + + if (event_type == "value") { + // Value listener + class VL : public firebase::database::ValueListener { + public: + VL(flutter::EventSink* events) + : events_(events) {} + void OnValueChanged(const DataSnapshot& snapshot) override { + EncodableMap event; + event[EncodableValue("eventType")] = EncodableValue("value"); + event[EncodableValue("previousChildKey")] = EncodableValue(); + event[EncodableValue("snapshot")] = EncodableValue( + FirebaseDatabasePlugin::DataSnapshotToEncodableMap(snapshot)); + events_->Success(EncodableValue(event)); + } + void OnCancelled(const Error& error, + const char* error_message) override { + events_->Error(FirebaseDatabasePlugin::GetDatabaseErrorCode(error), + error_message ? error_message : "Unknown error"); + } + + private: + flutter::EventSink* events_; + }; + value_listener_ = new VL(events_.get()); + query_.AddValueListener(value_listener_); + } else { + // Child listener + class CL : public firebase::database::ChildListener { + public: + CL(flutter::EventSink* events, + const std::string& event_type) + : events_(events), event_type_(event_type) {} + void OnChildAdded(const DataSnapshot& snapshot, + const char* prev) override { + if (event_type_ == "childAdded") Send("childAdded", snapshot, prev); + } + void OnChildChanged(const DataSnapshot& snapshot, + const char* prev) override { + if (event_type_ == "childChanged") + Send("childChanged", snapshot, prev); + } + void OnChildMoved(const DataSnapshot& snapshot, + const char* prev) override { + if (event_type_ == "childMoved") Send("childMoved", snapshot, prev); + } + void OnChildRemoved(const DataSnapshot& snapshot) override { + if (event_type_ == "childRemoved") + Send("childRemoved", snapshot, nullptr); + } + void OnCancelled(const Error& error, + const char* error_message) override { + events_->Error(FirebaseDatabasePlugin::GetDatabaseErrorCode(error), + error_message ? error_message : "Unknown error"); + } + + private: + void Send(const std::string& type, const DataSnapshot& snapshot, + const char* prev) { + EncodableMap event; + event[EncodableValue("eventType")] = EncodableValue(type); + event[EncodableValue("previousChildKey")] = + prev ? EncodableValue(std::string(prev)) : EncodableValue(); + event[EncodableValue("snapshot")] = EncodableValue( + FirebaseDatabasePlugin::DataSnapshotToEncodableMap(snapshot)); + events_->Success(EncodableValue(event)); + } + flutter::EventSink* events_; + std::string event_type_; + }; + child_listener_ = new CL(events_.get(), event_type); + query_.AddChildListener(child_listener_); + } + + return nullptr; + } + + std::unique_ptr> + OnCancelInternal(const flutter::EncodableValue* arguments) override { + if (value_listener_) { + query_.RemoveValueListener(value_listener_); + delete value_listener_; + value_listener_ = nullptr; + } + if (child_listener_) { + query_.RemoveChildListener(child_listener_); + delete child_listener_; + child_listener_ = nullptr; + } + if (events_) { + events_->EndOfStream(); + } + return nullptr; + } + + private: + firebase::database::Query query_; + firebase::database::ValueListener* value_listener_; + firebase::database::ChildListener* child_listener_; + std::unique_ptr> events_; + }; + + auto handler = std::make_unique(query); + std::string channelName = RegisterEventChannel( + "plugins.flutter.io/firebase_database/query/", std::move(handler)); + + result(channelName); +} + +void FirebaseDatabasePlugin::QueryKeepSynced( + const DatabasePigeonFirebaseApp& app, const QueryRequest& request, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + + DatabaseReference ref = database->GetReference(request.path().c_str()); + firebase::database::Query query = + ApplyQueryModifiers(ref, request.modifiers()); + + bool keep_synced = request.value() ? *request.value() : false; + query.SetKeepSynchronized(keep_synced); + result(std::nullopt); +} + +void FirebaseDatabasePlugin::QueryGet( + const DatabasePigeonFirebaseApp& app, const QueryRequest& request, + std::function reply)> result) { + Database* database = GetDatabaseFromPigeon(app); + if (!database) { + result(FlutterError("unknown", "Database instance not found")); + return; + } + + DatabaseReference ref = database->GetReference(request.path().c_str()); + firebase::database::Query query = + ApplyQueryModifiers(ref, request.modifiers()); + + query.GetValue().OnCompletion([result](const Future& future) { + if (future.error() == Error::kErrorNone) { + const DataSnapshot* snapshot = future.result(); + EncodableMap result_map; + if (snapshot) { + result_map[EncodableValue("snapshot")] = EncodableValue( + FirebaseDatabasePlugin::DataSnapshotToEncodableMap(*snapshot)); + } else { + result_map[EncodableValue("snapshot")] = EncodableValue(); + } + result(result_map); + } else { + result(FirebaseDatabasePlugin::ParseError(future)); + } + }); +} + +} // namespace firebase_database_windows diff --git a/packages/firebase_database/firebase_database/windows/firebase_database_plugin.h b/packages/firebase_database/firebase_database/windows/firebase_database_plugin.h new file mode 100644 index 000000000000..6a6fa145f6e0 --- /dev/null +++ b/packages/firebase_database/firebase_database/windows/firebase_database_plugin.h @@ -0,0 +1,144 @@ +/* + * 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. + */ + +#ifndef FLUTTER_PLUGIN_FIREBASE_DATABASE_PLUGIN_H_ +#define FLUTTER_PLUGIN_FIREBASE_DATABASE_PLUGIN_H_ + +#include +#include +#include + +#include + +#include "firebase/database.h" +#include "firebase/database/common.h" +#include "firebase/database/data_snapshot.h" +#include "messages.g.h" + +namespace firebase_database_windows { + +class FirebaseDatabasePlugin : public flutter::Plugin, + public FirebaseDatabaseHostApi { + public: + static void RegisterWithRegistrar(flutter::PluginRegistrarWindows* registrar); + + FirebaseDatabasePlugin(); + + virtual ~FirebaseDatabasePlugin(); + + // Disallow copy and assign. + FirebaseDatabasePlugin(const FirebaseDatabasePlugin&) = delete; + FirebaseDatabasePlugin& operator=(const FirebaseDatabasePlugin&) = delete; + + // Helper functions + static flutter::EncodableValue VariantToEncodableValue( + const firebase::Variant& variant); + static firebase::Variant EncodableValueToVariant( + const flutter::EncodableValue& value); + static std::string GetDatabaseErrorCode(firebase::database::Error error); + static std::string GetDatabaseErrorMessage(firebase::database::Error error); + static FlutterError ParseError(const firebase::FutureBase& future); + static flutter::EncodableMap DataSnapshotToEncodableMap( + const firebase::database::DataSnapshot& snapshot); + + // FirebaseDatabaseHostApi methods + void GoOnline( + const DatabasePigeonFirebaseApp& app, + std::function reply)> result) override; + void GoOffline( + const DatabasePigeonFirebaseApp& app, + std::function reply)> result) override; + void SetPersistenceEnabled( + const DatabasePigeonFirebaseApp& app, bool enabled, + std::function reply)> result) override; + void SetPersistenceCacheSizeBytes( + const DatabasePigeonFirebaseApp& app, int64_t cache_size, + std::function reply)> result) override; + void SetLoggingEnabled( + const DatabasePigeonFirebaseApp& app, bool enabled, + std::function reply)> result) override; + void UseDatabaseEmulator( + const DatabasePigeonFirebaseApp& app, const std::string& host, + int64_t port, + std::function reply)> result) override; + void Ref(const DatabasePigeonFirebaseApp& app, const std::string* path, + std::function reply)> result) + override; + void RefFromURL(const DatabasePigeonFirebaseApp& app, const std::string& url, + std::function reply)> + result) override; + void PurgeOutstandingWrites( + const DatabasePigeonFirebaseApp& app, + std::function reply)> result) override; + void DatabaseReferenceSet( + const DatabasePigeonFirebaseApp& app, + const DatabaseReferenceRequest& request, + std::function reply)> result) override; + void DatabaseReferenceSetWithPriority( + const DatabasePigeonFirebaseApp& app, + const DatabaseReferenceRequest& request, + std::function reply)> result) override; + void DatabaseReferenceUpdate( + const DatabasePigeonFirebaseApp& app, const UpdateRequest& request, + std::function reply)> result) override; + void DatabaseReferenceSetPriority( + const DatabasePigeonFirebaseApp& app, + const DatabaseReferenceRequest& request, + std::function reply)> result) override; + void DatabaseReferenceRunTransaction( + const DatabasePigeonFirebaseApp& app, const TransactionRequest& request, + std::function reply)> result) override; + void DatabaseReferenceGetTransactionResult( + const DatabasePigeonFirebaseApp& app, int64_t transaction_key, + std::function reply)> result) + override; + void OnDisconnectSet( + const DatabasePigeonFirebaseApp& app, + const DatabaseReferenceRequest& request, + std::function reply)> result) override; + void OnDisconnectSetWithPriority( + const DatabasePigeonFirebaseApp& app, + const DatabaseReferenceRequest& request, + std::function reply)> result) override; + void OnDisconnectUpdate( + const DatabasePigeonFirebaseApp& app, const UpdateRequest& request, + std::function reply)> result) override; + void OnDisconnectCancel( + const DatabasePigeonFirebaseApp& app, const std::string& path, + std::function reply)> result) override; + void QueryObserve( + const DatabasePigeonFirebaseApp& app, const QueryRequest& request, + std::function reply)> result) override; + void QueryKeepSynced( + const DatabasePigeonFirebaseApp& app, const QueryRequest& request, + std::function reply)> result) override; + void QueryGet(const DatabasePigeonFirebaseApp& app, + const QueryRequest& request, + std::function reply)> + result) override; + + static flutter::BinaryMessenger* messenger_; + static std::map< + std::string, + std::unique_ptr>> + event_channels_; + static std::map>> + stream_handlers_; + static std::map + database_instances_; + + private: + firebase::database::Database* GetDatabaseFromPigeon( + const DatabasePigeonFirebaseApp& app); + firebase::database::Query ApplyQueryModifiers( + firebase::database::Query query, const flutter::EncodableList& modifiers); + + std::map transaction_results_; +}; + +} // namespace firebase_database_windows + +#endif /* FLUTTER_PLUGIN_FIREBASE_DATABASE_PLUGIN_H_ */ diff --git a/packages/firebase_database/firebase_database/windows/firebase_database_plugin_c_api.cpp b/packages/firebase_database/firebase_database/windows/firebase_database_plugin_c_api.cpp new file mode 100644 index 000000000000..41cf8fae1737 --- /dev/null +++ b/packages/firebase_database/firebase_database/windows/firebase_database_plugin_c_api.cpp @@ -0,0 +1,16 @@ +// 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. + +#include "include/firebase_database/firebase_database_plugin_c_api.h" + +#include + +#include "firebase_database_plugin.h" + +void FirebaseDatabasePluginCApiRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + firebase_database_windows::FirebaseDatabasePlugin::RegisterWithRegistrar( + flutter::PluginRegistrarManager::GetInstance() + ->GetRegistrar(registrar)); +} diff --git a/packages/firebase_database/firebase_database/windows/include/firebase_database/firebase_database_plugin_c_api.h b/packages/firebase_database/firebase_database/windows/include/firebase_database/firebase_database_plugin_c_api.h new file mode 100644 index 000000000000..f333dc88edf3 --- /dev/null +++ b/packages/firebase_database/firebase_database/windows/include/firebase_database/firebase_database_plugin_c_api.h @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#ifndef FLUTTER_PLUGIN_FIREBASE_DATABASE_PLUGIN_C_API_H_ +#define FLUTTER_PLUGIN_FIREBASE_DATABASE_PLUGIN_C_API_H_ + +#include + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) +#else +#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +FLUTTER_PLUGIN_EXPORT void FirebaseDatabasePluginCApiRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif /* FLUTTER_PLUGIN_FIREBASE_DATABASE_PLUGIN_C_API_H_ */ diff --git a/packages/firebase_database/firebase_database/windows/messages.g.cpp b/packages/firebase_database/firebase_database/windows/messages.g.cpp new file mode 100644 index 000000000000..8c0aeeb54adc --- /dev/null +++ b/packages/firebase_database/firebase_database/windows/messages.g.cpp @@ -0,0 +1,1742 @@ +// 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_database_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("")); +} + +// DatabasePigeonSettings + +DatabasePigeonSettings::DatabasePigeonSettings() {} + +DatabasePigeonSettings::DatabasePigeonSettings(const bool* persistence_enabled, + const int64_t* cache_size_bytes, + const bool* logging_enabled, + const std::string* emulator_host, + const int64_t* emulator_port) + : persistence_enabled_(persistence_enabled + ? std::optional(*persistence_enabled) + : std::nullopt), + cache_size_bytes_(cache_size_bytes + ? std::optional(*cache_size_bytes) + : std::nullopt), + logging_enabled_(logging_enabled ? std::optional(*logging_enabled) + : std::nullopt), + emulator_host_(emulator_host ? std::optional(*emulator_host) + : std::nullopt), + emulator_port_(emulator_port ? std::optional(*emulator_port) + : std::nullopt) {} + +const bool* DatabasePigeonSettings::persistence_enabled() const { + return persistence_enabled_ ? &(*persistence_enabled_) : nullptr; +} + +void DatabasePigeonSettings::set_persistence_enabled(const bool* value_arg) { + persistence_enabled_ = + value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void DatabasePigeonSettings::set_persistence_enabled(bool value_arg) { + persistence_enabled_ = value_arg; +} + +const int64_t* DatabasePigeonSettings::cache_size_bytes() const { + return cache_size_bytes_ ? &(*cache_size_bytes_) : nullptr; +} + +void DatabasePigeonSettings::set_cache_size_bytes(const int64_t* value_arg) { + cache_size_bytes_ = + value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void DatabasePigeonSettings::set_cache_size_bytes(int64_t value_arg) { + cache_size_bytes_ = value_arg; +} + +const bool* DatabasePigeonSettings::logging_enabled() const { + return logging_enabled_ ? &(*logging_enabled_) : nullptr; +} + +void DatabasePigeonSettings::set_logging_enabled(const bool* value_arg) { + logging_enabled_ = value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void DatabasePigeonSettings::set_logging_enabled(bool value_arg) { + logging_enabled_ = value_arg; +} + +const std::string* DatabasePigeonSettings::emulator_host() const { + return emulator_host_ ? &(*emulator_host_) : nullptr; +} + +void DatabasePigeonSettings::set_emulator_host( + const std::string_view* value_arg) { + emulator_host_ = + value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void DatabasePigeonSettings::set_emulator_host(std::string_view value_arg) { + emulator_host_ = value_arg; +} + +const int64_t* DatabasePigeonSettings::emulator_port() const { + return emulator_port_ ? &(*emulator_port_) : nullptr; +} + +void DatabasePigeonSettings::set_emulator_port(const int64_t* value_arg) { + emulator_port_ = + value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void DatabasePigeonSettings::set_emulator_port(int64_t value_arg) { + emulator_port_ = value_arg; +} + +EncodableList DatabasePigeonSettings::ToEncodableList() const { + EncodableList list; + list.reserve(5); + list.push_back(persistence_enabled_ ? EncodableValue(*persistence_enabled_) + : EncodableValue()); + list.push_back(cache_size_bytes_ ? EncodableValue(*cache_size_bytes_) + : EncodableValue()); + list.push_back(logging_enabled_ ? EncodableValue(*logging_enabled_) + : EncodableValue()); + list.push_back(emulator_host_ ? EncodableValue(*emulator_host_) + : EncodableValue()); + list.push_back(emulator_port_ ? EncodableValue(*emulator_port_) + : EncodableValue()); + return list; +} + +DatabasePigeonSettings DatabasePigeonSettings::FromEncodableList( + const EncodableList& list) { + DatabasePigeonSettings decoded; + auto& encodable_persistence_enabled = list[0]; + if (!encodable_persistence_enabled.IsNull()) { + decoded.set_persistence_enabled( + std::get(encodable_persistence_enabled)); + } + auto& encodable_cache_size_bytes = list[1]; + if (!encodable_cache_size_bytes.IsNull()) { + decoded.set_cache_size_bytes(std::get(encodable_cache_size_bytes)); + } + auto& encodable_logging_enabled = list[2]; + if (!encodable_logging_enabled.IsNull()) { + decoded.set_logging_enabled(std::get(encodable_logging_enabled)); + } + auto& encodable_emulator_host = list[3]; + if (!encodable_emulator_host.IsNull()) { + decoded.set_emulator_host(std::get(encodable_emulator_host)); + } + auto& encodable_emulator_port = list[4]; + if (!encodable_emulator_port.IsNull()) { + decoded.set_emulator_port(std::get(encodable_emulator_port)); + } + return decoded; +} + +// DatabasePigeonFirebaseApp + +DatabasePigeonFirebaseApp::DatabasePigeonFirebaseApp( + const std::string& app_name, const DatabasePigeonSettings& settings) + : app_name_(app_name), + settings_(std::make_unique(settings)) {} + +DatabasePigeonFirebaseApp::DatabasePigeonFirebaseApp( + const std::string& app_name, const std::string* database_u_r_l, + const DatabasePigeonSettings& settings) + : app_name_(app_name), + database_u_r_l_(database_u_r_l + ? std::optional(*database_u_r_l) + : std::nullopt), + settings_(std::make_unique(settings)) {} + +DatabasePigeonFirebaseApp::DatabasePigeonFirebaseApp( + const DatabasePigeonFirebaseApp& other) + : app_name_(other.app_name_), + database_u_r_l_(other.database_u_r_l_ + ? std::optional(*other.database_u_r_l_) + : std::nullopt), + settings_(std::make_unique(*other.settings_)) {} + +DatabasePigeonFirebaseApp& DatabasePigeonFirebaseApp::operator=( + const DatabasePigeonFirebaseApp& other) { + app_name_ = other.app_name_; + database_u_r_l_ = other.database_u_r_l_; + settings_ = std::make_unique(*other.settings_); + return *this; +} + +const std::string& DatabasePigeonFirebaseApp::app_name() const { + return app_name_; +} + +void DatabasePigeonFirebaseApp::set_app_name(std::string_view value_arg) { + app_name_ = value_arg; +} + +const std::string* DatabasePigeonFirebaseApp::database_u_r_l() const { + return database_u_r_l_ ? &(*database_u_r_l_) : nullptr; +} + +void DatabasePigeonFirebaseApp::set_database_u_r_l( + const std::string_view* value_arg) { + database_u_r_l_ = + value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void DatabasePigeonFirebaseApp::set_database_u_r_l(std::string_view value_arg) { + database_u_r_l_ = value_arg; +} + +const DatabasePigeonSettings& DatabasePigeonFirebaseApp::settings() const { + return *settings_; +} + +void DatabasePigeonFirebaseApp::set_settings( + const DatabasePigeonSettings& value_arg) { + settings_ = std::make_unique(value_arg); +} + +EncodableList DatabasePigeonFirebaseApp::ToEncodableList() const { + EncodableList list; + list.reserve(3); + list.push_back(EncodableValue(app_name_)); + list.push_back(database_u_r_l_ ? EncodableValue(*database_u_r_l_) + : EncodableValue()); + list.push_back(CustomEncodableValue(*settings_)); + return list; +} + +DatabasePigeonFirebaseApp DatabasePigeonFirebaseApp::FromEncodableList( + const EncodableList& list) { + DatabasePigeonFirebaseApp decoded( + std::get(list[0]), + std::any_cast( + std::get(list[2]))); + auto& encodable_database_u_r_l = list[1]; + if (!encodable_database_u_r_l.IsNull()) { + decoded.set_database_u_r_l(std::get(encodable_database_u_r_l)); + } + return decoded; +} + +// DatabaseReferencePlatform + +DatabaseReferencePlatform::DatabaseReferencePlatform(const std::string& path) + : path_(path) {} + +const std::string& DatabaseReferencePlatform::path() const { return path_; } + +void DatabaseReferencePlatform::set_path(std::string_view value_arg) { + path_ = value_arg; +} + +EncodableList DatabaseReferencePlatform::ToEncodableList() const { + EncodableList list; + list.reserve(1); + list.push_back(EncodableValue(path_)); + return list; +} + +DatabaseReferencePlatform DatabaseReferencePlatform::FromEncodableList( + const EncodableList& list) { + DatabaseReferencePlatform decoded(std::get(list[0])); + return decoded; +} + +// DatabaseReferenceRequest + +DatabaseReferenceRequest::DatabaseReferenceRequest(const std::string& path) + : path_(path) {} + +DatabaseReferenceRequest::DatabaseReferenceRequest( + const std::string& path, const EncodableValue* value, + const EncodableValue* priority) + : path_(path), + value_(value ? std::optional(*value) : std::nullopt), + priority_(priority ? std::optional(*priority) + : std::nullopt) {} + +const std::string& DatabaseReferenceRequest::path() const { return path_; } + +void DatabaseReferenceRequest::set_path(std::string_view value_arg) { + path_ = value_arg; +} + +const EncodableValue* DatabaseReferenceRequest::value() const { + return value_ ? &(*value_) : nullptr; +} + +void DatabaseReferenceRequest::set_value(const EncodableValue* value_arg) { + value_ = value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void DatabaseReferenceRequest::set_value(const EncodableValue& value_arg) { + value_ = value_arg; +} + +const EncodableValue* DatabaseReferenceRequest::priority() const { + return priority_ ? &(*priority_) : nullptr; +} + +void DatabaseReferenceRequest::set_priority(const EncodableValue* value_arg) { + priority_ = + value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void DatabaseReferenceRequest::set_priority(const EncodableValue& value_arg) { + priority_ = value_arg; +} + +EncodableList DatabaseReferenceRequest::ToEncodableList() const { + EncodableList list; + list.reserve(3); + list.push_back(EncodableValue(path_)); + list.push_back(value_ ? *value_ : EncodableValue()); + list.push_back(priority_ ? *priority_ : EncodableValue()); + return list; +} + +DatabaseReferenceRequest DatabaseReferenceRequest::FromEncodableList( + const EncodableList& list) { + DatabaseReferenceRequest decoded(std::get(list[0])); + auto& encodable_value = list[1]; + if (!encodable_value.IsNull()) { + decoded.set_value(encodable_value); + } + auto& encodable_priority = list[2]; + if (!encodable_priority.IsNull()) { + decoded.set_priority(encodable_priority); + } + return decoded; +} + +// UpdateRequest + +UpdateRequest::UpdateRequest(const std::string& path, const EncodableMap& value) + : path_(path), value_(value) {} + +const std::string& UpdateRequest::path() const { return path_; } + +void UpdateRequest::set_path(std::string_view value_arg) { path_ = value_arg; } + +const EncodableMap& UpdateRequest::value() const { return value_; } + +void UpdateRequest::set_value(const EncodableMap& value_arg) { + value_ = value_arg; +} + +EncodableList UpdateRequest::ToEncodableList() const { + EncodableList list; + list.reserve(2); + list.push_back(EncodableValue(path_)); + list.push_back(EncodableValue(value_)); + return list; +} + +UpdateRequest UpdateRequest::FromEncodableList(const EncodableList& list) { + UpdateRequest decoded(std::get(list[0]), + std::get(list[1])); + return decoded; +} + +// TransactionRequest + +TransactionRequest::TransactionRequest(const std::string& path, + int64_t transaction_key, + bool apply_locally) + : path_(path), + transaction_key_(transaction_key), + apply_locally_(apply_locally) {} + +const std::string& TransactionRequest::path() const { return path_; } + +void TransactionRequest::set_path(std::string_view value_arg) { + path_ = value_arg; +} + +int64_t TransactionRequest::transaction_key() const { return transaction_key_; } + +void TransactionRequest::set_transaction_key(int64_t value_arg) { + transaction_key_ = value_arg; +} + +bool TransactionRequest::apply_locally() const { return apply_locally_; } + +void TransactionRequest::set_apply_locally(bool value_arg) { + apply_locally_ = value_arg; +} + +EncodableList TransactionRequest::ToEncodableList() const { + EncodableList list; + list.reserve(3); + list.push_back(EncodableValue(path_)); + list.push_back(EncodableValue(transaction_key_)); + list.push_back(EncodableValue(apply_locally_)); + return list; +} + +TransactionRequest TransactionRequest::FromEncodableList( + const EncodableList& list) { + TransactionRequest decoded(std::get(list[0]), + std::get(list[1]), + std::get(list[2])); + return decoded; +} + +// QueryRequest + +QueryRequest::QueryRequest(const std::string& path, + const EncodableList& modifiers) + : path_(path), modifiers_(modifiers) {} + +QueryRequest::QueryRequest(const std::string& path, + const EncodableList& modifiers, const bool* value) + : path_(path), + modifiers_(modifiers), + value_(value ? std::optional(*value) : std::nullopt) {} + +const std::string& QueryRequest::path() const { return path_; } + +void QueryRequest::set_path(std::string_view value_arg) { path_ = value_arg; } + +const EncodableList& QueryRequest::modifiers() const { return modifiers_; } + +void QueryRequest::set_modifiers(const EncodableList& value_arg) { + modifiers_ = value_arg; +} + +const bool* QueryRequest::value() const { + return value_ ? &(*value_) : nullptr; +} + +void QueryRequest::set_value(const bool* value_arg) { + value_ = value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void QueryRequest::set_value(bool value_arg) { value_ = value_arg; } + +EncodableList QueryRequest::ToEncodableList() const { + EncodableList list; + list.reserve(3); + list.push_back(EncodableValue(path_)); + list.push_back(EncodableValue(modifiers_)); + list.push_back(value_ ? EncodableValue(*value_) : EncodableValue()); + return list; +} + +QueryRequest QueryRequest::FromEncodableList(const EncodableList& list) { + QueryRequest decoded(std::get(list[0]), + std::get(list[1])); + auto& encodable_value = list[2]; + if (!encodable_value.IsNull()) { + decoded.set_value(std::get(encodable_value)); + } + return decoded; +} + +// TransactionHandlerResult + +TransactionHandlerResult::TransactionHandlerResult(bool aborted, bool exception) + : aborted_(aborted), exception_(exception) {} + +TransactionHandlerResult::TransactionHandlerResult(const EncodableValue* value, + bool aborted, bool exception) + : value_(value ? std::optional(*value) : std::nullopt), + aborted_(aborted), + exception_(exception) {} + +const EncodableValue* TransactionHandlerResult::value() const { + return value_ ? &(*value_) : nullptr; +} + +void TransactionHandlerResult::set_value(const EncodableValue* value_arg) { + value_ = value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void TransactionHandlerResult::set_value(const EncodableValue& value_arg) { + value_ = value_arg; +} + +bool TransactionHandlerResult::aborted() const { return aborted_; } + +void TransactionHandlerResult::set_aborted(bool value_arg) { + aborted_ = value_arg; +} + +bool TransactionHandlerResult::exception() const { return exception_; } + +void TransactionHandlerResult::set_exception(bool value_arg) { + exception_ = value_arg; +} + +EncodableList TransactionHandlerResult::ToEncodableList() const { + EncodableList list; + list.reserve(3); + list.push_back(value_ ? *value_ : EncodableValue()); + list.push_back(EncodableValue(aborted_)); + list.push_back(EncodableValue(exception_)); + return list; +} + +TransactionHandlerResult TransactionHandlerResult::FromEncodableList( + const EncodableList& list) { + TransactionHandlerResult decoded(std::get(list[1]), + std::get(list[2])); + auto& encodable_value = list[0]; + if (!encodable_value.IsNull()) { + decoded.set_value(encodable_value); + } + return decoded; +} + +PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} + +EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( + uint8_t type, flutter::ByteStreamReader* stream) const { + switch (type) { + case 129: { + return CustomEncodableValue(DatabasePigeonSettings::FromEncodableList( + std::get(ReadValue(stream)))); + } + case 130: { + return CustomEncodableValue(DatabasePigeonFirebaseApp::FromEncodableList( + std::get(ReadValue(stream)))); + } + case 131: { + return CustomEncodableValue(DatabaseReferencePlatform::FromEncodableList( + std::get(ReadValue(stream)))); + } + case 132: { + return CustomEncodableValue(DatabaseReferenceRequest::FromEncodableList( + std::get(ReadValue(stream)))); + } + case 133: { + return CustomEncodableValue(UpdateRequest::FromEncodableList( + std::get(ReadValue(stream)))); + } + case 134: { + return CustomEncodableValue(TransactionRequest::FromEncodableList( + std::get(ReadValue(stream)))); + } + case 135: { + return CustomEncodableValue(QueryRequest::FromEncodableList( + std::get(ReadValue(stream)))); + } + case 136: { + return CustomEncodableValue(TransactionHandlerResult::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(DatabasePigeonSettings)) { + stream->WriteByte(129); + WriteValue( + EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(DatabasePigeonFirebaseApp)) { + stream->WriteByte(130); + WriteValue( + EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(DatabaseReferencePlatform)) { + stream->WriteByte(131); + WriteValue( + EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(DatabaseReferenceRequest)) { + stream->WriteByte(132); + WriteValue( + EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(UpdateRequest)) { + stream->WriteByte(133); + WriteValue( + EncodableValue( + std::any_cast(*custom_value).ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(TransactionRequest)) { + stream->WriteByte(134); + WriteValue(EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(QueryRequest)) { + stream->WriteByte(135); + WriteValue( + EncodableValue( + std::any_cast(*custom_value).ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(TransactionHandlerResult)) { + stream->WriteByte(136); + WriteValue( + EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + } + flutter::StandardCodecSerializer::WriteValue(value, stream); +} + +/// The codec used by FirebaseDatabaseHostApi. +const flutter::StandardMessageCodec& FirebaseDatabaseHostApi::GetCodec() { + return flutter::StandardMessageCodec::GetInstance( + &PigeonInternalCodecSerializer::GetInstance()); +} + +// Sets up an instance of `FirebaseDatabaseHostApi` to handle messages through +// the `binary_messenger`. +void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, + FirebaseDatabaseHostApi* api) { + FirebaseDatabaseHostApi::SetUp(binary_messenger, api, ""); +} + +void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, + FirebaseDatabaseHostApi* 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_database_platform_interface." + "FirebaseDatabaseHostApi.goOnline" + + 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->GoOnline(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_database_platform_interface." + "FirebaseDatabaseHostApi.goOffline" + + 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->GoOffline(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_database_platform_interface." + "FirebaseDatabaseHostApi.setPersistenceEnabled" + + 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_enabled_arg = args.at(1); + if (encodable_enabled_arg.IsNull()) { + reply(WrapError("enabled_arg unexpectedly null.")); + return; + } + const auto& enabled_arg = std::get(encodable_enabled_arg); + api->SetPersistenceEnabled( + app_arg, enabled_arg, + [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.firebase_database_platform_interface." + "FirebaseDatabaseHostApi.setPersistenceCacheSizeBytes" + + 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_cache_size_arg = args.at(1); + if (encodable_cache_size_arg.IsNull()) { + reply(WrapError("cache_size_arg unexpectedly null.")); + return; + } + const int64_t cache_size_arg = + encodable_cache_size_arg.LongValue(); + api->SetPersistenceCacheSizeBytes( + app_arg, cache_size_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_database_platform_interface." + "FirebaseDatabaseHostApi.setLoggingEnabled" + + 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_enabled_arg = args.at(1); + if (encodable_enabled_arg.IsNull()) { + reply(WrapError("enabled_arg unexpectedly null.")); + return; + } + const auto& enabled_arg = std::get(encodable_enabled_arg); + api->SetLoggingEnabled( + app_arg, enabled_arg, + [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.firebase_database_platform_interface." + "FirebaseDatabaseHostApi.useDatabaseEmulator" + + 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_host_arg = args.at(1); + if (encodable_host_arg.IsNull()) { + reply(WrapError("host_arg unexpectedly null.")); + return; + } + const auto& host_arg = std::get(encodable_host_arg); + const auto& encodable_port_arg = args.at(2); + if (encodable_port_arg.IsNull()) { + reply(WrapError("port_arg unexpectedly null.")); + return; + } + const int64_t port_arg = encodable_port_arg.LongValue(); + api->UseDatabaseEmulator( + app_arg, host_arg, port_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_database_platform_interface." + "FirebaseDatabaseHostApi.ref" + + 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_path_arg = args.at(1); + const auto* path_arg = + std::get_if(&encodable_path_arg); + api->Ref(app_arg, path_arg, + [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back(CustomEncodableValue( + 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_database_platform_interface." + "FirebaseDatabaseHostApi.refFromURL" + + 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_url_arg = args.at(1); + if (encodable_url_arg.IsNull()) { + reply(WrapError("url_arg unexpectedly null.")); + return; + } + const auto& url_arg = std::get(encodable_url_arg); + api->RefFromURL( + app_arg, url_arg, + [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + CustomEncodableValue(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_database_platform_interface." + "FirebaseDatabaseHostApi.purgeOutstandingWrites" + + 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->PurgeOutstandingWrites( + 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_database_platform_interface." + "FirebaseDatabaseHostApi.databaseReferenceSet" + + 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_request_arg = args.at(1); + if (encodable_request_arg.IsNull()) { + reply(WrapError("request_arg unexpectedly null.")); + return; + } + const auto& request_arg = + std::any_cast( + std::get(encodable_request_arg)); + api->DatabaseReferenceSet( + app_arg, request_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_database_platform_interface." + "FirebaseDatabaseHostApi.databaseReferenceSetWithPriority" + + 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_request_arg = args.at(1); + if (encodable_request_arg.IsNull()) { + reply(WrapError("request_arg unexpectedly null.")); + return; + } + const auto& request_arg = + std::any_cast( + std::get(encodable_request_arg)); + api->DatabaseReferenceSetWithPriority( + app_arg, request_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_database_platform_interface." + "FirebaseDatabaseHostApi.databaseReferenceUpdate" + + 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_request_arg = args.at(1); + if (encodable_request_arg.IsNull()) { + reply(WrapError("request_arg unexpectedly null.")); + return; + } + const auto& request_arg = std::any_cast( + std::get(encodable_request_arg)); + api->DatabaseReferenceUpdate( + app_arg, request_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_database_platform_interface." + "FirebaseDatabaseHostApi.databaseReferenceSetPriority" + + 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_request_arg = args.at(1); + if (encodable_request_arg.IsNull()) { + reply(WrapError("request_arg unexpectedly null.")); + return; + } + const auto& request_arg = + std::any_cast( + std::get(encodable_request_arg)); + api->DatabaseReferenceSetPriority( + app_arg, request_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_database_platform_interface." + "FirebaseDatabaseHostApi.databaseReferenceRunTransaction" + + 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_request_arg = args.at(1); + if (encodable_request_arg.IsNull()) { + reply(WrapError("request_arg unexpectedly null.")); + return; + } + const auto& request_arg = + std::any_cast( + std::get(encodable_request_arg)); + api->DatabaseReferenceRunTransaction( + app_arg, request_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_database_platform_interface." + "FirebaseDatabaseHostApi.databaseReferenceGetTransactionResult" + + 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_transaction_key_arg = args.at(1); + if (encodable_transaction_key_arg.IsNull()) { + reply(WrapError("transaction_key_arg unexpectedly null.")); + return; + } + const int64_t transaction_key_arg = + encodable_transaction_key_arg.LongValue(); + api->DatabaseReferenceGetTransactionResult( + app_arg, transaction_key_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_database_platform_interface." + "FirebaseDatabaseHostApi.onDisconnectSet" + + 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_request_arg = args.at(1); + if (encodable_request_arg.IsNull()) { + reply(WrapError("request_arg unexpectedly null.")); + return; + } + const auto& request_arg = + std::any_cast( + std::get(encodable_request_arg)); + api->OnDisconnectSet( + app_arg, request_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_database_platform_interface." + "FirebaseDatabaseHostApi.onDisconnectSetWithPriority" + + 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_request_arg = args.at(1); + if (encodable_request_arg.IsNull()) { + reply(WrapError("request_arg unexpectedly null.")); + return; + } + const auto& request_arg = + std::any_cast( + std::get(encodable_request_arg)); + api->OnDisconnectSetWithPriority( + app_arg, request_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_database_platform_interface." + "FirebaseDatabaseHostApi.onDisconnectUpdate" + + 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_request_arg = args.at(1); + if (encodable_request_arg.IsNull()) { + reply(WrapError("request_arg unexpectedly null.")); + return; + } + const auto& request_arg = std::any_cast( + std::get(encodable_request_arg)); + api->OnDisconnectUpdate( + app_arg, request_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_database_platform_interface." + "FirebaseDatabaseHostApi.onDisconnectCancel" + + 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_path_arg = args.at(1); + if (encodable_path_arg.IsNull()) { + reply(WrapError("path_arg unexpectedly null.")); + return; + } + const auto& path_arg = std::get(encodable_path_arg); + api->OnDisconnectCancel( + app_arg, path_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_database_platform_interface." + "FirebaseDatabaseHostApi.queryObserve" + + 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_request_arg = args.at(1); + if (encodable_request_arg.IsNull()) { + reply(WrapError("request_arg unexpectedly null.")); + return; + } + const auto& request_arg = std::any_cast( + std::get(encodable_request_arg)); + api->QueryObserve( + app_arg, request_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_database_platform_interface." + "FirebaseDatabaseHostApi.queryKeepSynced" + + 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_request_arg = args.at(1); + if (encodable_request_arg.IsNull()) { + reply(WrapError("request_arg unexpectedly null.")); + return; + } + const auto& request_arg = std::any_cast( + std::get(encodable_request_arg)); + api->QueryKeepSynced( + app_arg, request_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_database_platform_interface." + "FirebaseDatabaseHostApi.queryGet" + + 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_request_arg = args.at(1); + if (encodable_request_arg.IsNull()) { + reply(WrapError("request_arg unexpectedly null.")); + return; + } + const auto& request_arg = std::any_cast( + std::get(encodable_request_arg)); + api->QueryGet(app_arg, request_arg, + [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue( + std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } +} + +EncodableValue FirebaseDatabaseHostApi::WrapError( + std::string_view error_message) { + return EncodableValue( + EncodableList{EncodableValue(std::string(error_message)), + EncodableValue("Error"), EncodableValue()}); +} + +EncodableValue FirebaseDatabaseHostApi::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++. +FirebaseDatabaseFlutterApi::FirebaseDatabaseFlutterApi( + flutter::BinaryMessenger* binary_messenger) + : binary_messenger_(binary_messenger), message_channel_suffix_("") {} + +FirebaseDatabaseFlutterApi::FirebaseDatabaseFlutterApi( + 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& FirebaseDatabaseFlutterApi::GetCodec() { + return flutter::StandardMessageCodec::GetInstance( + &PigeonInternalCodecSerializer::GetInstance()); +} + +void FirebaseDatabaseFlutterApi::CallTransactionHandler( + int64_t transaction_key_arg, const EncodableValue* snapshot_value_arg, + std::function&& on_success, + std::function&& on_error) { + const std::string channel_name = + "dev.flutter.pigeon.firebase_database_platform_interface." + "FirebaseDatabaseFlutterApi.callTransactionHandler" + + message_channel_suffix_; + BasicMessageChannel<> channel(binary_messenger_, channel_name, &GetCodec()); + EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ + EncodableValue(transaction_key_arg), + snapshot_value_arg ? *snapshot_value_arg : EncodableValue(), + }); + 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::any_cast( + std::get(list_return_value->at(0))); + on_success(return_value); + } + } else { + on_error(CreateConnectionError(channel_name)); + } + }); +} + +} // namespace firebase_database_windows diff --git a/packages/firebase_database/firebase_database/windows/messages.g.h b/packages/firebase_database/firebase_database/windows/messages.g.h new file mode 100644 index 000000000000..0a44f40b593f --- /dev/null +++ b/packages/firebase_database/firebase_database/windows/messages.g.h @@ -0,0 +1,449 @@ +// 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_database_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 FirebaseDatabaseHostApi; + friend class FirebaseDatabaseFlutterApi; + ErrorOr() = default; + T TakeValue() && { return std::get(std::move(v_)); } + + std::variant v_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class DatabasePigeonSettings { + public: + // Constructs an object setting all non-nullable fields. + DatabasePigeonSettings(); + + // Constructs an object setting all fields. + explicit DatabasePigeonSettings(const bool* persistence_enabled, + const int64_t* cache_size_bytes, + const bool* logging_enabled, + const std::string* emulator_host, + const int64_t* emulator_port); + + const bool* persistence_enabled() const; + void set_persistence_enabled(const bool* value_arg); + void set_persistence_enabled(bool value_arg); + + const int64_t* cache_size_bytes() const; + void set_cache_size_bytes(const int64_t* value_arg); + void set_cache_size_bytes(int64_t value_arg); + + const bool* logging_enabled() const; + void set_logging_enabled(const bool* value_arg); + void set_logging_enabled(bool value_arg); + + const std::string* emulator_host() const; + void set_emulator_host(const std::string_view* value_arg); + void set_emulator_host(std::string_view value_arg); + + const int64_t* emulator_port() const; + void set_emulator_port(const int64_t* value_arg); + void set_emulator_port(int64_t value_arg); + + private: + static DatabasePigeonSettings FromEncodableList( + const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class DatabasePigeonFirebaseApp; + friend class FirebaseDatabaseHostApi; + friend class FirebaseDatabaseFlutterApi; + friend class PigeonInternalCodecSerializer; + std::optional persistence_enabled_; + std::optional cache_size_bytes_; + std::optional logging_enabled_; + std::optional emulator_host_; + std::optional emulator_port_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class DatabasePigeonFirebaseApp { + public: + // Constructs an object setting all non-nullable fields. + explicit DatabasePigeonFirebaseApp(const std::string& app_name, + const DatabasePigeonSettings& settings); + + // Constructs an object setting all fields. + explicit DatabasePigeonFirebaseApp(const std::string& app_name, + const std::string* database_u_r_l, + const DatabasePigeonSettings& settings); + + ~DatabasePigeonFirebaseApp() = default; + DatabasePigeonFirebaseApp(const DatabasePigeonFirebaseApp& other); + DatabasePigeonFirebaseApp& operator=(const DatabasePigeonFirebaseApp& other); + DatabasePigeonFirebaseApp(DatabasePigeonFirebaseApp&& other) = default; + DatabasePigeonFirebaseApp& operator=( + DatabasePigeonFirebaseApp&& other) noexcept = default; + const std::string& app_name() const; + void set_app_name(std::string_view value_arg); + + const std::string* database_u_r_l() const; + void set_database_u_r_l(const std::string_view* value_arg); + void set_database_u_r_l(std::string_view value_arg); + + const DatabasePigeonSettings& settings() const; + void set_settings(const DatabasePigeonSettings& value_arg); + + private: + static DatabasePigeonFirebaseApp FromEncodableList( + const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class FirebaseDatabaseHostApi; + friend class FirebaseDatabaseFlutterApi; + friend class PigeonInternalCodecSerializer; + std::string app_name_; + std::optional database_u_r_l_; + std::unique_ptr settings_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class DatabaseReferencePlatform { + public: + // Constructs an object setting all fields. + explicit DatabaseReferencePlatform(const std::string& path); + + const std::string& path() const; + void set_path(std::string_view value_arg); + + private: + static DatabaseReferencePlatform FromEncodableList( + const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class FirebaseDatabaseHostApi; + friend class FirebaseDatabaseFlutterApi; + friend class PigeonInternalCodecSerializer; + std::string path_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class DatabaseReferenceRequest { + public: + // Constructs an object setting all non-nullable fields. + explicit DatabaseReferenceRequest(const std::string& path); + + // Constructs an object setting all fields. + explicit DatabaseReferenceRequest(const std::string& path, + const flutter::EncodableValue* value, + const flutter::EncodableValue* priority); + + const std::string& path() const; + void set_path(std::string_view value_arg); + + const flutter::EncodableValue* value() const; + void set_value(const flutter::EncodableValue* value_arg); + void set_value(const flutter::EncodableValue& value_arg); + + const flutter::EncodableValue* priority() const; + void set_priority(const flutter::EncodableValue* value_arg); + void set_priority(const flutter::EncodableValue& value_arg); + + private: + static DatabaseReferenceRequest FromEncodableList( + const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class FirebaseDatabaseHostApi; + friend class FirebaseDatabaseFlutterApi; + friend class PigeonInternalCodecSerializer; + std::string path_; + std::optional value_; + std::optional priority_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class UpdateRequest { + public: + // Constructs an object setting all fields. + explicit UpdateRequest(const std::string& path, + const flutter::EncodableMap& value); + + const std::string& path() const; + void set_path(std::string_view value_arg); + + const flutter::EncodableMap& value() const; + void set_value(const flutter::EncodableMap& value_arg); + + private: + static UpdateRequest FromEncodableList(const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class FirebaseDatabaseHostApi; + friend class FirebaseDatabaseFlutterApi; + friend class PigeonInternalCodecSerializer; + std::string path_; + flutter::EncodableMap value_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class TransactionRequest { + public: + // Constructs an object setting all fields. + explicit TransactionRequest(const std::string& path, int64_t transaction_key, + bool apply_locally); + + const std::string& path() const; + void set_path(std::string_view value_arg); + + int64_t transaction_key() const; + void set_transaction_key(int64_t value_arg); + + bool apply_locally() const; + void set_apply_locally(bool value_arg); + + private: + static TransactionRequest FromEncodableList( + const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class FirebaseDatabaseHostApi; + friend class FirebaseDatabaseFlutterApi; + friend class PigeonInternalCodecSerializer; + std::string path_; + int64_t transaction_key_; + bool apply_locally_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class QueryRequest { + public: + // Constructs an object setting all non-nullable fields. + explicit QueryRequest(const std::string& path, + const flutter::EncodableList& modifiers); + + // Constructs an object setting all fields. + explicit QueryRequest(const std::string& path, + const flutter::EncodableList& modifiers, + const bool* value); + + const std::string& path() const; + void set_path(std::string_view value_arg); + + const flutter::EncodableList& modifiers() const; + void set_modifiers(const flutter::EncodableList& value_arg); + + const bool* value() const; + void set_value(const bool* value_arg); + void set_value(bool value_arg); + + private: + static QueryRequest FromEncodableList(const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class FirebaseDatabaseHostApi; + friend class FirebaseDatabaseFlutterApi; + friend class PigeonInternalCodecSerializer; + std::string path_; + flutter::EncodableList modifiers_; + std::optional value_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class TransactionHandlerResult { + public: + // Constructs an object setting all non-nullable fields. + explicit TransactionHandlerResult(bool aborted, bool exception); + + // Constructs an object setting all fields. + explicit TransactionHandlerResult(const flutter::EncodableValue* value, + bool aborted, bool exception); + + const flutter::EncodableValue* value() const; + void set_value(const flutter::EncodableValue* value_arg); + void set_value(const flutter::EncodableValue& value_arg); + + bool aborted() const; + void set_aborted(bool value_arg); + + bool exception() const; + void set_exception(bool value_arg); + + private: + static TransactionHandlerResult FromEncodableList( + const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class FirebaseDatabaseHostApi; + friend class FirebaseDatabaseFlutterApi; + friend class PigeonInternalCodecSerializer; + std::optional value_; + bool aborted_; + bool exception_; +}; + +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 FirebaseDatabaseHostApi { + public: + FirebaseDatabaseHostApi(const FirebaseDatabaseHostApi&) = delete; + FirebaseDatabaseHostApi& operator=(const FirebaseDatabaseHostApi&) = delete; + virtual ~FirebaseDatabaseHostApi() {} + virtual void GoOnline( + const DatabasePigeonFirebaseApp& app, + std::function reply)> result) = 0; + virtual void GoOffline( + const DatabasePigeonFirebaseApp& app, + std::function reply)> result) = 0; + virtual void SetPersistenceEnabled( + const DatabasePigeonFirebaseApp& app, bool enabled, + std::function reply)> result) = 0; + virtual void SetPersistenceCacheSizeBytes( + const DatabasePigeonFirebaseApp& app, int64_t cache_size, + std::function reply)> result) = 0; + virtual void SetLoggingEnabled( + const DatabasePigeonFirebaseApp& app, bool enabled, + std::function reply)> result) = 0; + virtual void UseDatabaseEmulator( + const DatabasePigeonFirebaseApp& app, const std::string& host, + int64_t port, + std::function reply)> result) = 0; + virtual void Ref( + const DatabasePigeonFirebaseApp& app, const std::string* path, + std::function reply)> result) = 0; + virtual void RefFromURL( + const DatabasePigeonFirebaseApp& app, const std::string& url, + std::function reply)> result) = 0; + virtual void PurgeOutstandingWrites( + const DatabasePigeonFirebaseApp& app, + std::function reply)> result) = 0; + virtual void DatabaseReferenceSet( + const DatabasePigeonFirebaseApp& app, + const DatabaseReferenceRequest& request, + std::function reply)> result) = 0; + virtual void DatabaseReferenceSetWithPriority( + const DatabasePigeonFirebaseApp& app, + const DatabaseReferenceRequest& request, + std::function reply)> result) = 0; + virtual void DatabaseReferenceUpdate( + const DatabasePigeonFirebaseApp& app, const UpdateRequest& request, + std::function reply)> result) = 0; + virtual void DatabaseReferenceSetPriority( + const DatabasePigeonFirebaseApp& app, + const DatabaseReferenceRequest& request, + std::function reply)> result) = 0; + virtual void DatabaseReferenceRunTransaction( + const DatabasePigeonFirebaseApp& app, const TransactionRequest& request, + std::function reply)> result) = 0; + virtual void DatabaseReferenceGetTransactionResult( + const DatabasePigeonFirebaseApp& app, int64_t transaction_key, + std::function reply)> result) = 0; + virtual void OnDisconnectSet( + const DatabasePigeonFirebaseApp& app, + const DatabaseReferenceRequest& request, + std::function reply)> result) = 0; + virtual void OnDisconnectSetWithPriority( + const DatabasePigeonFirebaseApp& app, + const DatabaseReferenceRequest& request, + std::function reply)> result) = 0; + virtual void OnDisconnectUpdate( + const DatabasePigeonFirebaseApp& app, const UpdateRequest& request, + std::function reply)> result) = 0; + virtual void OnDisconnectCancel( + const DatabasePigeonFirebaseApp& app, const std::string& path, + std::function reply)> result) = 0; + virtual void QueryObserve( + const DatabasePigeonFirebaseApp& app, const QueryRequest& request, + std::function reply)> result) = 0; + virtual void QueryKeepSynced( + const DatabasePigeonFirebaseApp& app, const QueryRequest& request, + std::function reply)> result) = 0; + virtual void QueryGet( + const DatabasePigeonFirebaseApp& app, const QueryRequest& request, + std::function reply)> result) = 0; + + // The codec used by FirebaseDatabaseHostApi. + static const flutter::StandardMessageCodec& GetCodec(); + // Sets up an instance of `FirebaseDatabaseHostApi` to handle messages through + // the `binary_messenger`. + static void SetUp(flutter::BinaryMessenger* binary_messenger, + FirebaseDatabaseHostApi* api); + static void SetUp(flutter::BinaryMessenger* binary_messenger, + FirebaseDatabaseHostApi* api, + const std::string& message_channel_suffix); + static flutter::EncodableValue WrapError(std::string_view error_message); + static flutter::EncodableValue WrapError(const FlutterError& error); + + protected: + FirebaseDatabaseHostApi() = default; +}; +// Generated class from Pigeon that represents Flutter messages that can be +// called from C++. +class FirebaseDatabaseFlutterApi { + public: + FirebaseDatabaseFlutterApi(flutter::BinaryMessenger* binary_messenger); + FirebaseDatabaseFlutterApi(flutter::BinaryMessenger* binary_messenger, + const std::string& message_channel_suffix); + static const flutter::StandardMessageCodec& GetCodec(); + void CallTransactionHandler( + int64_t transaction_key, const flutter::EncodableValue* snapshot_value, + std::function&& on_success, + std::function&& on_error); + + private: + flutter::BinaryMessenger* binary_messenger_; + std::string message_channel_suffix_; +}; + +} // namespace firebase_database_windows +#endif // PIGEON_MESSAGES_G_H_ diff --git a/packages/firebase_database/firebase_database/windows/plugin_version.h.in b/packages/firebase_database/firebase_database/windows/plugin_version.h.in new file mode 100644 index 000000000000..7a405b7c9894 --- /dev/null +++ b/packages/firebase_database/firebase_database/windows/plugin_version.h.in @@ -0,0 +1,13 @@ +// 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. + +#ifndef PLUGIN_VERSION_CONFIG_H +#define PLUGIN_VERSION_CONFIG_H + +namespace firebase_database_windows { + +std::string getPluginVersion() { return "@PLUGIN_VERSION@"; } +} // namespace firebase_database_windows + +#endif // PLUGIN_VERSION_CONFIG_H diff --git a/packages/firebase_database/firebase_database_platform_interface/pigeons/messages.dart b/packages/firebase_database/firebase_database_platform_interface/pigeons/messages.dart index 3a752d5c8640..2db035bbae4c 100644 --- a/packages/firebase_database/firebase_database_platform_interface/pigeons/messages.dart +++ b/packages/firebase_database/firebase_database_platform_interface/pigeons/messages.dart @@ -16,6 +16,9 @@ import 'package:pigeon/pigeon.dart'; ), swiftOut: '../firebase_database/ios/firebase_database/Sources/firebase_database/FirebaseDatabaseMessages.g.swift', + cppHeaderOut: '../firebase_database/windows/messages.g.h', + cppSourceOut: '../firebase_database/windows/messages.g.cpp', + cppOptions: CppOptions(namespace: 'firebase_database_windows'), copyrightHeader: 'pigeons/copyright.txt', ), ) diff --git a/tests/windows/flutter/CMakeLists.txt b/tests/windows/flutter/CMakeLists.txt index 930d2071a324..903f4899d6fc 100644 --- a/tests/windows/flutter/CMakeLists.txt +++ b/tests/windows/flutter/CMakeLists.txt @@ -10,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") @@ -92,7 +97,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ + ${FLUTTER_TARGET_PLATFORM} $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS diff --git a/tests/windows/flutter/generated_plugin_registrant.cc b/tests/windows/flutter/generated_plugin_registrant.cc index 2fda6bf3095a..9a180bb54481 100644 --- a/tests/windows/flutter/generated_plugin_registrant.cc +++ b/tests/windows/flutter/generated_plugin_registrant.cc @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -16,6 +17,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi")); FirebaseCorePluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); + FirebaseDatabasePluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FirebaseDatabasePluginCApi")); FirebaseRemoteConfigPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FirebaseRemoteConfigPluginCApi")); FirebaseStoragePluginCApiRegisterWithRegistrar( diff --git a/tests/windows/flutter/generated_plugins.cmake b/tests/windows/flutter/generated_plugins.cmake index 7a8854af51e0..1a9da22be867 100644 --- a/tests/windows/flutter/generated_plugins.cmake +++ b/tests/windows/flutter/generated_plugins.cmake @@ -5,6 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST firebase_auth firebase_core + firebase_database firebase_remote_config firebase_storage )