[content shell] implement testRunner.overridePreference
[chromium-blink-merge.git] / chromeos / network / onc / onc_translator_shill_to_onc.cc
blobc33e0a95b9c8f52ab8a387c021244b87cce9586e
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 #include "chromeos/network/onc/onc_translator.h"
7 #include <string>
9 #include "base/basictypes.h"
10 #include "base/json/json_reader.h"
11 #include "base/json/json_writer.h"
12 #include "base/logging.h"
13 #include "base/values.h"
14 #include "chromeos/network/onc/onc_constants.h"
15 #include "chromeos/network/onc/onc_signature.h"
16 #include "chromeos/network/onc/onc_translation_tables.h"
17 #include "third_party/cros_system_api/dbus/service_constants.h"
19 namespace chromeos {
20 namespace onc {
22 namespace {
24 // Converts |str| to a base::Value of the given |type|. If the conversion fails,
25 // returns NULL.
26 scoped_ptr<base::Value> ConvertStringToValue(const std::string& str,
27 base::Value::Type type) {
28 base::Value* value;
29 if (type == base::Value::TYPE_STRING)
30 value = base::Value::CreateStringValue(str);
31 else
32 value = base::JSONReader::Read(str);
34 if (value == NULL || value->GetType() != type) {
35 delete value;
36 value = NULL;
38 return make_scoped_ptr(value);
41 // This class implements the translation of properties from the given
42 // |shill_dictionary| to a new ONC object of signature |onc_signature|. Using
43 // recursive calls to TranslateShillServiceToONCPart, nested objects are
44 // translated.
45 class ShillToONCTranslator {
46 public:
47 ShillToONCTranslator(const base::DictionaryValue& shill_dictionary,
48 const OncValueSignature& onc_signature)
49 : shill_dictionary_(&shill_dictionary),
50 onc_signature_(&onc_signature) {
53 // Translates the associated Shill dictionary and creates an ONC object of the
54 // given signature.
55 scoped_ptr<base::DictionaryValue> CreateTranslatedONCObject();
57 private:
58 void TranslateOpenVPN();
59 void TranslateVPN();
60 void TranslateNetworkConfiguration();
62 // Creates an ONC object from |shill_dictionary| according to the signature
63 // associated to |onc_field_name| and adds it to |onc_object_| at
64 // |onc_field_name|.
65 void TranslateAndAddNestedObject(const std::string& onc_field_name);
67 // Copies all entries from |shill_dictionary_| to |onc_object_| for which a
68 // translation (shill_property_name) is defined by |onc_signature_|.
69 void CopyPropertiesAccordingToSignature();
71 // If existent, translates the entry at |shill_property_name| in
72 // |shill_dictionary_| using |table|. It is an error if no matching table
73 // entry is found. Writes the result as entry at |onc_field_name| in
74 // |onc_object_|.
75 void TranslateWithTableAndSet(const std::string& shill_property_name,
76 const StringTranslationEntry table[],
77 const std::string& onc_field_name);
79 const base::DictionaryValue* shill_dictionary_;
80 const OncValueSignature* onc_signature_;
81 scoped_ptr<base::DictionaryValue> onc_object_;
83 DISALLOW_COPY_AND_ASSIGN(ShillToONCTranslator);
86 scoped_ptr<base::DictionaryValue>
87 ShillToONCTranslator::CreateTranslatedONCObject() {
88 onc_object_.reset(new base::DictionaryValue);
89 if (onc_signature_ == &kNetworkConfigurationSignature)
90 TranslateNetworkConfiguration();
91 else if (onc_signature_ == &kVPNSignature)
92 TranslateVPN();
93 else if (onc_signature_ == &kOpenVPNSignature)
94 TranslateOpenVPN();
95 else
96 CopyPropertiesAccordingToSignature();
97 return onc_object_.Pass();
100 void ShillToONCTranslator::TranslateOpenVPN() {
101 // Shill supports only one RemoteCertKU but ONC requires a list. If existing,
102 // wraps the value into a list.
103 std::string certKU;
104 if (shill_dictionary_->GetStringWithoutPathExpansion(
105 flimflam::kOpenVPNRemoteCertKUProperty, &certKU)) {
106 scoped_ptr<base::ListValue> certKUs(new base::ListValue);
107 certKUs->AppendString(certKU);
108 onc_object_->SetWithoutPathExpansion(vpn::kRemoteCertKU, certKUs.release());
111 for (const OncFieldSignature* field_signature = onc_signature_->fields;
112 field_signature->onc_field_name != NULL; ++field_signature) {
113 const base::Value* shill_value;
114 if (field_signature->shill_property_name == NULL ||
115 !shill_dictionary_->GetWithoutPathExpansion(
116 field_signature->shill_property_name, &shill_value)) {
117 continue;
120 scoped_ptr<base::Value> translated;
121 std::string shill_str;
122 const std::string& onc_field_name = field_signature->onc_field_name;
123 if (onc_field_name == vpn::kSaveCredentials ||
124 onc_field_name == vpn::kRemoteCertKU) {
125 translated.reset(shill_value->DeepCopy());
126 } else if (shill_value->GetAsString(&shill_str)) {
127 // Shill wants all Provider/VPN fields to be strings. Translates these
128 // strings back to the correct ONC type.
129 translated = ConvertStringToValue(
130 shill_str,
131 field_signature->value_signature->onc_type);
133 if (translated.get() == NULL) {
134 LOG(ERROR) << "Shill property '" << field_signature->shill_property_name
135 << "' with value '" << shill_value
136 << "' couldn't be converted to base::Value::Type "
137 << field_signature->value_signature->onc_type;
139 } else {
140 LOG(ERROR) << "Shill property '" << field_signature->shill_property_name
141 << "' has value '" << shill_value
142 << "', but expected a string";
144 onc_object_->SetWithoutPathExpansion(onc_field_name, translated.release());
148 void ShillToONCTranslator::TranslateVPN() {
149 TranslateWithTableAndSet(flimflam::kProviderTypeProperty, kVPNTypeTable,
150 kType);
151 CopyPropertiesAccordingToSignature();
153 std::string vpn_type;
154 if (onc_object_->GetStringWithoutPathExpansion(kType, &vpn_type)) {
155 if (vpn_type == vpn::kTypeL2TP_IPsec) {
156 TranslateAndAddNestedObject(vpn::kIPsec);
157 TranslateAndAddNestedObject(vpn::kL2TP);
158 } else {
159 TranslateAndAddNestedObject(vpn_type);
164 void ShillToONCTranslator::TranslateAndAddNestedObject(
165 const std::string& onc_field_name) {
166 const OncFieldSignature* field_signature =
167 GetFieldSignature(*onc_signature_, onc_field_name);
168 ShillToONCTranslator nested_translator(*shill_dictionary_,
169 *field_signature->value_signature);
170 scoped_ptr<base::DictionaryValue> nested_object =
171 nested_translator.CreateTranslatedONCObject();
172 onc_object_->SetWithoutPathExpansion(onc_field_name, nested_object.release());
175 void ShillToONCTranslator::TranslateNetworkConfiguration() {
176 TranslateWithTableAndSet(flimflam::kTypeProperty, kNetworkTypeTable, kType);
177 CopyPropertiesAccordingToSignature();
179 std::string network_type;
180 if (onc_object_->GetStringWithoutPathExpansion(kType, &network_type))
181 TranslateAndAddNestedObject(network_type);
184 void ShillToONCTranslator::CopyPropertiesAccordingToSignature() {
185 for (const OncFieldSignature* field_signature = onc_signature_->fields;
186 field_signature->onc_field_name != NULL; ++field_signature) {
187 const base::Value* shill_value;
188 if (field_signature->shill_property_name == NULL ||
189 !shill_dictionary_->GetWithoutPathExpansion(
190 field_signature->shill_property_name, &shill_value)) {
191 continue;
193 onc_object_->SetWithoutPathExpansion(
194 field_signature->onc_field_name, shill_value->DeepCopy());
198 void ShillToONCTranslator::TranslateWithTableAndSet(
199 const std::string& shill_property_name,
200 const StringTranslationEntry table[],
201 const std::string& onc_field_name) {
202 std::string shill_value;
203 if (!shill_dictionary_->GetStringWithoutPathExpansion(shill_property_name,
204 &shill_value)) {
205 return;
208 for (int i = 0; table[i].onc_value != NULL; ++i) {
209 if (shill_value != table[i].shill_value)
210 continue;
211 onc_object_->SetStringWithoutPathExpansion(onc_field_name,
212 table[i].onc_value);
213 return;
215 LOG(ERROR) << "Shill property '" << shill_property_name << "' with value '"
216 << shill_value << "' couldn't be translated to ONC";
219 } // namespace
221 scoped_ptr<base::DictionaryValue> TranslateShillServiceToONCPart(
222 const base::DictionaryValue& shill_dictionary,
223 const OncValueSignature* onc_signature) {
224 CHECK(onc_signature != NULL);
226 ShillToONCTranslator translator(shill_dictionary, *onc_signature);
227 return translator.CreateTranslatedONCObject();
230 } // namespace onc
231 } // namespace chromeos