Flutter Engine
fl_standard_method_codec.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 
5 #include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h"
6 
7 #include <gmodule.h>
8 
9 #include "flutter/shell/platform/linux/fl_standard_message_codec_private.h"
10 #include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_message_codec.h"
11 
12 // See lib/src/services/message_codecs.dart in Flutter source for description of
13 // encoding.
14 
15 // Envelope codes.
16 static constexpr guint8 kEnvelopeTypeSuccess = 0;
17 static constexpr guint8 kEnvelopeTypeError = 1;
18 
20  FlMethodCodec parent_instance;
21 
22  FlStandardMessageCodec* codec;
23 };
24 
25 G_DEFINE_TYPE(FlStandardMethodCodec,
26  fl_standard_method_codec,
28 
29 static void fl_standard_method_codec_dispose(GObject* object) {
30  FlStandardMethodCodec* self = FL_STANDARD_METHOD_CODEC(object);
31 
32  g_clear_object(&self->codec);
33 
34  G_OBJECT_CLASS(fl_standard_method_codec_parent_class)->dispose(object);
35 }
36 
37 // Implements FlMethodCodec::encode_method_call.
38 static GBytes* fl_standard_method_codec_encode_method_call(FlMethodCodec* codec,
39  const gchar* name,
40  FlValue* args,
41  GError** error) {
42  FlStandardMethodCodec* self = FL_STANDARD_METHOD_CODEC(codec);
43 
44  g_autoptr(GByteArray) buffer = g_byte_array_new();
45  g_autoptr(FlValue) name_value = fl_value_new_string(name);
46  if (!fl_standard_message_codec_write_value(self->codec, buffer, name_value,
47  error)) {
48  return nullptr;
49  }
50  if (!fl_standard_message_codec_write_value(self->codec, buffer, args,
51  error)) {
52  return nullptr;
53  }
54 
55  return g_byte_array_free_to_bytes(
56  static_cast<GByteArray*>(g_steal_pointer(&buffer)));
57 }
58 
59 // Implements FlMethodCodec::decode_method_call.
61  FlMethodCodec* codec,
62  GBytes* message,
63  gchar** name,
64  FlValue** args,
65  GError** error) {
66  FlStandardMethodCodec* self = FL_STANDARD_METHOD_CODEC(codec);
67 
68  size_t offset = 0;
69  g_autoptr(FlValue) name_value = fl_standard_message_codec_read_value(
70  self->codec, message, &offset, error);
71  if (name_value == nullptr) {
72  return FALSE;
73  }
74  if (fl_value_get_type(name_value) != FL_VALUE_TYPE_STRING) {
76  "Method call name wrong type");
77  return FALSE;
78  }
79 
80  g_autoptr(FlValue) args_value = fl_standard_message_codec_read_value(
81  self->codec, message, &offset, error);
82  if (args_value == nullptr) {
83  return FALSE;
84  }
85 
86  if (offset != g_bytes_get_size(message)) {
88  "Unexpected extra data");
89  return FALSE;
90  }
91 
92  *name = g_strdup(fl_value_get_string(name_value));
93  *args = fl_value_ref(args_value);
94 
95  return TRUE;
96 }
97 
98 // Implements FlMethodCodec::encode_success_envelope.
100  FlMethodCodec* codec,
101  FlValue* result,
102  GError** error) {
103  FlStandardMethodCodec* self = FL_STANDARD_METHOD_CODEC(codec);
104 
105  g_autoptr(GByteArray) buffer = g_byte_array_new();
106  guint8 type = kEnvelopeTypeSuccess;
107  g_byte_array_append(buffer, &type, 1);
108  if (!fl_standard_message_codec_write_value(self->codec, buffer, result,
109  error)) {
110  return nullptr;
111  }
112 
113  return g_byte_array_free_to_bytes(
114  static_cast<GByteArray*>(g_steal_pointer(&buffer)));
115 }
116 
117 // Implements FlMethodCodec::encode_error_envelope.
119  FlMethodCodec* codec,
120  const gchar* code,
121  const gchar* message,
122  FlValue* details,
123  GError** error) {
124  FlStandardMethodCodec* self = FL_STANDARD_METHOD_CODEC(codec);
125 
126  g_autoptr(GByteArray) buffer = g_byte_array_new();
127  guint8 type = kEnvelopeTypeError;
128  g_byte_array_append(buffer, &type, 1);
129  g_autoptr(FlValue) code_value = fl_value_new_string(code);
130  if (!fl_standard_message_codec_write_value(self->codec, buffer, code_value,
131  error)) {
132  return nullptr;
133  }
134  g_autoptr(FlValue) message_value =
135  message != nullptr ? fl_value_new_string(message) : nullptr;
136  if (!fl_standard_message_codec_write_value(self->codec, buffer, message_value,
137  error)) {
138  return nullptr;
139  }
140  if (!fl_standard_message_codec_write_value(self->codec, buffer, details,
141  error)) {
142  return nullptr;
143  }
144 
145  return g_byte_array_free_to_bytes(
146  static_cast<GByteArray*>(g_steal_pointer(&buffer)));
147 }
148 
149 // Implements FlMethodCodec::encode_decode_reponse.
151  FlMethodCodec* codec,
152  GBytes* message,
153  GError** error) {
154  FlStandardMethodCodec* self = FL_STANDARD_METHOD_CODEC(codec);
155 
156  if (g_bytes_get_size(message) == 0) {
157  g_set_error(error, FL_MESSAGE_CODEC_ERROR,
158  FL_MESSAGE_CODEC_ERROR_OUT_OF_DATA, "Empty response");
159  return nullptr;
160  }
161 
162  // First byte is response type.
163  const guint8* data =
164  static_cast<const guint8*>(g_bytes_get_data(message, nullptr));
165  guint8 type = data[0];
166  size_t offset = 1;
167 
168  g_autoptr(FlMethodResponse) response = nullptr;
169  if (type == kEnvelopeTypeError) {
171  self->codec, message, &offset, error);
172  if (code == nullptr) {
173  return nullptr;
174  }
177  "Error code wrong type");
178  return nullptr;
179  }
180 
181  g_autoptr(FlValue) error_message = fl_standard_message_codec_read_value(
182  self->codec, message, &offset, error);
183  if (error_message == nullptr) {
184  return nullptr;
185  }
186  if (fl_value_get_type(error_message) != FL_VALUE_TYPE_STRING &&
187  fl_value_get_type(error_message) != FL_VALUE_TYPE_NULL) {
189  "Error message wrong type");
190  return nullptr;
191  }
192 
193  g_autoptr(FlValue) details = fl_standard_message_codec_read_value(
194  self->codec, message, &offset, error);
195  if (details == nullptr) {
196  return nullptr;
197  }
198 
199  response = FL_METHOD_RESPONSE(fl_method_error_response_new(
200  fl_value_get_string(code),
201  fl_value_get_type(error_message) == FL_VALUE_TYPE_STRING
202  ? fl_value_get_string(error_message)
203  : nullptr,
204  fl_value_get_type(details) != FL_VALUE_TYPE_NULL ? details : nullptr));
205  } else if (type == kEnvelopeTypeSuccess) {
206  g_autoptr(FlValue) result = fl_standard_message_codec_read_value(
207  self->codec, message, &offset, error);
208 
209  if (result == nullptr) {
210  return nullptr;
211  }
212 
213  response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));
214  } else {
216  "Unknown envelope type %02x", type);
217  return nullptr;
218  }
219 
220  if (offset != g_bytes_get_size(message)) {
222  "Unexpected extra data");
223  return nullptr;
224  }
225 
226  return FL_METHOD_RESPONSE(g_object_ref(response));
227 }
228 
230  FlStandardMethodCodecClass* klass) {
231  G_OBJECT_CLASS(klass)->dispose = fl_standard_method_codec_dispose;
232  FL_METHOD_CODEC_CLASS(klass)->encode_method_call =
234  FL_METHOD_CODEC_CLASS(klass)->decode_method_call =
236  FL_METHOD_CODEC_CLASS(klass)->encode_success_envelope =
238  FL_METHOD_CODEC_CLASS(klass)->encode_error_envelope =
240  FL_METHOD_CODEC_CLASS(klass)->decode_response =
242 }
243 
244 static void fl_standard_method_codec_init(FlStandardMethodCodec* self) {
245  self->codec = fl_standard_message_codec_new();
246 }
247 
248 G_MODULE_EXPORT FlStandardMethodCodec* fl_standard_method_codec_new() {
249  return FL_STANDARD_METHOD_CODEC(
250  g_object_new(fl_standard_method_codec_get_type(), nullptr));
251 }
G_BEGIN_DECLS FlValue * args
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition: fl_value.cc:395
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:39
FlMethodResponse GError ** error
G_DEFINE_TYPE(FlStandardMethodCodec, fl_standard_method_codec, fl_method_codec_get_type()) static void fl_standard_method_codec_dispose(GObject *object)
static void fl_standard_method_codec_class_init(FlStandardMethodCodecClass *klass)
FlStandardMessageCodec * codec
#define FL_MESSAGE_CODEC_ERROR
static FlMethodResponse * fl_standard_method_codec_decode_response(FlMethodCodec *codec, GBytes *message, GError **error)
static gboolean fl_standard_method_codec_decode_method_call(FlMethodCodec *codec, GBytes *message, gchar **name, FlValue **args, GError **error)
static constexpr guint8 kEnvelopeTypeError
G_MODULE_EXPORT FlStandardMessageCodec * fl_standard_message_codec_new()
G_MODULE_EXPORT FlStandardMethodCodec * fl_standard_method_codec_new()
static GBytes * fl_standard_method_codec_encode_error_envelope(FlMethodCodec *codec, const gchar *code, const gchar *message, FlValue *details, GError **error)
G_MODULE_EXPORT FlValue * fl_value_new_string(const gchar *value)
Definition: fl_value.cc:247
G_MODULE_EXPORT FlValue * fl_value_ref(FlValue *self)
Definition: fl_value.cc:335
const char * name
Definition: fuchsia.cc:50
return TRUE
Definition: fl_view.cc:107
G_MODULE_EXPORT const gchar * fl_value_get_string(FlValue *self)
Definition: fl_value.cc:596
static void fl_standard_method_codec_init(FlStandardMethodCodec *self)
G_MODULE_EXPORT GType fl_method_codec_get_type()
static GBytes * fl_standard_method_codec_encode_method_call(FlMethodCodec *codec, const gchar *name, FlValue *args, GError **error)
FlValue * fl_standard_message_codec_read_value(FlStandardMessageCodec *self, GBytes *buffer, size_t *offset, GError **error)
static constexpr guint8 kEnvelopeTypeSuccess
G_MODULE_EXPORT FlMethodErrorResponse * fl_method_error_response_new(const gchar *code, const gchar *message, FlValue *details)
static GBytes * fl_standard_method_codec_encode_success_envelope(FlMethodCodec *codec, FlValue *result, GError **error)
gboolean fl_standard_message_codec_write_value(FlStandardMessageCodec *self, GByteArray *buffer, FlValue *value, GError **error)