Fix for Geolocation webTCT failures
[platform/framework/web/chromium-efl.git] / dbus / values_util.cc
1 // Copyright 2012 The Chromium Authors
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 "dbus/values_util.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/json/json_writer.h"
11 #include "base/logging.h"
12 #include "base/memory/raw_ptr.h"
13 #include "base/notreached.h"
14 #include "base/values.h"
15 #include "dbus/message.h"
16
17 namespace dbus {
18
19 namespace {
20
21 // Returns whether |value| is exactly representable by double or not.
22 template <typename T>
23 bool IsExactlyRepresentableByDouble(T value) {
24   return value == static_cast<T>(static_cast<double>(value));
25 }
26
27 // Pops values from |reader| and appends them to |list_value|.
28 bool PopListElements(MessageReader* reader, base::Value::List& list_value) {
29   while (reader->HasMoreData()) {
30     base::Value element_value = PopDataAsValue(reader);
31     if (element_value.is_none())
32       return false;
33     list_value.Append(std::move(element_value));
34   }
35   return true;
36 }
37
38 // Pops dict-entries from |reader| and sets them to |dictionary_value|
39 bool PopDictionaryEntries(MessageReader* reader,
40                           base::Value::Dict& dictionary_value) {
41   while (reader->HasMoreData()) {
42     DCHECK_EQ(Message::DICT_ENTRY, reader->GetDataType());
43     MessageReader entry_reader(nullptr);
44     if (!reader->PopDictEntry(&entry_reader))
45       return false;
46     // Get key as a string.
47     std::string key_string;
48     if (entry_reader.GetDataType() == Message::STRING) {
49       // If the type of keys is STRING, pop it directly.
50       if (!entry_reader.PopString(&key_string))
51         return false;
52     } else {
53       // If the type of keys is not STRING, convert it to string.
54       base::Value key = PopDataAsValue(&entry_reader);
55       if (key.is_none())
56         return false;
57       // Use JSONWriter to convert an arbitrary value to a string.
58       base::JSONWriter::Write(key, &key_string);
59     }
60     // Get the value and set the key-value pair.
61     base::Value value = PopDataAsValue(&entry_reader);
62     if (value.is_none())
63       return false;
64     dictionary_value.Set(key_string, std::move(value));
65   }
66   return true;
67 }
68
69 // Gets the D-Bus type signature for the value.
70 std::string GetTypeSignature(base::ValueView value) {
71   struct Visitor {
72     std::string operator()(absl::monostate) {
73       DLOG(ERROR) << "Unexpected type " << base::Value::Type::NONE;
74       return std::string();
75     }
76
77     std::string operator()(bool) { return "b"; }
78
79     std::string operator()(int) { return "i"; }
80
81     std::string operator()(double) { return "d"; }
82
83     std::string operator()(base::StringPiece) { return "s"; }
84
85     std::string operator()(const base::Value::BlobStorage&) { return "ay"; }
86
87     std::string operator()(const base::Value::Dict&) { return "a{sv}"; }
88
89     std::string operator()(const base::Value::List&) { return "av"; }
90   };
91   return value.Visit(Visitor());
92 }
93
94 }  // namespace
95
96 base::Value PopDataAsValue(MessageReader* reader) {
97   base::Value result;
98   switch (reader->GetDataType()) {
99     case Message::INVALID_DATA:
100       // Do nothing.
101       break;
102     case Message::BYTE: {
103       uint8_t value = 0;
104       if (reader->PopByte(&value))
105         result = base::Value(value);
106       break;
107     }
108     case Message::BOOL: {
109       bool value = false;
110       if (reader->PopBool(&value))
111         result = base::Value(value);
112       break;
113     }
114     case Message::INT16: {
115       int16_t value = 0;
116       if (reader->PopInt16(&value))
117         result = base::Value(value);
118       break;
119     }
120     case Message::UINT16: {
121       uint16_t value = 0;
122       if (reader->PopUint16(&value))
123         result = base::Value(value);
124       break;
125     }
126     case Message::INT32: {
127       int32_t value = 0;
128       if (reader->PopInt32(&value))
129         result = base::Value(value);
130       break;
131     }
132     case Message::UINT32: {
133       uint32_t value = 0;
134       if (reader->PopUint32(&value)) {
135         result = base::Value(static_cast<double>(value));
136       }
137       break;
138     }
139     case Message::INT64: {
140       int64_t value = 0;
141       if (reader->PopInt64(&value)) {
142         DLOG_IF(WARNING, !IsExactlyRepresentableByDouble(value))
143             << value << " is not exactly representable by double";
144         result = base::Value(static_cast<double>(value));
145       }
146       break;
147     }
148     case Message::UINT64: {
149       uint64_t value = 0;
150       if (reader->PopUint64(&value)) {
151         DLOG_IF(WARNING, !IsExactlyRepresentableByDouble(value))
152             << value << " is not exactly representable by double";
153         result = base::Value(static_cast<double>(value));
154       }
155       break;
156     }
157     case Message::DOUBLE: {
158       double value = 0;
159       if (reader->PopDouble(&value))
160         result = base::Value(value);
161       break;
162     }
163     case Message::STRING: {
164       std::string value;
165       if (reader->PopString(&value))
166         result = base::Value(value);
167       break;
168     }
169     case Message::OBJECT_PATH: {
170       ObjectPath value;
171       if (reader->PopObjectPath(&value))
172         result = base::Value(value.value());
173       break;
174     }
175     case Message::UNIX_FD: {
176       // Cannot distinguish a file descriptor from an int
177       NOTREACHED();
178       break;
179     }
180     case Message::ARRAY: {
181       MessageReader sub_reader(nullptr);
182       if (reader->PopArray(&sub_reader)) {
183         // If the type of the array's element is DICT_ENTRY, create a
184         // Value with type base::Value::Dict, otherwise create a
185         // Value with type base::Value::List.
186         if (sub_reader.GetDataType() == Message::DICT_ENTRY) {
187           base::Value::Dict dictionary_value;
188           if (PopDictionaryEntries(&sub_reader, dictionary_value))
189             result = base::Value(std::move(dictionary_value));
190         } else {
191           base::Value::List list_value;
192           if (PopListElements(&sub_reader, list_value))
193             result = base::Value(std::move(list_value));
194         }
195       }
196       break;
197     }
198     case Message::STRUCT: {
199       MessageReader sub_reader(nullptr);
200       if (reader->PopStruct(&sub_reader)) {
201         base::Value::List list_value;
202         if (PopListElements(&sub_reader, list_value))
203           result = base::Value(std::move(list_value));
204       }
205       break;
206     }
207     case Message::DICT_ENTRY:
208       // DICT_ENTRY must be popped as an element of an array.
209       NOTREACHED();
210       break;
211     case Message::VARIANT: {
212       MessageReader sub_reader(nullptr);
213       if (reader->PopVariant(&sub_reader))
214         result = PopDataAsValue(&sub_reader);
215       break;
216     }
217   }
218   return result;
219 }
220
221 void AppendBasicTypeValueData(MessageWriter* writer, base::ValueView value) {
222   struct Visitor {
223     raw_ptr<MessageWriter> writer;
224
225     void operator()(absl::monostate) {
226       DLOG(ERROR) << "Unexpected type: " << base::Value::Type::NONE;
227     }
228
229     void operator()(bool value) { writer->AppendBool(value); }
230
231     void operator()(int value) { writer->AppendInt32(value); }
232
233     void operator()(double value) { writer->AppendDouble(value); }
234
235     void operator()(base::StringPiece value) { writer->AppendString(value); }
236
237     void operator()(const base::Value::BlobStorage&) {
238       DLOG(ERROR) << "Unexpected type: " << base::Value::Type::BINARY;
239     }
240
241     void operator()(const base::Value::Dict&) {
242       DLOG(ERROR) << "Unexpected type: " << base::Value::Type::DICT;
243     }
244
245     void operator()(const base::Value::List&) {
246       DLOG(ERROR) << "Unexpected type: " << base::Value::Type::LIST;
247     }
248   };
249
250   value.Visit(Visitor{.writer = writer});
251 }
252
253 void AppendBasicTypeValueDataAsVariant(MessageWriter* writer,
254                                        base::ValueView value) {
255   MessageWriter sub_writer(nullptr);
256   writer->OpenVariant(GetTypeSignature(value), &sub_writer);
257   AppendBasicTypeValueData(&sub_writer, value);
258   writer->CloseContainer(&sub_writer);
259 }
260
261 void AppendValueData(MessageWriter* writer, base::ValueView value) {
262   struct Visitor {
263     raw_ptr<MessageWriter> writer;
264
265     void operator()(absl::monostate) {
266       DLOG(ERROR) << "Unexpected type: " << base::Value::Type::NONE;
267     }
268
269     void operator()(bool value) {
270       return AppendBasicTypeValueData(writer, value);
271     }
272
273     void operator()(int value) {
274       return AppendBasicTypeValueData(writer, value);
275     }
276
277     void operator()(double value) {
278       return AppendBasicTypeValueData(writer, value);
279     }
280
281     void operator()(base::StringPiece value) {
282       return AppendBasicTypeValueData(writer, value);
283     }
284
285     void operator()(const base::Value::BlobStorage& value) {
286       DLOG(ERROR) << "Unexpected type: " << base::Value::Type::BINARY;
287     }
288
289     void operator()(const base::Value::Dict& value) {
290       dbus::MessageWriter array_writer(nullptr);
291       writer->OpenArray("{sv}", &array_writer);
292       for (auto item : value) {
293         dbus::MessageWriter dict_entry_writer(nullptr);
294         array_writer.OpenDictEntry(&dict_entry_writer);
295         dict_entry_writer.AppendString(item.first);
296         AppendValueDataAsVariant(&dict_entry_writer, item.second);
297         array_writer.CloseContainer(&dict_entry_writer);
298       }
299       writer->CloseContainer(&array_writer);
300     }
301
302     void operator()(const base::Value::List& value) {
303       dbus::MessageWriter array_writer(nullptr);
304       writer->OpenArray("v", &array_writer);
305       for (const auto& value_in_list : value) {
306         AppendValueDataAsVariant(&array_writer, value_in_list);
307       }
308       writer->CloseContainer(&array_writer);
309     }
310   };
311
312   value.Visit(Visitor{.writer = writer});
313 }
314
315 void AppendValueDataAsVariant(MessageWriter* writer, base::ValueView value) {
316   MessageWriter variant_writer(nullptr);
317   writer->OpenVariant(GetTypeSignature(value), &variant_writer);
318   AppendValueData(&variant_writer, value);
319   writer->CloseContainer(&variant_writer);
320 }
321
322 }  // namespace dbus