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

Commit a638433

Browse files
committed
Add FlMethodChannel, FlMethodResponse, FlMethodCodec and FlStandardMethodCodec
1 parent 15f6ef8 commit a638433

15 files changed

+2268
-0
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,13 +1195,21 @@ FILE: ../../../flutter/shell/platform/linux/fl_engine.cc
11951195
FILE: ../../../flutter/shell/platform/linux/fl_engine_private.h
11961196
FILE: ../../../flutter/shell/platform/linux/fl_message_codec.cc
11971197
FILE: ../../../flutter/shell/platform/linux/fl_message_codec_test.cc
1198+
FILE: ../../../flutter/shell/platform/linux/fl_method_channel.cc
1199+
FILE: ../../../flutter/shell/platform/linux/fl_method_codec.cc
1200+
FILE: ../../../flutter/shell/platform/linux/fl_method_codec_private.h
1201+
FILE: ../../../flutter/shell/platform/linux/fl_method_codec_test.cc
1202+
FILE: ../../../flutter/shell/platform/linux/fl_method_response.cc
1203+
FILE: ../../../flutter/shell/platform/linux/fl_method_response_test.cc
11981204
FILE: ../../../flutter/shell/platform/linux/fl_renderer.cc
11991205
FILE: ../../../flutter/shell/platform/linux/fl_renderer.h
12001206
FILE: ../../../flutter/shell/platform/linux/fl_renderer_x11.cc
12011207
FILE: ../../../flutter/shell/platform/linux/fl_renderer_x11.h
12021208
FILE: ../../../flutter/shell/platform/linux/fl_standard_message_codec.cc
12031209
FILE: ../../../flutter/shell/platform/linux/fl_standard_message_codec_private.h
12041210
FILE: ../../../flutter/shell/platform/linux/fl_standard_message_codec_test.cc
1211+
FILE: ../../../flutter/shell/platform/linux/fl_standard_method_codec.cc
1212+
FILE: ../../../flutter/shell/platform/linux/fl_standard_method_codec_test.cc
12051213
FILE: ../../../flutter/shell/platform/linux/fl_string_codec.cc
12061214
FILE: ../../../flutter/shell/platform/linux/fl_string_codec_test.cc
12071215
FILE: ../../../flutter/shell/platform/linux/fl_value.cc
@@ -1213,7 +1221,11 @@ FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_binary_messe
12131221
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_dart_project.h
12141222
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_engine.h
12151223
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_message_codec.h
1224+
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_method_channel.h
1225+
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_method_codec.h
1226+
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_method_response.h
12161227
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_standard_message_codec.h
1228+
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h
12171229
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_string_codec.h
12181230
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_value.h
12191231
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_view.h

