diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index c67986f5f525992effa84d8a942a0004423889c0..05fd6718a9dfa5cb862a5f822ccd5f8837608671 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -55,6 +55,10 @@ class PlatformViewHolder { FXL_DISALLOW_COPY_AND_ASSIGN(PlatformViewHolder); }; +struct _FlutterPlatformMessageResponseHandle { + fxl::RefPtr message; +}; + FlutterResult FlutterEngineRun(size_t version, const FlutterRendererConfig* config, const FlutterProjectArgs* args, @@ -101,6 +105,25 @@ FlutterResult FlutterEngineRun(size_t version, return ptr(user_data); }; + shell::PlatformViewEmbedder::PlatformMessageResponseCallback + platform_message_response_callback = nullptr; + if (SAFE_ACCESS(args, platform_message_callback, nullptr) != nullptr) { + platform_message_response_callback = + [ ptr = args->platform_message_callback, + user_data ](fxl::RefPtr message) { + auto handle = new FlutterPlatformMessageResponseHandle(); + const FlutterPlatformMessage incoming_message = { + .struct_size = sizeof(FlutterPlatformMessage), + .channel = message->channel().c_str(), + .message = message->data().data(), + .message_size = message->data().size(), + .response_handle = handle, + }; + handle->message = std::move(message); + return ptr(&incoming_message, user_data); + }; + } + std::string icu_data_path; if (SAFE_ACCESS(args, icu_data_path, nullptr) != nullptr) { icu_data_path = SAFE_ACCESS(args, icu_data_path, nullptr); @@ -128,7 +151,9 @@ FlutterResult FlutterEngineRun(size_t version, .gl_make_current_callback = make_current, .gl_clear_current_callback = clear_current, .gl_present_callback = present, - .gl_fbo_callback = fbo_callback}; + .gl_fbo_callback = fbo_callback, + .platform_message_response_callback = platform_message_response_callback, + }; auto platform_view = std::make_shared(table); platform_view->Attach(); @@ -274,3 +299,25 @@ FlutterResult FlutterEngineSendPlatformMessage( }); return kSuccess; } + +FlutterResult FlutterEngineSendPlatformMessageResponse( + FlutterEngine engine, + const FlutterPlatformMessageResponseHandle* handle, + const uint8_t* data, + size_t data_length) { + if (data_length != 0 && data == nullptr) { + return kInvalidArguments; + } + + auto response = handle->message->response(); + + if (data_length == 0) { + response->CompleteEmpty(); + } else { + response->Complete({data, data + data_length}); + } + + delete handle; + + return kSuccess; +} diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index 1d7e193a5627f4372f9e836e3a195c3ccad635db..96ef4f1048cc6ff94ad6ae5cb8f247c33221525b 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -50,36 +50,6 @@ typedef struct { }; } FlutterRendererConfig; -typedef struct { - // The size of this struct. Must be sizeof(FlutterProjectArgs). - size_t struct_size; - // The path to the FLX file containing project assets. The string can be - // collected after the call to |FlutterEngineRun| returns. The string must be - // NULL terminated. - const char* assets_path; - // The path to the Dart file containing the |main| entry point. The string can - // be collected after the call to |FlutterEngineRun| returns. The string must - // be NULL terminated. - const char* main_path; - // The path to the |.packages| for the project. The string can be collected - // after the call to |FlutterEngineRun| returns. The string must be NULL - // terminated. - const char* packages_path; - // The path to the icudtl.dat file for the project. The string can be - // collected after the call to |FlutterEngineRun| returns. The string must - // be NULL terminated. - const char* icu_data_path; - // The command line argument count used to initialize the project. The string - // can be collected after the call to |FlutterEngineRun| returns. The string - // must be NULL terminated. - int command_line_argc; - // The command line arguments used to initialize the project. The strings can - // be collected after the call to |FlutterEngineRun| returns. The strings must - // be NULL terminated. - const char* const* command_line_argv; - -} FlutterProjectArgs; - typedef struct { // The size of this struct. Must be sizeof(FlutterWindowMetricsEvent). size_t struct_size; @@ -107,14 +77,64 @@ typedef struct { double y; } FlutterPointerEvent; +struct _FlutterPlatformMessageResponseHandle; +typedef struct _FlutterPlatformMessageResponseHandle + FlutterPlatformMessageResponseHandle; + typedef struct { // The size of this struct. Must be sizeof(FlutterPlatformMessage). size_t struct_size; const char* channel; const uint8_t* message; const size_t message_size; + // The response handle on which to invoke + // |FlutterEngineSendPlatformMessageResponse| when the response is ready. This + // field is ignored for messages being sent from the embedder to the + // framework. If the embedder ever receives a message with a non-null response + // handle, that handle must always be used with a + // |FlutterEngineSendPlatformMessageResponse| call. If not, this is a memory + // leak. It is not safe to send multiple responses on a single response + // object. + const FlutterPlatformMessageResponseHandle* response_handle; } FlutterPlatformMessage; +typedef void (*FlutterPlatformMessageCallback)( + const FlutterPlatformMessage* /* message*/, + void* /* user data */); + +typedef struct { + // The size of this struct. Must be sizeof(FlutterProjectArgs). + size_t struct_size; + // The path to the FLX file containing project assets. The string can be + // collected after the call to |FlutterEngineRun| returns. The string must be + // NULL terminated. + const char* assets_path; + // The path to the Dart file containing the |main| entry point. The string can + // be collected after the call to |FlutterEngineRun| returns. The string must + // be NULL terminated. + const char* main_path; + // The path to the |.packages| for the project. The string can be collected + // after the call to |FlutterEngineRun| returns. The string must be NULL + // terminated. + const char* packages_path; + // The path to the icudtl.dat file for the project. The string can be + // collected after the call to |FlutterEngineRun| returns. The string must + // be NULL terminated. + const char* icu_data_path; + // The command line argument count used to initialize the project. The string + // can be collected after the call to |FlutterEngineRun| returns. The string + // must be NULL terminated. + int command_line_argc; + // The command line arguments used to initialize the project. The strings can + // be collected after the call to |FlutterEngineRun| returns. The strings must + // be NULL terminated. + const char* const* command_line_argv; + // The callback invoked by the engine in order to give the embedder the chance + // to respond to platform messages from the Dart application. The callback + // will be invoked on the thread on which the |FlutterEngineRun| call is made. + FlutterPlatformMessageCallback platform_message_callback; +} FlutterProjectArgs; + FLUTTER_EXPORT FlutterResult FlutterEngineRun(size_t version, const FlutterRendererConfig* config, @@ -140,6 +160,13 @@ FlutterResult FlutterEngineSendPlatformMessage( FlutterEngine engine, const FlutterPlatformMessage* message); +FLUTTER_EXPORT +FlutterResult FlutterEngineSendPlatformMessageResponse( + FlutterEngine engine, + const FlutterPlatformMessageResponseHandle* handle, + const uint8_t* data, + size_t data_length); + #if defined(__cplusplus) } // extern "C" #endif diff --git a/shell/platform/embedder/platform_view_embedder.cc b/shell/platform/embedder/platform_view_embedder.cc index d69525b0bade5e3e027df540f8dae136c26e7259..c2cbba72431abfe9508b5d287e4355095e2c86ef 100644 --- a/shell/platform/embedder/platform_view_embedder.cc +++ b/shell/platform/embedder/platform_view_embedder.cc @@ -47,4 +47,22 @@ void PlatformViewEmbedder::RunFromSource(const std::string& assets_directory, FXL_LOG(INFO) << "Hot reloading is unsupported on this platform."; } +void PlatformViewEmbedder::HandlePlatformMessage( + fxl::RefPtr message) { + if (!message) { + return; + } + + if (!message->response()) { + return; + } + + if (dispatch_table_.platform_message_response_callback == nullptr) { + message->response()->CompleteEmpty(); + return; + } + + dispatch_table_.platform_message_response_callback(std::move(message)); +} + } // namespace shell diff --git a/shell/platform/embedder/platform_view_embedder.h b/shell/platform/embedder/platform_view_embedder.h index 75eea0e299c2e61b88dcc7f833c76d732335f406..7f3a4cdd979e16e1631be813a93f41472d4ad591 100644 --- a/shell/platform/embedder/platform_view_embedder.h +++ b/shell/platform/embedder/platform_view_embedder.h @@ -7,17 +7,22 @@ #include "flutter/shell/common/platform_view.h" #include "flutter/shell/gpu/gpu_surface_gl.h" +#include "flutter/shell/platform/embedder/embedder.h" #include "lib/fxl/macros.h" namespace shell { class PlatformViewEmbedder : public PlatformView, public GPUSurfaceGLDelegate { public: + using PlatformMessageResponseCallback = + std::function)>; struct DispatchTable { - std::function gl_make_current_callback; - std::function gl_clear_current_callback; - std::function gl_present_callback; - std::function gl_fbo_callback; + std::function gl_make_current_callback; // required + std::function gl_clear_current_callback; // required + std::function gl_present_callback; // required + std::function gl_fbo_callback; // required + PlatformMessageResponseCallback + platform_message_response_callback; // optional }; PlatformViewEmbedder(DispatchTable dispatch_table); @@ -47,6 +52,10 @@ class PlatformViewEmbedder : public PlatformView, public GPUSurfaceGLDelegate { const std::string& main, const std::string& packages) override; + // |shell::PlatformView| + void HandlePlatformMessage( + fxl::RefPtr message) override; + private: DispatchTable dispatch_table_;