-
Notifications
You must be signed in to change notification settings - Fork 6k
Add method channel support to Linux shell #18118
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| // 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_codec.h" | ||
|
|
||
| #include <gmodule.h> | ||
|
|
||
| G_DEFINE_QUARK(fl_codec_error_quark, fl_codec_error) | ||
|
|
||
| // Added here to stop the compiler from optimising this function away | ||
| G_MODULE_EXPORT GType fl_codec_get_type(); | ||
|
|
||
| G_DEFINE_TYPE(FlCodec, fl_codec, G_TYPE_OBJECT) | ||
|
|
||
| static void fl_codec_class_init(FlCodecClass* klass) {} | ||
|
|
||
| static void fl_codec_init(FlCodec* self) {} | ||
|
|
||
| G_MODULE_EXPORT gboolean fl_codec_write_value(FlCodec* self, | ||
| GByteArray* buffer, | ||
| FlValue* value, | ||
| GError** error) { | ||
| g_return_val_if_fail(FL_IS_CODEC(self), FALSE); | ||
| g_return_val_if_fail(buffer != nullptr, FALSE); | ||
|
|
||
| g_autoptr(FlValue) null_value = NULL; | ||
| if (value == nullptr) | ||
| value = null_value = fl_value_null_new(); | ||
robert-ancell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| return FL_CODEC_GET_CLASS(self)->write_value(self, buffer, value, error); | ||
| } | ||
|
|
||
| G_MODULE_EXPORT FlValue* fl_codec_read_value(FlCodec* self, | ||
| GBytes* buffer, | ||
| size_t* offset, | ||
| GError** error) { | ||
| g_return_val_if_fail(FL_IS_CODEC(self), nullptr); | ||
| g_return_val_if_fail(buffer != nullptr, nullptr); | ||
|
|
||
| size_t o = offset != nullptr ? *offset : 0; | ||
| if (o >= g_bytes_get_size(buffer)) { | ||
| g_set_error(error, FL_CODEC_ERROR, FL_CODEC_ERROR_OUT_OF_DATA, | ||
| "Out of data"); | ||
| return NULL; | ||
| } | ||
|
|
||
| FlValue* value = | ||
| FL_CODEC_GET_CLASS(self)->read_value(self, buffer, &o, error); | ||
| if (value != nullptr && offset != nullptr) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If offset is an i/o param, why is it valid for it to be null? It seems like this should just be an assertion at the start of the method.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm using it as an optional in/out param, i.e. NULL is "start at zero and I don't care what the result is". It could be asserted though, I wasn't 100% sure which way to go on this. I do find it annoying in APIs when you have to provide something like this and you don't care. This has been refactored though with the FlMessageCodec changes, so it may not be signficant anymore. I'll keep it in mind and we can bring up again if it remains in a a later PR. |
||
| *offset = o; | ||
| return value; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,186 @@ | ||
| // 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_codec.h" | ||
| #include "gtest/gtest.h" | ||
|
|
||
| G_DECLARE_FINAL_TYPE(FlTestCodec, fl_test_codec, FL, TEST_CODEC, FlCodec) | ||
|
|
||
| struct _FlTestCodec { | ||
| FlCodec parent_instance; | ||
| }; | ||
|
|
||
| G_DEFINE_TYPE(FlTestCodec, fl_test_codec, fl_codec_get_type()) | ||
|
|
||
| static gboolean fl_test_codec_write_value(FlCodec* codec, | ||
robert-ancell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| GByteArray* buffer, | ||
| FlValue* value, | ||
| GError** error) { | ||
| EXPECT_TRUE(FL_IS_TEST_CODEC(codec)); | ||
|
|
||
| if (fl_value_get_type(value) == FL_VALUE_TYPE_INT) { | ||
| char c = '0' + fl_value_get_int(value); | ||
| g_byte_array_append(buffer, reinterpret_cast<const guint8*>(&c), 1); | ||
| return TRUE; | ||
| } else { | ||
| g_set_error(error, FL_CODEC_ERROR, FL_CODEC_ERROR_FAILED, "ERROR"); | ||
| return FALSE; | ||
| } | ||
| } | ||
|
|
||
| static FlValue* fl_test_codec_read_value(FlCodec* codec, | ||
| GBytes* message, | ||
| size_t* offset, | ||
| GError** error) { | ||
| EXPECT_TRUE(FL_IS_TEST_CODEC(codec)); | ||
| EXPECT_TRUE(*offset < g_bytes_get_size(message)); | ||
|
|
||
| size_t data_length; | ||
| const uint8_t* data = | ||
| static_cast<const uint8_t*>(g_bytes_get_data(message, &data_length)); | ||
| if (data_length == 0) { | ||
| g_set_error(error, FL_CODEC_ERROR, FL_CODEC_ERROR_FAILED, "ERROR"); | ||
| return FALSE; | ||
| } | ||
|
|
||
| g_autoptr(FlValue) value = fl_value_int_new(data[*offset] - '0'); | ||
| (*offset)++; | ||
| return fl_value_ref(value); | ||
| } | ||
|
|
||
| static void fl_test_codec_class_init(FlTestCodecClass* klass) { | ||
| FL_CODEC_CLASS(klass)->write_value = fl_test_codec_write_value; | ||
| FL_CODEC_CLASS(klass)->read_value = fl_test_codec_read_value; | ||
| } | ||
|
|
||
| static void fl_test_codec_init(FlTestCodec* self) {} | ||
|
|
||
| static FlTestCodec* fl_test_codec_new() { | ||
| return FL_TEST_CODEC(g_object_new(fl_test_codec_get_type(), nullptr)); | ||
| } | ||
|
|
||
| TEST(FlCodecTest, WriteValue) { | ||
robert-ancell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| g_autoptr(FlTestCodec) codec = fl_test_codec_new(); | ||
| g_autoptr(GByteArray) buffer = g_byte_array_new(); | ||
|
|
||
| g_autoptr(FlValue) value = fl_value_int_new(1); | ||
| g_autoptr(GError) error = nullptr; | ||
| gboolean result = | ||
| fl_codec_write_value(FL_CODEC(codec), buffer, value, &error); | ||
| EXPECT_TRUE(result); | ||
| EXPECT_EQ(error, nullptr); | ||
| EXPECT_EQ(buffer->len, static_cast<unsigned int>(1)); | ||
| EXPECT_EQ(buffer->data[0], '1'); | ||
| } | ||
|
|
||
| TEST(FlCodecTest, WriteValues) { | ||
| g_autoptr(FlTestCodec) codec = fl_test_codec_new(); | ||
| g_autoptr(GByteArray) buffer = g_byte_array_new(); | ||
|
|
||
| for (int i = 1; i <= 5; i++) { | ||
| g_autoptr(FlValue) value = fl_value_int_new(i); | ||
| g_autoptr(GError) error = nullptr; | ||
| gboolean result = | ||
| fl_codec_write_value(FL_CODEC(codec), buffer, value, &error); | ||
| EXPECT_TRUE(result); | ||
| EXPECT_EQ(error, nullptr); | ||
| } | ||
|
|
||
| EXPECT_EQ(buffer->len, static_cast<unsigned int>(5)); | ||
| for (int i = 1; i <= 5; i++) | ||
| EXPECT_EQ(buffer->data[i - 1], '0' + i); | ||
| } | ||
|
|
||
| TEST(FlCodecTest, WriteValueError) { | ||
| g_autoptr(FlTestCodec) codec = fl_test_codec_new(); | ||
| g_autoptr(GByteArray) buffer = g_byte_array_new(); | ||
|
|
||
| g_autoptr(FlValue) value = fl_value_null_new(); | ||
| g_autoptr(GError) error = nullptr; | ||
| gboolean result = | ||
| fl_codec_write_value(FL_CODEC(codec), buffer, value, &error); | ||
| EXPECT_FALSE(result); | ||
| EXPECT_TRUE(g_error_matches(error, FL_CODEC_ERROR, FL_CODEC_ERROR_FAILED)); | ||
| EXPECT_EQ(buffer->len, static_cast<unsigned int>(0)); | ||
| } | ||
|
|
||
| TEST(FlCodecTest, ReadValueEmpty) { | ||
| g_autoptr(FlTestCodec) codec = fl_test_codec_new(); | ||
| g_autoptr(GBytes) message = g_bytes_new(nullptr, 0); | ||
|
|
||
| size_t offset = 0; | ||
| g_autoptr(GError) error = nullptr; | ||
| g_autoptr(FlValue) value = | ||
| fl_codec_read_value(FL_CODEC(codec), message, &offset, &error); | ||
| EXPECT_EQ(value, nullptr); | ||
| EXPECT_TRUE( | ||
| g_error_matches(error, FL_CODEC_ERROR, FL_CODEC_ERROR_OUT_OF_DATA)); | ||
| EXPECT_EQ(offset, static_cast<size_t>(0)); | ||
| } | ||
|
|
||
| TEST(FlCodecTest, ReadValue) { | ||
robert-ancell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| g_autoptr(FlTestCodec) codec = fl_test_codec_new(); | ||
| uint8_t data[] = {'1'}; | ||
| g_autoptr(GBytes) message = g_bytes_new(data, 1); | ||
|
|
||
| size_t offset = 0; | ||
| g_autoptr(GError) error = nullptr; | ||
| g_autoptr(FlValue) value = | ||
| fl_codec_read_value(FL_CODEC(codec), message, &offset, &error); | ||
| EXPECT_NE(value, nullptr); | ||
| EXPECT_EQ(error, nullptr); | ||
| EXPECT_EQ(offset, static_cast<size_t>(1)); | ||
|
|
||
| ASSERT_TRUE(fl_value_get_type(value) == FL_VALUE_TYPE_INT); | ||
| EXPECT_EQ(fl_value_get_int(value), 1); | ||
| } | ||
|
|
||
| TEST(FlCodecTest, ReadValues) { | ||
| g_autoptr(FlTestCodec) codec = fl_test_codec_new(); | ||
| uint8_t data[] = {'1', '2', '3', '4', '5'}; | ||
| g_autoptr(GBytes) message = g_bytes_new(data, 5); | ||
|
|
||
| size_t offset = 0; | ||
| for (int i = 1; i <= 5; i++) { | ||
| g_autoptr(GError) error = nullptr; | ||
| g_autoptr(FlValue) value = | ||
| fl_codec_read_value(FL_CODEC(codec), message, &offset, &error); | ||
| EXPECT_NE(value, nullptr); | ||
| EXPECT_EQ(error, nullptr); | ||
| ASSERT_TRUE(fl_value_get_type(value) == FL_VALUE_TYPE_INT); | ||
| EXPECT_EQ(fl_value_get_int(value), i); | ||
| } | ||
|
|
||
| EXPECT_EQ(offset, static_cast<size_t>(5)); | ||
| } | ||
|
|
||
| TEST(FlCodecTest, ReadValueNullOffset) { | ||
| g_autoptr(FlTestCodec) codec = fl_test_codec_new(); | ||
| uint8_t data[] = {'1'}; | ||
| g_autoptr(GBytes) message = g_bytes_new(data, 1); | ||
|
|
||
| g_autoptr(GError) error = nullptr; | ||
| g_autoptr(FlValue) value = | ||
| fl_codec_read_value(FL_CODEC(codec), message, NULL, &error); | ||
| EXPECT_NE(value, nullptr); | ||
| EXPECT_EQ(error, nullptr); | ||
|
|
||
| ASSERT_TRUE(fl_value_get_type(value) == FL_VALUE_TYPE_INT); | ||
| EXPECT_EQ(fl_value_get_int(value), 1); | ||
| } | ||
|
|
||
| TEST(FlCodecTest, ReadValueInvalidOffset) { | ||
| g_autoptr(FlTestCodec) codec = fl_test_codec_new(); | ||
| uint8_t data[] = {'1', '2', '3', '4', '5'}; | ||
| g_autoptr(GBytes) message = g_bytes_new(data, 5); | ||
|
|
||
| size_t offset = 9999; | ||
| g_autoptr(GError) error = nullptr; | ||
| g_autoptr(FlValue) value = | ||
| fl_codec_read_value(FL_CODEC(codec), message, &offset, &error); | ||
| EXPECT_EQ(value, nullptr); | ||
| EXPECT_TRUE( | ||
| g_error_matches(error, FL_CODEC_ERROR, FL_CODEC_ERROR_OUT_OF_DATA)); | ||
| EXPECT_EQ(offset, static_cast<size_t>(9999)); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.