-
Notifications
You must be signed in to change notification settings - Fork 26.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bf1287c
commit 9600354
Showing
5 changed files
with
354 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "flutter/shell/platform/linux/public/flutter_linux/fl_basic_message_channel.h" | ||
|
||
#include <gmodule.h> | ||
|
||
struct _FlBasicMessageChannel { | ||
GObject parent_instance; | ||
|
||
// Messenger to communicate on | ||
FlBinaryMessenger* messenger; | ||
|
||
// Channel name | ||
gchar* name; | ||
|
||
// Codec to en/decode messages | ||
FlMessageCodec* codec; | ||
|
||
// Function called when a message is received | ||
FlBasicMessageChannelMessageHandler message_handler; | ||
gpointer message_handler_data; | ||
}; | ||
|
||
// Wrap the binary messenger handle for type safety and to make the API | ||
// consistent | ||
struct _FlBasicMessageChannelResponseHandle { | ||
FlBinaryMessengerResponseHandle* response_handle; | ||
}; | ||
|
||
static FlBasicMessageChannelResponseHandle* response_handle_new( | ||
FlBinaryMessengerResponseHandle* response_handle) { | ||
FlBasicMessageChannelResponseHandle* handle = | ||
static_cast<FlBasicMessageChannelResponseHandle*>( | ||
g_malloc0(sizeof(FlBasicMessageChannelResponseHandle))); | ||
handle->response_handle = response_handle; | ||
|
||
return handle; | ||
} | ||
|
||
static void response_handle_free(FlBasicMessageChannelResponseHandle* handle) { | ||
g_free(handle); | ||
} | ||
|
||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(FlBasicMessageChannelResponseHandle, | ||
response_handle_free); | ||
|
||
// Added here to stop the compiler from optimising this function away | ||
G_MODULE_EXPORT GType fl_basic_message_channel_get_type(); | ||
|
||
G_DEFINE_TYPE(FlBasicMessageChannel, fl_basic_message_channel, G_TYPE_OBJECT) | ||
|
||
// Called when a binary message is received on this channel | ||
static void message_cb(FlBinaryMessenger* messenger, | ||
const gchar* channel, | ||
GBytes* message, | ||
FlBinaryMessengerResponseHandle* response_handle, | ||
gpointer user_data) { | ||
FlBasicMessageChannel* self = FL_BASIC_MESSAGE_CHANNEL(user_data); | ||
|
||
if (self->message_handler == nullptr) { | ||
fl_binary_messenger_send_response(messenger, response_handle, nullptr, | ||
nullptr); | ||
return; | ||
} | ||
|
||
g_autoptr(GError) error = nullptr; | ||
g_autoptr(FlValue) message_value = | ||
fl_message_codec_decode_message(self->codec, message, &error); | ||
if (message_value == nullptr) { | ||
g_warning("Failed to decode message: %s", error->message); | ||
fl_binary_messenger_send_response(messenger, response_handle, nullptr, | ||
nullptr); | ||
} | ||
|
||
self->message_handler(self, message_value, | ||
response_handle_new(response_handle), | ||
self->message_handler_data); | ||
} | ||
|
||
// Called when a response is received to a sent message | ||
static void message_response_cb(GObject* object, | ||
GAsyncResult* result, | ||
gpointer user_data) { | ||
GTask* task = G_TASK(user_data); | ||
g_task_return_pointer(task, result, g_object_unref); | ||
} | ||
|
||
static void fl_basic_message_channel_dispose(GObject* object) { | ||
FlBasicMessageChannel* self = FL_BASIC_MESSAGE_CHANNEL(object); | ||
|
||
if (self->messenger != nullptr) | ||
fl_binary_messenger_set_message_handler_on_channel( | ||
self->messenger, self->name, nullptr, nullptr); | ||
|
||
g_clear_object(&self->messenger); | ||
g_clear_pointer(&self->name, g_free); | ||
g_clear_object(&self->codec); | ||
|
||
G_OBJECT_CLASS(fl_basic_message_channel_parent_class)->dispose(object); | ||
} | ||
|
||
static void fl_basic_message_channel_class_init( | ||
FlBasicMessageChannelClass* klass) { | ||
G_OBJECT_CLASS(klass)->dispose = fl_basic_message_channel_dispose; | ||
} | ||
|
||
static void fl_basic_message_channel_init(FlBasicMessageChannel* self) {} | ||
|
||
G_MODULE_EXPORT FlBasicMessageChannel* fl_basic_message_channel_new( | ||
FlBinaryMessenger* messenger, | ||
const gchar* name, | ||
FlMessageCodec* codec) { | ||
g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr); | ||
g_return_val_if_fail(name != nullptr, nullptr); | ||
g_return_val_if_fail(FL_IS_MESSAGE_CODEC(codec), nullptr); | ||
|
||
FlBasicMessageChannel* self = FL_BASIC_MESSAGE_CHANNEL( | ||
g_object_new(fl_basic_message_channel_get_type(), nullptr)); | ||
|
||
self->messenger = FL_BINARY_MESSENGER(g_object_ref(messenger)); | ||
self->name = g_strdup(name); | ||
self->codec = FL_MESSAGE_CODEC(g_object_ref(codec)); | ||
|
||
fl_binary_messenger_set_message_handler_on_channel( | ||
self->messenger, self->name, message_cb, self); | ||
|
||
return self; | ||
} | ||
|
||
G_MODULE_EXPORT void fl_basic_message_channel_set_message_handler( | ||
FlBasicMessageChannel* self, | ||
FlBasicMessageChannelMessageHandler handler, | ||
gpointer user_data) { | ||
g_return_if_fail(FL_IS_BASIC_MESSAGE_CHANNEL(self)); | ||
|
||
self->message_handler = handler; | ||
self->message_handler_data = user_data; | ||
} | ||
|
||
G_MODULE_EXPORT gboolean fl_basic_message_channel_respond( | ||
FlBasicMessageChannel* self, | ||
FlBasicMessageChannelResponseHandle* response_handle, | ||
FlValue* message, | ||
GError** error) { | ||
g_return_val_if_fail(FL_IS_BASIC_MESSAGE_CHANNEL(self), FALSE); | ||
g_return_val_if_fail(response_handle != nullptr, FALSE); | ||
|
||
// Take reference to ensure it is freed | ||
g_autoptr(FlBasicMessageChannelResponseHandle) owned_response_handle = | ||
response_handle; | ||
|
||
g_autoptr(GBytes) data = | ||
fl_message_codec_encode_message(self->codec, message, error); | ||
if (data == nullptr) | ||
return FALSE; | ||
|
||
return fl_binary_messenger_send_response( | ||
self->messenger, owned_response_handle->response_handle, data, error); | ||
} | ||
|
||
G_MODULE_EXPORT void fl_basic_message_channel_send(FlBasicMessageChannel* self, | ||
FlValue* message, | ||
GCancellable* cancellable, | ||
GAsyncReadyCallback callback, | ||
gpointer user_data) { | ||
g_return_if_fail(FL_IS_BASIC_MESSAGE_CHANNEL(self)); | ||
g_return_if_fail(message != nullptr); | ||
|
||
g_autoptr(GTask) task = | ||
callback != nullptr ? g_task_new(self, cancellable, callback, user_data) | ||
: nullptr; | ||
|
||
g_autoptr(GError) error = nullptr; | ||
g_autoptr(GBytes) data = | ||
fl_message_codec_encode_message(self->codec, message, &error); | ||
if (data == nullptr) { | ||
if (task != nullptr) | ||
g_task_return_error(task, error); | ||
return; | ||
} | ||
|
||
fl_binary_messenger_send_on_channel( | ||
self->messenger, self->name, data, cancellable, | ||
callback != nullptr ? message_response_cb : nullptr, | ||
g_steal_pointer(&task)); | ||
} | ||
|
||
G_MODULE_EXPORT FlValue* fl_basic_message_channel_send_on_channel_finish( | ||
FlBasicMessageChannel* self, | ||
GAsyncResult* result, | ||
GError** error) { | ||
g_return_val_if_fail(FL_IS_BASIC_MESSAGE_CHANNEL(self), nullptr); | ||
g_return_val_if_fail(g_task_is_valid(result, self), nullptr); | ||
|
||
g_autoptr(GTask) task = G_TASK(result); | ||
GAsyncResult* r = G_ASYNC_RESULT(g_task_propagate_pointer(task, nullptr)); | ||
|
||
g_autoptr(GBytes) message = | ||
fl_binary_messenger_send_on_channel_finish(self->messenger, r, error); | ||
if (message == nullptr) | ||
return nullptr; | ||
|
||
return fl_message_codec_decode_message(self->codec, message, error); | ||
} |
143 changes: 143 additions & 0 deletions
143
shell/platform/linux/public/flutter_linux/fl_basic_message_channel.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_BASIC_MESSAGE_CHANNEL_H_ | ||
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_BASIC_MESSAGE_CHANNEL_H_ | ||
|
||
#if !defined(__FLUTTER_LINUX_INSIDE__) && !defined(FLUTTER_LINUX_COMPILATION) | ||
#error "Only <flutter_linux/flutter_linux.h> can be included directly." | ||
#endif | ||
|
||
#include <gio/gio.h> | ||
#include <glib-object.h> | ||
|
||
#include "fl_binary_messenger.h" | ||
#include "fl_message_codec.h" | ||
|
||
G_BEGIN_DECLS | ||
|
||
G_DECLARE_FINAL_TYPE(FlBasicMessageChannel, | ||
fl_basic_message_channel, | ||
FL, | ||
BASIC_MESSAGE_CHANNEL, | ||
GObject) | ||
|
||
/** | ||
* FlBasicMessageChannel: | ||
* | ||
* #FlBasicMessageChannel is an object that allows sending and receiving | ||
* messages to/from Dart code over platform channels. | ||
* | ||
* #FlBasicMessageChannel matches the BasicMessageChannel class in the Flutter | ||
* services library. | ||
*/ | ||
|
||
/** | ||
* FlBasicMessageChannelResponseHandle: | ||
* | ||
* A handle used to respond to messages. | ||
*/ | ||
typedef struct _FlBasicMessageChannelResponseHandle | ||
FlBasicMessageChannelResponseHandle; | ||
|
||
/** | ||
* FlBasicMessageChannelMessageHandler: | ||
* @channel: a #FlBasicMessageChannel | ||
* @message: message received | ||
* @response_handle: (transfer full): a handle to respond to the message with | ||
* @user_data: (closure): data provided when registering this handler | ||
* | ||
* Function called when a message is received. | ||
*/ | ||
typedef void (*FlBasicMessageChannelMessageHandler)( | ||
FlBasicMessageChannel* channel, | ||
FlValue* message, | ||
FlBasicMessageChannelResponseHandle* response_handle, | ||
gpointer user_data); | ||
|
||
/** | ||
* fl_basic_message_channel_new: | ||
* @messenger: a #FlBinaryMessenger | ||
* @name: a channel name | ||
* @codec: the message codec | ||
* | ||
* Create a new basic message channel. @codec must match the codec used on the | ||
* Dart end of the channel. | ||
* | ||
* Returns: a new #FlBasicMessageChannel. | ||
*/ | ||
FlBasicMessageChannel* fl_basic_message_channel_new( | ||
FlBinaryMessenger* messenger, | ||
const gchar* name, | ||
FlMessageCodec* codec); | ||
|
||
/** | ||
* fl_basic_message_channel_set_message_handler: | ||
* @channel: a #FlBasicMessageChannel | ||
* @handler: (allow-none): function to call when a message is received on this | ||
* channel or %NULL to disable the handler. | ||
* @user_data: (closure): user data to pass to @handler | ||
* | ||
* Set the function called when a message is received. | ||
*/ | ||
void fl_basic_message_channel_set_message_handler( | ||
FlBasicMessageChannel* channel, | ||
FlBasicMessageChannelMessageHandler handler, | ||
gpointer user_data); | ||
|
||
/** | ||
* fl_basic_message_channel_send_response: | ||
* @channel: a #FlBasicMessageChannel | ||
* @response_handle: (transfer full): handle that was provided in a | ||
* #FlBasicMessageChannelMessageHandler | ||
* @response: (allow-none): response to send or %NULL for an empty response | ||
* @error: (allow-none): #GError location to store the error occurring, or %NULL | ||
* to ignore | ||
* | ||
* Respond to a message. | ||
* | ||
* Returns: %TRUE on success. | ||
*/ | ||
gboolean fl_basic_message_channel_send_response( | ||
FlBasicMessageChannel* channel, | ||
FlBasicMessageChannelResponseHandle* response_handle, | ||
FlValue* response, | ||
GError** error); | ||
|
||
/** | ||
* fl_basic_message_channel_send: | ||
* @channel: a #FlBasicMessageChannel | ||
* @message: message to send, must match what the #FlMessageCodec supports | ||
* @cancellable: (allow-none): a #GCancellable or %NULL | ||
* @callback: (scope async): (allow-none): a #GAsyncReadyCallback to call when | ||
* the request is satisfied or %NULL to ignore the response. | ||
* @user_data: (closure): user data to pass to @callback | ||
* | ||
* Asynchronously send a message. | ||
*/ | ||
void fl_basic_message_channel_send(FlBasicMessageChannel* channel, | ||
FlValue* message, | ||
GCancellable* cancellable, | ||
GAsyncReadyCallback callback, | ||
gpointer user_data); | ||
|
||
/** | ||
* fl_basic_message_channel_send_finish: | ||
* @channel: a #FlBasicMessageChannel | ||
* @result: a #GAsyncResult | ||
* @error: (allow-none): #GError location to store the error occurring, or %NULL | ||
* to ignore. | ||
* | ||
* Complete request started with fl_basic_message_channel_send(). | ||
* | ||
* Returns: message response on success or %NULL on error. | ||
*/ | ||
FlValue* fl_basic_message_channel_send_on_channel_finish( | ||
FlBasicMessageChannel* channel, | ||
GAsyncResult* result, | ||
GError** error); | ||
|
||
G_END_DECLS | ||
|
||
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_BASIC_MESSAGE_CHANNEL_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters