| Flutter iOS Embedder |

json_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/common/json_method_codec.h"
6
7 #include "flutter/shell/platform/common/json_message_codec.h"
8
9 namespace flutter {
10
11 namespace {
12
13 // Keys used in MethodCall encoding.
14 constexpr char kMessageMethodKey[] = "method";
15 constexpr char kMessageArgumentsKey[] = "args";
16
17 // Returns a new document containing only |element|, which must be an element
18 // in |document|. This is a move rather than a copy, so it is efficient but
19 // destructive to the data in |document|.
20 std::unique_ptr<rapidjson::Document> ExtractElement(
21 rapidjson::Document* document,
22 rapidjson::Value* subtree) {
23 auto extracted = std::make_unique<rapidjson::Document>();
24 // Pull the subtree up to the root of the document.
25 document->Swap(*subtree);
26 // Swap the entire document into |extracted|. Unlike the swap above this moves
27 // the allocator ownership, so the data won't be deleted when |document| is
28 // destroyed.
29 extracted->Swap(*document);
30 return extracted;
31 }
32
33 } // namespace
34
35 // static
36 const JsonMethodCodec& JsonMethodCodec::GetInstance() {
37 static JsonMethodCodec sInstance;
38 return sInstance;
39 }
40
41 std::unique_ptr<MethodCall<rapidjson::Document>>
42 JsonMethodCodec::DecodeMethodCallInternal(const uint8_t* message,
43 size_t message_size) const {
44 std::unique_ptr<rapidjson::Document> json_message =
45 JsonMessageCodec::GetInstance().DecodeMessage(message, message_size);
46 if (!json_message) {
47 return nullptr;
48 }
49
50 auto method_name_iter = json_message->FindMember(kMessageMethodKey);
51 if (method_name_iter == json_message->MemberEnd()) {
52 return nullptr;
53 }
54 if (!method_name_iter->value.IsString()) {
55 return nullptr;
56 }
57 std::string method_name(method_name_iter->value.GetString());
58 auto arguments_iter = json_message->FindMember(kMessageArgumentsKey);
59 std::unique_ptr<rapidjson::Document> arguments;
60 if (arguments_iter != json_message->MemberEnd()) {
61 arguments = ExtractElement(json_message.get(), &(arguments_iter->value));
62 }
63 return std::make_unique<MethodCall<rapidjson::Document>>(
64 method_name, std::move(arguments));
65 }
66
67 std::unique_ptr<std::vector<uint8_t>> JsonMethodCodec::EncodeMethodCallInternal(
68 const MethodCall<rapidjson::Document>& method_call) const {
69 // TODO(stuartmorgan): Consider revisiting the codec APIs to avoid the need
70 // to copy everything when doing encoding (e.g., by having a version that
71 // takes owership of the object to encode, so that it can be moved instead).
72 rapidjson::Document message(rapidjson::kObjectType);
73 auto& allocator = message.GetAllocator();
74 rapidjson::Value name(method_call.method_name(), allocator);
75 rapidjson::Value arguments;
76 if (method_call.arguments()) {
77 arguments.CopyFrom(*method_call.arguments(), allocator);
78 }
79 message.AddMember(kMessageMethodKey, name, allocator);
80 message.AddMember(kMessageArgumentsKey, arguments, allocator);
81
82 return JsonMessageCodec::GetInstance().EncodeMessage(message);
83 }
84
85 std::unique_ptr<std::vector<uint8_t>>
86 JsonMethodCodec::EncodeSuccessEnvelopeInternal(
87 const rapidjson::Document* result) const {
88 rapidjson::Document envelope;
89 envelope.SetArray();
90 rapidjson::Value result_value;
91 if (result) {
92 result_value.CopyFrom(*result, envelope.GetAllocator());
93 }
94 envelope.PushBack(result_value, envelope.GetAllocator());
95
96 return JsonMessageCodec::GetInstance().EncodeMessage(envelope);
97 }
98
99 std::unique_ptr<std::vector<uint8_t>>
100 JsonMethodCodec::EncodeErrorEnvelopeInternal(
101 const std::string& error_code,
102 const std::string& error_message,
103 const rapidjson::Document* error_details) const {
104 // NOLINTNEXTLINE(clang-analyzer-core.NullDereference)
105 rapidjson::Document envelope(rapidjson::kArrayType);
106 auto& allocator = envelope.GetAllocator();
107 envelope.PushBack(rapidjson::Value(error_code, allocator), allocator);
108 envelope.PushBack(rapidjson::Value(error_message, allocator), allocator);
109 rapidjson::Value details_value;
110 if (error_details) {
111 details_value.CopyFrom(*error_details, allocator);
112 }
113 envelope.PushBack(details_value, allocator);
114
115 return JsonMessageCodec::GetInstance().EncodeMessage(envelope);
116 }
117
118 bool JsonMethodCodec::DecodeAndProcessResponseEnvelopeInternal(
119 const uint8_t* response,
120 size_t response_size,
121 MethodResult<rapidjson::Document>* result) const {
122 std::unique_ptr<rapidjson::Document> json_response =
123 JsonMessageCodec::GetInstance().DecodeMessage(response, response_size);
124 if (!json_response) {
125 return false;
126 }
127 if (!json_response->IsArray()) {
128 return false;
129 }
130 switch (json_response->Size()) {
131 case 1: {
132 std::unique_ptr<rapidjson::Document> value =
133 ExtractElement(json_response.get(), &((*json_response)[0]));
134 if (value->IsNull()) {
135 result->Success();
136 } else {
137 result->Success(*value);
138 }
139 return true;
140 }
141 case 3: {
142 std::string code = (*json_response)[0].GetString();
143 std::string message = (*json_response)[1].GetString();
144 std::unique_ptr<rapidjson::Document> details =
145 ExtractElement(json_response.get(), &((*json_response)[2]));
146 if (details->IsNull()) {
147 result->Error(code, message);
148 } else {
149 result->Error(code, message, *details);
150 }
151 return true;
152 }
153 default:
154 return false;
155 }
156 }
157
158 } // namespace flutter
flutter::JsonMethodCodec::DecodeMethodCallInternal
std::unique_ptr< MethodCall< rapidjson::Document > > DecodeMethodCallInternal(const uint8_t *message, const size_t message_size) const override
Definition: json_method_codec.cc:42
flutter::JsonMessageCodec::GetInstance
static const JsonMessageCodec & GetInstance()
Definition: json_message_codec.cc:17
flutter::JsonMethodCodec
Definition: json_method_codec.h:16
flutter::JsonMethodCodec::EncodeSuccessEnvelopeInternal
std::unique_ptr< std::vector< uint8_t > > EncodeSuccessEnvelopeInternal(const rapidjson::Document *result) const override
Definition: json_method_codec.cc:86
json_method_codec.h
json_message_codec.h
flutter::MessageCodec::DecodeMessage
std::unique_ptr< T > DecodeMessage(const uint8_t *binary_message, const size_t message_size) const
Definition: message_codec.h:29
flutter::JsonMethodCodec::GetInstance
static const JsonMethodCodec & GetInstance()
Definition: json_method_codec.cc:36
flutter::MethodCall
Definition: method_call.h:18
flutter::MethodResult::Error
void Error(const std::string &error_code, const std::string &error_message, const T &error_details)
Definition: method_result.h:41
flutter::JsonMethodCodec::DecodeAndProcessResponseEnvelopeInternal
bool DecodeAndProcessResponseEnvelopeInternal(const uint8_t *response, const size_t response_size, MethodResult< rapidjson::Document > *result) const override
Definition: json_method_codec.cc:118
flutter::JsonMethodCodec::EncodeMethodCallInternal
std::unique_ptr< std::vector< uint8_t > > EncodeMethodCallInternal(const MethodCall< rapidjson::Document > &method_call) const override
Definition: json_method_codec.cc:67
flutter
Definition: accessibility_bridge.h:28
flutter::MethodCall::method_name
const std::string & method_name() const
Definition: method_call.h:31
flutter::MethodResult::Success
void Success(const T &result)
Definition: method_result.h:29
flutter::MethodResult
Definition: method_result.h:17
flutter::MessageCodec::EncodeMessage
std::unique_ptr< std::vector< uint8_t > > EncodeMessage(const T &message) const
Definition: message_codec.h:45
flutter::JsonMethodCodec::EncodeErrorEnvelopeInternal
std::unique_ptr< std::vector< uint8_t > > EncodeErrorEnvelopeInternal(const std::string &error_code, const std::string &error_message, const rapidjson::Document *error_details) const override
Definition: json_method_codec.cc:100
flutter::MethodCall::arguments
const T * arguments() const
Definition: method_call.h:34