Flutter Linux Embedder
fl_method_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 
6 
7 #include <gmodule.h>
8 
12 
14  GObject parent_instance;
15 
16  // Messenger to communicate on.
17  FlBinaryMessenger* messenger;
18 
19  // TRUE if the channel has been closed.
20  gboolean channel_closed;
21 
22  // Channel name.
23  gchar* name;
24 
25  // Codec to en/decode messages.
26  FlMethodCodec* codec;
27 
28  // Function called when a method call is received.
29  FlMethodChannelMethodCallHandler method_call_handler;
32 };
33 
34 G_DEFINE_TYPE(FlMethodChannel, fl_method_channel, G_TYPE_OBJECT)
35 
36 // Called when a binary message is received on this channel.
37 static void message_cb(FlBinaryMessenger* messenger,
38  const gchar* channel,
39  GBytes* message,
40  FlBinaryMessengerResponseHandle* response_handle,
41  gpointer user_data) {
42  FlMethodChannel* self = FL_METHOD_CHANNEL(user_data);
43 
44  if (self->method_call_handler == nullptr) {
45  return;
46  }
47 
48  g_autofree gchar* method = nullptr;
49  g_autoptr(FlValue) args = nullptr;
50  g_autoptr(GError) error = nullptr;
51  if (!fl_method_codec_decode_method_call(self->codec, message, &method, &args,
52  &error)) {
53  g_warning("Failed to decode method call: %s", error->message);
54  return;
55  }
56 
57  g_autoptr(FlMethodCall) method_call =
58  fl_method_call_new(method, args, self, response_handle);
59  self->method_call_handler(self, method_call, self->method_call_handler_data);
60 }
61 
62 // Called when a response is received to a sent message.
63 static void message_response_cb(GObject* object,
64  GAsyncResult* result,
65  gpointer user_data) {
66  GTask* task = G_TASK(user_data);
67  g_task_return_pointer(task, result, g_object_unref);
68 }
69 
70 // Called when the channel handler is closed.
71 static void channel_closed_cb(gpointer user_data) {
72  g_autoptr(FlMethodChannel) self = FL_METHOD_CHANNEL(user_data);
73 
74  self->channel_closed = TRUE;
75 
76  // Disconnect handler.
77  if (self->method_call_handler_destroy_notify != nullptr) {
78  self->method_call_handler_destroy_notify(self->method_call_handler_data);
79  }
80  self->method_call_handler = nullptr;
81  self->method_call_handler_data = nullptr;
82  self->method_call_handler_destroy_notify = nullptr;
83 }
84 
85 static void fl_method_channel_dispose(GObject* object) {
86  FlMethodChannel* self = FL_METHOD_CHANNEL(object);
87 
88  // Note we don't have to clear the handler in messenger as it holds
89  // a reference to this object so the following code is only run after
90  // the messenger has closed the channel already.
91 
92  g_clear_object(&self->messenger);
93  g_clear_pointer(&self->name, g_free);
94  g_clear_object(&self->codec);
95 
96  if (self->method_call_handler_destroy_notify != nullptr) {
97  self->method_call_handler_destroy_notify(self->method_call_handler_data);
98  }
99  self->method_call_handler = nullptr;
100  self->method_call_handler_data = nullptr;
101  self->method_call_handler_destroy_notify = nullptr;
102 
103  G_OBJECT_CLASS(fl_method_channel_parent_class)->dispose(object);
104 }
105 
106 static void fl_method_channel_class_init(FlMethodChannelClass* klass) {
107  G_OBJECT_CLASS(klass)->dispose = fl_method_channel_dispose;
108 }
109 
110 static void fl_method_channel_init(FlMethodChannel* self) {}
111 
112 G_MODULE_EXPORT FlMethodChannel* fl_method_channel_new(
113  FlBinaryMessenger* messenger,
114  const gchar* name,
115  FlMethodCodec* codec) {
116  g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);
117  g_return_val_if_fail(name != nullptr, nullptr);
118  g_return_val_if_fail(FL_IS_METHOD_CODEC(codec), nullptr);
119 
120  FlMethodChannel* self =
121  FL_METHOD_CHANNEL(g_object_new(fl_method_channel_get_type(), nullptr));
122 
123  self->messenger = FL_BINARY_MESSENGER(g_object_ref(messenger));
124  self->name = g_strdup(name);
125  self->codec = FL_METHOD_CODEC(g_object_ref(codec));
126 
128  self->messenger, self->name, message_cb, g_object_ref(self),
130 
131  return self;
132 }
133 
135  FlMethodChannel* self,
136  FlMethodChannelMethodCallHandler handler,
137  gpointer user_data,
138  GDestroyNotify destroy_notify) {
139  g_return_if_fail(FL_IS_METHOD_CHANNEL(self));
140 
141  // Don't set handler if channel closed.
142  if (self->channel_closed) {
143  if (handler != nullptr) {
144  g_warning(
145  "Attempted to set method call handler on a closed FlMethodChannel");
146  }
147  if (destroy_notify != nullptr) {
148  destroy_notify(user_data);
149  }
150  return;
151  }
152 
153  if (self->method_call_handler_destroy_notify != nullptr) {
154  self->method_call_handler_destroy_notify(self->method_call_handler_data);
155  }
156 
157  self->method_call_handler = handler;
158  self->method_call_handler_data = user_data;
159  self->method_call_handler_destroy_notify = destroy_notify;
160 }
161 
162 G_MODULE_EXPORT void fl_method_channel_invoke_method(
163  FlMethodChannel* self,
164  const gchar* method,
165  FlValue* args,
166  GCancellable* cancellable,
167  GAsyncReadyCallback callback,
168  gpointer user_data) {
169  g_return_if_fail(FL_IS_METHOD_CHANNEL(self));
170  g_return_if_fail(method != nullptr);
171 
172  g_autoptr(GTask) task =
173  callback != nullptr ? g_task_new(self, cancellable, callback, user_data)
174  : nullptr;
175 
176  g_autoptr(GError) error = nullptr;
177  g_autoptr(GBytes) message =
178  fl_method_codec_encode_method_call(self->codec, method, args, &error);
179  if (message == nullptr) {
180  if (task != nullptr) {
181  g_task_return_error(task, error);
182  }
183  return;
184  }
185 
187  self->messenger, self->name, message, cancellable,
188  callback != nullptr ? message_response_cb : nullptr,
189  g_steal_pointer(&task));
190 }
191 
192 G_MODULE_EXPORT FlMethodResponse* fl_method_channel_invoke_method_finish(
193  FlMethodChannel* self,
194  GAsyncResult* result,
195  GError** error) {
196  g_return_val_if_fail(FL_IS_METHOD_CHANNEL(self), nullptr);
197  g_return_val_if_fail(g_task_is_valid(result, self), nullptr);
198 
199  g_autoptr(GTask) task = G_TASK(result);
200  GAsyncResult* r = G_ASYNC_RESULT(g_task_propagate_pointer(task, nullptr));
201 
202  g_autoptr(GBytes) response =
204  if (response == nullptr) {
205  return nullptr;
206  }
207 
208  return fl_method_codec_decode_response(self->codec, response, error);
209 }
210 
212  FlMethodChannel* self,
213  FlBinaryMessengerResponseHandle* response_handle,
214  FlMethodResponse* response,
215  GError** error) {
216  g_return_val_if_fail(FL_IS_METHOD_CHANNEL(self), FALSE);
217  g_return_val_if_fail(FL_IS_BINARY_MESSENGER_RESPONSE_HANDLE(response_handle),
218  FALSE);
219  g_return_val_if_fail(FL_IS_METHOD_SUCCESS_RESPONSE(response) ||
220  FL_IS_METHOD_ERROR_RESPONSE(response) ||
221  FL_IS_METHOD_NOT_IMPLEMENTED_RESPONSE(response),
222  FALSE);
223 
224  g_autoptr(GBytes) message = nullptr;
225  if (FL_IS_METHOD_SUCCESS_RESPONSE(response)) {
226  FlMethodSuccessResponse* r = FL_METHOD_SUCCESS_RESPONSE(response);
229  if (message == nullptr) {
230  return FALSE;
231  }
232  } else if (FL_IS_METHOD_ERROR_RESPONSE(response)) {
233  FlMethodErrorResponse* r = FL_METHOD_ERROR_RESPONSE(response);
235  self->codec, fl_method_error_response_get_code(r),
238  if (message == nullptr) {
239  return FALSE;
240  }
241  } else if (FL_IS_METHOD_NOT_IMPLEMENTED_RESPONSE(response)) {
242  message = nullptr;
243  } else {
244  g_assert_not_reached();
245  }
246 
247  return fl_binary_messenger_send_response(self->messenger, response_handle,
248  message, error);
249 }
fl_method_channel_private.h
_FlMethodChannel::name
gchar * name
Definition: fl_method_channel.cc:23
fl_method_channel_dispose
static void fl_method_channel_dispose(GObject *object)
Definition: fl_method_channel.cc:85
fl_method_codec_encode_method_call
GBytes * fl_method_codec_encode_method_call(FlMethodCodec *self, const gchar *name, FlValue *args, GError **error)
Definition: fl_method_codec.cc:16
fl_method_channel_new
G_MODULE_EXPORT FlMethodChannel * fl_method_channel_new(FlBinaryMessenger *messenger, const gchar *name, FlMethodCodec *codec)
Definition: fl_method_channel.cc:112
message_cb
static void message_cb(FlBinaryMessenger *messenger, const gchar *channel, GBytes *message, FlBinaryMessengerResponseHandle *response_handle, gpointer user_data)
Definition: fl_method_channel.cc:37
_FlMethodChannel::messenger
FlBinaryMessenger * messenger
Definition: fl_method_channel.cc:17
channel_closed_cb
static void channel_closed_cb(gpointer user_data)
Definition: fl_method_channel.cc:71
fl_method_channel.h
fl_method_channel_invoke_method_finish
G_MODULE_EXPORT FlMethodResponse * fl_method_channel_invoke_method_finish(FlMethodChannel *self, GAsyncResult *result, GError **error)
Definition: fl_method_channel.cc:192
FlValue
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
user_data
FlKeyEvent uint64_t FlKeyResponderAsyncCallback gpointer user_data
Definition: fl_key_channel_responder.cc:121
_FlMethodChannel::codec
FlMethodCodec * codec
Definition: fl_method_channel.cc:26
fl_method_error_response_get_message
const G_MODULE_EXPORT gchar * fl_method_error_response_get_message(FlMethodErrorResponse *self)
Definition: fl_method_response.cc:166
_FlMethodChannel
Definition: fl_method_channel.cc:13
fl_method_channel_init
static void fl_method_channel_init(FlMethodChannel *self)
Definition: fl_method_channel.cc:110
_FlMethodChannel::method_call_handler_destroy_notify
GDestroyNotify method_call_handler_destroy_notify
Definition: fl_method_channel.cc:31
_FlMethodChannel::channel_closed
gboolean channel_closed
Definition: fl_method_channel.cc:20
fl_method_error_response_get_details
G_MODULE_EXPORT FlValue * fl_method_error_response_get_details(FlMethodErrorResponse *self)
Definition: fl_method_response.cc:172
_FlMethodChannel::method_call_handler_data
gpointer method_call_handler_data
Definition: fl_method_channel.cc:30
method_call
G_BEGIN_DECLS G_MODULE_EXPORT FlMethodCall * method_call
Definition: fl_method_channel.h:120
fl_method_channel_respond
gboolean fl_method_channel_respond(FlMethodChannel *self, FlBinaryMessengerResponseHandle *response_handle, FlMethodResponse *response, GError **error)
Definition: fl_method_channel.cc:211
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_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:416
fl_method_success_response_get_result
G_MODULE_EXPORT FlValue * fl_method_success_response_get_result(FlMethodSuccessResponse *self)
Definition: fl_method_response.cc:138
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
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
message_response_cb
static void message_response_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_method_channel.cc:63
_FlMethodChannel::parent_instance
GObject parent_instance
Definition: fl_method_channel.cc:14
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_decode_response
FlMethodResponse * fl_method_codec_decode_response(FlMethodCodec *self, GBytes *message, GError **error)
Definition: fl_method_codec.cc:62
fl_binary_messenger_send_on_channel_finish
G_MODULE_EXPORT GBytes * fl_binary_messenger_send_on_channel_finish(FlBinaryMessenger *self, GAsyncResult *result, GError **error)
Definition: fl_binary_messenger.cc:457
fl_method_channel_invoke_method
G_MODULE_EXPORT void fl_method_channel_invoke_method(FlMethodChannel *self, const gchar *method, FlValue *args, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition: fl_method_channel.cc:162
fl_method_call_new
FlMethodCall * fl_method_call_new(const gchar *name, FlValue *args, FlMethodChannel *channel, FlBinaryMessengerResponseHandle *response_handle)
Definition: fl_method_call.cc:44
fl_method_channel_set_method_call_handler
G_MODULE_EXPORT void fl_method_channel_set_method_call_handler(FlMethodChannel *self, FlMethodChannelMethodCallHandler handler, gpointer user_data, GDestroyNotify destroy_notify)
Definition: fl_method_channel.cc:134
result
GAsyncResult * result
Definition: fl_text_input_handler.cc:106
fl_method_error_response_get_code
const G_MODULE_EXPORT gchar * fl_method_error_response_get_code(FlMethodErrorResponse *self)
Definition: fl_method_response.cc:160
args
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
Definition: fl_event_channel.h:89
error
const uint8_t uint32_t uint32_t GError ** error
Definition: fl_pixel_buffer_texture_test.cc:40
_FlMethodChannel::method_call_handler
FlMethodChannelMethodCallHandler method_call_handler
Definition: fl_method_channel.cc:29
fl_method_channel_class_init
static void fl_method_channel_class_init(FlMethodChannelClass *klass)
Definition: fl_method_channel.cc:106
fl_method_call_private.h
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
callback
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
Definition: fl_key_channel_responder.cc:120
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:430
fl_method_codec_private.h
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:443