Flutter Engine
 
Loading...
Searching...
No Matches
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
12static constexpr char kChannelName[] = "flutter/platform";
13static constexpr char kBadArgumentsError[] = "Bad Arguments";
14static constexpr char kGetClipboardDataMethod[] = "Clipboard.getData";
15static constexpr char kSetClipboardDataMethod[] = "Clipboard.setData";
16static constexpr char kClipboardHasStringsMethod[] = "Clipboard.hasStrings";
17static constexpr char kExitApplicationMethod[] = "System.exitApplication";
18static constexpr char kRequestAppExitMethod[] = "System.requestAppExit";
19static constexpr char kInitializationCompleteMethod[] =
20 "System.initializationComplete";
21static constexpr char kPlaySoundMethod[] = "SystemSound.play";
22static constexpr char kSystemNavigatorPopMethod[] = "SystemNavigator.pop";
23static constexpr char kTextKey[] = "text";
24static constexpr char kValueKey[] = "value";
25
26static constexpr char kExitTypeKey[] = "type";
27static constexpr char kExitTypeCancelable[] = "cancelable";
28static constexpr char kExitTypeRequired[] = "required";
29
30static constexpr char kExitResponseKey[] = "response";
31static constexpr char kExitResponseCancel[] = "cancel";
32static constexpr char kExitResponseExit[] = "exit";
33
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
46G_DEFINE_TYPE(FlPlatformChannel, fl_platform_channel, G_TYPE_OBJECT)
47
48static 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 ||
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
68static 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
81static 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.
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
120static 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 ||
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
149static 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
155static 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
168static 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
173static 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) {
184 } else if (strcmp(method, kGetClipboardDataMethod) == 0) {
186 } else if (strcmp(method, kClipboardHasStringsMethod) == 0) {
188 } else if (strcmp(method, kExitApplicationMethod) == 0) {
190 } else if (strcmp(method, kInitializationCompleteMethod) == 0) {
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
208static 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
216static void fl_platform_channel_class_init(FlPlatformChannelClass* klass) {
217 G_OBJECT_CLASS(klass)->dispose = fl_platform_channel_dispose;
218}
219
220static void fl_platform_channel_init(FlPlatformChannel* self) {}
221
222FlPlatformChannel* fl_platform_channel_new(FlBinaryMessenger* messenger,
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
245 GCancellable* cancellable,
246 GAsyncReadyCallback callback,
247 gpointer user_data) {
248 g_return_if_fail(FL_IS_PLATFORM_CHANNEL(self));
249
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) {
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}
GLenum 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)
g_autoptr(GMutexLocker) locker
return TRUE
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
G_MODULE_EXPORT FlJsonMethodCodec * fl_json_method_codec_new()
G_MODULE_EXPORT const gchar * fl_method_call_get_name(FlMethodCall *self)
G_MODULE_EXPORT gboolean fl_method_call_respond(FlMethodCall *self, FlMethodResponse *response, GError **error)
G_MODULE_EXPORT FlValue * fl_method_call_get_args(FlMethodCall *self)
G_MODULE_EXPORT FlMethodResponse * fl_method_channel_invoke_method_finish(FlMethodChannel *self, GAsyncResult *result, GError **error)
G_MODULE_EXPORT FlMethodChannel * fl_method_channel_new(FlBinaryMessenger *messenger, const gchar *name, FlMethodCodec *codec)
G_MODULE_EXPORT void fl_method_channel_invoke_method(FlMethodChannel *self, const gchar *method, FlValue *args, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
G_MODULE_EXPORT void fl_method_channel_set_method_call_handler(FlMethodChannel *self, FlMethodChannelMethodCallHandler handler, gpointer user_data, GDestroyNotify destroy_notify)
G_BEGIN_DECLS G_MODULE_EXPORT FlMethodCall * method_call
G_MODULE_EXPORT FlValue * fl_method_response_get_result(FlMethodResponse *self, GError **error)
G_MODULE_EXPORT FlMethodErrorResponse * fl_method_error_response_new(const gchar *code, const gchar *message, FlValue *details)
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)
G_MODULE_EXPORT FlMethodNotImplementedResponse * fl_method_not_implemented_response_new()
const gchar * channel
const uint8_t uint32_t uint32_t GError ** error
static void method_call_cb(FlMethodChannel *channel, FlMethodCall *method_call, gpointer user_data)
static constexpr char kValueKey[]
FlMethodResponse * fl_platform_channel_make_system_request_app_exit_response(FlPlatformChannelExitResponse exit_response)
static constexpr char kSystemNavigatorPopMethod[]
static constexpr char kInitializationCompleteMethod[]
gboolean fl_platform_channel_system_request_app_exit_finish(GObject *object, GAsyncResult *result, FlPlatformChannelExitResponse *exit_response, GError **error)
static constexpr char kClipboardHasStringsMethod[]
void fl_platform_channel_respond_clipboard_get_data(FlMethodCall *method_call, const gchar *text)
static FlMethodResponse * system_initialization_complete(FlPlatformChannel *self)
static constexpr char kExitTypeCancelable[]
static FlMethodResponse * clipboard_has_strings(FlPlatformChannel *self, FlMethodCall *method_call)
static FlMethodResponse * clipboard_set_data(FlPlatformChannel *self, FlMethodCall *method_call)
static void fl_platform_channel_init(FlPlatformChannel *self)
static constexpr char kGetClipboardDataMethod[]
static constexpr char kChannelName[]
FlPlatformChannelExitResponse get_exit_response(FlMethodResponse *response)
static constexpr char kExitApplicationMethod[]
static constexpr char kExitResponseExit[]
static constexpr char kRequestAppExitMethod[]
static constexpr char kBadArgumentsError[]
static FlMethodResponse * clipboard_get_data(FlPlatformChannel *self, FlMethodCall *method_call)
static FlMethodResponse * system_sound_play(FlPlatformChannel *self, FlValue *args)
void fl_platform_channel_system_request_app_exit(FlPlatformChannel *self, FlPlatformChannelExitType type, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
static constexpr char kExitTypeRequired[]
void fl_platform_channel_respond_system_exit_application(FlMethodCall *method_call, FlPlatformChannelExitResponse exit_response)
static constexpr char kExitResponseKey[]
static constexpr char kPlaySoundMethod[]
static FlMethodResponse * system_exit_application(FlPlatformChannel *self, FlMethodCall *method_call)
void fl_platform_channel_respond_clipboard_has_strings(FlMethodCall *method_call, gboolean has_strings)
static constexpr char kExitResponseCancel[]
static void fl_platform_channel_dispose(GObject *object)
static constexpr char kExitTypeKey[]
FlPlatformChannel * fl_platform_channel_new(FlBinaryMessenger *messenger, FlPlatformChannelVTable *vtable, gpointer user_data)
static void fl_platform_channel_class_init(FlPlatformChannelClass *klass)
static constexpr char kTextKey[]
static constexpr char kSetClipboardDataMethod[]
static FlMethodResponse * system_navigator_pop(FlPlatformChannel *self)
FlPlatformChannelExitResponse
@ FL_PLATFORM_CHANNEL_EXIT_RESPONSE_EXIT
@ FL_PLATFORM_CHANNEL_EXIT_RESPONSE_CANCEL
FlPlatformChannelExitType
@ FL_PLATFORM_CHANNEL_EXIT_TYPE_CANCELABLE
@ FL_PLATFORM_CHANNEL_EXIT_TYPE_REQUIRED
uint32_t uint32_t * format
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition fl_value.cc:366
G_MODULE_EXPORT void fl_value_set_string_take(FlValue *self, const gchar *key, FlValue *value)
Definition fl_value.cc:650
G_MODULE_EXPORT FlValue * fl_value_lookup_string(FlValue *self, const gchar *key)
Definition fl_value.cc:811
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition fl_value.cc:466
G_MODULE_EXPORT FlValue * fl_value_new_string(const gchar *value)
Definition fl_value.cc:276
G_MODULE_EXPORT FlValue * fl_value_new_bool(bool value)
Definition fl_value.cc:255
G_MODULE_EXPORT const gchar * fl_value_get_string(FlValue *self)
Definition fl_value.cc:682
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition fl_value.h:42
@ FL_VALUE_TYPE_STRING
Definition fl_value.h:68
@ FL_VALUE_TYPE_MAP
Definition fl_value.h:74
FlutterDesktopBinaryReply callback
std::u16string text
FlMethodChannel * channel
FlPlatformChannelVTable * vtable