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 TranslateCellularWithState();
83 void TranslateCellularDevice();
84 void TranslateNetworkWithState();
85 void TranslateIPConfig();
86 void TranslateSavedOrStaticIPConfig(const std::string
& nameserver_property
);
87 void TranslateSavedIPConfig();
88 void TranslateStaticIPConfig();
90 // Creates an ONC object from |dictionary| according to the signature
91 // associated to |onc_field_name| and adds it to |onc_object_| at
93 void TranslateAndAddNestedObject(const std::string
& onc_field_name
,
94 const base::DictionaryValue
& dictionary
);
96 // Creates an ONC object from |shill_dictionary_| according to the signature
97 // associated to |onc_field_name| and adds it to |onc_object_| at
99 void TranslateAndAddNestedObject(const std::string
& onc_field_name
);
101 // Sets |onc_field_name| in dictionary |onc_dictionary_name| in |onc_object_|
102 // to |value| if the dictionary exists.
103 void SetNestedOncValue(const std::string
& onc_dictionary_name
,
104 const std::string
& onc_field_name
,
105 const base::Value
& value
);
107 // Translates a list of nested objects and adds the list to |onc_object_| at
108 // |onc_field_name|. If there are errors while parsing individual objects or
109 // if the resulting list contains no entries, the result will not be added to
111 void TranslateAndAddListOfObjects(const std::string
& onc_field_name
,
112 const base::ListValue
& list
);
114 // Applies function CopyProperty to each field of |value_signature| and its
116 void CopyPropertiesAccordingToSignature(
117 const OncValueSignature
* value_signature
);
119 // Applies function CopyProperty to each field of |onc_signature_| and its
121 void CopyPropertiesAccordingToSignature();
123 // If |shill_property_name| is defined in |field_signature|, copies this
124 // entry from |shill_dictionary_| to |onc_object_| if it exists.
125 void CopyProperty(const OncFieldSignature
* field_signature
);
127 // If existent, translates the entry at |shill_property_name| in
128 // |shill_dictionary_| using |table|. It is an error if no matching table
129 // entry is found. Writes the result as entry at |onc_field_name| in
131 void TranslateWithTableAndSet(const std::string
& shill_property_name
,
132 const StringTranslationEntry table
[],
133 const std::string
& onc_field_name
);
135 // Returns the name of the Shill service provided in |shill_dictionary_|
137 std::string
GetName();
139 const base::DictionaryValue
* shill_dictionary_
;
140 ::onc::ONCSource onc_source_
;
141 const OncValueSignature
* onc_signature_
;
142 const FieldTranslationEntry
* field_translation_table_
;
143 scoped_ptr
<base::DictionaryValue
> onc_object_
;
145 DISALLOW_COPY_AND_ASSIGN(ShillToONCTranslator
);
148 scoped_ptr
<base::DictionaryValue
>
149 ShillToONCTranslator::CreateTranslatedONCObject() {
150 onc_object_
.reset(new base::DictionaryValue
);
151 if (onc_signature_
== &kNetworkWithStateSignature
) {
152 TranslateNetworkWithState();
153 } else if (onc_signature_
== &kEthernetSignature
) {
155 } else if (onc_signature_
== &kVPNSignature
) {
157 } else if (onc_signature_
== &kOpenVPNSignature
) {
159 } else if (onc_signature_
== &kIPsecSignature
) {
161 } else if (onc_signature_
== &kWiFiWithStateSignature
) {
162 TranslateWiFiWithState();
163 } else if (onc_signature_
== &kCellularWithStateSignature
) {
164 if (field_translation_table_
== kCellularDeviceTable
)
165 TranslateCellularDevice();
167 TranslateCellularWithState();
168 } else if (onc_signature_
== &kIPConfigSignature
) {
170 } else if (onc_signature_
== &kSavedIPConfigSignature
) {
171 TranslateSavedIPConfig();
172 } else if (onc_signature_
== &kStaticIPConfigSignature
) {
173 TranslateStaticIPConfig();
175 CopyPropertiesAccordingToSignature();
177 return onc_object_
.Pass();
180 void ShillToONCTranslator::TranslateEthernet() {
181 std::string shill_network_type
;
182 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kTypeProperty
,
183 &shill_network_type
);
184 const char* onc_auth
= ::onc::ethernet::kAuthenticationNone
;
185 if (shill_network_type
== shill::kTypeEthernetEap
)
186 onc_auth
= ::onc::ethernet::k8021X
;
187 onc_object_
->SetStringWithoutPathExpansion(::onc::ethernet::kAuthentication
,
191 void ShillToONCTranslator::TranslateOpenVPN() {
192 if (shill_dictionary_
->HasKey(shill::kOpenVPNVerifyX509NameProperty
))
193 TranslateAndAddNestedObject(::onc::openvpn::kVerifyX509
);
195 // Shill supports only one RemoteCertKU but ONC requires a list. If existing,
196 // wraps the value into a list.
198 if (shill_dictionary_
->GetStringWithoutPathExpansion(
199 shill::kOpenVPNRemoteCertKUProperty
, &certKU
)) {
200 scoped_ptr
<base::ListValue
> certKUs(new base::ListValue
);
201 certKUs
->AppendString(certKU
);
202 onc_object_
->SetWithoutPathExpansion(::onc::openvpn::kRemoteCertKU
,
206 for (const OncFieldSignature
* field_signature
= onc_signature_
->fields
;
207 field_signature
->onc_field_name
!= NULL
; ++field_signature
) {
208 const std::string
& onc_field_name
= field_signature
->onc_field_name
;
209 if (onc_field_name
== ::onc::openvpn::kRemoteCertKU
||
210 onc_field_name
== ::onc::openvpn::kServerCAPEMs
) {
211 CopyProperty(field_signature
);
215 std::string shill_property_name
;
216 const base::Value
* shill_value
= NULL
;
217 if (!field_translation_table_
||
218 !GetShillPropertyName(field_signature
->onc_field_name
,
219 field_translation_table_
,
220 &shill_property_name
) ||
221 !shill_dictionary_
->GetWithoutPathExpansion(shill_property_name
,
226 scoped_ptr
<base::Value
> translated
;
227 std::string shill_str
;
228 if (shill_value
->GetAsString(&shill_str
)) {
229 // Shill wants all Provider/VPN fields to be strings. Translates these
230 // strings back to the correct ONC type.
231 translated
= ConvertStringToValue(
233 field_signature
->value_signature
->onc_type
);
235 if (translated
.get() == NULL
) {
236 LOG(ERROR
) << "Shill property '" << shill_property_name
237 << "' with value " << *shill_value
238 << " couldn't be converted to base::Value::Type "
239 << field_signature
->value_signature
->onc_type
240 << ": " << GetName();
242 onc_object_
->SetWithoutPathExpansion(onc_field_name
,
243 translated
.release());
246 LOG(ERROR
) << "Shill property '" << shill_property_name
247 << "' has value " << *shill_value
248 << ", but expected a string: " << GetName();
253 void ShillToONCTranslator::TranslateIPsec() {
254 CopyPropertiesAccordingToSignature();
255 if (shill_dictionary_
->HasKey(shill::kL2tpIpsecXauthUserProperty
))
256 TranslateAndAddNestedObject(::onc::ipsec::kXAUTH
);
257 std::string client_cert_id
;
258 shill_dictionary_
->GetStringWithoutPathExpansion(
259 shill::kL2tpIpsecClientCertIdProperty
, &client_cert_id
);
260 std::string authentication_type
=
261 client_cert_id
.empty() ? ::onc::ipsec::kPSK
: ::onc::ipsec::kCert
;
262 onc_object_
->SetStringWithoutPathExpansion(::onc::ipsec::kAuthenticationType
,
263 authentication_type
);
266 void ShillToONCTranslator::TranslateVPN() {
267 CopyPropertiesAccordingToSignature();
269 // Parse Shill Provider dictionary. Note, this may not exist, e.g. if we are
270 // just translating network state in network_util::TranslateNetworkStateToONC.
271 const base::DictionaryValue
* provider
= NULL
;
272 if (!shill_dictionary_
->GetDictionaryWithoutPathExpansion(
273 shill::kProviderProperty
, &provider
)) {
276 std::string shill_provider_type
, onc_provider_type
;
277 provider
->GetStringWithoutPathExpansion(shill::kTypeProperty
,
278 &shill_provider_type
);
279 if (!TranslateStringToONC(
280 kVPNTypeTable
, shill_provider_type
, &onc_provider_type
)) {
283 onc_object_
->SetStringWithoutPathExpansion(::onc::vpn::kType
,
285 std::string provider_host
;
286 if (provider
->GetStringWithoutPathExpansion(shill::kHostProperty
,
288 onc_object_
->SetStringWithoutPathExpansion(::onc::vpn::kHost
,
292 // Translate the nested dictionary.
293 std::string provider_type_dictionary
;
294 if (onc_provider_type
== ::onc::vpn::kTypeL2TP_IPsec
) {
295 TranslateAndAddNestedObject(::onc::vpn::kIPsec
, *provider
);
296 TranslateAndAddNestedObject(::onc::vpn::kL2TP
, *provider
);
297 provider_type_dictionary
= ::onc::vpn::kIPsec
;
299 TranslateAndAddNestedObject(onc_provider_type
, *provider
);
300 provider_type_dictionary
= onc_provider_type
;
303 bool save_credentials
;
304 if (shill_dictionary_
->GetBooleanWithoutPathExpansion(
305 shill::kSaveCredentialsProperty
, &save_credentials
)) {
306 SetNestedOncValue(provider_type_dictionary
,
307 ::onc::vpn::kSaveCredentials
,
308 base::FundamentalValue(save_credentials
));
312 void ShillToONCTranslator::TranslateWiFiWithState() {
313 TranslateWithTableAndSet(
314 shill::kSecurityProperty
, kWiFiSecurityTable
, ::onc::wifi::kSecurity
);
315 std::string ssid
= shill_property_util::GetSSIDFromProperties(
316 *shill_dictionary_
, NULL
/* ignore unknown encoding */);
318 onc_object_
->SetStringWithoutPathExpansion(::onc::wifi::kSSID
, ssid
);
319 CopyPropertiesAccordingToSignature();
322 void ShillToONCTranslator::TranslateCellularWithState() {
323 CopyPropertiesAccordingToSignature();
324 TranslateWithTableAndSet(shill::kActivationStateProperty
,
325 kActivationStateTable
,
326 ::onc::cellular::kActivationState
);
327 TranslateWithTableAndSet(shill::kRoamingStateProperty
,
329 ::onc::cellular::kRoamingState
);
330 const base::DictionaryValue
* dictionary
= NULL
;
331 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
332 shill::kServingOperatorProperty
, &dictionary
)) {
333 TranslateAndAddNestedObject(::onc::cellular::kServingOperator
, *dictionary
);
335 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
336 shill::kCellularApnProperty
, &dictionary
)) {
337 TranslateAndAddNestedObject(::onc::cellular::kAPN
, *dictionary
);
339 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
340 shill::kCellularLastGoodApnProperty
, &dictionary
)) {
341 TranslateAndAddNestedObject(::onc::cellular::kLastGoodAPN
, *dictionary
);
343 // Merge the Device dictionary with this one (Cellular) using the
344 // CellularDevice signature.
345 const base::DictionaryValue
* device_dictionary
= NULL
;
346 if (!shill_dictionary_
->GetDictionaryWithoutPathExpansion(
347 shill::kDeviceProperty
, &device_dictionary
)) {
350 ShillToONCTranslator
nested_translator(*device_dictionary
,
352 kCellularWithStateSignature
,
353 kCellularDeviceTable
);
354 scoped_ptr
<base::DictionaryValue
> nested_object
=
355 nested_translator
.CreateTranslatedONCObject();
356 onc_object_
->MergeDictionary(nested_object
.get());
359 void ShillToONCTranslator::TranslateCellularDevice() {
360 CopyPropertiesAccordingToSignature();
361 const base::DictionaryValue
* shill_sim_lock_status
= NULL
;
362 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
363 shill::kSIMLockStatusProperty
, &shill_sim_lock_status
)) {
364 TranslateAndAddNestedObject(::onc::cellular::kSIMLockStatus
,
365 *shill_sim_lock_status
);
367 const base::ListValue
* shill_apns
= NULL
;
368 if (shill_dictionary_
->GetListWithoutPathExpansion(
369 shill::kCellularApnListProperty
, &shill_apns
)) {
370 TranslateAndAddListOfObjects(::onc::cellular::kAPNList
, *shill_apns
);
372 const base::ListValue
* shill_found_networks
= NULL
;
373 if (shill_dictionary_
->GetListWithoutPathExpansion(
374 shill::kFoundNetworksProperty
, &shill_found_networks
)) {
375 TranslateAndAddListOfObjects(::onc::cellular::kFoundNetworks
,
376 *shill_found_networks
);
380 void ShillToONCTranslator::TranslateNetworkWithState() {
381 CopyPropertiesAccordingToSignature();
383 std::string shill_network_type
;
384 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kTypeProperty
,
385 &shill_network_type
);
386 std::string onc_network_type
= ::onc::network_type::kEthernet
;
387 if (shill_network_type
!= shill::kTypeEthernet
&&
388 shill_network_type
!= shill::kTypeEthernetEap
) {
389 TranslateStringToONC(
390 kNetworkTypeTable
, shill_network_type
, &onc_network_type
);
392 // Translate nested Cellular, WiFi, etc. properties.
393 if (!onc_network_type
.empty()) {
394 onc_object_
->SetStringWithoutPathExpansion(::onc::network_config::kType
,
396 TranslateAndAddNestedObject(onc_network_type
);
399 // Since Name is a read only field in Shill unless it's a VPN, it is copied
400 // here, but not when going the other direction (if it's not a VPN).
402 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kNameProperty
, &name
);
403 onc_object_
->SetStringWithoutPathExpansion(::onc::network_config::kName
,
406 // Limit ONC state to "NotConnected", "Connected", or "Connecting".
408 if (shill_dictionary_
->GetStringWithoutPathExpansion(shill::kStateProperty
,
410 std::string onc_state
= ::onc::connection_state::kNotConnected
;
411 if (NetworkState::StateIsConnected(state
)) {
412 onc_state
= ::onc::connection_state::kConnected
;
413 } else if (NetworkState::StateIsConnecting(state
)) {
414 onc_state
= ::onc::connection_state::kConnecting
;
416 onc_object_
->SetStringWithoutPathExpansion(
417 ::onc::network_config::kConnectionState
, onc_state
);
418 // Only set 'RestrictedConnectivity' if true.
419 if (state
== shill::kStatePortal
) {
420 onc_object_
->SetBooleanWithoutPathExpansion(
421 ::onc::network_config::kRestrictedConnectivity
, true);
425 std::string profile_path
;
426 if (onc_source_
!= ::onc::ONC_SOURCE_UNKNOWN
&&
427 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kProfileProperty
,
430 if (onc_source_
== ::onc::ONC_SOURCE_DEVICE_POLICY
)
431 source
= ::onc::network_config::kSourceDevicePolicy
;
432 else if (onc_source_
== ::onc::ONC_SOURCE_USER_POLICY
)
433 source
= ::onc::network_config::kSourceUserPolicy
;
434 else if (profile_path
== NetworkProfileHandler::GetSharedProfilePath())
435 source
= ::onc::network_config::kSourceDevice
;
436 else if (!profile_path
.empty())
437 source
= ::onc::network_config::kSourceUser
;
439 source
= ::onc::network_config::kSourceNone
;
440 onc_object_
->SetStringWithoutPathExpansion(
441 ::onc::network_config::kSource
, source
);
444 // Use a human-readable aa:bb format for any hardware MAC address. Note:
445 // this property is provided by the caller but is not part of the Shill
446 // Service properties (it is copied from the Device properties).
448 if (shill_dictionary_
->GetStringWithoutPathExpansion(shill::kAddressProperty
,
450 onc_object_
->SetStringWithoutPathExpansion(
451 ::onc::network_config::kMacAddress
,
452 network_util::FormattedMacAddress(address
));
455 // Shill's Service has an IPConfig property (note the singular), not an
456 // IPConfigs property. However, we require the caller of the translation to
457 // patch the Shill dictionary before passing it to the translator.
458 const base::ListValue
* shill_ipconfigs
= NULL
;
459 if (shill_dictionary_
->GetListWithoutPathExpansion(shill::kIPConfigsProperty
,
461 TranslateAndAddListOfObjects(::onc::network_config::kIPConfigs
,
465 TranslateAndAddNestedObject(::onc::network_config::kSavedIPConfig
);
466 TranslateAndAddNestedObject(::onc::network_config::kStaticIPConfig
);
469 void ShillToONCTranslator::TranslateIPConfig() {
470 CopyPropertiesAccordingToSignature();
471 std::string shill_ip_method
;
472 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kMethodProperty
,
475 if (shill_ip_method
== shill::kTypeIPv4
||
476 shill_ip_method
== shill::kTypeDHCP
) {
477 type
= ::onc::ipconfig::kIPv4
;
478 } else if (shill_ip_method
== shill::kTypeIPv6
||
479 shill_ip_method
== shill::kTypeDHCP6
) {
480 type
= ::onc::ipconfig::kIPv6
;
482 return; // Ignore unhandled IPConfig types, e.g. bootp, zeroconf, ppp
485 onc_object_
->SetStringWithoutPathExpansion(::onc::ipconfig::kType
, type
);
488 void ShillToONCTranslator::TranslateSavedOrStaticIPConfig(
489 const std::string
& nameserver_property
) {
490 CopyPropertiesAccordingToSignature();
491 // Saved/Static IP config nameservers are stored as a comma separated list.
492 std::string shill_nameservers
;
493 shill_dictionary_
->GetStringWithoutPathExpansion(
494 nameserver_property
, &shill_nameservers
);
495 std::vector
<std::string
> onc_nameserver_vector
;
496 if (Tokenize(shill_nameservers
, ",", &onc_nameserver_vector
) > 0) {
497 scoped_ptr
<base::ListValue
> onc_nameservers(new base::ListValue
);
498 for (std::vector
<std::string
>::iterator iter
=
499 onc_nameserver_vector
.begin();
500 iter
!= onc_nameserver_vector
.end(); ++iter
) {
501 onc_nameservers
->AppendString(*iter
);
503 onc_object_
->SetWithoutPathExpansion(::onc::ipconfig::kNameServers
,
504 onc_nameservers
.release());
506 // Static and Saved IPConfig in Shill are always of type IPv4. Set this type
507 // in ONC, but not if the object would be empty except the type.
508 if (!onc_object_
->empty()) {
509 onc_object_
->SetStringWithoutPathExpansion(::onc::ipconfig::kType
,
510 ::onc::ipconfig::kIPv4
);
514 void ShillToONCTranslator::TranslateSavedIPConfig() {
515 TranslateSavedOrStaticIPConfig(shill::kSavedIPNameServersProperty
);
518 void ShillToONCTranslator::TranslateStaticIPConfig() {
519 TranslateSavedOrStaticIPConfig(shill::kStaticIPNameServersProperty
);
522 void ShillToONCTranslator::TranslateAndAddNestedObject(
523 const std::string
& onc_field_name
) {
524 TranslateAndAddNestedObject(onc_field_name
, *shill_dictionary_
);
527 void ShillToONCTranslator::TranslateAndAddNestedObject(
528 const std::string
& onc_field_name
,
529 const base::DictionaryValue
& dictionary
) {
530 const OncFieldSignature
* field_signature
=
531 GetFieldSignature(*onc_signature_
, onc_field_name
);
532 if (!field_signature
) {
533 NOTREACHED() << "Unable to find signature for field: " << onc_field_name
;
536 ShillToONCTranslator
nested_translator(
537 dictionary
, onc_source_
, *field_signature
->value_signature
);
538 scoped_ptr
<base::DictionaryValue
> nested_object
=
539 nested_translator
.CreateTranslatedONCObject();
540 if (nested_object
->empty())
542 onc_object_
->SetWithoutPathExpansion(onc_field_name
, nested_object
.release());
545 void ShillToONCTranslator::SetNestedOncValue(
546 const std::string
& onc_dictionary_name
,
547 const std::string
& onc_field_name
,
548 const base::Value
& value
) {
549 base::DictionaryValue
* nested
;
550 if (!onc_object_
->GetDictionaryWithoutPathExpansion(
551 onc_dictionary_name
, &nested
)) {
552 nested
= new base::DictionaryValue
;
553 onc_object_
->SetWithoutPathExpansion(onc_dictionary_name
, nested
);
555 nested
->SetWithoutPathExpansion(onc_field_name
, value
.DeepCopy());
558 void ShillToONCTranslator::TranslateAndAddListOfObjects(
559 const std::string
& onc_field_name
,
560 const base::ListValue
& list
) {
561 const OncFieldSignature
* field_signature
=
562 GetFieldSignature(*onc_signature_
, onc_field_name
);
563 if (field_signature
->value_signature
->onc_type
!= base::Value::TYPE_LIST
) {
564 LOG(ERROR
) << "ONC Field name: '" << onc_field_name
<< "' has type '"
565 << field_signature
->value_signature
->onc_type
566 << "', expected: base::Value::TYPE_LIST: " << GetName();
569 DCHECK(field_signature
->value_signature
->onc_array_entry_signature
);
570 scoped_ptr
<base::ListValue
> result(new base::ListValue());
571 for (base::ListValue::const_iterator it
= list
.begin();
572 it
!= list
.end(); ++it
) {
573 const base::DictionaryValue
* shill_value
= NULL
;
574 if (!(*it
)->GetAsDictionary(&shill_value
))
576 ShillToONCTranslator
nested_translator(
579 *field_signature
->value_signature
->onc_array_entry_signature
);
580 scoped_ptr
<base::DictionaryValue
> nested_object
=
581 nested_translator
.CreateTranslatedONCObject();
582 // If the nested object couldn't be parsed, simply omit it.
583 if (nested_object
->empty())
585 result
->Append(nested_object
.release());
587 // If there are no entries in the list, there is no need to expose this field.
590 onc_object_
->SetWithoutPathExpansion(onc_field_name
, result
.release());
593 void ShillToONCTranslator::CopyPropertiesAccordingToSignature() {
594 CopyPropertiesAccordingToSignature(onc_signature_
);
597 void ShillToONCTranslator::CopyPropertiesAccordingToSignature(
598 const OncValueSignature
* value_signature
) {
599 if (value_signature
->base_signature
)
600 CopyPropertiesAccordingToSignature(value_signature
->base_signature
);
601 if (!value_signature
->fields
)
603 for (const OncFieldSignature
* field_signature
= value_signature
->fields
;
604 field_signature
->onc_field_name
!= NULL
; ++field_signature
) {
605 CopyProperty(field_signature
);
609 void ShillToONCTranslator::CopyProperty(
610 const OncFieldSignature
* field_signature
) {
611 std::string shill_property_name
;
612 const base::Value
* shill_value
= NULL
;
613 if (!field_translation_table_
||
614 !GetShillPropertyName(field_signature
->onc_field_name
,
615 field_translation_table_
,
616 &shill_property_name
) ||
617 !shill_dictionary_
->GetWithoutPathExpansion(shill_property_name
,
622 if (shill_value
->GetType() != field_signature
->value_signature
->onc_type
) {
623 LOG(ERROR
) << "Shill property '" << shill_property_name
624 << "' with value " << *shill_value
625 << " has base::Value::Type " << shill_value
->GetType()
626 << " but ONC field '" << field_signature
->onc_field_name
627 << "' requires type "
628 << field_signature
->value_signature
->onc_type
629 << ": " << GetName();
633 onc_object_
->SetWithoutPathExpansion(field_signature
->onc_field_name
,
634 shill_value
->DeepCopy());
637 void ShillToONCTranslator::TranslateWithTableAndSet(
638 const std::string
& shill_property_name
,
639 const StringTranslationEntry table
[],
640 const std::string
& onc_field_name
) {
641 std::string shill_value
;
642 if (!shill_dictionary_
->GetStringWithoutPathExpansion(shill_property_name
,
646 std::string onc_value
;
647 if (TranslateStringToONC(table
, shill_value
, &onc_value
)) {
648 onc_object_
->SetStringWithoutPathExpansion(onc_field_name
, onc_value
);
651 LOG(ERROR
) << "Shill property '" << shill_property_name
<< "' with value "
652 << shill_value
<< " couldn't be translated to ONC: " << GetName();
655 std::string
ShillToONCTranslator::GetName() {
656 DCHECK(shill_dictionary_
);
658 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kNameProperty
, &name
);
664 scoped_ptr
<base::DictionaryValue
> TranslateShillServiceToONCPart(
665 const base::DictionaryValue
& shill_dictionary
,
666 ::onc::ONCSource onc_source
,
667 const OncValueSignature
* onc_signature
) {
668 CHECK(onc_signature
!= NULL
);
670 ShillToONCTranslator
translator(shill_dictionary
, onc_source
, *onc_signature
);
671 return translator
.CreateTranslatedONCObject();
675 } // namespace chromeos