1 // Copyright (c) 2012 The Chromium 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 "chromeos/network/onc/onc_mapper.h"
6 
7 #include <utility>
8 
9 #include "base/logging.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/values.h"
12 #include "chromeos/network/onc/onc_signature.h"
13 
14 namespace chromeos {
15 namespace onc {
16 
17 Mapper::Mapper() = default;
18 
19 Mapper::~Mapper() = default;
20 
MapValue(const OncValueSignature & signature,const base::Value & onc_value,bool * error)21 std::unique_ptr<base::Value> Mapper::MapValue(
22     const OncValueSignature& signature,
23     const base::Value& onc_value,
24     bool* error) {
25   std::unique_ptr<base::Value> result_value;
26   switch (onc_value.type()) {
27     case base::Value::Type::DICTIONARY: {
28       const base::DictionaryValue* dict = NULL;
29       onc_value.GetAsDictionary(&dict);
30       result_value = MapObject(signature, *dict, error);
31       break;
32     }
33     case base::Value::Type::LIST: {
34       const base::ListValue* list = NULL;
35       onc_value.GetAsList(&list);
36       result_value = MapArray(signature, *list, error);
37       break;
38     }
39     default: {
40       result_value = MapPrimitive(signature, onc_value, error);
41       break;
42     }
43   }
44 
45   return result_value;
46 }
47 
MapObject(const OncValueSignature & signature,const base::Value & onc_object,bool * error)48 std::unique_ptr<base::DictionaryValue> Mapper::MapObject(
49     const OncValueSignature& signature,
50     const base::Value& onc_object,
51     bool* error) {
52   std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue);
53 
54   bool found_unknown_field = false;
55   MapFields(signature, onc_object, &found_unknown_field, error, result.get());
56   if (found_unknown_field)
57     *error = true;
58   return result;
59 }
60 
MapPrimitive(const OncValueSignature & signature,const base::Value & onc_primitive,bool * error)61 std::unique_ptr<base::Value> Mapper::MapPrimitive(
62     const OncValueSignature& signature,
63     const base::Value& onc_primitive,
64     bool* error) {
65   return base::WrapUnique(onc_primitive.DeepCopy());
66 }
67 
MapFields(const OncValueSignature & object_signature,const base::Value & onc_object,bool * found_unknown_field,bool * nested_error,base::DictionaryValue * result)68 void Mapper::MapFields(const OncValueSignature& object_signature,
69                        const base::Value& onc_object,
70                        bool* found_unknown_field,
71                        bool* nested_error,
72                        base::DictionaryValue* result) {
73   DCHECK(onc_object.is_dict());
74   for (auto it : onc_object.DictItems()) {
75     bool current_field_unknown = false;
76     std::unique_ptr<base::Value> result_value =
77         MapField(it.first, object_signature, it.second, &current_field_unknown,
78                  nested_error);
79 
80     if (current_field_unknown)
81       *found_unknown_field = true;
82     else if (result_value.get() != NULL)
83       result->SetWithoutPathExpansion(it.first, std::move(result_value));
84     else
85       DCHECK(*nested_error);
86   }
87 }
88 
MapField(const std::string & field_name,const OncValueSignature & object_signature,const base::Value & onc_value,bool * found_unknown_field,bool * error)89 std::unique_ptr<base::Value> Mapper::MapField(
90     const std::string& field_name,
91     const OncValueSignature& object_signature,
92     const base::Value& onc_value,
93     bool* found_unknown_field,
94     bool* error) {
95   const OncFieldSignature* field_signature =
96       GetFieldSignature(object_signature, field_name);
97 
98   if (field_signature != NULL) {
99     DCHECK(field_signature->value_signature != NULL)
100         << "Found missing value signature at field '" << field_name << "'.";
101 
102     return MapValue(*field_signature->value_signature, onc_value, error);
103   } else {
104     DVLOG(1) << "Found unknown field name: '" << field_name << "'";
105     *found_unknown_field = true;
106     return std::unique_ptr<base::Value>();
107   }
108 }
109 
MapArray(const OncValueSignature & array_signature,const base::ListValue & onc_array,bool * nested_error)110 std::unique_ptr<base::ListValue> Mapper::MapArray(
111     const OncValueSignature& array_signature,
112     const base::ListValue& onc_array,
113     bool* nested_error) {
114   DCHECK(array_signature.onc_array_entry_signature != NULL)
115       << "Found missing onc_array_entry_signature.";
116 
117   std::unique_ptr<base::ListValue> result_array(new base::ListValue);
118   int original_index = 0;
119   for (const auto& entry : onc_array) {
120     std::unique_ptr<base::Value> result_entry;
121     result_entry =
122         MapEntry(original_index, *array_signature.onc_array_entry_signature,
123                  entry, nested_error);
124     if (result_entry.get() != NULL)
125       result_array->Append(std::move(result_entry));
126     else
127       DCHECK(*nested_error);
128     ++original_index;
129   }
130   return result_array;
131 }
132 
MapEntry(int index,const OncValueSignature & signature,const base::Value & onc_value,bool * error)133 std::unique_ptr<base::Value> Mapper::MapEntry(
134     int index,
135     const OncValueSignature& signature,
136     const base::Value& onc_value,
137     bool* error) {
138   return MapValue(signature, onc_value, error);
139 }
140 
141 }  // namespace onc
142 }  // namespace chromeos
143