Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit b7c58d3

Browse files
committed
Add FlBasicMessageChannel
1 parent dc93db5 commit b7c58d3

File tree

5 files changed

+354
-0
lines changed

5 files changed

+354
-0
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,7 @@ FILE: ../../../flutter/shell/platform/glfw/platform_handler.h
11851185
FILE: ../../../flutter/shell/platform/glfw/public/flutter_glfw.h
11861186
FILE: ../../../flutter/shell/platform/glfw/text_input_plugin.cc
11871187
FILE: ../../../flutter/shell/platform/glfw/text_input_plugin.h
1188+
FILE: ../../../flutter/shell/platform/linux/fl_basic_message_channel.cc
11881189
FILE: ../../../flutter/shell/platform/linux/fl_binary_codec.cc
11891190
FILE: ../../../flutter/shell/platform/linux/fl_binary_codec_test.cc
11901191
FILE: ../../../flutter/shell/platform/linux/fl_binary_messenger.cc
@@ -1207,6 +1208,7 @@ FILE: ../../../flutter/shell/platform/linux/fl_string_codec_test.cc
12071208
FILE: ../../../flutter/shell/platform/linux/fl_value.cc
12081209
FILE: ../../../flutter/shell/platform/linux/fl_value_test.cc
12091210
FILE: ../../../flutter/shell/platform/linux/fl_view.cc
1211+
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_basic_message_channel.h
12101212
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_binary_codec.h
12111213
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_binary_messenger.h
12121214
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_dart_project.h

shell/platform/linux/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ if (build_glfw_shell) {
4444
}
4545

