Flutter Engine
fl_basic_message_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_basic_message_channel.h"
6 
7 #include <gmodule.h>
8 
10  GObject parent_instance;
11 
12  // Messenger to communicate on.
13  FlBinaryMessenger* messenger;
14 
15  // TRUE if the channel has been closed.
16  gboolean channel_closed;
17 
18  // Channel name.
19  gchar* name;
20 
21  // Codec to en/decode messages.
22  FlMessageCodec* codec;
23 
24  // Function called when a message is received.
28 };
29 
31  GObject parent_instance;
32 
33  FlBinaryMessengerResponseHandle* response_handle;
34 };
35 
36 // Added here to stop the compiler from optimising this function away.
37 G_MODULE_EXPORT GType fl_basic_message_channel_get_type();
38 
39 G_DEFINE_TYPE(FlBasicMessageChannel, fl_basic_message_channel, G_TYPE_OBJECT)
40 G_DEFINE_TYPE(FlBasicMessageChannelResponseHandle,
42  G_TYPE_OBJECT)
43 
44 static void fl_basic_message_channel_response_handle_dispose(GObject* object) {
45  FlBasicMessageChannelResponseHandle* self =
46  FL_BASIC_MESSAGE_CHANNEL_RESPONSE_HANDLE(object);
47 
48  g_clear_object(&self->response_handle);
49 
50  G_OBJECT_CLASS(fl_basic_message_channel_response_handle_parent_class)
51  ->dispose(object);
52 }
53 
55  FlBasicMessageChannelResponseHandleClass* klass) {
56  G_OBJECT_CLASS(klass)->dispose =
57  fl_basic_message_channel_response_handle_dispose;
58 }
59 
61  FlBasicMessageChannelResponseHandle* self) {}
62 
63 static FlBasicMessageChannelResponseHandle*
65  FlBinaryMessengerResponseHandle* response_handle) {
66  FlBasicMessageChannelResponseHandle* self =
67  FL_BASIC_MESSAGE_CHANNEL_RESPONSE_HANDLE(g_object_new(
68  fl_basic_message_channel_response_handle_get_type(), nullptr));
69 
70  self->response_handle =
71  FL_BINARY_MESSENGER_RESPONSE_HANDLE(g_object_ref(response_handle));
72 
73  return self;
74 }
75 
76 // Called when a binary message is received on this channel.
77 static void message_cb(FlBinaryMessenger* messenger,
78  const gchar* channel,
79  GBytes* message,
80  FlBinaryMessengerResponseHandle* response_handle,
81  gpointer user_data) {
82  FlBasicMessageChannel* self = FL_BASIC_MESSAGE_CHANNEL(user_data);
83 
84  if (self->message_handler == nullptr) {
85  fl_binary_messenger_send_response(messenger, response_handle, nullptr,
86  nullptr);
87  return;
88  }
89 
90  g_autoptr(GError) error = nullptr;
91  g_autoptr(FlValue) message_value =
92  fl_message_codec_decode_message(self->codec, message, &error);
93  if (message_value == nullptr) {
94  g_warning("Failed to decode message: %s", error->message);
95  fl_binary_messenger_send_response(messenger, response_handle, nullptr,
96  nullptr);
97  }
98 
99  g_autoptr(FlBasicMessageChannelResponseHandle) handle =
101  self->message_handler(self, message_value, handle,
102  self->message_handler_data);
103 }
104 
105 // Called when a response is received to a sent message.
106 static void message_response_cb(GObject* object,
107  GAsyncResult* result,
108  gpointer user_data) {
109  GTask* task = G_TASK(user_data);
110  g_task_return_pointer(task, result, g_object_unref);
111 }
112 
113 // Called when the channel handler is closed.
114 static void channel_closed_cb(gpointer user_data) {
115  g_autoptr(FlBasicMessageChannel) self = FL_BASIC_MESSAGE_CHANNEL(user_data);
116 
117  self->channel_closed = TRUE;
118 
119  // Disconnect handler.
120  if (self->message_handler_destroy_notify != nullptr) {
121  self->message_handler_destroy_notify(self->message_handler_data);
122  }
123  self->message_handler = nullptr;
124  self->message_handler_data = nullptr;
125  self->message_handler_destroy_notify = nullptr;
126 }
127 
128 static void fl_basic_message_channel_dispose(GObject* object) {
129  FlBasicMessageChannel* self = FL_BASIC_MESSAGE_CHANNEL(object);
130 
131  if (self->messenger != nullptr) {
133  self->messenger, self->name, nullptr, nullptr, nullptr);
134  }
135 
136  g_clear_object(&self->messenger);
137  g_clear_pointer(&self->name, g_free);
138  g_clear_object(&self->codec);
139 
140  if (self->message_handler_destroy_notify != nullptr) {
141  self->message_handler_destroy_notify(self->message_handler_data);
142  }
143  self->message_handler = nullptr;
144  self->message_handler_data = nullptr;
145  self->message_handler_destroy_notify = nullptr;
146 
147  G_OBJECT_CLASS(fl_basic_message_channel_parent_class)->dispose(object);
148 }
149 
151  FlBasicMessageChannelClass* klass) {
152  G_OBJECT_CLASS(klass)->dispose = fl_basic_message_channel_dispose;
153 }
154 
155 static void fl_basic_message_channel_init(FlBasicMessageChannel* self) {}
156 
157 G_MODULE_EXPORT FlBasicMessageChannel* fl_basic_message_channel_new(
158  FlBinaryMessenger* messenger,
159  const gchar* name,
160  FlMessageCodec* codec) {
161  g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);
162  g_return_val_if_fail(name != nullptr, nullptr);
163  g_return_val_if_fail(FL_IS_MESSAGE_CODEC(codec), nullptr);
164 
165  FlBasicMessageChannel* self = FL_BASIC_MESSAGE_CHANNEL(
166  g_object_new(fl_basic_message_channel_get_type(), nullptr));
167 
168  self->messenger = FL_BINARY_MESSENGER(g_object_ref(messenger));
169  self->name = g_strdup(name);
170  self->codec = FL_MESSAGE_CODEC(g_object_ref(codec));
171 
173  self->messenger, self->name, message_cb, g_object_ref(self),
175 
176  return self;
177 }
178 
180  FlBasicMessageChannel* self,
182  gpointer user_data,
183  GDestroyNotify destroy_notify) {
184  g_return_if_fail(FL_IS_BASIC_MESSAGE_CHANNEL(self));
185 
186  // Don't set handler if channel closed.
187  if (self->channel_closed) {
188  if (handler != nullptr) {
189  g_warning(
190  "Attempted to set message handler on a closed FlBasicMessageChannel");
191  }
192  if (destroy_notify != nullptr) {
193  destroy_notify(user_data);
194  }
195  return;
196  }
197 
198  if (self->message_handler_destroy_notify != nullptr) {
199  self->message_handler_destroy_notify(self->message_handler_data);
200  }
201 
202  self->message_handler = handler;
203  self->message_handler_data = user_data;
204  self->message_handler_destroy_notify = destroy_notify;
205 }
206 
207 G_MODULE_EXPORT gboolean fl_basic_message_channel_respond(
208  FlBasicMessageChannel* self,
209  FlBasicMessageChannelResponseHandle* response_handle,
210  FlValue* message,
211  GError** error) {
212  g_return_val_if_fail(FL_IS_BASIC_MESSAGE_CHANNEL(self), FALSE);
213  g_return_val_if_fail(response_handle != nullptr, FALSE);
214  g_return_val_if_fail(response_handle->response_handle != nullptr, FALSE);
215 
216  g_autoptr(GBytes) data =
217  fl_message_codec_encode_message(self->codec, message, error);
218  if (data == nullptr) {
219  return FALSE;
220  }
221 
222  gboolean result = fl_binary_messenger_send_response(
223  self->messenger, response_handle->response_handle, data, error);
224  g_clear_object(&response_handle->response_handle);
225 
226  return result;
227 }
228 
229 G_MODULE_EXPORT void fl_basic_message_channel_send(FlBasicMessageChannel* self,
230  FlValue* message,
231  GCancellable* cancellable,
232  GAsyncReadyCallback callback,
233  gpointer user_data) {
234  g_return_if_fail(FL_IS_BASIC_MESSAGE_CHANNEL(self));
235  g_return_if_fail(message != nullptr);
236 
237  g_autoptr(GTask) task =
238  callback != nullptr ? g_task_new(self, cancellable, callback, user_data)
239  : nullptr;
240 
241  g_autoptr(GError) error = nullptr;
242  g_autoptr(GBytes) data =
243  fl_message_codec_encode_message(self->codec, message, &error);
244  if (data == nullptr) {
245  if (task != nullptr) {
246  g_task_return_error(task, error);
247  }
248  return;
249  }
250 
252  self->messenger, self->name, data, cancellable,
253  callback != nullptr ? message_response_cb : nullptr,
254  g_steal_pointer(&task));
255 }
256 
258  FlBasicMessageChannel* self,
259  GAsyncResult* result,
260  GError** error) {
261  g_return_val_if_fail(FL_IS_BASIC_MESSAGE_CHANNEL(self), nullptr);
262  g_return_val_if_fail(g_task_is_valid(result, self), nullptr);
263 
264  g_autoptr(GTask) task = G_TASK(result);
265  GAsyncResult* r = G_ASYNC_RESULT(g_task_propagate_pointer(task, nullptr));
266 
267  g_autoptr(GBytes) message =
268  fl_binary_messenger_send_on_channel_finish(self->messenger, r, error);
269  if (message == nullptr) {
270  return nullptr;
271  }
272 
273  return fl_message_codec_decode_message(self->codec, message, error);
274 }
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)
G_MODULE_EXPORT gboolean fl_basic_message_channel_respond(FlBasicMessageChannel *self, FlBasicMessageChannelResponseHandle *response_handle, FlValue *message, GError **error)
static void fl_basic_message_channel_class_init(FlBasicMessageChannelClass *klass)
FlBinaryMessengerResponseHandle * response_handle
static FlBasicMessageChannelResponseHandle * fl_basic_message_channel_response_handle_new(FlBinaryMessengerResponseHandle *response_handle)
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:39
FlMethodResponse GError ** error
G_MODULE_EXPORT GType fl_basic_message_channel_get_type()
G_MODULE_EXPORT GBytes * fl_binary_messenger_send_on_channel_finish(FlBinaryMessenger *self, GAsyncResult *result, GError **error)
G_BEGIN_DECLS GObject typedef void(* FlBasicMessageChannelMessageHandler)(FlBasicMessageChannel *channel, FlValue *message, FlBasicMessageChannelResponseHandle *response_handle, gpointer user_data)
G_MODULE_EXPORT FlBasicMessageChannel * fl_basic_message_channel_new(FlBinaryMessenger *messenger, const gchar *name, FlMessageCodec *codec)
G_MODULE_EXPORT FlValue * fl_basic_message_channel_send_finish(FlBasicMessageChannel *self, GAsyncResult *result, GError **error)
G_MODULE_EXPORT gboolean fl_binary_messenger_send_response(FlBinaryMessenger *self, FlBinaryMessengerResponseHandle *response_handle, GBytes *response, GError **error)
G_BEGIN_DECLS FlValue gpointer user_data
static void fl_basic_message_channel_dispose(GObject *object)
G_BEGIN_DECLS fl_basic_message_channel_response_handle
static void fl_basic_message_channel_response_handle_class_init(FlBasicMessageChannelResponseHandleClass *klass)
static void channel_closed_cb(gpointer user_data)
G_MODULE_EXPORT void fl_binary_messenger_send_on_channel(FlBinaryMessenger *self, const gchar *channel, GBytes *message, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
G_MODULE_EXPORT void fl_basic_message_channel_send(FlBasicMessageChannel *self, FlValue *message, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
G_MODULE_EXPORT void fl_basic_message_channel_set_message_handler(FlBasicMessageChannel *self, FlBasicMessageChannelMessageHandler handler, gpointer user_data, GDestroyNotify destroy_notify)
G_MODULE_EXPORT GBytes * fl_message_codec_encode_message(FlMessageCodec *self, FlValue *message, GError **error)
return TRUE
Definition: fl_view.cc:107
G_DEFINE_TYPE(FlBasicMessageChannelResponseHandle, fl_basic_message_channel_response_handle, G_TYPE_OBJECT) static void fl_basic_message_channel_response_handle_dispose(GObject *object)
FlBasicMessageChannelMessageHandler message_handler
static void fl_basic_message_channel_init(FlBasicMessageChannel *self)
G_MODULE_EXPORT FlValue * fl_message_codec_decode_message(FlMessageCodec *self, GBytes *message, GError **error)
GDestroyNotify message_handler_destroy_notify
static void message_response_cb(GObject *object, GAsyncResult *result, gpointer user_data)
static void fl_basic_message_channel_response_handle_init(FlBasicMessageChannelResponseHandle *self)
static void message_cb(FlBinaryMessenger *messenger, const gchar *channel, GBytes *message, FlBinaryMessengerResponseHandle *response_handle, gpointer user_data)