[content shell] implement testRunner.overridePreference
[chromium-blink-merge.git] / chromeos / network / onc / onc_translator_onc_to_shill.cc
blobcd8a4eb788d2abc00fc50e0d297a4aea8e02754f
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.
5 // The implementation of TranslateONCObjectToShill is structured in two parts:
6 // - The recursion through the existing ONC hierarchy
7 // see TranslateONCHierarchy
8 // - The local translation of an object depending on the associated signature
9 // see LocalTranslator::TranslateFields
11 #include "chromeos/network/onc/onc_translator.h"
13 #include <string>
15 #include "base/json/json_reader.h"
16 #include "base/json/json_writer.h"
17 #include "base/logging.h"
18 #include "base/values.h"
19 #include "chromeos/network/onc/onc_constants.h"
20 #include "chromeos/network/onc/onc_signature.h"
21 #include "chromeos/network/onc/onc_translation_tables.h"
22 #include "third_party/cros_system_api/dbus/service_constants.h"
24 namespace chromeos {
25 namespace onc {
27 namespace {
29 scoped_ptr<base::StringValue> ConvertValueToString(const base::Value& value) {
30 std::string str;
31 if (!value.GetAsString(&str))
32 base::JSONWriter::Write(&value, &str);
33 return make_scoped_ptr(base::Value::CreateStringValue(str));
36 // This class is responsible to translate the local fields of the given
37 // |onc_object| according to |onc_signature| into |shill_dictionary|. This
38 // translation should consider (if possible) only fields of this ONC object and
39 // not nested objects because recursion is handled by the calling function
40 // TranslateONCHierarchy.
41 class LocalTranslator {
42 public:
43 LocalTranslator(const OncValueSignature& onc_signature,
44 const base::DictionaryValue& onc_object,
45 base::DictionaryValue* shill_dictionary)
46 : onc_signature_(&onc_signature),
47 onc_object_(&onc_object),
48 shill_dictionary_(shill_dictionary) {
51 void TranslateFields();
53 private:
54 void TranslateOpenVPN();
55 void TranslateVPN();
56 void TranslateNetworkConfiguration();
58 // Copies all entries from |onc_object_| to |shill_dictionary_| for which a
59 // translation (shill_property_name) is defined by |onc_signature_|.
60 void CopyFieldsAccordingToSignature();
62 // Adds |value| to |shill_dictionary| at the field shill_property_name given
63 // by the associated signature. Takes ownership of |value|. Does nothing if
64 // |value| is NULL or the property name cannot be read from the signature.
65 void AddValueAccordingToSignature(const std::string& onc_field_name,
66 scoped_ptr<base::Value> value);
68 // If existent, translates the entry at |onc_field_name| in |onc_object_|
69 // using |table|. It is an error if no matching table entry is found. Writes
70 // the result as entry at |shill_property_name| in |shill_dictionary_|.
71 void TranslateWithTableAndSet(const std::string& onc_field_name,
72 const StringTranslationEntry table[],
73 const std::string& shill_property_name);
75 const OncValueSignature* onc_signature_;
76 const base::DictionaryValue* onc_object_;
77 base::DictionaryValue* shill_dictionary_;
79 DISALLOW_COPY_AND_ASSIGN(LocalTranslator);
82 void LocalTranslator::TranslateFields() {
83 if (onc_signature_ == &kNetworkConfigurationSignature)
84 TranslateNetworkConfiguration();
85 else if (onc_signature_ == &kVPNSignature)
86 TranslateVPN();
87 else if (onc_signature_ == &kOpenVPNSignature)
88 TranslateOpenVPN();
89 else
90 CopyFieldsAccordingToSignature();
93 void LocalTranslator::TranslateOpenVPN() {
94 // Shill supports only one RemoteCertKU but ONC a list.
95 // Copy only the first entry if existing.
96 const base::ListValue* certKUs;
97 std::string certKU;
98 if (onc_object_->GetListWithoutPathExpansion(vpn::kRemoteCertKU, &certKUs) &&
99 certKUs->GetString(0, &certKU)) {
100 shill_dictionary_->SetStringWithoutPathExpansion(
101 flimflam::kOpenVPNRemoteCertKUProperty, certKU);
104 for (base::DictionaryValue::Iterator it(*onc_object_); it.HasNext();
105 it.Advance()) {
106 scoped_ptr<base::Value> translated;
107 if (it.key() == vpn::kSaveCredentials || it.key() == vpn::kRemoteCertKU) {
108 translated.reset(it.value().DeepCopy());
109 } else {
110 // Shill wants all Provider/VPN fields to be strings.
111 translated = ConvertValueToString(it.value());
113 AddValueAccordingToSignature(it.key(), translated.Pass());
117 void LocalTranslator::TranslateVPN() {
118 TranslateWithTableAndSet(kType, kVPNTypeTable,
119 flimflam::kProviderTypeProperty);
120 CopyFieldsAccordingToSignature();
123 void LocalTranslator::TranslateNetworkConfiguration() {
124 TranslateWithTableAndSet(kType, kNetworkTypeTable, flimflam::kTypeProperty);
125 CopyFieldsAccordingToSignature();
128 void LocalTranslator::CopyFieldsAccordingToSignature() {
129 for (base::DictionaryValue::Iterator it(*onc_object_); it.HasNext();
130 it.Advance()) {
131 AddValueAccordingToSignature(it.key(),
132 make_scoped_ptr(it.value().DeepCopy()));
136 void LocalTranslator::AddValueAccordingToSignature(
137 const std::string& onc_name,
138 scoped_ptr<base::Value> value) {
139 if (value.get() == NULL)
140 return;
141 const OncFieldSignature* field_signature =
142 GetFieldSignature(*onc_signature_, onc_name);
143 DCHECK(field_signature != NULL);
144 if (field_signature == NULL || field_signature->shill_property_name == NULL)
145 return;
147 shill_dictionary_->SetWithoutPathExpansion(
148 field_signature->shill_property_name, value.release());
151 void LocalTranslator::TranslateWithTableAndSet(
152 const std::string& onc_field_name,
153 const StringTranslationEntry table[],
154 const std::string& shill_property_name) {
155 std::string onc_value;
156 if (!onc_object_->GetStringWithoutPathExpansion(onc_field_name, &onc_value))
157 return;
159 for (int i = 0; table[i].onc_value != NULL; ++i) {
160 if (onc_value != table[i].onc_value)
161 continue;
162 shill_dictionary_->SetStringWithoutPathExpansion(shill_property_name,
163 table[i].shill_value);
164 return;
166 // As we previously validate ONC, this case should never occur. If it still
167 // occurs, we should check here. Otherwise the failure will only show up much
168 // later in Shill.
169 LOG(ERROR) << "Value '" << onc_value << "' for field '"
170 << onc_field_name << "' cannot be translated to Shill";
173 // Iterates recursively over |onc_object| and its |signature|. At each object
174 // applies the local translation using LocalTranslator::TranslateFields. The
175 // results are written to |shill_dictionary|.
176 void TranslateONCHierarchy(const OncValueSignature& signature,
177 const base::DictionaryValue& onc_object,
178 base::DictionaryValue* shill_dictionary) {
179 // Translates fields of |onc_object| and writes them to |shill_dictionary_|.
180 LocalTranslator translator(signature, onc_object, shill_dictionary);
181 translator.TranslateFields();
183 // Recurse into nested objects.
184 for (base::DictionaryValue::Iterator it(onc_object); it.HasNext();
185 it.Advance()) {
186 const base::DictionaryValue* inner_object;
187 if (!it.value().GetAsDictionary(&inner_object))
188 continue;
190 const OncFieldSignature* field_signature =
191 GetFieldSignature(signature, it.key());
193 TranslateONCHierarchy(*field_signature->value_signature, *inner_object,
194 shill_dictionary);
198 } // namespace
200 scoped_ptr<base::DictionaryValue> TranslateONCObjectToShill(
201 const OncValueSignature* onc_signature,
202 const base::DictionaryValue& onc_object) {
203 CHECK(onc_signature != NULL);
204 scoped_ptr<base::DictionaryValue> shill_dictionary(new base::DictionaryValue);
205 TranslateONCHierarchy(*onc_signature, onc_object, shill_dictionary.get());
206 return shill_dictionary.Pass();
209 } // namespace onc
210 } // namespace chromeos