Flutter macOS Embedder
core_implementations.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // This file contains the implementations of any class in the wrapper that
6 // - is not fully inline, and
7 // - is necessary for all clients of the wrapper (either app or plugin).
8 // It exists instead of the usual structure of having some_class_name.cc files
9 // so that changes to the set of things that need non-header implementations
10 // are not breaking changes for the template.
11 //
12 // If https://github.com/flutter/flutter/issues/57146 is fixed, this can be
13 // removed in favor of the normal structure since templates will no longer
14 // manually include files.
15 
16 #include <cassert>
17 #include <iostream>
18 #include <variant>
19 
20 #include "binary_messenger_impl.h"
24 #include "texture_registrar_impl.h"
25 
26 namespace flutter {
27 
28 // ========== binary_messenger_impl.h ==========
29 
30 namespace {
31 
32 using FlutterDesktopMessengerScopedLock =
33  std::unique_ptr<FlutterDesktopMessenger,
35 
36 // Passes |message| to |user_data|, which must be a BinaryMessageHandler, along
37 // with a BinaryReply that will send a response on |message|'s response handle.
38 //
39 // This serves as an adaptor between the function-pointer-based message callback
40 // interface provided by the C API and the std::function-based message handler
41 // interface of BinaryMessenger.
42 void ForwardToHandler(FlutterDesktopMessengerRef messenger,
43  const FlutterDesktopMessage* message,
44  void* user_data) {
45  auto* response_handle = message->response_handle;
46  auto messenger_ptr = std::shared_ptr<FlutterDesktopMessenger>(
49  BinaryReply reply_handler = [messenger_ptr, response_handle](
50  const uint8_t* reply,
51  size_t reply_size) mutable {
52  // Note: This lambda can be called on any thread.
53  auto lock = FlutterDesktopMessengerScopedLock(
54  FlutterDesktopMessengerLock(messenger_ptr.get()),
56  if (!FlutterDesktopMessengerIsAvailable(messenger_ptr.get())) {
57  // Drop reply if it comes in after the engine is destroyed.
58  return;
59  }
60  if (!response_handle) {
61  std::cerr << "Error: Response can be set only once. Ignoring "
62  "duplicate response."
63  << std::endl;
64  return;
65  }
66  FlutterDesktopMessengerSendResponse(messenger_ptr.get(), response_handle,
67  reply, reply_size);
68  // The engine frees the response handle once
69  // FlutterDesktopSendMessageResponse is called.
70  response_handle = nullptr;
71  };
72 
73  const BinaryMessageHandler& message_handler =
74  *static_cast<BinaryMessageHandler*>(user_data);
75 
76  message_handler(message->message, message->message_size,
77  std::move(reply_handler));
78 }
79 } // namespace
80 
82  FlutterDesktopMessengerRef core_messenger)
83  : messenger_(core_messenger) {}
84 
86 
87 void BinaryMessengerImpl::Send(const std::string& channel,
88  const uint8_t* message,
89  size_t message_size,
90  BinaryReply reply) const {
91  if (reply == nullptr) {
92  FlutterDesktopMessengerSend(messenger_, channel.c_str(), message,
93  message_size);
94  return;
95  }
96  struct Captures {
97  BinaryReply reply;
98  };
99  auto captures = new Captures();
100  captures->reply = reply;
101 
102  auto message_reply = [](const uint8_t* data, size_t data_size,
103  void* user_data) {
104  auto captures = reinterpret_cast<Captures*>(user_data);
105  captures->reply(data, data_size);
106  delete captures;
107  };
109  messenger_, channel.c_str(), message, message_size, message_reply,
110  captures);
111  if (!result) {
112  delete captures;
113  }
114 }
115 
116 void BinaryMessengerImpl::SetMessageHandler(const std::string& channel,
117  BinaryMessageHandler handler) {
118  if (!handler) {
119  handlers_.erase(channel);
120  FlutterDesktopMessengerSetCallback(messenger_, channel.c_str(), nullptr,
121  nullptr);
122  return;
123  }
124  // Save the handler, to keep it alive.
125  handlers_[channel] = std::move(handler);
126  BinaryMessageHandler* message_handler = &handlers_[channel];
127  // Set an adaptor callback that will invoke the handler.
128  FlutterDesktopMessengerSetCallback(messenger_, channel.c_str(),
129  ForwardToHandler, message_handler);
130 }
131 
132 // ========== engine_method_result.h ==========
133 
134 namespace internal {
135 
137  : reply_handler_(std::move(reply_handler)) {
138  assert(reply_handler_);
139 }
140 
142  if (reply_handler_) {
143  // Warn, rather than send a not-implemented response, since the engine may
144  // no longer be valid at this point.
145  std::cerr
146  << "Warning: Failed to respond to a message. This is a memory leak."
147  << std::endl;
148  }
149 }
150 
151 void ReplyManager::SendResponseData(const std::vector<uint8_t>* data) {
152  if (!reply_handler_) {
153  std::cerr
154  << "Error: Only one of Success, Error, or NotImplemented can be "
155  "called,"
156  << " and it can be called exactly once. Ignoring duplicate result."
157  << std::endl;
158  return;
159  }
160 
161  const uint8_t* message = data && !data->empty() ? data->data() : nullptr;
162  size_t message_size = data ? data->size() : 0;
163  reply_handler_(message, message_size);
164  reply_handler_ = nullptr;
165 }
166 
167 } // namespace internal
168 
169 // ========== method_channel.h ==========
170 
171 namespace {
172 
173 constexpr char kControlChannelName[] = "dev.flutter/channel-buffers";
174 constexpr char kResizeMethod[] = "resize";
175 constexpr char kOverflowMethod[] = "overflow";
176 
177 } // namespace
178 
179 namespace internal {
180 
181 void ResizeChannel(BinaryMessenger* messenger, std::string name, int new_size) {
182  auto control_channel = std::make_unique<MethodChannel<EncodableValue>>(
183  messenger, kControlChannelName, &StandardMethodCodec::GetInstance());
184 
185  // The deserialization logic handles only 32 bits values, see
186  // https://github.com/flutter/engine/blob/93e8901490e78c7ba7e319cce4470d9c6478c6dc/lib/ui/channel_buffers.dart#L495.
187  control_channel->InvokeMethod(
188  kResizeMethod, std::make_unique<EncodableValue>(EncodableList{
189  EncodableValue(name),
190  EncodableValue(static_cast<int32_t>(new_size)),
191  }));
192 }
193 
195  std::string name,
196  bool warns) {
197  auto control_channel = std::make_unique<MethodChannel<EncodableValue>>(
198  messenger, kControlChannelName, &StandardMethodCodec::GetInstance());
199 
200  control_channel->InvokeMethod(kOverflowMethod,
201  std::make_unique<EncodableValue>(EncodableList{
202  EncodableValue(name),
203  EncodableValue(!warns),
204  }));
205 }
206 
207 } // namespace internal
208 
209 // ========== texture_registrar_impl.h ==========
210 
212  FlutterDesktopTextureRegistrarRef texture_registrar_ref)
213  : texture_registrar_ref_(texture_registrar_ref) {}
214 
216 
218  FlutterDesktopTextureInfo info = {};
219  if (auto pixel_buffer_texture = std::get_if<PixelBufferTexture>(texture)) {
221  info.pixel_buffer_config.user_data = pixel_buffer_texture;
223  [](size_t width, size_t height,
224  void* user_data) -> const FlutterDesktopPixelBuffer* {
225  auto texture = static_cast<PixelBufferTexture*>(user_data);
226  return texture->CopyPixelBuffer(width, height);
227  };
228  } else if (auto gpu_surface_texture =
229  std::get_if<GpuSurfaceTexture>(texture)) {
233  info.gpu_surface_config.type = gpu_surface_texture->surface_type();
234  info.gpu_surface_config.user_data = gpu_surface_texture;
236  [](size_t width, size_t height,
238  auto texture = static_cast<GpuSurfaceTexture*>(user_data);
239  return texture->ObtainDescriptor(width, height);
240  };
241  } else {
242  std::cerr << "Attempting to register unknown texture variant." << std::endl;
243  return -1;
244  }
245 
247  texture_registrar_ref_, &info);
248  return texture_id;
249 } // namespace flutter
250 
253  texture_registrar_ref_, texture_id);
254 }
255 
257  std::function<void()> callback) {
258  if (callback == nullptr) {
260  texture_registrar_ref_, texture_id, nullptr, nullptr);
261  return;
262  }
263 
264  struct Captures {
265  std::function<void()> callback;
266  };
267  auto captures = new Captures();
268  captures->callback = std::move(callback);
270  texture_registrar_ref_, texture_id,
271  [](void* opaque) {
272  auto captures = reinterpret_cast<Captures*>(opaque);
273  captures->callback();
274  delete captures;
275  },
276  captures);
277 }
278 
280  UnregisterTexture(texture_id, nullptr);
281  return true;
282 }
283 
284 } // namespace flutter
flutter::internal::ReplyManager::ReplyManager
ReplyManager(BinaryReply reply_handler_)
Definition: core_implementations.cc:136
flutter::TextureRegistrarImpl::TextureRegistrarImpl
TextureRegistrarImpl(FlutterDesktopTextureRegistrarRef texture_registrar_ref)
Definition: core_implementations.cc:211
engine_method_result.h
FlutterDesktopMessengerAddRef
FLUTTER_EXPORT FlutterDesktopMessengerRef FlutterDesktopMessengerAddRef(FlutterDesktopMessengerRef messenger)
FlutterDesktopMessengerUnlock
FLUTTER_EXPORT void FlutterDesktopMessengerUnlock(FlutterDesktopMessengerRef messenger)
flutter::BinaryMessengerImpl::BinaryMessengerImpl
BinaryMessengerImpl(FlutterDesktopMessengerRef core_messenger)
Definition: core_implementations.cc:81
kFlutterDesktopGpuSurfaceTexture
@ kFlutterDesktopGpuSurfaceTexture
Definition: flutter_texture_registrar.h:28
FlutterDesktopTextureRegistrarRegisterExternalTexture
FLUTTER_EXPORT int64_t FlutterDesktopTextureRegistrarRegisterExternalTexture(FlutterDesktopTextureRegistrarRef texture_registrar, const FlutterDesktopTextureInfo *info)
kOverflowMethod
static NSString *const kOverflowMethod
Definition: FlutterChannels.mm:13
FlutterDesktopPixelBuffer
Definition: flutter_texture_registrar.h:56
flutter::TextureRegistrarImpl::MarkTextureFrameAvailable
bool MarkTextureFrameAvailable(int64_t texture_id) override
Definition: core_implementations.cc:251
FlutterDesktopMessengerSendWithReply
FLUTTER_EXPORT bool FlutterDesktopMessengerSendWithReply(FlutterDesktopMessengerRef messenger, const char *channel, const uint8_t *message, const size_t message_size, const FlutterDesktopBinaryReply reply, void *user_data)
user_data
void * user_data
Definition: texture_registrar_unittests.cc:27
FlutterDesktopPixelBufferTextureConfig::user_data
void * user_data
Definition: flutter_texture_registrar.h:134
standard_method_codec.h
FlutterDesktopGpuSurfaceTextureConfig::user_data
void * user_data
Definition: flutter_texture_registrar.h:148
flutter::BinaryMessengerImpl::~BinaryMessengerImpl
virtual ~BinaryMessengerImpl()
FlutterDesktopPixelBufferTextureConfig::callback
FlutterDesktopPixelBufferTextureCallback callback
Definition: flutter_texture_registrar.h:132
flutter::BinaryMessenger
Definition: binary_messenger.h:28
flutter::GpuSurfaceTexture
Definition: texture_registrar.h:47
FlutterDesktopTextureInfo::type
FlutterDesktopTextureType type
Definition: flutter_texture_registrar.h:152
kResizeMethod
static NSString *const kResizeMethod
Definition: FlutterChannels.mm:12
FlutterDesktopMessengerSetCallback
FLUTTER_EXPORT void FlutterDesktopMessengerSetCallback(FlutterDesktopMessengerRef messenger, const char *channel, FlutterDesktopMessageCallback callback, void *user_data)
FlutterDesktopMessage::message_size
size_t message_size
Definition: flutter_messenger.h:39
FlutterDesktopTextureRegistrarRef
struct FlutterDesktopTextureRegistrar * FlutterDesktopTextureRegistrarRef
Definition: flutter_texture_registrar.h:19
FlutterDesktopGpuSurfaceTextureConfig::struct_size
size_t struct_size
Definition: flutter_texture_registrar.h:141
FlutterDesktopTextureInfo::pixel_buffer_config
FlutterDesktopPixelBufferTextureConfig pixel_buffer_config
Definition: flutter_texture_registrar.h:154
flutter::BinaryReply
std::function< void(const uint8_t *reply, size_t reply_size)> BinaryReply
Definition: binary_messenger.h:17
FlutterDesktopGpuSurfaceTextureConfig::type
FlutterDesktopGpuSurfaceType type
Definition: flutter_texture_registrar.h:144
flutter::PixelBufferTexture::CopyPixelBuffer
const FlutterDesktopPixelBuffer * CopyPixelBuffer(size_t width, size_t height) const
Definition: texture_registrar.h:37
FlutterDesktopTextureInfo
Definition: flutter_texture_registrar.h:151
FlutterDesktopMessengerRelease
FLUTTER_EXPORT void FlutterDesktopMessengerRelease(FlutterDesktopMessengerRef messenger)
FlutterDesktopGpuSurfaceTextureConfig::callback
FlutterDesktopGpuSurfaceTextureCallback callback
Definition: flutter_texture_registrar.h:146
flutter::TextureVariant
std::variant< PixelBufferTexture, GpuSurfaceTexture > TextureVariant
Definition: texture_registrar.h:79
FlutterDesktopMessengerSendResponse
FLUTTER_EXPORT void FlutterDesktopMessengerSendResponse(FlutterDesktopMessengerRef messenger, const FlutterDesktopMessageResponseHandle *handle, const uint8_t *data, size_t data_length)
flutter::internal::ResizeChannel
void ResizeChannel(BinaryMessenger *messenger, std::string name, int new_size)
Definition: core_implementations.cc:181
binary_messenger_impl.h
flutter::internal::ReplyManager::~ReplyManager
~ReplyManager()
Definition: core_implementations.cc:141
flutter
Definition: AccessibilityBridgeMac.h:16
FlutterDesktopGpuSurfaceDescriptor
Definition: flutter_texture_registrar.h:70
flutter::TextureRegistrarImpl::~TextureRegistrarImpl
virtual ~TextureRegistrarImpl()
flutter::PixelBufferTexture
Definition: texture_registrar.h:19
flutter::TextureRegistrarImpl::UnregisterTexture
void UnregisterTexture(int64_t texture_id, std::function< void()> callback) override
Definition: core_implementations.cc:256
FlutterDesktopTextureInfo::gpu_surface_config
FlutterDesktopGpuSurfaceTextureConfig gpu_surface_config
Definition: flutter_texture_registrar.h:155
FlutterDesktopMessengerLock
FLUTTER_EXPORT FlutterDesktopMessengerRef FlutterDesktopMessengerLock(FlutterDesktopMessengerRef messenger)
flutter::EncodableValue
Definition: encodable_value.h:165
flutter::internal::SetChannelWarnsOnOverflow
void SetChannelWarnsOnOverflow(BinaryMessenger *messenger, std::string name, bool warns)
Definition: core_implementations.cc:194
flutter::BinaryMessengerImpl::SetMessageHandler
void SetMessageHandler(const std::string &channel, BinaryMessageHandler handler) override
Definition: core_implementations.cc:116
FlutterDesktopMessengerSend
FLUTTER_EXPORT bool FlutterDesktopMessengerSend(FlutterDesktopMessengerRef messenger, const char *channel, const uint8_t *message, const size_t message_size)
FlutterDesktopTextureRegistrarUnregisterExternalTexture
FLUTTER_EXPORT void FlutterDesktopTextureRegistrarUnregisterExternalTexture(FlutterDesktopTextureRegistrarRef texture_registrar, int64_t texture_id, void(*callback)(void *user_data), void *user_data)
FlutterDesktopMessengerRef
struct FlutterDesktopMessenger * FlutterDesktopMessengerRef
Definition: flutter_messenger.h:19
flutter::EncodableList
std::vector< EncodableValue > EncodableList
Definition: encodable_value.h:94
method_channel.h
FlutterDesktopMessage
Definition: flutter_messenger.h:31
FlutterDesktopGpuSurfaceTextureConfig
Definition: flutter_texture_registrar.h:138
flutter::internal::ReplyManager::SendResponseData
void SendResponseData(const std::vector< uint8_t > *data)
Definition: core_implementations.cc:151
FlutterDesktopTextureRegistrarMarkExternalTextureFrameAvailable
FLUTTER_EXPORT bool FlutterDesktopTextureRegistrarMarkExternalTextureFrameAvailable(FlutterDesktopTextureRegistrarRef texture_registrar, int64_t texture_id)
flutter::TextureRegistrarImpl::RegisterTexture
int64_t RegisterTexture(TextureVariant *texture) override
Definition: core_implementations.cc:217
texture_registrar_impl.h
flutter::BinaryMessageHandler
std::function< void(const uint8_t *message, size_t message_size, BinaryReply reply)> BinaryMessageHandler
Definition: binary_messenger.h:24
flutter::GpuSurfaceTexture::ObtainDescriptor
const FlutterDesktopGpuSurfaceDescriptor * ObtainDescriptor(size_t width, size_t height) const
Definition: texture_registrar.h:62
FlutterDesktopMessage::response_handle
const FlutterDesktopMessageResponseHandle * response_handle
Definition: flutter_messenger.h:42
FlutterDesktopMessengerIsAvailable
FLUTTER_EXPORT bool FlutterDesktopMessengerIsAvailable(FlutterDesktopMessengerRef messenger)
FlutterDesktopMessage::message
const uint8_t * message
Definition: flutter_messenger.h:37
texture_id
int64_t texture_id
Definition: texture_registrar_unittests.cc:24
kFlutterDesktopPixelBufferTexture
@ kFlutterDesktopPixelBufferTexture
Definition: flutter_texture_registrar.h:26
flutter::StandardMethodCodec::GetInstance
static const StandardMethodCodec & GetInstance(const StandardCodecSerializer *serializer=nullptr)
Definition: standard_codec.cc:340
flutter::BinaryMessengerImpl::Send
void Send(const std::string &channel, const uint8_t *message, size_t message_size, BinaryReply reply) const override
Definition: core_implementations.cc:87