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"
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/strings/string_util.h"
14 #include "base/values.h"
15 #include "chromeos/network/network_profile_handler.h"
16 #include "chromeos/network/network_state.h"
17 #include "chromeos/network/network_util.h"
18 #include "chromeos/network/onc/onc_signature.h"
19 #include "chromeos/network/onc/onc_translation_tables.h"
20 #include "chromeos/network/shill_property_util.h"
21 #include "components/onc/onc_constants.h"
22 #include "third_party/cros_system_api/dbus/service_constants.h"
29 // Converts |str| to a base::Value of the given |type|. If the conversion fails,
31 scoped_ptr<base::Value> ConvertStringToValue(const std::string& str,
32 base::Value::Type type) {
34 if (type == base::Value::TYPE_STRING) {
35 value = new base::StringValue(str);
37 value = base::JSONReader::Read(str);
40 if (value == NULL || value->GetType() != type) {
44 return make_scoped_ptr(value);
47 // This class implements the translation of properties from the given
48 // |shill_dictionary| to a new ONC object of signature |onc_signature|. Using
49 // recursive calls to CreateTranslatedONCObject of new instances, nested objects
51 class ShillToONCTranslator {
53 ShillToONCTranslator(const base::DictionaryValue& shill_dictionary,
54 ::onc::ONCSource onc_source,
55 const OncValueSignature& onc_signature)
56 : shill_dictionary_(&shill_dictionary),
57 onc_source_(onc_source),
58 onc_signature_(&onc_signature) {
59 field_translation_table_ = GetFieldTranslationTable(onc_signature);
62 ShillToONCTranslator(const base::DictionaryValue& shill_dictionary,
63 ::onc::ONCSource onc_source,
64 const OncValueSignature& onc_signature,
65 const FieldTranslationEntry* field_translation_table)
66 : shill_dictionary_(&shill_dictionary),
67 onc_source_(onc_source),
68 onc_signature_(&onc_signature),
69 field_translation_table_(field_translation_table) {
72 // Translates the associated Shill dictionary and creates an ONC object of the
74 scoped_ptr<base::DictionaryValue> CreateTranslatedONCObject();
77 void TranslateEthernet();
78 void TranslateOpenVPN();
79 void TranslateIPsec();
81 void TranslateWiFiWithState();
82 void TranslateWiMAXWithState();
83 void TranslateCellularWithState();
84 void TranslateCellularDevice();
85 void TranslateNetworkWithState();
86 void TranslateIPConfig();
87 void TranslateSavedOrStaticIPConfig(const std::string& nameserver_property);
88 void TranslateSavedIPConfig();
89 void TranslateStaticIPConfig();
91 // Creates an ONC object from |dictionary| according to the signature
92 // associated to |onc_field_name| and adds it to |onc_object_| at
94 void TranslateAndAddNestedObject(const std::string& onc_field_name,
95 const base::DictionaryValue& dictionary);
97 // Creates an ONC object from |shill_dictionary_| according to the signature
98 // associated to |onc_field_name| and adds it to |onc_object_| at
100 void TranslateAndAddNestedObject(const std::string& onc_field_name);
102 // Sets |onc_field_name| in dictionary |onc_dictionary_name| in |onc_object_|
103 // to |value| if the dictionary exists.
104 void SetNestedOncValue(const std::string& onc_dictionary_name,
105 const std::string& onc_field_name,
106 const base::Value& value);
108 // Translates a list of nested objects and adds the list to |onc_object_| at
109 // |onc_field_name|. If there are errors while parsing individual objects or
110 // if the resulting list contains no entries, the result will not be added to
112 void TranslateAndAddListOfObjects(const std::string& onc_field_name,
113 const base::ListValue& list);
115 // Applies function CopyProperty to each field of |value_signature| and its
117 void CopyPropertiesAccordingToSignature(
118 const OncValueSignature* value_signature);
120 // Applies function CopyProperty to each field of |onc_signature_| and its
122 void CopyPropertiesAccordingToSignature();
124 // If |shill_property_name| is defined in |field_signature|, copies this
125 // entry from |shill_dictionary_| to |onc_object_| if it exists.
126 void CopyProperty(const OncFieldSignature* field_signature);
128 // If existent, translates the entry at |shill_property_name| in
129 // |shill_dictionary_| using |table|. It is an error if no matching table
130 // entry is found. Writes the result as entry at |onc_field_name| in
132 void TranslateWithTableAndSet(const std::string& shill_property_name,
133 const StringTranslationEntry table[],
134 const std::string& onc_field_name);
136 // Returns the name of the Shill service provided in |shill_dictionary_|
138 std::string GetName();
140 const base::DictionaryValue* shill_dictionary_;
141 ::onc::ONCSource onc_source_;
142 const OncValueSignature* onc_signature_;
143 const FieldTranslationEntry* field_translation_table_;
144 scoped_ptr<base::DictionaryValue> onc_object_;
146 DISALLOW_COPY_AND_ASSIGN(ShillToONCTranslator);
149 scoped_ptr<base::DictionaryValue>
150 ShillToONCTranslator::CreateTranslatedONCObject() {
151 onc_object_.reset(new base::DictionaryValue);
152 if (onc_signature_ == &kNetworkWithStateSignature) {
153 TranslateNetworkWithState();
154 } else if (onc_signature_ == &kEthernetSignature) {
156 } else if (onc_signature_ == &kVPNSignature) {
158 } else if (onc_signature_ == &kOpenVPNSignature) {
160 } else if (onc_signature_ == &kIPsecSignature) {
162 } else if (onc_signature_ == &kWiFiWithStateSignature) {
163 TranslateWiFiWithState();
164 } else if (onc_signature_ == &kWiMAXWithStateSignature) {
165 TranslateWiMAXWithState();
166 } else if (onc_signature_ == &kCellularWithStateSignature) {
167 if (field_translation_table_ == kCellularDeviceTable)
168 TranslateCellularDevice();
170 TranslateCellularWithState();
171 } else if (onc_signature_ == &kIPConfigSignature) {
173 } else if (onc_signature_ == &kSavedIPConfigSignature) {
174 TranslateSavedIPConfig();
175 } else if (onc_signature_ == &kStaticIPConfigSignature) {
176 TranslateStaticIPConfig();
178 CopyPropertiesAccordingToSignature();
180 return onc_object_.Pass();
183 void ShillToONCTranslator::TranslateEthernet() {
184 std::string shill_network_type;
185 shill_dictionary_->GetStringWithoutPathExpansion(shill::kTypeProperty,
186 &shill_network_type);
187 const char* onc_auth = ::onc::ethernet::kAuthenticationNone;
188 if (shill_network_type == shill::kTypeEthernetEap)
189 onc_auth = ::onc::ethernet::k8021X;
190 onc_object_->SetStringWithoutPathExpansion(::onc::ethernet::kAuthentication,
194 void ShillToONCTranslator::TranslateOpenVPN() {
195 if (shill_dictionary_->HasKey(shill::kOpenVPNVerifyX509NameProperty))
196 TranslateAndAddNestedObject(::onc::openvpn::kVerifyX509);
198 // Shill supports only one RemoteCertKU but ONC requires a list. If existing,
199 // wraps the value into a list.
201 if (shill_dictionary_->GetStringWithoutPathExpansion(
202 shill::kOpenVPNRemoteCertKUProperty, &certKU)) {
203 scoped_ptr<base::ListValue> certKUs(new base::ListValue);
204 certKUs->AppendString(certKU);
205 onc_object_->SetWithoutPathExpansion(::onc::openvpn::kRemoteCertKU,
209 for (const OncFieldSignature* field_signature = onc_signature_->fields;
210 field_signature->onc_field_name != NULL; ++field_signature) {
211 const std::string& onc_field_name = field_signature->onc_field_name;
212 if (onc_field_name == ::onc::openvpn::kRemoteCertKU ||
213 onc_field_name == ::onc::openvpn::kServerCAPEMs) {
214 CopyProperty(field_signature);
218 std::string shill_property_name;
219 const base::Value* shill_value = NULL;
220 if (!field_translation_table_ ||
221 !GetShillPropertyName(field_signature->onc_field_name,
222 field_translation_table_,
223 &shill_property_name) ||
224 !shill_dictionary_->GetWithoutPathExpansion(shill_property_name,
229 scoped_ptr<base::Value> translated;
230 std::string shill_str;
231 if (shill_value->GetAsString(&shill_str)) {
232 // Shill wants all Provider/VPN fields to be strings. Translates these
233 // strings back to the correct ONC type.
234 translated = ConvertStringToValue(
236 field_signature->value_signature->onc_type);
238 if (translated.get() == NULL) {
239 LOG(ERROR) << "Shill property '" << shill_property_name
240 << "' with value " << *shill_value
241 << " couldn't be converted to base::Value::Type "
242 << field_signature->value_signature->onc_type
243 << ": " << GetName();
245 onc_object_->SetWithoutPathExpansion(onc_field_name,
246 translated.release());
249 LOG(ERROR) << "Shill property '" << shill_property_name
250 << "' has value " << *shill_value
251 << ", but expected a string: " << GetName();
256 void ShillToONCTranslator::TranslateIPsec() {
257 CopyPropertiesAccordingToSignature();
258 if (shill_dictionary_->HasKey(shill::kL2tpIpsecXauthUserProperty))
259 TranslateAndAddNestedObject(::onc::ipsec::kXAUTH);
260 std::string client_cert_id;
261 shill_dictionary_->GetStringWithoutPathExpansion(
262 shill::kL2tpIpsecClientCertIdProperty, &client_cert_id);
263 std::string authentication_type =
264 client_cert_id.empty() ? ::onc::ipsec::kPSK : ::onc::ipsec::kCert;
265 onc_object_->SetStringWithoutPathExpansion(::onc::ipsec::kAuthenticationType,
266 authentication_type);
269 void ShillToONCTranslator::TranslateVPN() {
270 CopyPropertiesAccordingToSignature();
272 // Parse Shill Provider dictionary. Note, this may not exist, e.g. if we are
273 // just translating network state in network_util::TranslateNetworkStateToONC.
274 const base::DictionaryValue* provider = NULL;
275 if (!shill_dictionary_->GetDictionaryWithoutPathExpansion(
276 shill::kProviderProperty, &provider)) {
279 std::string shill_provider_type, onc_provider_type;
280 provider->GetStringWithoutPathExpansion(shill::kTypeProperty,
281 &shill_provider_type);
282 if (!TranslateStringToONC(
283 kVPNTypeTable, shill_provider_type, &onc_provider_type)) {
286 onc_object_->SetStringWithoutPathExpansion(::onc::vpn::kType,
288 std::string provider_host;
289 if (provider->GetStringWithoutPathExpansion(shill::kHostProperty,
291 onc_object_->SetStringWithoutPathExpansion(::onc::vpn::kHost,
295 // Translate the nested dictionary.
296 std::string provider_type_dictionary;
297 if (onc_provider_type == ::onc::vpn::kTypeL2TP_IPsec) {
298 TranslateAndAddNestedObject(::onc::vpn::kIPsec, *provider);
299 TranslateAndAddNestedObject(::onc::vpn::kL2TP, *provider);
300 provider_type_dictionary = ::onc::vpn::kIPsec;
302 TranslateAndAddNestedObject(onc_provider_type, *provider);
303 provider_type_dictionary = onc_provider_type;
306 bool save_credentials;
307 if (shill_dictionary_->GetBooleanWithoutPathExpansion(
308 shill::kSaveCredentialsProperty, &save_credentials)) {
309 SetNestedOncValue(provider_type_dictionary,
310 ::onc::vpn::kSaveCredentials,
311 base::FundamentalValue(save_credentials));
315 void ShillToONCTranslator::TranslateWiFiWithState() {
316 TranslateWithTableAndSet(
317 shill::kSecurityProperty, kWiFiSecurityTable, ::onc::wifi::kSecurity);
318 std::string ssid = shill_property_util::GetSSIDFromProperties(
319 *shill_dictionary_, NULL /* ignore unknown encoding */);
321 onc_object_->SetStringWithoutPathExpansion(::onc::wifi::kSSID, ssid);
323 bool link_monitor_disable;
324 if (shill_dictionary_->GetBooleanWithoutPathExpansion(
325 shill::kLinkMonitorDisableProperty, &link_monitor_disable)) {
326 onc_object_->SetBooleanWithoutPathExpansion(
327 ::onc::wifi::kAllowGatewayARPPolling, !link_monitor_disable);
330 CopyPropertiesAccordingToSignature();
331 TranslateAndAddNestedObject(::onc::wifi::kEAP);
334 void ShillToONCTranslator::TranslateWiMAXWithState() {
335 CopyPropertiesAccordingToSignature();
336 TranslateAndAddNestedObject(::onc::wimax::kEAP);
339 void ShillToONCTranslator::TranslateCellularWithState() {
340 CopyPropertiesAccordingToSignature();
341 TranslateWithTableAndSet(shill::kActivationStateProperty,
342 kActivationStateTable,
343 ::onc::cellular::kActivationState);
344 TranslateWithTableAndSet(shill::kRoamingStateProperty,
346 ::onc::cellular::kRoamingState);
347 const base::DictionaryValue* dictionary = NULL;
348 if (shill_dictionary_->GetDictionaryWithoutPathExpansion(
349 shill::kServingOperatorProperty, &dictionary)) {
350 TranslateAndAddNestedObject(::onc::cellular::kServingOperator, *dictionary);
352 if (shill_dictionary_->GetDictionaryWithoutPathExpansion(
353 shill::kCellularApnProperty, &dictionary)) {
354 TranslateAndAddNestedObject(::onc::cellular::kAPN, *dictionary);
356 if (shill_dictionary_->GetDictionaryWithoutPathExpansion(
357 shill::kCellularLastGoodApnProperty, &dictionary)) {
358 TranslateAndAddNestedObject(::onc::cellular::kLastGoodAPN, *dictionary);
360 // Merge the Device dictionary with this one (Cellular) using the
361 // CellularDevice signature.
362 const base::DictionaryValue* device_dictionary = NULL;
363 if (!shill_dictionary_->GetDictionaryWithoutPathExpansion(
364 shill::kDeviceProperty, &device_dictionary)) {
367 ShillToONCTranslator nested_translator(*device_dictionary,
369 kCellularWithStateSignature,
370 kCellularDeviceTable);
371 scoped_ptr<base::DictionaryValue> nested_object =
372 nested_translator.CreateTranslatedONCObject();
373 onc_object_->MergeDictionary(nested_object.get());
376 void ShillToONCTranslator::TranslateCellularDevice() {
377 CopyPropertiesAccordingToSignature();
378 const base::DictionaryValue* shill_sim_lock_status = NULL;
379 if (shill_dictionary_->GetDictionaryWithoutPathExpansion(
380 shill::kSIMLockStatusProperty, &shill_sim_lock_status)) {
381 TranslateAndAddNestedObject(::onc::cellular::kSIMLockStatus,
382 *shill_sim_lock_status);
384 const base::ListValue* shill_apns = NULL;
385 if (shill_dictionary_->GetListWithoutPathExpansion(
386 shill::kCellularApnListProperty, &shill_apns)) {
387 TranslateAndAddListOfObjects(::onc::cellular::kAPNList, *shill_apns);
389 const base::ListValue* shill_found_networks = NULL;
390 if (shill_dictionary_->GetListWithoutPathExpansion(
391 shill::kFoundNetworksProperty, &shill_found_networks)) {
392 TranslateAndAddListOfObjects(::onc::cellular::kFoundNetworks,
393 *shill_found_networks);
397 void ShillToONCTranslator::TranslateNetworkWithState() {
398 CopyPropertiesAccordingToSignature();
400 std::string shill_network_type;
401 shill_dictionary_->GetStringWithoutPathExpansion(shill::kTypeProperty,
402 &shill_network_type);
403 std::string onc_network_type = ::onc::network_type::kEthernet;
404 if (shill_network_type != shill::kTypeEthernet &&
405 shill_network_type != shill::kTypeEthernetEap) {
406 TranslateStringToONC(
407 kNetworkTypeTable, shill_network_type, &onc_network_type);
409 // Translate nested Cellular, WiFi, etc. properties.
410 if (!onc_network_type.empty()) {
411 onc_object_->SetStringWithoutPathExpansion(::onc::network_config::kType,
413 TranslateAndAddNestedObject(onc_network_type);
416 // Since Name is a read only field in Shill unless it's a VPN, it is copied
417 // here, but not when going the other direction (if it's not a VPN).
419 shill_dictionary_->GetStringWithoutPathExpansion(shill::kNameProperty, &name);
420 onc_object_->SetStringWithoutPathExpansion(::onc::network_config::kName,
423 // Limit ONC state to "NotConnected", "Connected", or "Connecting".
425 if (shill_dictionary_->GetStringWithoutPathExpansion(shill::kStateProperty,
427 std::string onc_state = ::onc::connection_state::kNotConnected;
428 if (NetworkState::StateIsConnected(state)) {
429 onc_state = ::onc::connection_state::kConnected;
430 } else if (NetworkState::StateIsConnecting(state)) {
431 onc_state = ::onc::connection_state::kConnecting;
433 onc_object_->SetStringWithoutPathExpansion(
434 ::onc::network_config::kConnectionState, onc_state);
435 // Only set 'RestrictedConnectivity' if true.
436 if (state == shill::kStatePortal) {
437 onc_object_->SetBooleanWithoutPathExpansion(
438 ::onc::network_config::kRestrictedConnectivity, true);
442 std::string profile_path;
443 if (onc_source_ != ::onc::ONC_SOURCE_UNKNOWN &&
444 shill_dictionary_->GetStringWithoutPathExpansion(shill::kProfileProperty,
447 if (onc_source_ == ::onc::ONC_SOURCE_DEVICE_POLICY)
448 source = ::onc::network_config::kSourceDevicePolicy;
449 else if (onc_source_ == ::onc::ONC_SOURCE_USER_POLICY)
450 source = ::onc::network_config::kSourceUserPolicy;
451 else if (profile_path == NetworkProfileHandler::GetSharedProfilePath())
452 source = ::onc::network_config::kSourceDevice;
453 else if (!profile_path.empty())
454 source = ::onc::network_config::kSourceUser;
456 source = ::onc::network_config::kSourceNone;
457 onc_object_->SetStringWithoutPathExpansion(
458 ::onc::network_config::kSource, source);
461 // Use a human-readable aa:bb format for any hardware MAC address. Note:
462 // this property is provided by the caller but is not part of the Shill
463 // Service properties (it is copied from the Device properties).
465 if (shill_dictionary_->GetStringWithoutPathExpansion(shill::kAddressProperty,
467 onc_object_->SetStringWithoutPathExpansion(
468 ::onc::network_config::kMacAddress,
469 network_util::FormattedMacAddress(address));
472 // Shill's Service has an IPConfig property (note the singular), not an
473 // IPConfigs property. However, we require the caller of the translation to
474 // patch the Shill dictionary before passing it to the translator.
475 const base::ListValue* shill_ipconfigs = NULL;
476 if (shill_dictionary_->GetListWithoutPathExpansion(shill::kIPConfigsProperty,
478 TranslateAndAddListOfObjects(::onc::network_config::kIPConfigs,
482 TranslateAndAddNestedObject(::onc::network_config::kSavedIPConfig);
483 TranslateAndAddNestedObject(::onc::network_config::kStaticIPConfig);
486 void ShillToONCTranslator::TranslateIPConfig() {
487 CopyPropertiesAccordingToSignature();
488 std::string shill_ip_method;
489 shill_dictionary_->GetStringWithoutPathExpansion(shill::kMethodProperty,
492 if (shill_ip_method == shill::kTypeIPv4 ||
493 shill_ip_method == shill::kTypeDHCP) {
494 type = ::onc::ipconfig::kIPv4;
495 } else if (shill_ip_method == shill::kTypeIPv6 ||
496 shill_ip_method == shill::kTypeDHCP6) {
497 type = ::onc::ipconfig::kIPv6;
499 return; // Ignore unhandled IPConfig types, e.g. bootp, zeroconf, ppp
502 onc_object_->SetStringWithoutPathExpansion(::onc::ipconfig::kType, type);
505 void ShillToONCTranslator::TranslateSavedOrStaticIPConfig(
506 const std::string& nameserver_property) {
507 CopyPropertiesAccordingToSignature();
508 // Saved/Static IP config nameservers are stored as a comma separated list.
509 std::string shill_nameservers;
510 shill_dictionary_->GetStringWithoutPathExpansion(
511 nameserver_property, &shill_nameservers);
512 std::vector<std::string> onc_nameserver_vector;
513 if (Tokenize(shill_nameservers, ",", &onc_nameserver_vector) > 0) {
514 scoped_ptr<base::ListValue> onc_nameservers(new base::ListValue);
515 for (std::vector<std::string>::iterator iter =
516 onc_nameserver_vector.begin();
517 iter != onc_nameserver_vector.end(); ++iter) {
518 onc_nameservers->AppendString(*iter);
520 onc_object_->SetWithoutPathExpansion(::onc::ipconfig::kNameServers,
521 onc_nameservers.release());
523 // Static and Saved IPConfig in Shill are always of type IPv4. Set this type
524 // in ONC, but not if the object would be empty except the type.
525 if (!onc_object_->empty()) {
526 onc_object_->SetStringWithoutPathExpansion(::onc::ipconfig::kType,
527 ::onc::ipconfig::kIPv4);
531 void ShillToONCTranslator::TranslateSavedIPConfig() {
532 TranslateSavedOrStaticIPConfig(shill::kSavedIPNameServersProperty);
535 void ShillToONCTranslator::TranslateStaticIPConfig() {
536 TranslateSavedOrStaticIPConfig(shill::kStaticIPNameServersProperty);
539 void ShillToONCTranslator::TranslateAndAddNestedObject(
540 const std::string& onc_field_name) {
541 TranslateAndAddNestedObject(onc_field_name, *shill_dictionary_);
544 void ShillToONCTranslator::TranslateAndAddNestedObject(
545 const std::string& onc_field_name,
546 const base::DictionaryValue& dictionary) {
547 const OncFieldSignature* field_signature =
548 GetFieldSignature(*onc_signature_, onc_field_name);
549 if (!field_signature) {
550 NOTREACHED() << "Unable to find signature for field: " << onc_field_name;
553 ShillToONCTranslator nested_translator(
554 dictionary, onc_source_, *field_signature->value_signature);
555 scoped_ptr<base::DictionaryValue> nested_object =
556 nested_translator.CreateTranslatedONCObject();
557 if (nested_object->empty())
559 onc_object_->SetWithoutPathExpansion(onc_field_name, nested_object.release());
562 void ShillToONCTranslator::SetNestedOncValue(
563 const std::string& onc_dictionary_name,
564 const std::string& onc_field_name,
565 const base::Value& value) {
566 base::DictionaryValue* nested;
567 if (!onc_object_->GetDictionaryWithoutPathExpansion(
568 onc_dictionary_name, &nested)) {
569 nested = new base::DictionaryValue;
570 onc_object_->SetWithoutPathExpansion(onc_dictionary_name, nested);
572 nested->SetWithoutPathExpansion(onc_field_name, value.DeepCopy());
575 void ShillToONCTranslator::TranslateAndAddListOfObjects(
576 const std::string& onc_field_name,
577 const base::ListValue& list) {
578 const OncFieldSignature* field_signature =
579 GetFieldSignature(*onc_signature_, onc_field_name);
580 if (field_signature->value_signature->onc_type != base::Value::TYPE_LIST) {
581 LOG(ERROR) << "ONC Field name: '" << onc_field_name << "' has type '"
582 << field_signature->value_signature->onc_type
583 << "', expected: base::Value::TYPE_LIST: " << GetName();
586 DCHECK(field_signature->value_signature->onc_array_entry_signature);
587 scoped_ptr<base::ListValue> result(new base::ListValue());
588 for (base::ListValue::const_iterator it = list.begin();
589 it != list.end(); ++it) {
590 const base::DictionaryValue* shill_value = NULL;
591 if (!(*it)->GetAsDictionary(&shill_value))
593 ShillToONCTranslator nested_translator(
596 *field_signature->value_signature->onc_array_entry_signature);
597 scoped_ptr<base::DictionaryValue> nested_object =
598 nested_translator.CreateTranslatedONCObject();
599 // If the nested object couldn't be parsed, simply omit it.
600 if (nested_object->empty())
602 result->Append(nested_object.release());
604 // If there are no entries in the list, there is no need to expose this field.
607 onc_object_->SetWithoutPathExpansion(onc_field_name, result.release());
610 void ShillToONCTranslator::CopyPropertiesAccordingToSignature() {
611 CopyPropertiesAccordingToSignature(onc_signature_);
614 void ShillToONCTranslator::CopyPropertiesAccordingToSignature(
615 const OncValueSignature* value_signature) {
616 if (value_signature->base_signature)
617 CopyPropertiesAccordingToSignature(value_signature->base_signature);
618 if (!value_signature->fields)
620 for (const OncFieldSignature* field_signature = value_signature->fields;
621 field_signature->onc_field_name != NULL; ++field_signature) {
622 CopyProperty(field_signature);
626 void ShillToONCTranslator::CopyProperty(
627 const OncFieldSignature* field_signature) {
628 std::string shill_property_name;
629 const base::Value* shill_value = NULL;
630 if (!field_translation_table_ ||
631 !GetShillPropertyName(field_signature->onc_field_name,
632 field_translation_table_,
633 &shill_property_name) ||
634 !shill_dictionary_->GetWithoutPathExpansion(shill_property_name,
639 if (shill_value->GetType() != field_signature->value_signature->onc_type) {
640 LOG(ERROR) << "Shill property '" << shill_property_name
641 << "' with value " << *shill_value
642 << " has base::Value::Type " << shill_value->GetType()
643 << " but ONC field '" << field_signature->onc_field_name
644 << "' requires type "
645 << field_signature->value_signature->onc_type
646 << ": " << GetName();
650 onc_object_->SetWithoutPathExpansion(field_signature->onc_field_name,
651 shill_value->DeepCopy());
654 void ShillToONCTranslator::TranslateWithTableAndSet(
655 const std::string& shill_property_name,
656 const StringTranslationEntry table[],
657 const std::string& onc_field_name) {
658 std::string shill_value;
659 if (!shill_dictionary_->GetStringWithoutPathExpansion(shill_property_name,
663 std::string onc_value;
664 if (TranslateStringToONC(table, shill_value, &onc_value)) {
665 onc_object_->SetStringWithoutPathExpansion(onc_field_name, onc_value);
668 LOG(ERROR) << "Shill property '" << shill_property_name << "' with value "
669 << shill_value << " couldn't be translated to ONC: " << GetName();
672 std::string ShillToONCTranslator::GetName() {
673 DCHECK(shill_dictionary_);
675 shill_dictionary_->GetStringWithoutPathExpansion(shill::kNameProperty, &name);
681 scoped_ptr<base::DictionaryValue> TranslateShillServiceToONCPart(
682 const base::DictionaryValue& shill_dictionary,
683 ::onc::ONCSource onc_source,
684 const OncValueSignature* onc_signature) {
685 CHECK(onc_signature != NULL);
687 ShillToONCTranslator translator(shill_dictionary, onc_source, *onc_signature);
688 return translator.CreateTranslatedONCObject();
692 } // namespace chromeos