| Flutter Linux Embedder |

fl_event_channel.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 #include "flutter/shell/platform/linux/public/flutter_linux/fl_event_channel.h"
6
7 #include <gmodule.h>
8
9 #include "flutter/shell/platform/linux/fl_method_codec_private.h"
10
11 static constexpr char kListenMethod[] = "listen";
12 static constexpr char kCancelMethod[] = "cancel";
13 static constexpr char kEventRequestError[] = "error";
14
15 struct _FlEventChannel {
16 GObject parent_instance;
17
18 // Messenger to communicate on.
19 FlBinaryMessenger* messenger;
20
21 // TRUE if the channel has been closed.
22 gboolean channel_closed;
23
24 // Channel name.
25 gchar* name;
26
27 // Codec to en/decode messages.
28 FlMethodCodec* codec;
29
30 // Function called when the stream is listened to / cancelled.
31 FlEventChannelHandler listen_handler;
32 FlEventChannelHandler cancel_handler;
33 gpointer handler_data;
34 GDestroyNotify handler_data_destroy_notify;
35 };
36
37 struct _FlEventChannelResponseHandle {
38 GObject parent_instance;
39
40 FlBinaryMessengerResponseHandle* response_handle;
41 };
42
43 G_DEFINE_TYPE(FlEventChannel, fl_event_channel, G_TYPE_OBJECT)
44
45 // Handle method calls from the Dart side of the channel.
46 static FlMethodErrorResponse* handle_method_call(FlEventChannel* self,
47 const gchar* name,
48 FlValue* args) {
49 FlEventChannelHandler handler;
50 if (g_strcmp0(name, kListenMethod) == 0) {
51 handler = self->listen_handler;
52 } else if (g_strcmp0(name, kCancelMethod) == 0) {
53 handler = self->cancel_handler;
54 } else {
55 g_autofree gchar* message =
56 g_strdup_printf("Unknown event channel request '%s'", name);
57 return fl_method_error_response_new(kEventRequestError, message, nullptr);
58 }
59
60 // If not handled, just accept requests.
61 if (handler == nullptr) {
62 return nullptr;
63 }
64
65 return handler(self, args, self->handler_data);
66 }
67
68 // Called when a binary message is received on this channel.
69 static void message_cb(FlBinaryMessenger* messenger,
70 const gchar* channel,
71 GBytes* message,
72 FlBinaryMessengerResponseHandle* response_handle,
73 gpointer user_data) {
74 FlEventChannel* self = FL_EVENT_CHANNEL(user_data);
75
76 g_autofree gchar* name = nullptr;
77 g_autoptr(GError) error = nullptr;
78 g_autoptr(FlValue) args = nullptr;
79 if (!fl_method_codec_decode_method_call(self->codec, message, &name, &args,
80 &error)) {
81 g_warning("Failed to decode message on event channel %s: %s", self->name,
82 error->message);
83 fl_binary_messenger_send_response(messenger, response_handle, nullptr,
84 nullptr);
85 return;
86 }
87
88 g_autoptr(FlMethodErrorResponse) response =
89 handle_method_call(self, name, args);
90
91 g_autoptr(GBytes) data = nullptr;
92 if (response == nullptr) {
93 g_autoptr(GError) codec_error = nullptr;
94 data = fl_method_codec_encode_success_envelope(self->codec, nullptr,
95 &codec_error);
96 if (data == nullptr) {
97 g_warning("Failed to encode event channel %s success response: %s",
98 self->name, codec_error->message);
99 }
100 } else {
101 g_autoptr(GError) codec_error = nullptr;
102 data = fl_method_codec_encode_error_envelope(
103 self->codec, fl_method_error_response_get_code(response),
104 fl_method_error_response_get_message(response),
105 fl_method_error_response_get_details(response), &codec_error);
106 if (data == nullptr) {
107 g_warning("Failed to encode event channel %s error response: %s",
108 self->name, codec_error->message);
109 }
110 }
111
112 if (!fl_binary_messenger_send_response(messenger, response_handle, data,
113 &error)) {
114 g_warning("Failed to send event channel response: %s", error->message);
115 }
116 }
117
118 // Removes handlers and their associated data.
119 static void remove_handlers(FlEventChannel* self) {
120 if (self->handler_data_destroy_notify != nullptr) {
121 self->handler_data_destroy_notify(self->handler_data);
122 }
123 self->listen_handler = nullptr;
124 self->cancel_handler = nullptr;
125 self->handler_data = nullptr;
126 self->handler_data_destroy_notify = nullptr;
127 }
128
129 // Called when the channel handler is closed.
130 static void channel_closed_cb(gpointer user_data) {
131 g_autoptr(FlEventChannel) self = FL_EVENT_CHANNEL(user_data);
132 self->channel_closed = TRUE;
133 remove_handlers(self);
134 }
135
136 static void fl_event_channel_dispose(GObject* object) {
137 FlEventChannel* self = FL_EVENT_CHANNEL(object);
138
139 if (!self->channel_closed) {
140 fl_binary_messenger_set_message_handler_on_channel(
141 self->messenger, self->name, nullptr, nullptr, nullptr);
142 }
143
144 g_clear_object(&self->messenger);
145 g_clear_pointer(&self->name, g_free);
146 g_clear_object(&self->codec);
147
148 remove_handlers(self);
149
150 G_OBJECT_CLASS(fl_event_channel_parent_class)->dispose(object);
151 }
152
153 static void fl_event_channel_class_init(FlEventChannelClass* klass) {
154 G_OBJECT_CLASS(klass)->dispose = fl_event_channel_dispose;
155 }
156
157 static void fl_event_channel_init(FlEventChannel* self) {}
158
159 G_MODULE_EXPORT FlEventChannel* fl_event_channel_new(
160 FlBinaryMessenger* messenger,
161 const gchar* name,
162 FlMethodCodec* codec) {
163 g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);
164 g_return_val_if_fail(name != nullptr, nullptr);
165 g_return_val_if_fail(FL_IS_METHOD_CODEC(codec), nullptr);
166
167 FlEventChannel* self =
168 FL_EVENT_CHANNEL(g_object_new(fl_event_channel_get_type(), nullptr));
169
170 self->messenger = FL_BINARY_MESSENGER(g_object_ref(messenger));
171 self->name = g_strdup(name);
172 self->codec = FL_METHOD_CODEC(g_object_ref(codec));
173
174 fl_binary_messenger_set_message_handler_on_channel(
175 self->messenger, self->name, message_cb, g_object_ref(self),
176 channel_closed_cb);
177
178 return self;
179 }
180
181 G_MODULE_EXPORT void fl_event_channel_set_stream_handlers(
182 FlEventChannel* self,
183 FlEventChannelHandler listen_handler,
184 FlEventChannelHandler cancel_handler,
185 gpointer user_data,
186 GDestroyNotify destroy_notify) {
187 g_return_if_fail(FL_IS_EVENT_CHANNEL(self));
188
189 remove_handlers(self);
190 self->listen_handler = listen_handler;
191 self->cancel_handler = cancel_handler;
192 self->handler_data = user_data;
193 self->handler_data_destroy_notify = destroy_notify;
194 }
195
196 G_MODULE_EXPORT gboolean fl_event_channel_send(FlEventChannel* self,
197 FlValue* event,
198 GCancellable* cancellable,
199 GError** error) {
200 g_return_val_if_fail(FL_IS_EVENT_CHANNEL(self), FALSE);
201 g_return_val_if_fail(event != nullptr, FALSE);
202
203 g_autoptr(GBytes) data =
204 fl_method_codec_encode_success_envelope(self->codec, event, error);
205 if (data == nullptr) {
206 return FALSE;
207 }
208
209 fl_binary_messenger_send_on_channel(self->messenger, self->name, data,
210 cancellable, nullptr, nullptr);
211
212 return TRUE;
213 }
214
215 G_MODULE_EXPORT gboolean fl_event_channel_send_error(FlEventChannel* self,
216 const gchar* code,
217 const gchar* message,
218 FlValue* details,
219 GCancellable* cancellable,
220 GError** error) {
221 g_return_val_if_fail(FL_IS_EVENT_CHANNEL(self), FALSE);
222 g_return_val_if_fail(code != nullptr, FALSE);
223 g_return_val_if_fail(message != nullptr, FALSE);
224
225 g_autoptr(GBytes) data = fl_method_codec_encode_error_envelope(
226 self->codec, code, message, details, error);
227 if (data == nullptr) {
228 return FALSE;
229 }
230
231 fl_binary_messenger_send_on_channel(self->messenger, self->name, data,
232 cancellable, nullptr, nullptr);
233
234 return TRUE;
235 }
236
237 G_MODULE_EXPORT gboolean fl_event_channel_send_end_of_stream(
238 FlEventChannel* self,
239 GCancellable* cancellable,
240 GError** error) {
241 g_return_val_if_fail(FL_IS_EVENT_CHANNEL(self), FALSE);
242 fl_binary_messenger_send_on_channel(self->messenger, self->name, nullptr,
243 cancellable, nullptr, nullptr);
244 return TRUE;
245 }
G_DEFINE_TYPE
G_DEFINE_TYPE(FlBasicMessageChannelResponseHandle, fl_basic_message_channel_response_handle, G_TYPE_OBJECT) static void fl_basic_message_channel_response_handle_dispose(GObject *object)
Definition: fl_basic_message_channel.cc:37
fl_binary_messenger_set_message_handler_on_channel
G_MODULE_EXPORT void fl_binary_messenger_set_message_handler_on_channel(FlBinaryMessenger *self, const gchar *channel, FlBinaryMessengerMessageHandler handler, gpointer user_data, GDestroyNotify destroy_notify)
Definition: fl_binary_messenger.cc:408
fl_binary_messenger_send_on_channel
G_MODULE_EXPORT void fl_binary_messenger_send_on_channel(FlBinaryMessenger *self, const gchar *channel, GBytes *message, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition: fl_binary_messenger.cc:435
fl_binary_messenger_send_response
G_MODULE_EXPORT gboolean fl_binary_messenger_send_response(FlBinaryMessenger *self, FlBinaryMessengerResponseHandle *response_handle, GBytes *response, GError **error)
Definition: fl_binary_messenger.cc:422
fl_event_channel_send
G_MODULE_EXPORT gboolean fl_event_channel_send(FlEventChannel *self, FlValue *event, GCancellable *cancellable, GError **error)
Definition: fl_event_channel.cc:196
message_cb
static void message_cb(FlBinaryMessenger *messenger, const gchar *channel, GBytes *message, FlBinaryMessengerResponseHandle *response_handle, gpointer user_data)
Definition: fl_event_channel.cc:69
fl_event_channel_send_end_of_stream
G_MODULE_EXPORT gboolean fl_event_channel_send_end_of_stream(FlEventChannel *self, GCancellable *cancellable, GError **error)
Definition: fl_event_channel.cc:237
fl_event_channel_send_error
G_MODULE_EXPORT gboolean fl_event_channel_send_error(FlEventChannel *self, const gchar *code, const gchar *message, FlValue *details, GCancellable *cancellable, GError **error)
Definition: fl_event_channel.cc:215
fl_event_channel_dispose
static void fl_event_channel_dispose(GObject *object)
Definition: fl_event_channel.cc:136
fl_event_channel_class_init
static void fl_event_channel_class_init(FlEventChannelClass *klass)
Definition: fl_event_channel.cc:153
kListenMethod
static constexpr char kListenMethod[]
Definition: fl_event_channel.cc:11
fl_event_channel_set_stream_handlers
G_MODULE_EXPORT void fl_event_channel_set_stream_handlers(FlEventChannel *self, FlEventChannelHandler listen_handler, FlEventChannelHandler cancel_handler, gpointer user_data, GDestroyNotify destroy_notify)
Definition: fl_event_channel.cc:181
fl_event_channel_init
static void fl_event_channel_init(FlEventChannel *self)
Definition: fl_event_channel.cc:157
fl_event_channel_new
G_MODULE_EXPORT FlEventChannel * fl_event_channel_new(FlBinaryMessenger *messenger, const gchar *name, FlMethodCodec *codec)
Definition: fl_event_channel.cc:159
handle_method_call
static FlMethodErrorResponse * handle_method_call(FlEventChannel *self, const gchar *name, FlValue *args)
Definition: fl_event_channel.cc:46
kEventRequestError
static constexpr char kEventRequestError[]
Definition: fl_event_channel.cc:13
remove_handlers
static void remove_handlers(FlEventChannel *self)
Definition: fl_event_channel.cc:119
channel_closed_cb
static void channel_closed_cb(gpointer user_data)
Definition: fl_event_channel.cc:130
kCancelMethod
static constexpr char kCancelMethod[]
Definition: fl_event_channel.cc:12
fl_event_channel.h
args
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
Definition: fl_event_channel.h:89
user_data
G_BEGIN_DECLS G_MODULE_EXPORT FlValue gpointer user_data
Definition: fl_event_channel.h:90
fl_method_codec_encode_success_envelope
GBytes * fl_method_codec_encode_success_envelope(FlMethodCodec *self, FlValue *result, GError **error)
Definition: fl_method_codec.cc:41
fl_method_codec_encode_error_envelope
GBytes * fl_method_codec_encode_error_envelope(FlMethodCodec *self, const gchar *code, const gchar *message, FlValue *details, GError **error)
Definition: fl_method_codec.cc:50
fl_method_codec_decode_method_call
gboolean fl_method_codec_decode_method_call(FlMethodCodec *self, GBytes *message, gchar **name, FlValue **args, GError **error)
Definition: fl_method_codec.cc:27
fl_method_codec_private.h
fl_method_error_response_new
G_MODULE_EXPORT FlMethodErrorResponse * fl_method_error_response_new(const gchar *code, const gchar *message, FlValue *details)
Definition: fl_method_response.cc:144
fl_method_error_response_get_code
G_MODULE_EXPORT const gchar * fl_method_error_response_get_code(FlMethodErrorResponse *self)
Definition: fl_method_response.cc:160
fl_method_error_response_get_message
G_MODULE_EXPORT const gchar * fl_method_error_response_get_message(FlMethodErrorResponse *self)
Definition: fl_method_response.cc:166
fl_method_error_response_get_details
G_MODULE_EXPORT FlValue * fl_method_error_response_get_details(FlMethodErrorResponse *self)
Definition: fl_method_response.cc:172
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
error
const uint8_t uint32_t uint32_t GError ** error
Definition: fl_pixel_buffer_texture_test.cc:40
FlValue
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
_FlEventChannel
Definition: fl_event_channel.cc:15
_FlEventChannel::handler_data_destroy_notify
GDestroyNotify handler_data_destroy_notify
Definition: fl_event_channel.cc:34
_FlEventChannel::name
gchar * name
Definition: fl_event_channel.cc:25
_FlEventChannel::cancel_handler
FlEventChannelHandler cancel_handler
Definition: fl_event_channel.cc:32
_FlEventChannel::messenger
FlBinaryMessenger * messenger
Definition: fl_event_channel.cc:19
_FlEventChannel::listen_handler
FlEventChannelHandler listen_handler
Definition: fl_event_channel.cc:31
_FlEventChannel::parent_instance
GObject parent_instance
Definition: fl_event_channel.cc:16
_FlEventChannel::handler_data
gpointer handler_data
Definition: fl_event_channel.cc:33
_FlEventChannel::channel_closed
gboolean channel_closed
Definition: fl_event_channel.cc:22
_FlEventChannel::codec
FlMethodCodec * codec
Definition: fl_event_channel.cc:28
_FlEventChannelResponseHandle
Definition: fl_event_channel.cc:37
_FlEventChannelResponseHandle::parent_instance
GObject parent_instance
Definition: fl_event_channel.cc:38
_FlEventChannelResponseHandle::response_handle
FlBinaryMessengerResponseHandle * response_handle
Definition: fl_event_channel.cc:40