cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / chromeos / network / onc / onc_translator_shill_to_onc.cc
blob7782aa536eb00b358ce31b95bfc8261593c25a2c
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/network_state.h"
15 #include "chromeos/network/onc/onc_constants.h"
16 #include "chromeos/network/onc/onc_signature.h"
17 #include "chromeos/network/onc/onc_translation_tables.h"
18 #include "third_party/cros_system_api/dbus/service_constants.h"
20 namespace chromeos {
21 namespace onc {
23 namespace {
25 // Converts |str| to a base::Value of the given |type|. If the conversion fails,
26 // returns NULL.
27 scoped_ptr<base::Value> ConvertStringToValue(const std::string& str,
28 base::Value::Type type) {
29 base::Value* value;
30 if (type == base::Value::TYPE_STRING) {
31 value = base::Value::CreateStringValue(str);
32 } else {
33 value = base::JSONReader::Read(str);
36 if (value == NULL || value->GetType() != type) {
37 delete value;
38 value = NULL;
40 return make_scoped_ptr(value);
43 // This class implements the translation of properties from the given
44 // |shill_dictionary| to a new ONC object of signature |onc_signature|. Using
45 // recursive calls to CreateTranslatedONCObject of new instances, nested objects
46 // are translated.
47 class ShillToONCTranslator {
48 public:
49 ShillToONCTranslator(const base::DictionaryValue& shill_dictionary,
50 const OncValueSignature& onc_signature)
51 : shill_dictionary_(&shill_dictionary),
52 onc_signature_(&onc_signature) {
53 field_translation_table_ = GetFieldTranslationTable(onc_signature);
56 // Translates the associated Shill dictionary and creates an ONC object of the
57 // given signature.
58 scoped_ptr<base::DictionaryValue> CreateTranslatedONCObject();
60 private:
61 void TranslateOpenVPN();
62 void TranslateVPN();
63 void TranslateWiFiWithState();
64 void TranslateCellularWithState();
65 void TranslateNetworkWithState();
67 // Creates an ONC object from |dictionary| according to the signature
68 // associated to |onc_field_name| and adds it to |onc_object_| at
69 // |onc_field_name|.
70 void TranslateAndAddNestedObject(const std::string& onc_field_name,
71 const base::DictionaryValue& dictionary);
73 // Creates an ONC object from |shill_dictionary_| according to the signature
74 // associated to |onc_field_name| and adds it to |onc_object_| at
75 // |onc_field_name|.
76 void TranslateAndAddNestedObject(const std::string& onc_field_name);
78 // Applies function CopyProperty to each field of |value_signature| and its
79 // base signatures.
80 void CopyPropertiesAccordingToSignature(
81 const OncValueSignature* value_signature);
83 // Applies function CopyProperty to each field of |onc_signature_| and its
84 // base signatures.
85 void CopyPropertiesAccordingToSignature();
87 // If |shill_property_name| is defined in |field_signature|, copies this
88 // entry from |shill_dictionary_| to |onc_object_| if it exists.
89 void CopyProperty(const OncFieldSignature* field_signature);
91 // If existent, translates the entry at |shill_property_name| in
92 // |shill_dictionary_| using |table|. It is an error if no matching table
93 // entry is found. Writes the result as entry at |onc_field_name| in
94 // |onc_object_|.
95 void TranslateWithTableAndSet(const std::string& shill_property_name,
96 const StringTranslationEntry table[],
97 const std::string& onc_field_name);
99 const base::DictionaryValue* shill_dictionary_;
100 const OncValueSignature* onc_signature_;
101 const FieldTranslationEntry* field_translation_table_;
102 scoped_ptr<base::DictionaryValue> onc_object_;
104 DISALLOW_COPY_AND_ASSIGN(ShillToONCTranslator);
107 scoped_ptr<base::DictionaryValue>
108 ShillToONCTranslator::CreateTranslatedONCObject() {
109 onc_object_.reset(new base::DictionaryValue);
110 if (onc_signature_ == &kNetworkWithStateSignature) {
111 TranslateNetworkWithState();
112 } else if (onc_signature_ == &kVPNSignature) {
113 TranslateVPN();
114 } else if (onc_signature_ == &kOpenVPNSignature) {
115 TranslateOpenVPN();
116 } else if (onc_signature_ == &kWiFiWithStateSignature) {
117 TranslateWiFiWithState();
118 } else if (onc_signature_ == &kCellularWithStateSignature) {
119 TranslateCellularWithState();
120 } else {
121 CopyPropertiesAccordingToSignature();
123 return onc_object_.Pass();
126 void ShillToONCTranslator::TranslateOpenVPN() {
127 // Shill supports only one RemoteCertKU but ONC requires a list. If existing,
128 // wraps the value into a list.
129 std::string certKU;
130 if (shill_dictionary_->GetStringWithoutPathExpansion(
131 flimflam::kOpenVPNRemoteCertKUProperty, &certKU)) {
132 scoped_ptr<base::ListValue> certKUs(new base::ListValue);
133 certKUs->AppendString(certKU);
134 onc_object_->SetWithoutPathExpansion(openvpn::kRemoteCertKU,
135 certKUs.release());
138 for (const OncFieldSignature* field_signature = onc_signature_->fields;
139 field_signature->onc_field_name != NULL; ++field_signature) {
140 const std::string& onc_field_name = field_signature->onc_field_name;
141 if (onc_field_name == vpn::kSaveCredentials ||
142 onc_field_name == openvpn::kRemoteCertKU ||
143 onc_field_name == openvpn::kServerCAPEMs) {
144 CopyProperty(field_signature);
145 continue;
148 std::string shill_property_name;
149 const base::Value* shill_value = NULL;
150 if (!field_translation_table_ ||
151 !GetShillPropertyName(field_signature->onc_field_name,
152 field_translation_table_,
153 &shill_property_name) ||
154 !shill_dictionary_->GetWithoutPathExpansion(shill_property_name,
155 &shill_value)) {
156 continue;
159 scoped_ptr<base::Value> translated;
160 std::string shill_str;
161 if (shill_value->GetAsString(&shill_str)) {
162 // Shill wants all Provider/VPN fields to be strings. Translates these
163 // strings back to the correct ONC type.
164 translated = ConvertStringToValue(
165 shill_str,
166 field_signature->value_signature->onc_type);
168 if (translated.get() == NULL) {
169 LOG(ERROR) << "Shill property '" << shill_property_name
170 << "' with value " << *shill_value
171 << " couldn't be converted to base::Value::Type "
172 << field_signature->value_signature->onc_type;
173 } else {
174 onc_object_->SetWithoutPathExpansion(onc_field_name,
175 translated.release());
177 } else {
178 LOG(ERROR) << "Shill property '" << shill_property_name
179 << "' has value " << *shill_value
180 << ", but expected a string";
185 void ShillToONCTranslator::TranslateVPN() {
186 TranslateWithTableAndSet(flimflam::kProviderTypeProperty, kVPNTypeTable,
187 vpn::kType);
188 CopyPropertiesAccordingToSignature();
190 std::string vpn_type;
191 if (onc_object_->GetStringWithoutPathExpansion(vpn::kType,
192 &vpn_type)) {
193 if (vpn_type == vpn::kTypeL2TP_IPsec) {
194 TranslateAndAddNestedObject(vpn::kIPsec);
195 TranslateAndAddNestedObject(vpn::kL2TP);
196 } else {
197 TranslateAndAddNestedObject(vpn_type);
202 void ShillToONCTranslator::TranslateWiFiWithState() {
203 TranslateWithTableAndSet(flimflam::kSecurityProperty, kWiFiSecurityTable,
204 wifi::kSecurity);
205 CopyPropertiesAccordingToSignature();
208 void ShillToONCTranslator::TranslateCellularWithState() {
209 CopyPropertiesAccordingToSignature();
210 const base::DictionaryValue* serving_operator = NULL;
211 if (shill_dictionary_->GetDictionaryWithoutPathExpansion(
212 flimflam::kServingOperatorProperty, &serving_operator)) {
213 TranslateAndAddNestedObject(cellular::kServingOperator, *serving_operator);
217 void ShillToONCTranslator::TranslateNetworkWithState() {
218 TranslateWithTableAndSet(flimflam::kTypeProperty, kNetworkTypeTable,
219 network_config::kType);
220 CopyPropertiesAccordingToSignature();
222 std::string network_type;
223 if (onc_object_->GetStringWithoutPathExpansion(network_config::kType,
224 &network_type)) {
225 TranslateAndAddNestedObject(network_type);
228 // Since Name is a read only field in Shill unless it's a VPN, it is copied
229 // here, but not when going the other direction (if it's not a VPN).
230 std::string name;
231 shill_dictionary_->GetStringWithoutPathExpansion(flimflam::kNameProperty,
232 &name);
233 onc_object_->SetStringWithoutPathExpansion(network_config::kName, name);
235 std::string state;
236 if (shill_dictionary_->GetStringWithoutPathExpansion(flimflam::kStateProperty,
237 &state)) {
238 std::string onc_state = connection_state::kNotConnected;
239 if (NetworkState::StateIsConnected(state)) {
240 onc_state = connection_state::kConnected;
241 } else if (NetworkState::StateIsConnecting(state)) {
242 onc_state = connection_state::kConnecting;
244 onc_object_->SetStringWithoutPathExpansion(network_config::kConnectionState,
245 onc_state);
249 void ShillToONCTranslator::TranslateAndAddNestedObject(
250 const std::string& onc_field_name) {
251 TranslateAndAddNestedObject(onc_field_name, *shill_dictionary_);
254 void ShillToONCTranslator::TranslateAndAddNestedObject(
255 const std::string& onc_field_name,
256 const base::DictionaryValue& dictionary) {
257 const OncFieldSignature* field_signature =
258 GetFieldSignature(*onc_signature_, onc_field_name);
259 ShillToONCTranslator nested_translator(dictionary,
260 *field_signature->value_signature);
261 scoped_ptr<base::DictionaryValue> nested_object =
262 nested_translator.CreateTranslatedONCObject();
263 if (nested_object->empty())
264 return;
265 onc_object_->SetWithoutPathExpansion(onc_field_name, nested_object.release());
268 void ShillToONCTranslator::CopyPropertiesAccordingToSignature() {
269 CopyPropertiesAccordingToSignature(onc_signature_);
272 void ShillToONCTranslator::CopyPropertiesAccordingToSignature(
273 const OncValueSignature* value_signature) {
274 if (value_signature->base_signature)
275 CopyPropertiesAccordingToSignature(value_signature->base_signature);
276 for (const OncFieldSignature* field_signature = value_signature->fields;
277 field_signature->onc_field_name != NULL; ++field_signature) {
278 CopyProperty(field_signature);
282 void ShillToONCTranslator::CopyProperty(
283 const OncFieldSignature* field_signature) {
284 std::string shill_property_name;
285 const base::Value* shill_value = NULL;
286 if (!field_translation_table_ ||
287 !GetShillPropertyName(field_signature->onc_field_name,
288 field_translation_table_,
289 &shill_property_name) ||
290 !shill_dictionary_->GetWithoutPathExpansion(shill_property_name,
291 &shill_value)) {
292 return;
295 if (shill_value->GetType() != field_signature->value_signature->onc_type) {
296 LOG(ERROR) << "Shill property '" << shill_property_name
297 << "' with value " << *shill_value
298 << " has base::Value::Type " << shill_value->GetType()
299 << " but ONC field '" << field_signature->onc_field_name
300 << "' requires type "
301 << field_signature->value_signature->onc_type << ".";
302 return;
305 onc_object_->SetWithoutPathExpansion(field_signature->onc_field_name,
306 shill_value->DeepCopy());
309 void ShillToONCTranslator::TranslateWithTableAndSet(
310 const std::string& shill_property_name,
311 const StringTranslationEntry table[],
312 const std::string& onc_field_name) {
313 std::string shill_value;
314 if (!shill_dictionary_->GetStringWithoutPathExpansion(shill_property_name,
315 &shill_value)) {
316 return;
318 std::string onc_value;
319 if (TranslateStringToONC(table, shill_value, &onc_value)) {
320 onc_object_->SetStringWithoutPathExpansion(onc_field_name, onc_value);
321 return;
323 LOG(ERROR) << "Shill property '" << shill_property_name << "' with value "
324 << shill_value << " couldn't be translated to ONC";
327 } // namespace
329 scoped_ptr<base::DictionaryValue> TranslateShillServiceToONCPart(
330 const base::DictionaryValue& shill_dictionary,
331 const OncValueSignature* onc_signature) {
332 CHECK(onc_signature != NULL);
334 ShillToONCTranslator translator(shill_dictionary, *onc_signature);
335 return translator.CreateTranslatedONCObject();
338 } // namespace onc
339 } // namespace chromeos