shell/platform/linux/BUILD.gn

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ _public_headers = [
5050
"public/flutter_linux/fl_dart_project.h",
5151
"public/flutter_linux/fl_engine.h",
5252
"public/flutter_linux/fl_message_codec.h",
53+
"public/flutter_linux/fl_method_channel.h",
54+
"public/flutter_linux/fl_method_codec.h",
55+
"public/flutter_linux/fl_method_response.h",
5356
"public/flutter_linux/fl_standard_message_codec.h",
57+
"public/flutter_linux/fl_standard_method_codec.h",
5458
"public/flutter_linux/fl_string_codec.h",
5559
"public/flutter_linux/fl_value.h",
5660
"public/flutter_linux/fl_view.h",
@@ -71,9 +75,13 @@ source_set("flutter_linux") {
7175
"fl_dart_project.cc",
7276
"fl_engine.cc",
7377
"fl_message_codec.cc",
78+
"fl_method_channel.cc",
79+
"fl_method_codec.cc",
80+
"fl_method_response.cc",
7481
"fl_renderer.cc",
7582
"fl_renderer_x11.cc",
7683
"fl_standard_message_codec.cc",
84+
"fl_standard_method_codec.cc",
7785
"fl_string_codec.cc",
7886
"fl_value.cc",
7987
"fl_view.cc",
@@ -104,7 +112,10 @@ executable("flutter_linux_unittests") {
104112
"fl_binary_codec_test.cc",
105113
"fl_dart_project_test.cc",
106114
"fl_message_codec_test.cc",
115+
"fl_method_codec_test.cc",
116+
"fl_method_response_test.cc",
107117
"fl_standard_message_codec_test.cc",
118+
"fl_standard_method_codec_test.cc",
108119
"fl_string_codec_test.cc",
109120
"fl_value_test.cc",
110121
"testing/fl_test.cc",
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
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_method_channel.h"
6+
7+
#include "flutter/shell/platform/linux/fl_method_codec_private.h"
8+
9+
#include <gmodule.h>
10+
11+
struct _FlMethodChannel {
12+
GObject parent_instance;
13+
14+
// Messenger to communicate on
15+
FlBinaryMessenger* messenger;
16+
17+
// Channel name
18+
gchar* name;
19+
20+
// Codec to en/decode messages
21+
FlMethodCodec* codec;
22+
23+
// Function to handle method calls
24+
FlMethodChannelCallback callback;
25+
gpointer callback_data;
26+
};
27+
28+
// Added here to stop the compiler from optimising this function away
29+
G_MODULE_EXPORT GType fl_method_channel_get_type();
30+
31+
G_DEFINE_TYPE(FlMethodChannel, fl_method_channel, G_TYPE_OBJECT)
32+
33+
struct _FlMethodChannelResponseHandle {
34+
FlBinaryMessengerResponseHandle* response_handle;
35+
};
36+
37+
static FlMethodChannelResponseHandle* response_handle_new(
38+
FlBinaryMessengerResponseHandle* response_handle) {
39+
FlMethodChannelResponseHandle* handle =
40+
static_cast<FlMethodChannelResponseHandle*>(
41+
g_malloc0(sizeof(FlMethodChannelResponseHandle)));
42+
handle->response_handle = response_handle;
43+
44+
return handle;
45+
}
46+
47+
static void response_handle_free(FlMethodChannelResponseHandle* handle) {
48+
g_free(handle);
49+
}
50+
51+
G_DEFINE_AUTOPTR_CLEANUP_FUNC(FlMethodChannelResponseHandle,
52+
response_handle_free);
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+
FlMethodChannel* self = FL_METHOD_CHANNEL(user_data);
61+
62+
if (self->callback == nullptr) {
63+
fl_method_channel_respond_not_implemented(
64+
self, response_handle_new(response_handle), nullptr);
65+
return;
66+
}
67+
68+
g_autofree gchar* method = nullptr;
69+
g_autoptr(FlValue) args = nullptr;
70+
g_autoptr(GError) error = nullptr;
71+
if (!fl_method_codec_decode_method_call(self->codec, message, &method, &args,
72+
&error)) {
73+
g_warning("Failed to decode method call: %s", error->message);
74+
fl_method_channel_respond_not_implemented(
75+
self, response_handle_new(response_handle), nullptr);
76+
return;
77+
}
78+
79+
self->callback(self, method, args, response_handle_new(response_handle),
80+
self->callback_data);
81+
}
82+
83+
// Called when a response is received to a sent message
84+
static void message_response_cb(GObject* object,
85+
GAsyncResult* result,
86+
gpointer user_data) {
87+
GTask* task = static_cast<GTask*>(user_data);
88+
g_task_return_pointer(task, result, g_object_unref);
89+
}
90+
91+
static void fl_method_channel_dispose(GObject* object) {
92+
FlMethodChannel* self = FL_METHOD_CHANNEL(object);
93+
94+
if (self->messenger != nullptr)
95+
fl_binary_messenger_set_message_handler_on_channel(
96+
self->messenger, self->name, nullptr, nullptr);
97+
98+
g_clear_object(&self->messenger);
99+
g_clear_pointer(&self->name, g_free);
100+
g_clear_object(&self->codec);
101+
102+
G_OBJECT_CLASS(fl_method_channel_parent_class)->dispose(object);
103+
}
104+
105+
static void fl_method_channel_class_init(FlMethodChannelClass* klass) {
106+
G_OBJECT_CLASS(klass)->dispose = fl_method_channel_dispose;
107+
}
108+
109+
static void fl_method_channel_init(FlMethodChannel* self) {}
110+
111+
G_MODULE_EXPORT FlMethodChannel* fl_method_channel_new(
112+
FlBinaryMessenger* messenger,
113+
const gchar* name,
114+
FlMethodCodec* codec) {
115+
g_return_val_if_fail(name != nullptr, nullptr);
116+
g_return_val_if_fail(FL_IS_METHOD_CODEC(codec), nullptr);
117+
118+
FlMethodChannel* self = static_cast<FlMethodChannel*>(
119+
g_object_new(fl_method_channel_get_type(), nullptr));
120+
self->messenger = static_cast<FlBinaryMessenger*>(g_object_ref(messenger));
121+
self->name = g_strdup(name);
122+
self->codec = static_cast<FlMethodCodec*>(g_object_ref(codec));
123+
124+
fl_binary_messenger_set_message_handler_on_channel(messenger, name,
125+
message_cb, self);
126+
127+
return self;
128+
}
129+
130+
G_MODULE_EXPORT void fl_method_channel_set_callback(
131+
FlMethodChannel* self,
132+
FlMethodChannelCallback callback,
133+
gpointer user_data) {
134+
g_return_if_fail(FL_IS_METHOD_CHANNEL(self));
135+
self->callback = callback;
136+
self->callback_data = user_data;
137+
}
138+
139+
G_MODULE_EXPORT void fl_method_channel_invoke_method(
140+
FlMethodChannel* self,
141+
const gchar* method,
142+
FlValue* args,
143+
GCancellable* cancellable,
144+
GAsyncReadyCallback callback,
145+
gpointer user_data) {
146+
g_return_if_fail(FL_IS_METHOD_CHANNEL(self));
147+
g_return_if_fail(method != nullptr);
148+
149+
g_autoptr(GTask) task =
150+
callback != nullptr ? g_task_new(self, cancellable, callback, user_data)
151+
: nullptr;
152+
153+
g_autoptr(GError) error = nullptr;
154+
g_autoptr(GBytes) message =
155+
fl_method_codec_encode_method_call(self->codec, method, args, &error);
156+
if (message == nullptr) {
157+
if (task != nullptr)
158+
g_task_return_error(task, error);
159+
return;
160+
}
161+
162+
fl_binary_messenger_send_on_channel(
163+
self->messenger, self->name, message, cancellable,
164+
callback != nullptr ? message_response_cb : nullptr,
165+
g_steal_pointer(&task));
166+
}
167+
168+
G_MODULE_EXPORT FlMethodResponse* fl_method_channel_invoke_method_finish(
169+
FlMethodChannel* self,
170+
GAsyncResult* result,
171+
GError** error) {
172+
g_return_val_if_fail(FL_IS_METHOD_CHANNEL(self), nullptr);
173+
g_return_val_if_fail(g_task_is_valid(result, self), nullptr);
174+
175+
g_autoptr(GTask) task = reinterpret_cast<GTask*>(result);
176+
GAsyncResult* r =
177+
static_cast<GAsyncResult*>(g_task_propagate_pointer(task, nullptr));
178+
179+
g_autoptr(GBytes) response =
180+
fl_binary_messenger_send_on_channel_finish(self->messenger, r, error);
181+
if (response == nullptr)
182+
return nullptr;
183+
184+
return fl_method_codec_decode_response(self->codec, response, error);
185+
}
186+
187+
G_MODULE_EXPORT gboolean
188+
fl_method_channel_respond(FlMethodChannel* self,
189+
FlMethodChannelResponseHandle* response_handle,
190+
FlValue* result,
191+
GError** error) {
192+
g_return_val_if_fail(FL_IS_METHOD_CHANNEL(self), FALSE);
193+
g_return_val_if_fail(response_handle != nullptr, FALSE);
194+
195+
// Take reference to ensure it is freed
196+
g_autoptr(FlMethodChannelResponseHandle) handle = response_handle;
197+
198+
g_autoptr(GBytes) response =
199+
fl_method_codec_encode_success_envelope(self->codec, result, error);
200+
if (response == nullptr)
201+
return FALSE;
202+
203+
return fl_binary_messenger_send_response(
204+
self->messenger, handle->response_handle, response, error);
205+
}
206+
207+
G_MODULE_EXPORT gboolean
208+
fl_method_channel_respond_error(FlMethodChannel* self,
209+
FlMethodChannelResponseHandle* response_handle,
210+
const gchar* code,
211+
const gchar* message,
212+
FlValue* details,
213+
GError** error) {
214+
g_return_val_if_fail(FL_IS_METHOD_CHANNEL(self), FALSE);
215+
g_return_val_if_fail(response_handle != nullptr, FALSE);
216+
g_return_val_if_fail(code != nullptr, FALSE);
217+
218+
// Take reference to ensure it is freed
219+
g_autoptr(FlMethodChannelResponseHandle) owned_response_handle =
220+
response_handle;
221+
222+
g_autoptr(GBytes) response = fl_method_codec_encode_error_envelope(
223+
self->codec, code, message, details, error);
224+
if (response == nullptr)
225+
return FALSE;
226+
227+
return fl_binary_messenger_send_response(
228+
self->messenger, owned_response_handle->response_handle, response, error);
229+
}
230+
231+
G_MODULE_EXPORT gboolean fl_method_channel_respond_not_implemented(
232+
FlMethodChannel* self,
233+
FlMethodChannelResponseHandle* response_handle,
234+
GError** error) {
235+
g_return_val_if_fail(FL_IS_METHOD_CHANNEL(self), FALSE);
236+
g_return_val_if_fail(response_handle != nullptr, FALSE);
237+
238+
// Take reference to ensure it is freed
239+
g_autoptr(FlMethodChannelResponseHandle) owned_response_handle =
240+
response_handle;
241+
242+
return fl_binary_messenger_send_response(
243+
self->messenger, owned_response_handle->response_handle, nullptr, error);
244+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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_method_codec.h"
6+
#include "flutter/shell/platform/linux/fl_method_codec_private.h"
7+
8+
#include <gmodule.h>
9+
10+
// Added here to stop the compiler from optimising this function away
11+
G_MODULE_EXPORT GType fl_method_codec_get_type();
12+
13+
G_DEFINE_TYPE(FlMethodCodec, fl_method_codec, G_TYPE_OBJECT)
14+
15+
static void fl_method_codec_class_init(FlMethodCodecClass* klass) {}
16+
17+
static void fl_method_codec_init(FlMethodCodec* self) {}
18+
19+
GBytes* fl_method_codec_encode_method_call(FlMethodCodec* self,
20+
const gchar* name,
21+
FlValue* args,
22+
GError** error) {
23+
g_return_val_if_fail(FL_IS_METHOD_CODEC(self), nullptr);
24+
g_return_val_if_fail(name != nullptr, nullptr);
25+
26+
return FL_METHOD_CODEC_GET_CLASS(self)->encode_method_call(self, name, args,
27+
error);
28+
}
29+
30+
gboolean fl_method_codec_decode_method_call(FlMethodCodec* self,
31+
GBytes* message,
32+
gchar** name,
33+
FlValue** args,
34+
GError** error) {
35+
g_return_val_if_fail(FL_IS_METHOD_CODEC(self), FALSE);
36+
g_return_val_if_fail(message != nullptr, FALSE);
37+
g_return_val_if_fail(name != nullptr, FALSE);
38+
g_return_val_if_fail(args != nullptr, FALSE);
39+
40+
return FL_METHOD_CODEC_GET_CLASS(self)->decode_method_call(self, message,
41+
name, args, error);
42+
}
43+
44+
GBytes* fl_method_codec_encode_success_envelope(FlMethodCodec* self,
45+
FlValue* result,
46+
GError** error) {
47+
g_return_val_if_fail(FL_IS_METHOD_CODEC(self), nullptr);
48+
49+
return FL_METHOD_CODEC_GET_CLASS(self)->encode_success_envelope(self, result,
50+
error);
51+
}
52+
53+
GBytes* fl_method_codec_encode_error_envelope(FlMethodCodec* self,
54+
const gchar* code,
55+
const gchar* message,
56+
FlValue* details,
57+
GError** error) {
58+
g_return_val_if_fail(FL_IS_METHOD_CODEC(self), nullptr);
59+
g_return_val_if_fail(code != nullptr, nullptr);
60+
61+
return FL_METHOD_CODEC_GET_CLASS(self)->encode_error_envelope(
62+
self, code, message, details, error);
63+
}
64+
65+
FlMethodResponse* fl_method_codec_decode_response(FlMethodCodec* self,
66+
GBytes* message,
67+
GError** error) {
68+
g_return_val_if_fail(FL_IS_METHOD_CODEC(self), nullptr);
69+
g_return_val_if_fail(message != nullptr, nullptr);
70+
71+
if (g_bytes_get_size(message) == 0)
72+
return FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
73+
74+
return FL_METHOD_CODEC_GET_CLASS(self)->decode_response(self, message, error);
75+
}

0 commit comments

Comments
 (0)