From bc851cd89a15f5a7b498b5bea9e50e5e0d58a89e Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Sat, 10 Nov 2018 15:56:50 -0800 Subject: [PATCH 1/2] Split JsonMessageCodec out from JsonMethodCodec Separates the basic JSON<->byte stream logic out into JsonMessageCodec, which is an eventual part of the final channel interface. Eventually this class will inherit from a generic MessageCodec interface, but in order to make this functionality available for library use while the type handling of the public interface is worked out, the new class is internal for now. --- .../json_method_codec.h | 7 --- .../linux/src/internal/json_message_codec.cc | 55 +++++++++++++++++ .../linux/src/internal/json_message_codec.h | 59 +++++++++++++++++++ library/linux/src/json_method_codec.cc | 36 +++-------- 4 files changed, 123 insertions(+), 34 deletions(-) create mode 100644 library/linux/src/internal/json_message_codec.cc create mode 100644 library/linux/src/internal/json_message_codec.h diff --git a/library/linux/include/flutter_desktop_embedding/json_method_codec.h b/library/linux/include/flutter_desktop_embedding/json_method_codec.h index 6d1064ce1..38ac8fcc6 100644 --- a/library/linux/include/flutter_desktop_embedding/json_method_codec.h +++ b/library/linux/include/flutter_desktop_embedding/json_method_codec.h @@ -14,8 +14,6 @@ #ifndef LIBRARY_LINUX_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_METHOD_CODEC_H_ #define LIBRARY_LINUX_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_METHOD_CODEC_H_ -#include - #include "method_codec.h" namespace flutter_desktop_embedding { @@ -49,11 +47,6 @@ class JsonMethodCodec : public MethodCodec { std::unique_ptr> EncodeErrorEnvelopeInternal( const std::string &error_code, const std::string &error_message, const void *error_details) const override; - - private: - // Serializes |json| into a byte stream. - std::unique_ptr> EncodeJsonObject( - const Json::Value &json) const; }; } // namespace flutter_desktop_embedding diff --git a/library/linux/src/internal/json_message_codec.cc b/library/linux/src/internal/json_message_codec.cc new file mode 100644 index 000000000..ad40e807b --- /dev/null +++ b/library/linux/src/internal/json_message_codec.cc @@ -0,0 +1,55 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "library/linux/src/internal/json_message_codec.h" + +#include +#include + +namespace flutter_desktop_embedding { + +// static +const JsonMessageCodec &JsonMessageCodec::GetInstance() { + static JsonMessageCodec sInstance; + return sInstance; +} + +std::unique_ptr> JsonMessageCodec::EncodeMessage( + const Json::Value &message) const { + Json::StreamWriterBuilder writer_builder; + std::string serialization = Json::writeString(writer_builder, message); + + return std::make_unique>(serialization.begin(), + serialization.end()); +} + +std::unique_ptr JsonMessageCodec::DecodeMessage( + const uint8_t *message, const size_t message_size) const { + Json::CharReaderBuilder reader_builder; + std::unique_ptr parser(reader_builder.newCharReader()); + + auto raw_message = reinterpret_cast(message); + auto json_message = std::make_unique(); + std::string parse_errors; + bool parsing_successful = + parser->parse(raw_message, raw_message + message_size, json_message.get(), + &parse_errors); + if (!parsing_successful) { + std::cerr << "Unable to parse JSON message:" << std::endl + << parse_errors << std::endl; + return nullptr; + } + return json_message; +} + +} // namespace flutter_desktop_embedding diff --git a/library/linux/src/internal/json_message_codec.h b/library/linux/src/internal/json_message_codec.h new file mode 100644 index 000000000..bbb55fdcb --- /dev/null +++ b/library/linux/src/internal/json_message_codec.h @@ -0,0 +1,59 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef LIBRARY_LINUX_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_MESSAGE_CODEC_H_ +#define LIBRARY_LINUX_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_MESSAGE_CODEC_H_ + +#include +#include + +#include + +namespace flutter_desktop_embedding { + +// A message encoding/decoding mechanism for communications to/from the +// Flutter engine via JSON channels. +// +// TODO: Make this public, once generalizing a MessageCodec parent interface is +// addressed; this is complicated by the return type of EncodeMessage. +// Part of issue #102. +class JsonMessageCodec { + public: + // Returns the shared instance of the codec. + static const JsonMessageCodec &GetInstance(); + + ~JsonMessageCodec() = default; + + // Prevent copying. + JsonMessageCodec(JsonMessageCodec const &) = delete; + JsonMessageCodec &operator=(JsonMessageCodec const &) = delete; + + // Returns a binary encoding of the given message, or nullptr if the + // message cannot be serialized by this codec. + std::unique_ptr> EncodeMessage( + const Json::Value &message) const; + + // Returns the MethodCall encoded in |message|, or nullptr if it cannot be + // decoded. + // TODO: Consider adding absl as a dependency and using absl::Span. + std::unique_ptr DecodeMessage(const uint8_t *message, + const size_t message_size) const; + + protected: + // Instances should be obtained via GetInstance. + JsonMessageCodec() = default; +}; + +} // namespace flutter_desktop_embedding + +#endif // LIBRARY_LINUX_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_MESSAGE_CODEC_H_ diff --git a/library/linux/src/json_method_codec.cc b/library/linux/src/json_method_codec.cc index f11c3df35..29107110f 100644 --- a/library/linux/src/json_method_codec.cc +++ b/library/linux/src/json_method_codec.cc @@ -13,9 +13,8 @@ // limitations under the License. #include "library/linux/include/flutter_desktop_embedding/json_method_codec.h" -#include - #include "library/linux/include/flutter_desktop_embedding/json_method_call.h" +#include "library/linux/src/internal/json_message_codec.h" namespace flutter_desktop_embedding { @@ -33,25 +32,17 @@ const JsonMethodCodec &JsonMethodCodec::GetInstance() { std::unique_ptr JsonMethodCodec::DecodeMethodCallInternal( const uint8_t *message, const size_t message_size) const { - Json::CharReaderBuilder reader_builder; - std::unique_ptr parser(reader_builder.newCharReader()); - - auto raw_message = reinterpret_cast(message); - Json::Value json_message; - std::string parse_errors; - bool parsing_successful = parser->parse( - raw_message, raw_message + message_size, &json_message, &parse_errors); - if (!parsing_successful) { - std::cerr << "Unable to parse JSON method call:" << std::endl - << parse_errors << std::endl; + std::unique_ptr json_message = + JsonMessageCodec::GetInstance().DecodeMessage(message, message_size); + if (!json_message) { return nullptr; } - Json::Value method = json_message[kMessageMethodKey]; + Json::Value method = (*json_message)[kMessageMethodKey]; if (method.isNull()) { return nullptr; } - Json::Value arguments = json_message[kMessageArgumentsKey]; + Json::Value arguments = (*json_message)[kMessageArgumentsKey]; return std::make_unique(method.asString(), arguments); } @@ -62,7 +53,7 @@ std::unique_ptr> JsonMethodCodec::EncodeMethodCallInternal( message[kMessageArgumentsKey] = *static_cast(method_call.arguments()); - return EncodeJsonObject(message); + return JsonMessageCodec::GetInstance().EncodeMessage(message); } std::unique_ptr> @@ -71,7 +62,7 @@ JsonMethodCodec::EncodeSuccessEnvelopeInternal(const void *result) const { envelope.append(result == nullptr ? Json::Value() : *static_cast(result)); - return EncodeJsonObject(envelope); + return JsonMessageCodec::GetInstance().EncodeMessage(envelope); } std::unique_ptr> @@ -84,16 +75,7 @@ JsonMethodCodec::EncodeErrorEnvelopeInternal(const std::string &error_code, envelope.append(error_details == nullptr ? Json::Value() : *static_cast(error_details)); - return EncodeJsonObject(envelope); -} - -std::unique_ptr> JsonMethodCodec::EncodeJsonObject( - const Json::Value &json) const { - Json::StreamWriterBuilder writer_builder; - std::string serialization = Json::writeString(writer_builder, json); - - return std::make_unique>(serialization.begin(), - serialization.end()); + return JsonMessageCodec::GetInstance().EncodeMessage(envelope); } } // namespace flutter_desktop_embedding From bf56da2750fdb68624b4d44bde1b3af0175c77a3 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 14 Nov 2018 15:54:34 -0500 Subject: [PATCH 2/2] Fix method comment --- library/linux/src/internal/json_message_codec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/linux/src/internal/json_message_codec.h b/library/linux/src/internal/json_message_codec.h index bbb55fdcb..34d47ca88 100644 --- a/library/linux/src/internal/json_message_codec.h +++ b/library/linux/src/internal/json_message_codec.h @@ -43,7 +43,7 @@ class JsonMessageCodec { std::unique_ptr> EncodeMessage( const Json::Value &message) const; - // Returns the MethodCall encoded in |message|, or nullptr if it cannot be + // Returns the JSON object encoded in |message|, or nullptr if it cannot be // decoded. // TODO: Consider adding absl as a dependency and using absl::Span. std::unique_ptr DecodeMessage(const uint8_t *message,