| Flutter iOS 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"
21 #include "include/flutter/engine_method_result.h"
22 #include "include/flutter/method_channel.h"
23 #include "include/flutter/standard_method_codec.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,
34 decltype(&FlutterDesktopMessengerUnlock)>;
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>(
47 FlutterDesktopMessengerAddRef(messenger),
48 &FlutterDesktopMessengerRelease);
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()),
55 &FlutterDesktopMessengerUnlock);
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
81 BinaryMessengerImpl::BinaryMessengerImpl(
82 FlutterDesktopMessengerRef core_messenger)
83 : messenger_(core_messenger) {}
84
85 BinaryMessengerImpl::~BinaryMessengerImpl() = default;
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 };
108 bool result = FlutterDesktopMessengerSendWithReply(
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
136 ReplyManager::ReplyManager(BinaryReply reply_handler)
137 : reply_handler_(std::move(reply_handler)) {
138 assert(reply_handler_);
139 }
140
141 ReplyManager::~ReplyManager() {
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
194 void SetChannelWarnsOnOverflow(BinaryMessenger* messenger,
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
211 TextureRegistrarImpl::TextureRegistrarImpl(
212 FlutterDesktopTextureRegistrarRef texture_registrar_ref)
213 : texture_registrar_ref_(texture_registrar_ref) {}
214
215 TextureRegistrarImpl::~TextureRegistrarImpl() = default;
216
217 int64_t TextureRegistrarImpl::RegisterTexture(TextureVariant* texture) {
218 FlutterDesktopTextureInfo info = {};
219 if (auto pixel_buffer_texture = std::get_if<PixelBufferTexture>(texture)) {
220 info.type = kFlutterDesktopPixelBufferTexture;
221 info.pixel_buffer_config.user_data = pixel_buffer_texture;
222 info.pixel_buffer_config.callback =
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)) {
230 info.type = kFlutterDesktopGpuSurfaceTexture;
231 info.gpu_surface_config.struct_size =
232 sizeof(FlutterDesktopGpuSurfaceTextureConfig);
233 info.gpu_surface_config.type = gpu_surface_texture->surface_type();
234 info.gpu_surface_config.user_data = gpu_surface_texture;
235 info.gpu_surface_config.callback =
236 [](size_t width, size_t height,
237 void* user_data) -> const FlutterDesktopGpuSurfaceDescriptor* {
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
246 int64_t texture_id = FlutterDesktopTextureRegistrarRegisterExternalTexture(
247 texture_registrar_ref_, &info);
248 return texture_id;
249 } // namespace flutter
250
251 bool TextureRegistrarImpl::MarkTextureFrameAvailable(int64_t texture_id) {
252 return FlutterDesktopTextureRegistrarMarkExternalTextureFrameAvailable(
253 texture_registrar_ref_, texture_id);
254 }
255
256 void TextureRegistrarImpl::UnregisterTexture(int64_t texture_id,
257 std::function<void()> callback) {
258 if (callback == nullptr) {
259 FlutterDesktopTextureRegistrarUnregisterExternalTexture(
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);
269 FlutterDesktopTextureRegistrarUnregisterExternalTexture(
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
279 bool TextureRegistrarImpl::UnregisterTexture(int64_t texture_id) {
280 UnregisterTexture(texture_id, nullptr);
281 return true;
282 }
283
284 } // namespace flutter
kOverflowMethod
static NSString *const kOverflowMethod
Definition: FlutterChannels.mm:13
kResizeMethod
static NSString *const kResizeMethod
Definition: FlutterChannels.mm:12
binary_messenger_impl.h
flutter::BinaryMessenger
Definition: binary_messenger.h:28
flutter::BinaryMessengerImpl::~BinaryMessengerImpl
virtual ~BinaryMessengerImpl()
flutter::BinaryMessengerImpl::BinaryMessengerImpl
BinaryMessengerImpl(FlutterDesktopMessengerRef core_messenger)
Definition: core_implementations.cc:81
flutter::BinaryMessengerImpl::SetMessageHandler
void SetMessageHandler(const std::string &channel, BinaryMessageHandler handler) override
Definition: core_implementations.cc:116
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
flutter::EncodableValue
Definition: encodable_value.h:165
flutter::GpuSurfaceTexture
Definition: texture_registrar.h:47
flutter::GpuSurfaceTexture::ObtainDescriptor
const FlutterDesktopGpuSurfaceDescriptor * ObtainDescriptor(size_t width, size_t height) const
Definition: texture_registrar.h:62
flutter::PixelBufferTexture
Definition: texture_registrar.h:19
flutter::PixelBufferTexture::CopyPixelBuffer
const FlutterDesktopPixelBuffer * CopyPixelBuffer(size_t width, size_t height) const
Definition: texture_registrar.h:37
flutter::StandardMethodCodec::GetInstance
static const StandardMethodCodec & GetInstance(const StandardCodecSerializer *serializer=nullptr)
Definition: standard_codec.cc:341
flutter::TextureRegistrarImpl::RegisterTexture
int64_t RegisterTexture(TextureVariant *texture) override
Definition: core_implementations.cc:217
flutter::TextureRegistrarImpl::MarkTextureFrameAvailable
bool MarkTextureFrameAvailable(int64_t texture_id) override
Definition: core_implementations.cc:251
flutter::TextureRegistrarImpl::TextureRegistrarImpl
TextureRegistrarImpl(FlutterDesktopTextureRegistrarRef texture_registrar_ref)
Definition: core_implementations.cc:211
flutter::TextureRegistrarImpl::UnregisterTexture
void UnregisterTexture(int64_t texture_id, std::function< void()> callback) override
Definition: core_implementations.cc:256
flutter::TextureRegistrarImpl::~TextureRegistrarImpl
virtual ~TextureRegistrarImpl()
flutter::internal::ReplyManager::~ReplyManager
~ReplyManager()
Definition: core_implementations.cc:141
flutter::internal::ReplyManager::ReplyManager
ReplyManager(BinaryReply reply_handler_)
Definition: core_implementations.cc:136
flutter::internal::ReplyManager::SendResponseData
void SendResponseData(const std::vector< uint8_t > *data)
Definition: core_implementations.cc:151
engine_method_result.h
FlutterDesktopMessengerRef
struct FlutterDesktopMessenger * FlutterDesktopMessengerRef
Definition: flutter_messenger.h:19
FlutterDesktopMessengerSendResponse
FLUTTER_EXPORT void FlutterDesktopMessengerSendResponse(FlutterDesktopMessengerRef messenger, const FlutterDesktopMessageResponseHandle *handle, const uint8_t *data, size_t data_length)
FlutterDesktopMessengerIsAvailable
FLUTTER_EXPORT bool FlutterDesktopMessengerIsAvailable(FlutterDesktopMessengerRef messenger)
FlutterDesktopMessengerLock
FLUTTER_EXPORT FlutterDesktopMessengerRef FlutterDesktopMessengerLock(FlutterDesktopMessengerRef messenger)
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)
FlutterDesktopMessengerSetCallback
FLUTTER_EXPORT void FlutterDesktopMessengerSetCallback(FlutterDesktopMessengerRef messenger, const char *channel, FlutterDesktopMessageCallback callback, void *user_data)
FlutterDesktopMessengerAddRef
FLUTTER_EXPORT FlutterDesktopMessengerRef FlutterDesktopMessengerAddRef(FlutterDesktopMessengerRef messenger)
FlutterDesktopMessengerSend
FLUTTER_EXPORT bool FlutterDesktopMessengerSend(FlutterDesktopMessengerRef messenger, const char *channel, const uint8_t *message, const size_t message_size)
FlutterDesktopMessengerRelease
FLUTTER_EXPORT void FlutterDesktopMessengerRelease(FlutterDesktopMessengerRef messenger)
FlutterDesktopMessengerUnlock
FLUTTER_EXPORT void FlutterDesktopMessengerUnlock(FlutterDesktopMessengerRef messenger)
FlutterDesktopTextureRegistrarRef
struct FlutterDesktopTextureRegistrar * FlutterDesktopTextureRegistrarRef
Definition: flutter_texture_registrar.h:19
FlutterDesktopTextureRegistrarMarkExternalTextureFrameAvailable
FLUTTER_EXPORT bool FlutterDesktopTextureRegistrarMarkExternalTextureFrameAvailable(FlutterDesktopTextureRegistrarRef texture_registrar, int64_t texture_id)
FlutterDesktopTextureRegistrarUnregisterExternalTexture
FLUTTER_EXPORT void FlutterDesktopTextureRegistrarUnregisterExternalTexture(FlutterDesktopTextureRegistrarRef texture_registrar, int64_t texture_id, void(*callback)(void *user_data), void *user_data)
FlutterDesktopTextureRegistrarRegisterExternalTexture
FLUTTER_EXPORT int64_t FlutterDesktopTextureRegistrarRegisterExternalTexture(FlutterDesktopTextureRegistrarRef texture_registrar, const FlutterDesktopTextureInfo *info)
kFlutterDesktopGpuSurfaceTexture
@ kFlutterDesktopGpuSurfaceTexture
Definition: flutter_texture_registrar.h:28
kFlutterDesktopPixelBufferTexture
@ kFlutterDesktopPixelBufferTexture
Definition: flutter_texture_registrar.h:26
method_channel.h
flutter::internal::SetChannelWarnsOnOverflow
void SetChannelWarnsOnOverflow(BinaryMessenger *messenger, std::string name, bool warns)
Definition: core_implementations.cc:194
flutter::internal::ResizeChannel
void ResizeChannel(BinaryMessenger *messenger, std::string name, int new_size)
Definition: core_implementations.cc:181
flutter
Definition: accessibility_bridge.h:26
flutter::BinaryMessageHandler
std::function< void(const uint8_t *message, size_t message_size, BinaryReply reply)> BinaryMessageHandler
Definition: binary_messenger.h:24
flutter::BinaryReply
std::function< void(const uint8_t *reply, size_t reply_size)> BinaryReply
Definition: binary_messenger.h:17
flutter::EncodableList
std::vector< EncodableValue > EncodableList
Definition: encodable_value.h:94
flutter::TextureVariant
std::variant< PixelBufferTexture, GpuSurfaceTexture > TextureVariant
Definition: texture_registrar.h:79
standard_method_codec.h
FlutterDesktopGpuSurfaceDescriptor
Definition: flutter_texture_registrar.h:70
FlutterDesktopGpuSurfaceTextureConfig
Definition: flutter_texture_registrar.h:138
FlutterDesktopGpuSurfaceTextureConfig::callback
FlutterDesktopGpuSurfaceTextureCallback callback
Definition: flutter_texture_registrar.h:146
FlutterDesktopGpuSurfaceTextureConfig::type
FlutterDesktopGpuSurfaceType type
Definition: flutter_texture_registrar.h:144
FlutterDesktopGpuSurfaceTextureConfig::user_data
void * user_data
Definition: flutter_texture_registrar.h:148
FlutterDesktopGpuSurfaceTextureConfig::struct_size
size_t struct_size
Definition: flutter_texture_registrar.h:141
FlutterDesktopMessage
Definition: flutter_messenger.h:31
FlutterDesktopMessage::message
const uint8_t * message
Definition: flutter_messenger.h:37
FlutterDesktopMessage::response_handle
const FlutterDesktopMessageResponseHandle * response_handle
Definition: flutter_messenger.h:42
FlutterDesktopMessage::message_size
size_t message_size
Definition: flutter_messenger.h:39
FlutterDesktopPixelBuffer
Definition: flutter_texture_registrar.h:56
FlutterDesktopPixelBufferTextureConfig::user_data
void * user_data
Definition: flutter_texture_registrar.h:134
FlutterDesktopPixelBufferTextureConfig::callback
FlutterDesktopPixelBufferTextureCallback callback
Definition: flutter_texture_registrar.h:132
FlutterDesktopTextureInfo
Definition: flutter_texture_registrar.h:151
FlutterDesktopTextureInfo::gpu_surface_config
FlutterDesktopGpuSurfaceTextureConfig gpu_surface_config
Definition: flutter_texture_registrar.h:155
FlutterDesktopTextureInfo::type
FlutterDesktopTextureType type
Definition: flutter_texture_registrar.h:152
FlutterDesktopTextureInfo::pixel_buffer_config
FlutterDesktopPixelBufferTextureConfig pixel_buffer_config
Definition: flutter_texture_registrar.h:154
texture_registrar_impl.h
user_data
void * user_data
Definition: texture_registrar_unittests.cc:27
texture_id
int64_t texture_id
Definition: texture_registrar_unittests.cc:24