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/onc/onc_utils.h"
21 #include "chromeos/network/shill_property_util.h"
22 #include "components/onc/onc_constants.h"
23 #include "third_party/cros_system_api/dbus/service_constants.h"
30 // Converts |str| to a base::Value of the given |type|. If the conversion fails,
32 scoped_ptr
<base::Value
> ConvertStringToValue(const std::string
& str
,
33 base::Value::Type type
) {
35 if (type
== base::Value::TYPE_STRING
) {
36 value
= new base::StringValue(str
);
38 value
= base::JSONReader::DeprecatedRead(str
);
41 if (value
== NULL
|| value
->GetType() != type
) {
45 return make_scoped_ptr(value
);
48 // This class implements the translation of properties from the given
49 // |shill_dictionary| to a new ONC object of signature |onc_signature|. Using
50 // recursive calls to CreateTranslatedONCObject of new instances, nested objects
52 class ShillToONCTranslator
{
54 ShillToONCTranslator(const base::DictionaryValue
& shill_dictionary
,
55 ::onc::ONCSource onc_source
,
56 const OncValueSignature
& onc_signature
,
57 const NetworkState
* network_state
)
58 : shill_dictionary_(&shill_dictionary
),
59 onc_source_(onc_source
),
60 onc_signature_(&onc_signature
),
61 network_state_(network_state
) {
62 field_translation_table_
= GetFieldTranslationTable(onc_signature
);
65 ShillToONCTranslator(const base::DictionaryValue
& shill_dictionary
,
66 ::onc::ONCSource onc_source
,
67 const OncValueSignature
& onc_signature
,
68 const FieldTranslationEntry
* field_translation_table
,
69 const NetworkState
* network_state
)
70 : shill_dictionary_(&shill_dictionary
),
71 onc_source_(onc_source
),
72 onc_signature_(&onc_signature
),
73 field_translation_table_(field_translation_table
),
74 network_state_(network_state
) {}
76 // Translates the associated Shill dictionary and creates an ONC object of the
78 scoped_ptr
<base::DictionaryValue
> CreateTranslatedONCObject();
81 void TranslateEthernet();
82 void TranslateOpenVPN();
83 void TranslateIPsec();
84 void TranslateThirdPartyVPN();
86 void TranslateWiFiWithState();
87 void TranslateWiMAXWithState();
88 void TranslateCellularWithState();
89 void TranslateCellularDevice();
90 void TranslateNetworkWithState();
91 void TranslateIPConfig();
92 void TranslateSavedOrStaticIPConfig();
93 void TranslateSavedIPConfig();
94 void TranslateStaticIPConfig();
96 // Creates an ONC object from |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
,
100 const base::DictionaryValue
& dictionary
);
102 // Creates an ONC object from |shill_dictionary_| according to the signature
103 // associated to |onc_field_name| and adds it to |onc_object_| at
105 void TranslateAndAddNestedObject(const std::string
& onc_field_name
);
107 // Sets |onc_field_name| in dictionary |onc_dictionary_name| in |onc_object_|
108 // to |value| if the dictionary exists.
109 void SetNestedOncValue(const std::string
& onc_dictionary_name
,
110 const std::string
& onc_field_name
,
111 const base::Value
& value
);
113 // Translates a list of nested objects and adds the list to |onc_object_| at
114 // |onc_field_name|. If there are errors while parsing individual objects or
115 // if the resulting list contains no entries, the result will not be added to
117 void TranslateAndAddListOfObjects(const std::string
& onc_field_name
,
118 const base::ListValue
& list
);
120 // Applies function CopyProperty to each field of |value_signature| and its
122 void CopyPropertiesAccordingToSignature(
123 const OncValueSignature
* value_signature
);
125 // Applies function CopyProperty to each field of |onc_signature_| and its
127 void CopyPropertiesAccordingToSignature();
129 // If |shill_property_name| is defined in |field_signature|, copies this
130 // entry from |shill_dictionary_| to |onc_object_| if it exists.
131 void CopyProperty(const OncFieldSignature
* field_signature
);
133 // If existent, translates the entry at |shill_property_name| in
134 // |shill_dictionary_| using |table|. It is an error if no matching table
135 // entry is found. Writes the result as entry at |onc_field_name| in
137 void TranslateWithTableAndSet(const std::string
& shill_property_name
,
138 const StringTranslationEntry table
[],
139 const std::string
& onc_field_name
);
141 // Returns the name of the Shill service provided in |shill_dictionary_|
143 std::string
GetName();
145 const base::DictionaryValue
* shill_dictionary_
;
146 ::onc::ONCSource onc_source_
;
147 const OncValueSignature
* onc_signature_
;
148 const FieldTranslationEntry
* field_translation_table_
;
149 scoped_ptr
<base::DictionaryValue
> onc_object_
;
150 const NetworkState
* network_state_
;
152 DISALLOW_COPY_AND_ASSIGN(ShillToONCTranslator
);
155 scoped_ptr
<base::DictionaryValue
>
156 ShillToONCTranslator::CreateTranslatedONCObject() {
157 onc_object_
.reset(new base::DictionaryValue
);
158 if (onc_signature_
== &kNetworkWithStateSignature
) {
159 TranslateNetworkWithState();
160 } else if (onc_signature_
== &kEthernetSignature
) {
162 } else if (onc_signature_
== &kVPNSignature
) {
164 } else if (onc_signature_
== &kOpenVPNSignature
) {
166 } else if (onc_signature_
== &kIPsecSignature
) {
168 } else if (onc_signature_
== &kThirdPartyVPNSignature
) {
169 TranslateThirdPartyVPN();
170 } else if (onc_signature_
== &kWiFiWithStateSignature
) {
171 TranslateWiFiWithState();
172 } else if (onc_signature_
== &kWiMAXWithStateSignature
) {
173 TranslateWiMAXWithState();
174 } else if (onc_signature_
== &kCellularWithStateSignature
) {
175 if (field_translation_table_
== kCellularDeviceTable
)
176 TranslateCellularDevice();
178 TranslateCellularWithState();
179 } else if (onc_signature_
== &kIPConfigSignature
) {
181 } else if (onc_signature_
== &kSavedIPConfigSignature
) {
182 TranslateSavedIPConfig();
183 } else if (onc_signature_
== &kStaticIPConfigSignature
) {
184 TranslateStaticIPConfig();
186 CopyPropertiesAccordingToSignature();
188 return onc_object_
.Pass();
191 void ShillToONCTranslator::TranslateEthernet() {
192 std::string shill_network_type
;
193 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kTypeProperty
,
194 &shill_network_type
);
195 const char* onc_auth
= ::onc::ethernet::kAuthenticationNone
;
196 if (shill_network_type
== shill::kTypeEthernetEap
)
197 onc_auth
= ::onc::ethernet::k8021X
;
198 onc_object_
->SetStringWithoutPathExpansion(::onc::ethernet::kAuthentication
,
202 void ShillToONCTranslator::TranslateOpenVPN() {
203 if (shill_dictionary_
->HasKey(shill::kOpenVPNVerifyX509NameProperty
))
204 TranslateAndAddNestedObject(::onc::openvpn::kVerifyX509
);
206 // Shill supports only one RemoteCertKU but ONC requires a list. If existing,
207 // wraps the value into a list.
209 if (shill_dictionary_
->GetStringWithoutPathExpansion(
210 shill::kOpenVPNRemoteCertKUProperty
, &certKU
)) {
211 scoped_ptr
<base::ListValue
> certKUs(new base::ListValue
);
212 certKUs
->AppendString(certKU
);
213 onc_object_
->SetWithoutPathExpansion(::onc::openvpn::kRemoteCertKU
,
217 for (const OncFieldSignature
* field_signature
= onc_signature_
->fields
;
218 field_signature
->onc_field_name
!= NULL
; ++field_signature
) {
219 const std::string
& onc_field_name
= field_signature
->onc_field_name
;
220 if (onc_field_name
== ::onc::openvpn::kRemoteCertKU
||
221 onc_field_name
== ::onc::openvpn::kServerCAPEMs
) {
222 CopyProperty(field_signature
);
226 std::string shill_property_name
;
227 const base::Value
* shill_value
= NULL
;
228 if (!field_translation_table_
||
229 !GetShillPropertyName(field_signature
->onc_field_name
,
230 field_translation_table_
, &shill_property_name
) ||
231 !shill_dictionary_
->GetWithoutPathExpansion(shill_property_name
,
236 scoped_ptr
<base::Value
> translated
;
237 std::string shill_str
;
238 if (shill_value
->GetAsString(&shill_str
)) {
239 // Shill wants all Provider/VPN fields to be strings. Translates these
240 // strings back to the correct ONC type.
241 translated
= ConvertStringToValue(
242 shill_str
, field_signature
->value_signature
->onc_type
);
244 if (translated
.get() == NULL
) {
245 LOG(ERROR
) << "Shill property '" << shill_property_name
246 << "' with value " << *shill_value
247 << " couldn't be converted to base::Value::Type "
248 << field_signature
->value_signature
->onc_type
<< ": "
251 onc_object_
->SetWithoutPathExpansion(onc_field_name
,
252 translated
.release());
255 LOG(ERROR
) << "Shill property '" << shill_property_name
<< "' has value "
256 << *shill_value
<< ", but expected a string: " << GetName();
261 void ShillToONCTranslator::TranslateIPsec() {
262 CopyPropertiesAccordingToSignature();
263 if (shill_dictionary_
->HasKey(shill::kL2tpIpsecXauthUserProperty
))
264 TranslateAndAddNestedObject(::onc::ipsec::kXAUTH
);
265 std::string client_cert_id
;
266 shill_dictionary_
->GetStringWithoutPathExpansion(
267 shill::kL2tpIpsecClientCertIdProperty
, &client_cert_id
);
268 std::string authentication_type
=
269 client_cert_id
.empty() ? ::onc::ipsec::kPSK
: ::onc::ipsec::kCert
;
270 onc_object_
->SetStringWithoutPathExpansion(::onc::ipsec::kAuthenticationType
,
271 authentication_type
);
274 void ShillToONCTranslator::TranslateThirdPartyVPN() {
275 CopyPropertiesAccordingToSignature();
277 // For third-party VPNs, |shill::kProviderHostProperty| is used to store the
278 // provider's extension ID.
279 std::string shill_extension_id
;
280 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kHostProperty
,
281 &shill_extension_id
);
282 onc_object_
->SetStringWithoutPathExpansion(
283 ::onc::third_party_vpn::kExtensionID
, shill_extension_id
);
286 void ShillToONCTranslator::TranslateVPN() {
287 CopyPropertiesAccordingToSignature();
289 // Parse Shill Provider dictionary. Note, this may not exist, e.g. if we are
290 // just translating network state in network_util::TranslateNetworkStateToONC.
291 const base::DictionaryValue
* provider
= NULL
;
292 if (!shill_dictionary_
->GetDictionaryWithoutPathExpansion(
293 shill::kProviderProperty
, &provider
)) {
296 std::string shill_provider_type
, onc_provider_type
;
297 provider
->GetStringWithoutPathExpansion(shill::kTypeProperty
,
298 &shill_provider_type
);
299 if (!TranslateStringToONC(kVPNTypeTable
, shill_provider_type
,
300 &onc_provider_type
)) {
303 onc_object_
->SetStringWithoutPathExpansion(::onc::vpn::kType
,
305 std::string shill_provider_host
;
306 if (onc_provider_type
!= ::onc::vpn::kThirdPartyVpn
&&
307 provider
->GetStringWithoutPathExpansion(shill::kHostProperty
,
308 &shill_provider_host
)) {
309 onc_object_
->SetStringWithoutPathExpansion(::onc::vpn::kHost
,
310 shill_provider_host
);
313 // Translate the nested dictionary.
314 std::string provider_type_dictionary
;
315 if (onc_provider_type
== ::onc::vpn::kTypeL2TP_IPsec
) {
316 TranslateAndAddNestedObject(::onc::vpn::kIPsec
, *provider
);
317 TranslateAndAddNestedObject(::onc::vpn::kL2TP
, *provider
);
318 provider_type_dictionary
= ::onc::vpn::kIPsec
;
320 TranslateAndAddNestedObject(onc_provider_type
, *provider
);
321 provider_type_dictionary
= onc_provider_type
;
324 bool save_credentials
;
325 if (onc_provider_type
!= ::onc::vpn::kThirdPartyVpn
&&
326 shill_dictionary_
->GetBooleanWithoutPathExpansion(
327 shill::kSaveCredentialsProperty
, &save_credentials
)) {
328 SetNestedOncValue(provider_type_dictionary
, ::onc::vpn::kSaveCredentials
,
329 base::FundamentalValue(save_credentials
));
333 void ShillToONCTranslator::TranslateWiFiWithState() {
334 TranslateWithTableAndSet(shill::kSecurityClassProperty
, kWiFiSecurityTable
,
335 ::onc::wifi::kSecurity
);
336 bool unknown_encoding
= true;
337 std::string ssid
= shill_property_util::GetSSIDFromProperties(
338 *shill_dictionary_
, false /* verbose_logging */, &unknown_encoding
);
339 if (!unknown_encoding
&& !ssid
.empty())
340 onc_object_
->SetStringWithoutPathExpansion(::onc::wifi::kSSID
, ssid
);
342 bool link_monitor_disable
;
343 if (shill_dictionary_
->GetBooleanWithoutPathExpansion(
344 shill::kLinkMonitorDisableProperty
, &link_monitor_disable
)) {
345 onc_object_
->SetBooleanWithoutPathExpansion(
346 ::onc::wifi::kAllowGatewayARPPolling
, !link_monitor_disable
);
349 CopyPropertiesAccordingToSignature();
350 TranslateAndAddNestedObject(::onc::wifi::kEAP
);
353 void ShillToONCTranslator::TranslateWiMAXWithState() {
354 CopyPropertiesAccordingToSignature();
355 TranslateAndAddNestedObject(::onc::wimax::kEAP
);
358 void ShillToONCTranslator::TranslateCellularWithState() {
359 CopyPropertiesAccordingToSignature();
360 TranslateWithTableAndSet(shill::kActivationStateProperty
,
361 kActivationStateTable
,
362 ::onc::cellular::kActivationState
);
363 TranslateWithTableAndSet(shill::kNetworkTechnologyProperty
,
364 kNetworkTechnologyTable
,
365 ::onc::cellular::kNetworkTechnology
);
366 const base::DictionaryValue
* dictionary
= NULL
;
367 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
368 shill::kServingOperatorProperty
, &dictionary
)) {
369 TranslateAndAddNestedObject(::onc::cellular::kServingOperator
, *dictionary
);
371 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
372 shill::kCellularApnProperty
, &dictionary
)) {
373 TranslateAndAddNestedObject(::onc::cellular::kAPN
, *dictionary
);
375 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
376 shill::kCellularLastGoodApnProperty
, &dictionary
)) {
377 TranslateAndAddNestedObject(::onc::cellular::kLastGoodAPN
, *dictionary
);
379 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
380 shill::kPaymentPortalProperty
, &dictionary
)) {
381 TranslateAndAddNestedObject(::onc::cellular::kPaymentPortal
, *dictionary
);
384 const base::DictionaryValue
* device_dictionary
= NULL
;
385 bool requires_roaming
= false;
386 shill_dictionary_
->GetDictionaryWithoutPathExpansion(shill::kDeviceProperty
,
388 if (device_dictionary
) {
389 // Merge the Device dictionary with this one (Cellular) using the
390 // CellularDevice signature.
391 ShillToONCTranslator
nested_translator(
392 *device_dictionary
, onc_source_
, kCellularWithStateSignature
,
393 kCellularDeviceTable
, network_state_
);
394 scoped_ptr
<base::DictionaryValue
> nested_object
=
395 nested_translator
.CreateTranslatedONCObject();
396 onc_object_
->MergeDictionary(nested_object
.get());
398 /// Get the requires_roaming from the Device dictionary.
399 device_dictionary
->GetBooleanWithoutPathExpansion(
400 shill::kProviderRequiresRoamingProperty
, &requires_roaming
);
402 if (requires_roaming
) {
403 onc_object_
->SetStringWithoutPathExpansion(
404 ::onc::cellular::kRoamingState
, ::onc::cellular::kRoamingRequired
);
406 TranslateWithTableAndSet(shill::kRoamingStateProperty
, kRoamingStateTable
,
407 ::onc::cellular::kRoamingState
);
411 void ShillToONCTranslator::TranslateCellularDevice() {
412 CopyPropertiesAccordingToSignature();
413 const base::DictionaryValue
* shill_sim_lock_status
= NULL
;
414 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
415 shill::kSIMLockStatusProperty
, &shill_sim_lock_status
)) {
416 TranslateAndAddNestedObject(::onc::cellular::kSIMLockStatus
,
417 *shill_sim_lock_status
);
419 const base::DictionaryValue
* shill_home_provider
= NULL
;
420 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
421 shill::kHomeProviderProperty
, &shill_home_provider
)) {
422 TranslateAndAddNestedObject(::onc::cellular::kHomeProvider
,
423 *shill_home_provider
);
425 const base::ListValue
* shill_apns
= NULL
;
426 if (shill_dictionary_
->GetListWithoutPathExpansion(
427 shill::kCellularApnListProperty
, &shill_apns
)) {
428 TranslateAndAddListOfObjects(::onc::cellular::kAPNList
, *shill_apns
);
430 const base::ListValue
* shill_found_networks
= NULL
;
431 if (shill_dictionary_
->GetListWithoutPathExpansion(
432 shill::kFoundNetworksProperty
, &shill_found_networks
)) {
433 TranslateAndAddListOfObjects(::onc::cellular::kFoundNetworks
,
434 *shill_found_networks
);
438 void ShillToONCTranslator::TranslateNetworkWithState() {
439 CopyPropertiesAccordingToSignature();
441 std::string shill_network_type
;
442 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kTypeProperty
,
443 &shill_network_type
);
444 std::string onc_network_type
= ::onc::network_type::kEthernet
;
445 if (shill_network_type
!= shill::kTypeEthernet
&&
446 shill_network_type
!= shill::kTypeEthernetEap
) {
447 TranslateStringToONC(kNetworkTypeTable
, shill_network_type
,
450 // Translate nested Cellular, WiFi, etc. properties.
451 if (!onc_network_type
.empty()) {
452 onc_object_
->SetStringWithoutPathExpansion(::onc::network_config::kType
,
454 TranslateAndAddNestedObject(onc_network_type
);
457 // Since Name is a read only field in Shill unless it's a VPN, it is copied
458 // here, but not when going the other direction (if it's not a VPN).
460 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kNameProperty
, &name
);
461 onc_object_
->SetStringWithoutPathExpansion(::onc::network_config::kName
,
464 // Limit ONC state to "NotConnected", "Connected", or "Connecting".
466 if (shill_dictionary_
->GetStringWithoutPathExpansion(shill::kStateProperty
,
468 std::string onc_state
= ::onc::connection_state::kNotConnected
;
469 if (NetworkState::StateIsConnected(state
)) {
470 onc_state
= ::onc::connection_state::kConnected
;
471 } else if (NetworkState::StateIsConnecting(state
)) {
472 onc_state
= ::onc::connection_state::kConnecting
;
474 onc_object_
->SetStringWithoutPathExpansion(
475 ::onc::network_config::kConnectionState
, onc_state
);
476 // Only set 'RestrictedConnectivity' if captive portal state is true.
477 if (NetworkState::NetworkStateIsCaptivePortal(*shill_dictionary_
)) {
478 onc_object_
->SetBooleanWithoutPathExpansion(
479 ::onc::network_config::kRestrictedConnectivity
, true);
483 // 'ErrorState' reflects the most recent error maintained in NetworkState
484 // (which may not match Shill's Error or PreviousError properties). Non
485 // visible networks (with null network_state_) do not set ErrorState.
486 if (network_state_
) {
487 std::string error_state
= network_state_
->GetErrorState();
488 if (!error_state
.empty()) {
489 onc_object_
->SetStringWithoutPathExpansion(
490 ::onc::network_config::kErrorState
, error_state
);
494 std::string profile_path
;
495 if (onc_source_
!= ::onc::ONC_SOURCE_UNKNOWN
&&
496 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kProfileProperty
,
499 if (onc_source_
== ::onc::ONC_SOURCE_DEVICE_POLICY
)
500 source
= ::onc::network_config::kSourceDevicePolicy
;
501 else if (onc_source_
== ::onc::ONC_SOURCE_USER_POLICY
)
502 source
= ::onc::network_config::kSourceUserPolicy
;
503 else if (profile_path
== NetworkProfileHandler::GetSharedProfilePath())
504 source
= ::onc::network_config::kSourceDevice
;
505 else if (!profile_path
.empty())
506 source
= ::onc::network_config::kSourceUser
;
508 source
= ::onc::network_config::kSourceNone
;
509 onc_object_
->SetStringWithoutPathExpansion(::onc::network_config::kSource
,
513 // Use a human-readable aa:bb format for any hardware MAC address. Note:
514 // this property is provided by the caller but is not part of the Shill
515 // Service properties (it is copied from the Device properties).
517 if (shill_dictionary_
->GetStringWithoutPathExpansion(shill::kAddressProperty
,
519 onc_object_
->SetStringWithoutPathExpansion(
520 ::onc::network_config::kMacAddress
,
521 network_util::FormattedMacAddress(address
));
524 // Shill's Service has an IPConfig property (note the singular), not an
525 // IPConfigs property. However, we require the caller of the translation to
526 // patch the Shill dictionary before passing it to the translator.
527 const base::ListValue
* shill_ipconfigs
= NULL
;
528 if (shill_dictionary_
->GetListWithoutPathExpansion(shill::kIPConfigsProperty
,
530 TranslateAndAddListOfObjects(::onc::network_config::kIPConfigs
,
534 const base::DictionaryValue
* saved_ipconfig
= nullptr;
535 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
536 shill::kSavedIPConfigProperty
, &saved_ipconfig
)) {
537 TranslateAndAddNestedObject(::onc::network_config::kSavedIPConfig
,
541 // Translate the StaticIPConfig object and set the IP config types.
542 const base::DictionaryValue
* static_ipconfig
= nullptr;
543 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
544 shill::kStaticIPConfigProperty
, &static_ipconfig
)) {
545 std::string ip_address
;
546 if (static_ipconfig
->GetStringWithoutPathExpansion(shill::kAddressProperty
,
548 !ip_address
.empty()) {
549 onc_object_
->SetStringWithoutPathExpansion(
550 ::onc::network_config::kIPAddressConfigType
,
551 ::onc::network_config::kIPConfigTypeStatic
);
553 const base::ListValue
* name_servers
= nullptr;
554 if (static_ipconfig
->GetListWithoutPathExpansion(
555 shill::kNameServersProperty
, &name_servers
) &&
556 !name_servers
->empty()) {
557 onc_object_
->SetStringWithoutPathExpansion(
558 ::onc::network_config::kNameServersConfigType
,
559 ::onc::network_config::kIPConfigTypeStatic
);
561 if (!ip_address
.empty() || (name_servers
&& !name_servers
->empty())) {
562 TranslateAndAddNestedObject(::onc::network_config::kStaticIPConfig
,
567 std::string proxy_config_str
;
568 if (shill_dictionary_
->GetStringWithoutPathExpansion(
569 shill::kProxyConfigProperty
, &proxy_config_str
) &&
570 !proxy_config_str
.empty()) {
571 scoped_ptr
<base::DictionaryValue
> proxy_config_value(
572 ReadDictionaryFromJson(proxy_config_str
));
573 if (proxy_config_value
) {
574 scoped_ptr
<base::DictionaryValue
> proxy_settings
=
575 ConvertProxyConfigToOncProxySettings(*proxy_config_value
);
576 if (proxy_settings
) {
577 onc_object_
->SetWithoutPathExpansion(
578 ::onc::network_config::kProxySettings
, proxy_settings
.release());
584 void ShillToONCTranslator::TranslateIPConfig() {
585 CopyPropertiesAccordingToSignature();
586 std::string shill_ip_method
;
587 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kMethodProperty
,
590 if (shill_ip_method
== shill::kTypeIPv4
||
591 shill_ip_method
== shill::kTypeDHCP
) {
592 type
= ::onc::ipconfig::kIPv4
;
593 } else if (shill_ip_method
== shill::kTypeIPv6
||
594 shill_ip_method
== shill::kTypeDHCP6
) {
595 type
= ::onc::ipconfig::kIPv6
;
597 return; // Ignore unhandled IPConfig types, e.g. bootp, zeroconf, ppp
600 onc_object_
->SetStringWithoutPathExpansion(::onc::ipconfig::kType
, type
);
603 void ShillToONCTranslator::TranslateSavedOrStaticIPConfig() {
604 CopyPropertiesAccordingToSignature();
606 // Static and Saved IPConfig in Shill are always of type IPv4. Set this type
607 // in ONC, but not if the object would be empty except the type.
608 if (!onc_object_
->empty()) {
609 onc_object_
->SetStringWithoutPathExpansion(::onc::ipconfig::kType
,
610 ::onc::ipconfig::kIPv4
);
614 void ShillToONCTranslator::TranslateSavedIPConfig() {
615 TranslateSavedOrStaticIPConfig();
618 void ShillToONCTranslator::TranslateStaticIPConfig() {
619 TranslateSavedOrStaticIPConfig();
622 void ShillToONCTranslator::TranslateAndAddNestedObject(
623 const std::string
& onc_field_name
) {
624 TranslateAndAddNestedObject(onc_field_name
, *shill_dictionary_
);
627 void ShillToONCTranslator::TranslateAndAddNestedObject(
628 const std::string
& onc_field_name
,
629 const base::DictionaryValue
& dictionary
) {
630 const OncFieldSignature
* field_signature
=
631 GetFieldSignature(*onc_signature_
, onc_field_name
);
632 if (!field_signature
) {
633 NOTREACHED() << "Unable to find signature for field: " << onc_field_name
;
636 ShillToONCTranslator
nested_translator(dictionary
, onc_source_
,
637 *field_signature
->value_signature
,
639 scoped_ptr
<base::DictionaryValue
> nested_object
=
640 nested_translator
.CreateTranslatedONCObject();
641 if (nested_object
->empty())
643 onc_object_
->SetWithoutPathExpansion(onc_field_name
, nested_object
.release());
646 void ShillToONCTranslator::SetNestedOncValue(
647 const std::string
& onc_dictionary_name
,
648 const std::string
& onc_field_name
,
649 const base::Value
& value
) {
650 base::DictionaryValue
* nested
;
651 if (!onc_object_
->GetDictionaryWithoutPathExpansion(onc_dictionary_name
,
653 nested
= new base::DictionaryValue
;
654 onc_object_
->SetWithoutPathExpansion(onc_dictionary_name
, nested
);
656 nested
->SetWithoutPathExpansion(onc_field_name
, value
.DeepCopy());
659 void ShillToONCTranslator::TranslateAndAddListOfObjects(
660 const std::string
& onc_field_name
,
661 const base::ListValue
& list
) {
662 const OncFieldSignature
* field_signature
=
663 GetFieldSignature(*onc_signature_
, onc_field_name
);
664 if (field_signature
->value_signature
->onc_type
!= base::Value::TYPE_LIST
) {
665 LOG(ERROR
) << "ONC Field name: '" << onc_field_name
<< "' has type '"
666 << field_signature
->value_signature
->onc_type
667 << "', expected: base::Value::TYPE_LIST: " << GetName();
670 DCHECK(field_signature
->value_signature
->onc_array_entry_signature
);
671 scoped_ptr
<base::ListValue
> result(new base::ListValue());
672 for (base::ListValue::const_iterator it
= list
.begin(); it
!= list
.end();
674 const base::DictionaryValue
* shill_value
= NULL
;
675 if (!(*it
)->GetAsDictionary(&shill_value
))
677 ShillToONCTranslator
nested_translator(
678 *shill_value
, onc_source_
,
679 *field_signature
->value_signature
->onc_array_entry_signature
,
681 scoped_ptr
<base::DictionaryValue
> nested_object
=
682 nested_translator
.CreateTranslatedONCObject();
683 // If the nested object couldn't be parsed, simply omit it.
684 if (nested_object
->empty())
686 result
->Append(nested_object
.release());
688 // If there are no entries in the list, there is no need to expose this field.
691 onc_object_
->SetWithoutPathExpansion(onc_field_name
, result
.release());
694 void ShillToONCTranslator::CopyPropertiesAccordingToSignature() {
695 CopyPropertiesAccordingToSignature(onc_signature_
);
698 void ShillToONCTranslator::CopyPropertiesAccordingToSignature(
699 const OncValueSignature
* value_signature
) {
700 if (value_signature
->base_signature
)
701 CopyPropertiesAccordingToSignature(value_signature
->base_signature
);
702 if (!value_signature
->fields
)
704 for (const OncFieldSignature
* field_signature
= value_signature
->fields
;
705 field_signature
->onc_field_name
!= NULL
; ++field_signature
) {
706 CopyProperty(field_signature
);
710 void ShillToONCTranslator::CopyProperty(
711 const OncFieldSignature
* field_signature
) {
712 std::string shill_property_name
;
713 const base::Value
* shill_value
= NULL
;
714 if (!field_translation_table_
||
715 !GetShillPropertyName(field_signature
->onc_field_name
,
716 field_translation_table_
, &shill_property_name
) ||
717 !shill_dictionary_
->GetWithoutPathExpansion(shill_property_name
,
722 if (shill_value
->GetType() != field_signature
->value_signature
->onc_type
) {
723 LOG(ERROR
) << "Shill property '" << shill_property_name
<< "' with value "
724 << *shill_value
<< " has base::Value::Type "
725 << shill_value
->GetType() << " but ONC field '"
726 << field_signature
->onc_field_name
<< "' requires type "
727 << field_signature
->value_signature
->onc_type
<< ": "
732 onc_object_
->SetWithoutPathExpansion(field_signature
->onc_field_name
,
733 shill_value
->DeepCopy());
736 void ShillToONCTranslator::TranslateWithTableAndSet(
737 const std::string
& shill_property_name
,
738 const StringTranslationEntry table
[],
739 const std::string
& onc_field_name
) {
740 std::string shill_value
;
741 if (!shill_dictionary_
->GetStringWithoutPathExpansion(shill_property_name
,
745 std::string onc_value
;
746 if (TranslateStringToONC(table
, shill_value
, &onc_value
)) {
747 onc_object_
->SetStringWithoutPathExpansion(onc_field_name
, onc_value
);
750 LOG(ERROR
) << "Shill property '" << shill_property_name
<< "' with value "
751 << shill_value
<< " couldn't be translated to ONC: " << GetName();
754 std::string
ShillToONCTranslator::GetName() {
755 DCHECK(shill_dictionary_
);
757 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kNameProperty
, &name
);
763 scoped_ptr
<base::DictionaryValue
> TranslateShillServiceToONCPart(
764 const base::DictionaryValue
& shill_dictionary
,
765 ::onc::ONCSource onc_source
,
766 const OncValueSignature
* onc_signature
,
767 const NetworkState
* network_state
) {
768 CHECK(onc_signature
!= NULL
);
770 ShillToONCTranslator
translator(shill_dictionary
, onc_source
, *onc_signature
,
772 return translator
.CreateTranslatedONCObject();
776 } // namespace chromeos