4646
_public_headers = [
47+
"public/flutter_linux/fl_basic_message_channel.h",
4748
"public/flutter_linux/fl_binary_codec.h",
4849
"public/flutter_linux/fl_binary_messenger.h",
4950
"public/flutter_linux/fl_dart_project.h",
@@ -64,6 +65,7 @@ source_set("flutter_linux") {
6465
public = _public_headers
6566

6667
sources = [
68+
"fl_basic_message_channel.cc",
6769
"fl_binary_codec.cc",
6870
"fl_binary_messenger.cc",
6971
"fl_dart_project.cc",
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
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+
9+
struct _FlBasicMessageChannel {
10+
GObject parent_instance;
11+
12+
// Messenger to communicate on
13+
FlBinaryMessenger* messenger;
14+
15+
// Channel name
16+
gchar* name;
17+
18+
// Codec to en/decode messages
19+
FlMessageCodec* codec;
20+
21+
// Function called when a message is received
22+
FlBasicMessageChannelMessageHandler message_handler;
23+
gpointer message_handler_data;
24+
};
25+
26+
// Wrap the binary messenger handle for type safety and to make the API
27+
// consistent
28+
struct _FlBasicMessageChannelResponseHandle {
29+
FlBinaryMessengerResponseHandle* response_handle;
30+
};
31+
32+
static FlBasicMessageChannelResponseHandle* response_handle_new(
33+
FlBinaryMessengerResponseHandle* response_handle) {
34+
FlBasicMessageChannelResponseHandle* handle =
35+
static_cast<FlBasicMessageChannelResponseHandle*>(
36+
g_malloc0(sizeof(FlBasicMessageChannelResponseHandle)));
37+
handle->response_handle = response_handle;
38+
39+
return handle;
40+
}
41+
42+
static void response_handle_free(FlBasicMessageChannelResponseHandle* handle) {
43+
g_free(handle);
44+
}
45+
46+
G_DEFINE_AUTOPTR_CLEANUP_FUNC(FlBasicMessageChannelResponseHandle,
47+
response_handle_free);
48+
49+
// Added here to stop the compiler from optimising this function away
50+
G_MODULE_EXPORT GType fl_basic_message_channel_get_type();
51+
52+
G_DEFINE_TYPE(FlBasicMessageChannel, fl_basic_message_channel, G_TYPE_OBJECT)
53+
54+
// Called when a binary message is received on this channel
55+
static void message_cb(FlBinaryMessenger* messenger,
56+
const gchar* channel,
57+
GBytes* message,
58+
FlBinaryMessengerResponseHandle* response_handle,
59+
gpointer user_data) {
60+
FlBasicMessageChannel* self = FL_BASIC_MESSAGE_CHANNEL(user_data);
61+
62+
if (self->message_handler == nullptr) {
63+
fl_binary_messenger_send_response(messenger, response_handle, nullptr,
64+
nullptr);
65+
return;
66+
}
67+
68+
g_autoptr(GError) error = nullptr;
69+
g_autoptr(FlValue) message_value =
70+
fl_message_codec_decode_message(self->codec, message, &error);
71+
if (message_value == nullptr) {
72+
g_warning("Failed to decode message: %s", error->message);
73+
fl_binary_messenger_send_response(messenger, response_handle, nullptr,
74+
nullptr);
75+
}
76+
77+
self->message_handler(self, message_value,
78+
response_handle_new(response_handle),
79+
self->message_handler_data);
80+
}
81+
82+
// Called when a response is received to a sent message
83+
static void message_response_cb(GObject* object,
84+
GAsyncResult* result,
85+
gpointer user_data) {
86+
GTask* task = G_TASK(user_data);
87+
g_task_return_pointer(task, result, g_object_unref);
88+
}
89+
90+
static void fl_basic_message_channel_dispose(GObject* object) {
91+
FlBasicMessageChannel* self = FL_BASIC_MESSAGE_CHANNEL(object);
92+
93+
if (self->messenger != nullptr)
94+
fl_binary_messenger_set_message_handler_on_channel(
95+
self->messenger, self->name, nullptr, nullptr);
96+
97+
g_clear_object(&self->messenger);
98+
g_clear_pointer(&self->name, g_free);
99+
g_clear_object(&self->codec);
100+
101+
G_OBJECT_CLASS(fl_basic_message_channel_parent_class)->dispose(object);
102+
}
103+
104+
static void fl_basic_message_channel_class_init(
105+
FlBasicMessageChannelClass* klass) {
106+
G_OBJECT_CLASS(klass)->dispose = fl_basic_message_channel_dispose;
107+
}
108+
109+
static void fl_basic_message_channel_init(FlBasicMessageChannel* self) {}
110+
111+
G_MODULE_EXPORT FlBasicMessageChannel* fl_basic_message_channel_new(
112+
FlBinaryMessenger* messenger,
113+
const gchar* name,
114+
FlMessageCodec* codec) {
115+
g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);
116+
g_return_val_if_fail(name != nullptr, nullptr);
117+
g_return_val_if_fail(FL_IS_MESSAGE_CODEC(codec), nullptr);
118+
119+
FlBasicMessageChannel* self = FL_BASIC_MESSAGE_CHANNEL(
120+
g_object_new(fl_basic_message_channel_get_type(), nullptr));
121+
122+
self->messenger = FL_BINARY_MESSENGER(g_object_ref(messenger));
123+
self->name = g_strdup(name);
124+
self->codec = FL_MESSAGE_CODEC(g_object_ref(codec));
125+
126+
fl_binary_messenger_set_message_handler_on_channel(
127+
self->messenger, self->name, message_cb, self);
128+
129+
return self;
130+
}
131+
132+
G_MODULE_EXPORT void fl_basic_message_channel_set_message_handler(
133+
FlBasicMessageChannel* self,
134+
FlBasicMessageChannelMessageHandler handler,
135+
gpointer user_data) {
136+
g_return_if_fail(FL_IS_BASIC_MESSAGE_CHANNEL(self));
137+
138+
self->message_handler = handler;
139+
self->message_handler_data = user_data;
140+
}
141+
142+
G_MODULE_EXPORT gboolean fl_basic_message_channel_respond(
143+
FlBasicMessageChannel* self,
144+
FlBasicMessageChannelResponseHandle* response_handle,
145+
FlValue* message,
146+
GError** error) {
147+
g_return_val_if_fail(FL_IS_BASIC_MESSAGE_CHANNEL(self), FALSE);
148+
g_return_val_if_fail(response_handle != nullptr, FALSE);
149+
150+
// Take reference to ensure it is freed
151+
g_autoptr(FlBasicMessageChannelResponseHandle) owned_response_handle =
152+
response_handle;
153+
154+
g_autoptr(GBytes) data =
155+
fl_message_codec_encode_message(self->codec, message, error);
156+
if (data == nullptr)
157+
return FALSE;
158+
159+
return fl_binary_messenger_send_response(
160+
self->messenger, owned_response_handle->response_handle, data, error);
161+
}
162+
163+
G_MODULE_EXPORT void fl_basic_message_channel_send(FlBasicMessageChannel* self,
164+
FlValue* message,
165+
GCancellable* cancellable,
166+
GAsyncReadyCallback callback,
167+
gpointer user_data) {
168+
g_return_if_fail(FL_IS_BASIC_MESSAGE_CHANNEL(self));
169+
g_return_if_fail(message != nullptr);
170+
171+
g_autoptr(GTask) task =
172+
callback != nullptr ? g_task_new(self, cancellable, callback, user_data)
173+
: nullptr;
174+
175+
g_autoptr(GError) error = nullptr;
176+
g_autoptr(GBytes) data =
177+
fl_message_codec_encode_message(self->codec, message, &error);
178+
if (data == nullptr) {
179+
if (task != nullptr)
180+
g_task_return_error(task, error);
181+
return;
182+
}
183+
184+
fl_binary_messenger_send_on_channel(
185+
self->messenger, self->name, data, cancellable,
186+
callback != nullptr ? message_response_cb : nullptr,
187+
g_steal_pointer(&task));
188+
}
189+
190+
G_MODULE_EXPORT FlValue* fl_basic_message_channel_send_on_channel_finish(
191+
FlBasicMessageChannel* self,
192+
GAsyncResult* result,
193+
GError** error) {
194+
g_return_val_if_fail(FL_IS_BASIC_MESSAGE_CHANNEL(self), nullptr);
195+
g_return_val_if_fail(g_task_is_valid(result, self), nullptr);
196+
197+
g_autoptr(GTask) task = G_TASK(result);
198+
GAsyncResult* r = G_ASYNC_RESULT(g_task_propagate_pointer(task, nullptr));
199+
200+
g_autoptr(GBytes) message =
201+
fl_binary_messenger_send_on_channel_finish(self->messenger, r, error);
202+
if (message == nullptr)
203+
return nullptr;
204+
205+
return fl_message_codec_decode_message(self->codec, message, error);
206+
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
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+
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_BASIC_MESSAGE_CHANNEL_H_
6+
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_BASIC_MESSAGE_CHANNEL_H_
7+
8+
#if !defined(__FLUTTER_LINUX_INSIDE__) && !defined(FLUTTER_LINUX_COMPILATION)
9+
#error "Only <flutter_linux/flutter_linux.h> can be included directly."
10+
#endif
11+
12+
#include <gio/gio.h>
13+
#include <glib-object.h>
14+
15+
#include "fl_binary_messenger.h"
16+
#include "fl_message_codec.h"
17+
18+
G_BEGIN_DECLS
19+
20+
G_DECLARE_FINAL_TYPE(FlBasicMessageChannel,
21+
fl_basic_message_channel,
22+
FL,
23+
BASIC_MESSAGE_CHANNEL,
24+
GObject)
25+
26+
/**
27+
* FlBasicMessageChannel:
28+
*
29+
* #FlBasicMessageChannel is an object that allows sending and receiving
30+
* messages to/from Dart code over platform channels.
31+
*
32+
* #FlBasicMessageChannel matches the BasicMessageChannel class in the Flutter
33+
* services library.
34+
*/
35+
36+
/**
37+
* FlBasicMessageChannelResponseHandle:
38+
*
39+
* A handle used to respond to messages.
40+
*/
41+
typedef struct _FlBasicMessageChannelResponseHandle
42+
FlBasicMessageChannelResponseHandle;
43+
44+
/**
45+
* FlBasicMessageChannelMessageHandler:
46+
* @channel: a #FlBasicMessageChannel
47+
* @message: message received
48+
* @response_handle: (transfer full): a handle to respond to the message with
49+
* @user_data: (closure): data provided when registering this handler
50+
*
51+
* Function called when a message is received.
52+
*/
53+
typedef void (*FlBasicMessageChannelMessageHandler)(
54+
FlBasicMessageChannel* channel,
55+
FlValue* message,
56+
FlBasicMessageChannelResponseHandle* response_handle,
57+
gpointer user_data);
58+
59+
/**
60+
* fl_basic_message_channel_new:
61+
* @messenger: a #FlBinaryMessenger
62+
* @name: a channel name
63+
* @codec: the message codec
64+
*
65+
* Create a new basic message channel. @codec must match the codec used on the
66+
* Dart end of the channel.
67+
*
68+
* Returns: a new #FlBasicMessageChannel.
69+
*/
70+
FlBasicMessageChannel* fl_basic_message_channel_new(
71+
FlBinaryMessenger* messenger,
72+
const gchar* name,
73+
FlMessageCodec* codec);
74+
75+
/**
76+
* fl_basic_message_channel_set_message_handler:
77+
* @channel: a #FlBasicMessageChannel
78+
* @handler: (allow-none): function to call when a message is received on this
79+
* channel or %NULL to disable the handler.
80+
* @user_data: (closure): user data to pass to @handler
81+
*
82+
* Set the function called when a message is received.
83+
*/
84+
void fl_basic_message_channel_set_message_handler(
85+
FlBasicMessageChannel* channel,
86+
FlBasicMessageChannelMessageHandler handler,
87+
gpointer user_data);
88+
89+
/**
90+
* fl_basic_message_channel_send_response:
91+
* @channel: a #FlBasicMessageChannel
92+
* @response_handle: (transfer full): handle that was provided in a
93+
* #FlBasicMessageChannelMessageHandler
94+
* @response: (allow-none): response to send or %NULL for an empty response
95+
* @error: (allow-none): #GError location to store the error occurring, or %NULL
96+
* to ignore
97+
*
98+
* Respond to a message.
99+
*
100+
* Returns: %TRUE on success.
101+
*/
102+
gboolean fl_basic_message_channel_send_response(
103+
FlBasicMessageChannel* channel,
104+
FlBasicMessageChannelResponseHandle* response_handle,
105+
FlValue* response,
106+
GError** error);
107+
108+
/**
109+
* fl_basic_message_channel_send:
110+
* @channel: a #FlBasicMessageChannel
111+
* @message: message to send, must match what the #FlMessageCodec supports
112+
* @cancellable: (allow-none): a #GCancellable or %NULL
113+
* @callback: (scope async): (allow-none): a #GAsyncReadyCallback to call when
114+
* the request is satisfied or %NULL to ignore the response.
115+
* @user_data: (closure): user data to pass to @callback
116+
*
117+
* Asynchronously send a message.
118+
*/
119+
void fl_basic_message_channel_send(FlBasicMessageChannel* channel,
120+
FlValue* message,
121+
GCancellable* cancellable,
122+
GAsyncReadyCallback callback,
123+
gpointer user_data);
124+
125+
/**
126+
* fl_basic_message_channel_send_finish:
127+
* @channel: a #FlBasicMessageChannel
128+
* @result: a #GAsyncResult
129+
* @error: (allow-none): #GError location to store the error occurring, or %NULL
130+
* to ignore.
131+
*
132+
* Complete request started with fl_basic_message_channel_send().
133+
*
134+
* Returns: message response on success or %NULL on error.
135+
*/
136+
FlValue* fl_basic_message_channel_send_on_channel_finish(
137+
FlBasicMessageChannel* channel,
138+
GAsyncResult* result,
139+
GError** error);
140+
141+
G_END_DECLS
142+
143+
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_BASIC_MESSAGE_CHANNEL_H_

shell/platform/linux/public/flutter_linux/flutter_linux.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#define __FLUTTER_LINUX_INSIDE__
99

10+
#include <flutter_linux/fl_basic_message_channel.h>
1011
#include <flutter_linux/fl_binary_codec.h>
1112
#include <flutter_linux/fl_binary_messenger.h>
1213
#include <flutter_linux/fl_dart_project.h>

0 commit comments

Comments
 (0)