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

Commit 20f527b

Browse files
committed
Add FlMethodChannel, FlMethodResponse, FlMethodCodec and FlStandardMethodCodec
1 parent dc93db5 commit 20f527b

15 files changed

+2279
-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
@@ -1212,7 +1220,11 @@ FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_binary_messe
12121220
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_dart_project.h
12131221
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_engine.h
12141222
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_message_codec.h
1223+
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_method_channel.h
1224+
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_method_codec.h
1225+
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_method_response.h
12151226
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_standard_message_codec.h
1227+
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h
12161228
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_string_codec.h
12171229
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_value.h
12181230
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
@@ -49,7 +49,11 @@ _public_headers = [
4949
"public/flutter_linux/fl_dart_project.h",
5050
"public/flutter_linux/fl_engine.h",
5151
"public/flutter_linux/fl_message_codec.h",
52+
"public/flutter_linux/fl_method_channel.h",
53+
"public/flutter_linux/fl_method_codec.h",
54+
"public/flutter_linux/fl_method_response.h",
5255
"public/flutter_linux/fl_standard_message_codec.h",
56+
"public/flutter_linux/fl_standard_method_codec.h",
5357
"public/flutter_linux/fl_string_codec.h",
5458
"public/flutter_linux/fl_value.h",
5559
"public/flutter_linux/fl_view.h",
@@ -69,9 +73,13 @@ source_set("flutter_linux") {
6973
"fl_dart_project.cc",
7074
"fl_engine.cc",
7175
"fl_message_codec.cc",
76+
"fl_method_channel.cc",
77+
"fl_method_codec.cc",
78+
"fl_method_response.cc",
7279
"fl_renderer.cc",
7380
"fl_renderer_x11.cc",
7481
"fl_standard_message_codec.cc",
82+
"fl_standard_method_codec.cc",
7583
"fl_string_codec.cc",
7684
"fl_value.cc",
7785
"fl_view.cc",
@@ -102,7 +110,10 @@ executable("flutter_linux_unittests") {
102110
"fl_binary_codec_test.cc",
103111
"fl_dart_project_test.cc",
104112
"fl_message_codec_test.cc",
113+
"fl_method_codec_test.cc",
114+
"fl_method_response_test.cc",
105115
"fl_standard_message_codec_test.cc",
116+
"fl_standard_method_codec_test.cc",
106117
"fl_string_codec_test.cc",
107118
"fl_value_test.cc",
108119
"testing/fl_test.cc",
Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
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 called when a method call is received
24+
FlMethodChannelMethodCallHandler method_call_handler;
25+
gpointer method_call_handler_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+
// Wrap the binary messenger handle for type safety and to make the API
34+
// consistent
35+
struct _FlMethodChannelResponseHandle {
36+
FlBinaryMessengerResponseHandle* response_handle;
37+
};
38+
39+
static FlMethodChannelResponseHandle* response_handle_new(
40+
FlBinaryMessengerResponseHandle* response_handle) {
41+
FlMethodChannelResponseHandle* handle =
42+
static_cast<FlMethodChannelResponseHandle*>(
43+
g_malloc0(sizeof(FlMethodChannelResponseHandle)));
44+
handle->response_handle = response_handle;
45+
46+
return handle;
47+
}
48+
49+
static void response_handle_free(FlMethodChannelResponseHandle* handle) {
50+
g_free(handle);
51+
}
52+
53+
G_DEFINE_AUTOPTR_CLEANUP_FUNC(FlMethodChannelResponseHandle,
54+
response_handle_free);
55+
56+
// Called when a binary message is received on this channel
57+
static void message_cb(FlBinaryMessenger* messenger,
58+
const gchar* channel,
59+
GBytes* message,
60+
FlBinaryMessengerResponseHandle* response_handle,
61+
gpointer user_data) {
62+
FlMethodChannel* self = FL_METHOD_CHANNEL(user_data);
63+
64+
if (self->method_call_handler == nullptr) {
65+
fl_method_channel_respond_not_implemented(
66+
self, response_handle_new(response_handle), nullptr);
67+
return;
68+
}
69+
70+
g_autofree gchar* method = nullptr;
71+
g_autoptr(FlValue) args = nullptr;
72+
g_autoptr(GError) error = nullptr;
73+
if (!fl_method_codec_decode_method_call(self->codec, message, &method, &args,
74+
&error)) {
75+
g_warning("Failed to decode method call: %s", error->message);
76+
fl_method_channel_respond_not_implemented(
77+
self, response_handle_new(response_handle), nullptr);
78+
return;
79+
}
80+
81+
self->method_call_handler(self, method, args,
82+
response_handle_new(response_handle),
83+
self->method_call_handler_data);
84+
}
85+
86+
// Called when a response is received to a sent message
87+
static void message_response_cb(GObject* object,
88+
GAsyncResult* result,
89+
gpointer user_data) {
90+
GTask* task = G_TASK(user_data);
91+
g_task_return_pointer(task, result, g_object_unref);
92+
}
93+
94+
static void fl_method_channel_dispose(GObject* object) {
95+
FlMethodChannel* self = FL_METHOD_CHANNEL(object);
96+
97+
if (self->messenger != nullptr)
98+
fl_binary_messenger_set_message_handler_on_channel(
99+
self->messenger, self->name, nullptr, nullptr);
100+
101+
g_clear_object(&self->messenger);
102+
g_clear_pointer(&self->name, g_free);
103+
g_clear_object(&self->codec);
104+
105+
G_OBJECT_CLASS(fl_method_channel_parent_class)->dispose(object);
106+
}
107+
108+
static void fl_method_channel_class_init(FlMethodChannelClass* klass) {
109+
G_OBJECT_CLASS(klass)->dispose = fl_method_channel_dispose;
110+
}
111+
112+
static void fl_method_channel_init(FlMethodChannel* self) {}
113+
114+
G_MODULE_EXPORT FlMethodChannel* fl_method_channel_new(
115+
FlBinaryMessenger* messenger,
116+
const gchar* name,
117+
FlMethodCodec* codec) {
118+
g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);
119+
g_return_val_if_fail(name != nullptr, nullptr);
120+
g_return_val_if_fail(FL_IS_METHOD_CODEC(codec), nullptr);
121+
122+
FlMethodChannel* self =
123+
FL_METHOD_CHANNEL(g_object_new(fl_method_channel_get_type(), nullptr));
124+
125+
self->messenger = FL_BINARY_MESSENGER(g_object_ref(messenger));
126+
self->name = g_strdup(name);
127+
self->codec = FL_METHOD_CODEC(g_object_ref(codec));
128+
129+
fl_binary_messenger_set_message_handler_on_channel(
130+
self->messenger, self->name, message_cb, self);
131+
132+
return self;
133+
}
134+
135+
G_MODULE_EXPORT void fl_method_channel_set_method_call_handler(
136+
FlMethodChannel* self,
137+
FlMethodChannelMethodCallHandler handler,
138+
gpointer user_data) {
139+
g_return_if_fail(FL_IS_METHOD_CHANNEL(self));
140+
141+
self->method_call_handler = handler;
142+
self->method_call_handler_data = user_data;
143+
}
144+
145+
G_MODULE_EXPORT void fl_method_channel_invoke_method(
146+
FlMethodChannel* self,
147+
const gchar* method,
148+
FlValue* args,
149+
GCancellable* cancellable,
150+
GAsyncReadyCallback callback,
151+
gpointer user_data) {
152+
g_return_if_fail(FL_IS_METHOD_CHANNEL(self));
153+
g_return_if_fail(method != nullptr);
154+
155+
g_autoptr(GTask) task =
156+
callback != nullptr ? g_task_new(self, cancellable, callback, user_data)
157+
: nullptr;
158+
159+
g_autoptr(GError) error = nullptr;
160+
g_autoptr(GBytes) message =
161+
fl_method_codec_encode_method_call(self->codec, method, args, &error);
162+
if (message == nullptr) {
163+
if (task != nullptr)
164+
g_task_return_error(task, error);
165+
return;
166+
}
167+
168+
fl_binary_messenger_send_on_channel(
169+
self->messenger, self->name, message, cancellable,
170+
callback != nullptr ? message_response_cb : nullptr,
171+
g_steal_pointer(&task));
172+
}
173+
174+
G_MODULE_EXPORT FlMethodResponse* fl_method_channel_invoke_method_finish(
175+
FlMethodChannel* self,
176+
GAsyncResult* result,
177+
GError** error) {
178+
g_return_val_if_fail(FL_IS_METHOD_CHANNEL(self), nullptr);
179+
g_return_val_if_fail(g_task_is_valid(result, self), nullptr);
180+
181+
g_autoptr(GTask) task = G_TASK(result);
182+
GAsyncResult* r = G_ASYNC_RESULT(g_task_propagate_pointer(task, nullptr));
183+
184+
g_autoptr(GBytes) response =
185+
fl_binary_messenger_send_on_channel_finish(self->messenger, r, error);
186+
if (response == nullptr)
187+
return nullptr;
188+
189+
return fl_method_codec_decode_response(self->codec, response, error);
190+
}
191+
192+
G_MODULE_EXPORT gboolean
193+
fl_method_channel_respond(FlMethodChannel* self,
194+
FlMethodChannelResponseHandle* response_handle,
195+
FlValue* result,
196+
GError** error) {
197+
g_return_val_if_fail(FL_IS_METHOD_CHANNEL(self), FALSE);
198+
g_return_val_if_fail(response_handle != nullptr, FALSE);
199+
200+
// Take reference to ensure it is freed
201+
g_autoptr(FlMethodChannelResponseHandle) handle = response_handle;
202+
203+
g_autoptr(GBytes) response =
204+
fl_method_codec_encode_success_envelope(self->codec, result, error);
205+
if (response == nullptr)
206+
return FALSE;
207+
208+
return fl_binary_messenger_send_response(
209+
self->messenger, handle->response_handle, response, error);
210+
}
211+
212+
G_MODULE_EXPORT gboolean
213+
fl_method_channel_respond_error(FlMethodChannel* self,
214+
FlMethodChannelResponseHandle* response_handle,
215+
const gchar* code,
216+
const gchar* message,
217+
FlValue* details,
218+
GError** error) {
219+
g_return_val_if_fail(FL_IS_METHOD_CHANNEL(self), FALSE);
220+
g_return_val_if_fail(response_handle != nullptr, FALSE);
221+
g_return_val_if_fail(code != nullptr, FALSE);
222+
223+
// Take reference to ensure it is freed
224+
g_autoptr(FlMethodChannelResponseHandle) owned_response_handle =
225+
response_handle;
226+
227+
g_autoptr(GBytes) response = fl_method_codec_encode_error_envelope(
228+
self->codec, code, message, details, error);
229+
if (response == nullptr)
230+
return FALSE;
231+
232+
return fl_binary_messenger_send_response(
233+
self->messenger, owned_response_handle->response_handle, response, error);
234+
}
235+
236+
G_MODULE_EXPORT gboolean fl_method_channel_respond_not_implemented(
237+
FlMethodChannel* self,
238+
FlMethodChannelResponseHandle* response_handle,
239+
GError** error) {
240+
g_return_val_if_fail(FL_IS_METHOD_CHANNEL(self), FALSE);
241+
g_return_val_if_fail(response_handle != nullptr, FALSE);
242+
243+
// Take reference to ensure it is freed
244+
g_autoptr(FlMethodChannelResponseHandle) owned_response_handle =
245+
response_handle;
246+
247+
return fl_binary_messenger_send_response(
248+
self->messenger, owned_response_handle->response_handle, nullptr, error);
249+
}
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)