Flutter Engine
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/cpp/json_method_codec.h"
6 
7 #include "flutter/shell/platform/common/cpp/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
37  static JsonMethodCodec sInstance;
38  return sInstance;
39 }
40 
41 std::unique_ptr<MethodCall<rapidjson::Document>>
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(
69  // TODO: Consider revisiting the codec APIs to avoid the need to copy
70  // everything when doing encoding (e.g., by having a version that takes
71  // 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 
83 }
84 
85 std::unique_ptr<std::vector<uint8_t>>
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 
97 }
98 
99 std::unique_ptr<std::vector<uint8_t>>
101  const std::string& error_code,
102  const std::string& error_message,
103  const rapidjson::Document* error_details) const {
104  rapidjson::Document envelope(rapidjson::kArrayType);
105  auto& allocator = envelope.GetAllocator();
106  envelope.PushBack(rapidjson::Value(error_code, allocator), allocator);
107  envelope.PushBack(rapidjson::Value(error_message, allocator), allocator);
108  rapidjson::Value details_value;
109  if (error_details) {
110  details_value.CopyFrom(*error_details, allocator);
111  }
112  envelope.PushBack(details_value, allocator);
113 
114  return JsonMessageCodec::GetInstance().EncodeMessage(envelope);
115 }
116 
118  const uint8_t* response,
119  size_t response_size,
120  MethodResult<rapidjson::Document>* result) const {
121  std::unique_ptr<rapidjson::Document> json_response =
122  JsonMessageCodec::GetInstance().DecodeMessage(response, response_size);
123  if (!json_response) {
124  return false;
125  }
126  if (!json_response->IsArray()) {
127  return false;
128  }
129  switch (json_response->Size()) {
130  case 1: {
131  std::unique_ptr<rapidjson::Document> value =
132  ExtractElement(json_response.get(), &((*json_response)[0]));
133  if (value->IsNull()) {
134  result->Success();
135  } else {
136  result->Success(*value);
137  }
138  return true;
139  }
140  case 3: {
141  std::string code = (*json_response)[0].GetString();
142  std::string message = (*json_response)[1].GetString();
143  std::unique_ptr<rapidjson::Document> details =
144  ExtractElement(json_response.get(), &((*json_response)[2]));
145  if (details->IsNull()) {
146  result->Error(code, message);
147  } else {
148  result->Error(code, message, *details);
149  }
150  return true;
151  }
152  default:
153  return false;
154  }
155 }
156 
157 } // namespace flutter
G_BEGIN_DECLS FlMethodCall * method_call
std::unique_ptr< MethodCall< rapidjson::Document > > DecodeMethodCallInternal(const uint8_t *message, const size_t message_size) const override
const T * arguments() const
Definition: method_call.h:34
void Error(const std::string &error_code, const std::string &error_message, const T &error_details)
Definition: method_result.h:41
static const JsonMethodCodec & GetInstance()
std::unique_ptr< std::vector< uint8_t > > EncodeSuccessEnvelopeInternal(const rapidjson::Document *result) const override
bool DecodeAndProcessResponseEnvelopeInternal(const uint8_t *response, const size_t response_size, MethodResult< rapidjson::Document > *result) const override
void Success(const T &result)
Definition: method_result.h:29
uint8_t value
std::unique_ptr< T > DecodeMessage(const uint8_t *binary_message, const size_t message_size) const
Definition: message_codec.h:29
std::unique_ptr< std::vector< uint8_t > > EncodeMethodCallInternal(const MethodCall< rapidjson::Document > &method_call) const override
static const JsonMessageCodec & GetInstance()
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
const char * name
Definition: fuchsia.cc:50
const std::string & method_name() const
Definition: method_call.h:31
std::unique_ptr< std::vector< uint8_t > > EncodeMessage(const T &message) const
Definition: message_codec.h:45