Flutter Linux Embedder
fl_platform_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 <cstring>
8 
11 
12 static constexpr char kChannelName[] = "flutter/platform";
13 static constexpr char kBadArgumentsError[] = "Bad Arguments";
14 static constexpr char kGetClipboardDataMethod[] = "Clipboard.getData";
15 static constexpr char kSetClipboardDataMethod[] = "Clipboard.setData";
16 static constexpr char kClipboardHasStringsMethod[] = "Clipboard.hasStrings";
17 static constexpr char kExitApplicationMethod[] = "System.exitApplication";
18 static constexpr char kRequestAppExitMethod[] = "System.requestAppExit";
19 static constexpr char kInitializationCompleteMethod[] =
20  "System.initializationComplete";
21 static constexpr char kPlaySoundMethod[] = "SystemSound.play";
22 static constexpr char kSystemNavigatorPopMethod[] = "SystemNavigator.pop";
23 static constexpr char kTextKey[] = "text";
24 static constexpr char kValueKey[] = "value";
25 
26 static constexpr char kExitTypeKey[] = "type";
27 static constexpr char kExitTypeCancelable[] = "cancelable";
28 static constexpr char kExitTypeRequired[] = "required";
29 
30 static constexpr char kExitResponseKey[] = "response";
31 static constexpr char kExitResponseCancel[] = "cancel";
32 static constexpr char kExitResponseExit[] = "exit";
33 
35  GObject parent_instance;
36 
37  FlMethodChannel* channel;
38 
39  // Handlers for incoming method calls.
41 
42  // User data to pass to method call handlers.
43  gpointer user_data;
44 };
45 
46 G_DEFINE_TYPE(FlPlatformChannel, fl_platform_channel, G_TYPE_OBJECT)
47 
48 static FlMethodResponse* clipboard_set_data(FlPlatformChannel* self,
49  FlMethodCall* method_call) {
51 
53  return FL_METHOD_RESPONSE(fl_method_error_response_new(
54  kBadArgumentsError, "Argument map missing or malformed", nullptr));
55  }
56 
58  if (text_value == nullptr ||
59  fl_value_get_type(text_value) != FL_VALUE_TYPE_STRING) {
60  return FL_METHOD_RESPONSE(fl_method_error_response_new(
61  kBadArgumentsError, "Missing clipboard text", nullptr));
62  }
63  const gchar* text = fl_value_get_string(text_value);
64 
65  return self->vtable->clipboard_set_data(method_call, text, self->user_data);
66 }
67 
68 static FlMethodResponse* clipboard_get_data(FlPlatformChannel* self,
69  FlMethodCall* method_call) {
71 
73  return FL_METHOD_RESPONSE(fl_method_error_response_new(
74  kBadArgumentsError, "Expected string", nullptr));
75  }
76  const gchar* format = fl_value_get_string(args);
77 
78  return self->vtable->clipboard_get_data(method_call, format, self->user_data);
79 }
80 
81 static FlMethodResponse* clipboard_has_strings(FlPlatformChannel* self,
82  FlMethodCall* method_call) {
83  return self->vtable->clipboard_has_strings(method_call, self->user_data);
84 }
85 
86 // Get the exit response from a System.requestAppExit method call.
87 FlPlatformChannelExitResponse get_exit_response(FlMethodResponse* response) {
88  if (response == nullptr) {
90  }
91 
92  g_autoptr(GError) error = nullptr;
93  FlValue* result = fl_method_response_get_result(response, &error);
94  if (result == nullptr) {
95  g_warning("Error returned from System.requestAppExit: %s", error->message);
97  }
98  if (fl_value_get_type(result) != FL_VALUE_TYPE_MAP) {
99  g_warning("System.requestAppExit result argument map missing or malformed");
101  }
102 
103  FlValue* response_value = fl_value_lookup_string(result, kExitResponseKey);
104  if (fl_value_get_type(response_value) != FL_VALUE_TYPE_STRING) {
105  g_warning("Invalid response from System.requestAppExit");
107  }
108  const char* response_string = fl_value_get_string(response_value);
109 
110  if (strcmp(response_string, kExitResponseCancel) == 0) {
112  } else if (strcmp(response_string, kExitResponseExit) == 0) {
114  }
115 
116  // If something went wrong, then just exit.
118 }
119 
120 static FlMethodResponse* system_exit_application(FlPlatformChannel* self,
121  FlMethodCall* method_call) {
124  return FL_METHOD_RESPONSE(fl_method_error_response_new(
125  kBadArgumentsError, "Argument map missing or malformed", nullptr));
126  }
127 
129  if (type_value == nullptr ||
130  fl_value_get_type(type_value) != FL_VALUE_TYPE_STRING) {
131  return FL_METHOD_RESPONSE(fl_method_error_response_new(
132  kBadArgumentsError, "Missing type argument", nullptr));
133  }
134  const char* type_string = fl_value_get_string(type_value);
136  if (strcmp(type_string, kExitTypeCancelable) == 0) {
138  } else if (strcmp(type_string, kExitTypeRequired) == 0) {
140  } else {
141  return FL_METHOD_RESPONSE(fl_method_error_response_new(
142  kBadArgumentsError, "Invalid exit type", nullptr));
143  }
144 
145  return self->vtable->system_exit_application(method_call, type,
146  self->user_data);
147 }
148 
149 static FlMethodResponse* system_initialization_complete(
150  FlPlatformChannel* self) {
151  self->vtable->system_initialization_complete(self->user_data);
152  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
153 }
154 
155 static FlMethodResponse* system_sound_play(FlPlatformChannel* self,
156  FlValue* args) {
158  return FL_METHOD_RESPONSE(fl_method_error_response_new(
159  kBadArgumentsError, "Expected string", nullptr));
160  }
161  const gchar* type = fl_value_get_string(args);
162 
163  self->vtable->system_sound_play(type, self->user_data);
164 
165  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
166 }
167 
168 static FlMethodResponse* system_navigator_pop(FlPlatformChannel* self) {
169  self->vtable->system_navigator_pop(self->user_data);
170  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
171 }
172 
173 static void method_call_cb(FlMethodChannel* channel,
174  FlMethodCall* method_call,
175  gpointer user_data) {
176  FlPlatformChannel* self = FL_PLATFORM_CHANNEL(user_data);
177 
178  const gchar* method = fl_method_call_get_name(method_call);
180 
181  g_autoptr(FlMethodResponse) response = nullptr;
182  if (strcmp(method, kSetClipboardDataMethod) == 0) {
183  response = clipboard_set_data(self, method_call);
184  } else if (strcmp(method, kGetClipboardDataMethod) == 0) {
185  response = clipboard_get_data(self, method_call);
186  } else if (strcmp(method, kClipboardHasStringsMethod) == 0) {
187  response = clipboard_has_strings(self, method_call);
188  } else if (strcmp(method, kExitApplicationMethod) == 0) {
189  response = system_exit_application(self, method_call);
190  } else if (strcmp(method, kInitializationCompleteMethod) == 0) {
191  response = system_initialization_complete(self);
192  } else if (strcmp(method, kPlaySoundMethod) == 0) {
193  response = system_sound_play(self, args);
194  } else if (strcmp(method, kSystemNavigatorPopMethod) == 0) {
195  response = system_navigator_pop(self);
196  } else {
197  response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
198  }
199 
200  if (response != nullptr) {
201  g_autoptr(GError) error = nullptr;
202  if (!fl_method_call_respond(method_call, response, &error)) {
203  g_warning("Failed to send method call response: %s", error->message);
204  }
205  }
206 }
207 
208 static void fl_platform_channel_dispose(GObject* object) {
209  FlPlatformChannel* self = FL_PLATFORM_CHANNEL(object);
210 
211  g_clear_object(&self->channel);
212 
213  G_OBJECT_CLASS(fl_platform_channel_parent_class)->dispose(object);
214 }
215 
216 static void fl_platform_channel_class_init(FlPlatformChannelClass* klass) {
217  G_OBJECT_CLASS(klass)->dispose = fl_platform_channel_dispose;
218 }
219 
220 static void fl_platform_channel_init(FlPlatformChannel* self) {}
221 
222 FlPlatformChannel* fl_platform_channel_new(FlBinaryMessenger* messenger,
223  FlPlatformChannelVTable* vtable,
224  gpointer user_data) {
225  g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);
226  g_return_val_if_fail(vtable != nullptr, nullptr);
227 
228  FlPlatformChannel* self = FL_PLATFORM_CHANNEL(
229  g_object_new(fl_platform_channel_get_type(), nullptr));
230 
231  self->vtable = vtable;
232  self->user_data = user_data;
233 
234  g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
235  self->channel =
236  fl_method_channel_new(messenger, kChannelName, FL_METHOD_CODEC(codec));
238  nullptr);
239 
240  return self;
241 }
242 
243 void fl_platform_channel_system_request_app_exit(FlPlatformChannel* self,
245  GCancellable* cancellable,
246  GAsyncReadyCallback callback,
247  gpointer user_data) {
248  g_return_if_fail(FL_IS_PLATFORM_CHANNEL(self));
249 
250  g_autoptr(FlValue) args = fl_value_new_map();
251  const gchar* type_string;
252  switch (type) {
254  type_string = kExitTypeCancelable;
255  break;
257  type_string = kExitTypeRequired;
258  break;
259  default:
260  g_assert_not_reached();
261  }
263  fl_value_new_string(type_string));
265  cancellable, callback, user_data);
266 }
267 
269  GObject* object,
270  GAsyncResult* result,
271  FlPlatformChannelExitResponse* exit_response,
272  GError** error) {
273  g_autoptr(FlMethodResponse) response = fl_method_channel_invoke_method_finish(
274  FL_METHOD_CHANNEL(object), result, error);
275  if (response == nullptr) {
276  return FALSE;
277  }
278 
279  *exit_response = get_exit_response(response);
280 
281  return TRUE;
282 }
283 
285  const gchar* text) {
286  g_autoptr(FlValue) result = nullptr;
287  if (text != nullptr) {
288  result = fl_value_new_map();
290  }
291 
292  g_autoptr(FlMethodResponse) response =
293  FL_METHOD_RESPONSE(fl_method_success_response_new(result));
294 
295  g_autoptr(GError) error = nullptr;
296  if (!fl_method_call_respond(method_call, response, &error)) {
297  g_warning("Failed to send response to %s: %s", kGetClipboardDataMethod,
298  error->message);
299  }
300 }
301 
303  FlMethodCall* method_call,
304  gboolean has_strings) {
305  g_autoptr(FlValue) result = fl_value_new_map();
307 
308  g_autoptr(FlMethodResponse) response =
309  FL_METHOD_RESPONSE(fl_method_success_response_new(result));
310 
311  g_autoptr(GError) error = nullptr;
312  if (!fl_method_call_respond(method_call, response, &error)) {
313  g_warning("Failed to send response to %s: %s", kClipboardHasStringsMethod,
314  error->message);
315  }
316 }
317 
319  FlMethodCall* method_call,
320  FlPlatformChannelExitResponse exit_response) {
321  g_autoptr(FlMethodResponse) response =
323  g_autoptr(GError) error = nullptr;
324  if (!fl_method_call_respond(method_call, response, &error)) {
325  g_warning("Failed to send response to System.exitApplication: %s",
326  error->message);
327  }
328 }
329 
331  FlPlatformChannelExitResponse exit_response) {
332  g_autoptr(FlValue) exit_result = fl_value_new_map();
333  const gchar* exit_response_string;
334  switch (exit_response) {
336  exit_response_string = kExitResponseCancel;
337  break;
339  exit_response_string = kExitResponseExit;
340  break;
341  default:
342  g_assert_not_reached();
343  }
345  fl_value_new_string(exit_response_string));
346  return FL_METHOD_RESPONSE(fl_method_success_response_new(exit_result));
347 }
kExitApplicationMethod
static constexpr char kExitApplicationMethod[]
Definition: fl_platform_channel.cc:17
fl_json_method_codec_new
G_MODULE_EXPORT FlJsonMethodCodec * fl_json_method_codec_new()
Definition: fl_json_method_codec.cc:205
FL_VALUE_TYPE_MAP
@ FL_VALUE_TYPE_MAP
Definition: fl_value.h:74
fl_platform_channel_system_request_app_exit_finish
gboolean fl_platform_channel_system_request_app_exit_finish(GObject *object, GAsyncResult *result, FlPlatformChannelExitResponse *exit_response, GError **error)
Definition: fl_platform_channel.cc:268
kClipboardHasStringsMethod
static constexpr char kClipboardHasStringsMethod[]
Definition: fl_platform_channel.cc:16
fl_platform_channel_make_system_request_app_exit_response
FlMethodResponse * fl_platform_channel_make_system_request_app_exit_response(FlPlatformChannelExitResponse exit_response)
Definition: fl_platform_channel.cc:330
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
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
type
uint8_t type
Definition: fl_standard_message_codec_test.cc:1115
fl_platform_channel_init
static void fl_platform_channel_init(FlPlatformChannel *self)
Definition: fl_platform_channel.cc:220
kExitResponseCancel
static constexpr char kExitResponseCancel[]
Definition: fl_platform_channel.cc:31
fl_value_set_string_take
G_MODULE_EXPORT void fl_value_set_string_take(FlValue *self, const gchar *key, FlValue *value)
Definition: fl_value.cc:650
FlPlatformChannelExitResponse
FlPlatformChannelExitResponse
Definition: fl_platform_channel.h:18
fl_method_not_implemented_response_new
G_MODULE_EXPORT FlMethodNotImplementedResponse * fl_method_not_implemented_response_new()
Definition: fl_method_response.cc:179
kExitTypeKey
static constexpr char kExitTypeKey[]
Definition: fl_platform_channel.cc:26
fl_platform_channel_class_init
static void fl_platform_channel_class_init(FlPlatformChannelClass *klass)
Definition: fl_platform_channel.cc:216
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
fl_value_new_bool
G_MODULE_EXPORT FlValue * fl_value_new_bool(bool value)
Definition: fl_value.cc:255
FlValue
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
clipboard_has_strings
static FlMethodResponse * clipboard_has_strings(FlPlatformChannel *self, FlMethodCall *method_call)
Definition: fl_platform_channel.cc:81
clipboard_get_data
static FlMethodResponse * clipboard_get_data(FlPlatformChannel *self, FlMethodCall *method_call)
Definition: fl_platform_channel.cc:68
kChannelName
static constexpr char kChannelName[]
Definition: fl_platform_channel.cc:12
kExitResponseKey
static constexpr char kExitResponseKey[]
Definition: fl_platform_channel.cc:30
fl_method_response_get_result
G_MODULE_EXPORT FlValue * fl_method_response_get_result(FlMethodResponse *self, GError **error)
Definition: fl_method_response.cc:82
fl_value_lookup_string
G_MODULE_EXPORT FlValue * fl_value_lookup_string(FlValue *self, const gchar *key)
Definition: fl_value.cc:811
fl_value_get_string
const G_MODULE_EXPORT gchar * fl_value_get_string(FlValue *self)
Definition: fl_value.cc:682
FL_PLATFORM_CHANNEL_EXIT_RESPONSE_CANCEL
@ FL_PLATFORM_CHANNEL_EXIT_RESPONSE_CANCEL
Definition: fl_platform_channel.h:19
kExitResponseExit
static constexpr char kExitResponseExit[]
Definition: fl_platform_channel.cc:32
fl_method_success_response_new
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)
Definition: fl_method_response.cc:126
kPlaySoundMethod
static constexpr char kPlaySoundMethod[]
Definition: fl_platform_channel.cc:21
kExitTypeRequired
static constexpr char kExitTypeRequired[]
Definition: fl_platform_channel.cc:28
_FlPlatformChannel::vtable
FlPlatformChannelVTable * vtable
Definition: fl_platform_channel.cc:40
system_exit_application
static FlMethodResponse * system_exit_application(FlPlatformChannel *self, FlMethodCall *method_call)
Definition: fl_platform_channel.cc:120
user_data
G_BEGIN_DECLS G_MODULE_EXPORT FlValue gpointer user_data
Definition: fl_event_channel.h:90
fl_method_call_respond
G_MODULE_EXPORT gboolean fl_method_call_respond(FlMethodCall *self, FlMethodResponse *response, GError **error)
Definition: fl_method_call.cc:77
kGetClipboardDataMethod
static constexpr char kGetClipboardDataMethod[]
Definition: fl_platform_channel.cc:14
fl_value_new_map
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition: fl_value.cc:366
kValueKey
static constexpr char kValueKey[]
Definition: fl_platform_channel.cc:24
fl_value_get_type
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition: fl_value.cc:466
method_call_cb
static void method_call_cb(FlMethodChannel *channel, FlMethodCall *method_call, gpointer user_data)
Definition: fl_platform_channel.cc:173
method_call
G_BEGIN_DECLS G_MODULE_EXPORT FlMethodCall * method_call
Definition: fl_method_channel.h:120
_FlPlatformChannel::parent_instance
GObject parent_instance
Definition: fl_platform_channel.cc:35
FL_VALUE_TYPE_STRING
@ FL_VALUE_TYPE_STRING
Definition: fl_value.h:68
FlPlatformChannelExitType
FlPlatformChannelExitType
Definition: fl_platform_channel.h:13
fl_method_call_get_name
const G_MODULE_EXPORT gchar * fl_method_call_get_name(FlMethodCall *self)
Definition: fl_method_call.cc:67
_FlPlatformChannel::user_data
gpointer user_data
Definition: fl_platform_channel.cc:43
fl_platform_channel_system_request_app_exit
void fl_platform_channel_system_request_app_exit(FlPlatformChannel *self, FlPlatformChannelExitType type, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition: fl_platform_channel.cc:243
fl_platform_channel_dispose
static void fl_platform_channel_dispose(GObject *object)
Definition: fl_platform_channel.cc:208
kRequestAppExitMethod
static constexpr char kRequestAppExitMethod[]
Definition: fl_platform_channel.cc:18
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
fl_platform_channel_respond_clipboard_has_strings
void fl_platform_channel_respond_clipboard_has_strings(FlMethodCall *method_call, gboolean has_strings)
Definition: fl_platform_channel.cc:302
fl_platform_channel_respond_clipboard_get_data
void fl_platform_channel_respond_clipboard_get_data(FlMethodCall *method_call, const gchar *text)
Definition: fl_platform_channel.cc:284
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_PLATFORM_CHANNEL_EXIT_TYPE_CANCELABLE
@ FL_PLATFORM_CHANNEL_EXIT_TYPE_CANCELABLE
Definition: fl_platform_channel.h:14
kBadArgumentsError
static constexpr char kBadArgumentsError[]
Definition: fl_platform_channel.cc:13
FlPlatformChannelVTable
Definition: fl_platform_channel.h:36
_FlPlatformChannel::channel
FlMethodChannel * channel
Definition: fl_platform_channel.cc:37
FL_PLATFORM_CHANNEL_EXIT_TYPE_REQUIRED
@ FL_PLATFORM_CHANNEL_EXIT_TYPE_REQUIRED
Definition: fl_platform_channel.h:15
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
system_sound_play
static FlMethodResponse * system_sound_play(FlPlatformChannel *self, FlValue *args)
Definition: fl_platform_channel.cc:155
system_navigator_pop
static FlMethodResponse * system_navigator_pop(FlPlatformChannel *self)
Definition: fl_platform_channel.cc:168
fl_platform_channel_new
FlPlatformChannel * fl_platform_channel_new(FlBinaryMessenger *messenger, FlPlatformChannelVTable *vtable, gpointer user_data)
Definition: fl_platform_channel.cc:222
FL_PLATFORM_CHANNEL_EXIT_RESPONSE_EXIT
@ FL_PLATFORM_CHANNEL_EXIT_RESPONSE_EXIT
Definition: fl_platform_channel.h:20
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
kTextKey
static constexpr char kTextKey[]
Definition: fl_platform_channel.cc:23
get_exit_response
FlPlatformChannelExitResponse get_exit_response(FlMethodResponse *response)
Definition: fl_platform_channel.cc:87
fl_method_call_get_args
G_MODULE_EXPORT FlValue * fl_method_call_get_args(FlMethodCall *self)
Definition: fl_method_call.cc:72
system_initialization_complete
static FlMethodResponse * system_initialization_complete(FlPlatformChannel *self)
Definition: fl_platform_channel.cc:149
kSystemNavigatorPopMethod
static constexpr char kSystemNavigatorPopMethod[]
Definition: fl_platform_channel.cc:22
kSetClipboardDataMethod
static constexpr char kSetClipboardDataMethod[]
Definition: fl_platform_channel.cc:15
clipboard_set_data
static FlMethodResponse * clipboard_set_data(FlPlatformChannel *self, FlMethodCall *method_call)
Definition: fl_platform_channel.cc:48
format
uint32_t uint32_t * format
Definition: fl_texture_registrar_test.cc:42
fl_platform_channel_respond_system_exit_application
void fl_platform_channel_respond_system_exit_application(FlMethodCall *method_call, FlPlatformChannelExitResponse exit_response)
Definition: fl_platform_channel.cc:318
kExitTypeCancelable
static constexpr char kExitTypeCancelable[]
Definition: fl_platform_channel.cc:27
fl_json_method_codec.h
_FlPlatformChannel
Definition: fl_platform_channel.cc:34
fl_value_new_string
G_MODULE_EXPORT FlValue * fl_value_new_string(const gchar *value)
Definition: fl_value.cc:276
kInitializationCompleteMethod
static constexpr char kInitializationCompleteMethod[]
Definition: fl_platform_channel.cc:19
fl_platform_channel.h