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
) {
34 scoped_ptr
<base::Value
> value
;
35 if (type
== base::Value::TYPE_STRING
) {
36 value
.reset(new base::StringValue(str
));
38 value
= base::JSONReader::Read(str
);
40 if (value
&& value
->GetType() != type
)
46 // This class implements the translation of properties from the given
47 // |shill_dictionary| to a new ONC object of signature |onc_signature|. Using
48 // recursive calls to CreateTranslatedONCObject of new instances, nested objects
50 class ShillToONCTranslator
{
52 ShillToONCTranslator(const base::DictionaryValue
& shill_dictionary
,
53 ::onc::ONCSource onc_source
,
54 const OncValueSignature
& onc_signature
,
55 const NetworkState
* network_state
)
56 : shill_dictionary_(&shill_dictionary
),
57 onc_source_(onc_source
),
58 onc_signature_(&onc_signature
),
59 network_state_(network_state
) {
60 field_translation_table_
= GetFieldTranslationTable(onc_signature
);
63 ShillToONCTranslator(const base::DictionaryValue
& shill_dictionary
,
64 ::onc::ONCSource onc_source
,
65 const OncValueSignature
& onc_signature
,
66 const FieldTranslationEntry
* field_translation_table
,
67 const NetworkState
* network_state
)
68 : shill_dictionary_(&shill_dictionary
),
69 onc_source_(onc_source
),
70 onc_signature_(&onc_signature
),
71 field_translation_table_(field_translation_table
),
72 network_state_(network_state
) {}
74 // Translates the associated Shill dictionary and creates an ONC object of the
76 scoped_ptr
<base::DictionaryValue
> CreateTranslatedONCObject();
79 void TranslateEthernet();
80 void TranslateOpenVPN();
81 void TranslateIPsec();
82 void TranslateThirdPartyVPN();
84 void TranslateWiFiWithState();
85 void TranslateWiMAXWithState();
86 void TranslateCellularWithState();
87 void TranslateCellularDevice();
88 void TranslateNetworkWithState();
89 void TranslateIPConfig();
90 void TranslateSavedOrStaticIPConfig();
91 void TranslateSavedIPConfig();
92 void TranslateStaticIPConfig();
94 // Creates an ONC object from |dictionary| according to the signature
95 // associated to |onc_field_name| and adds it to |onc_object_| at
97 void TranslateAndAddNestedObject(const std::string
& onc_field_name
,
98 const base::DictionaryValue
& dictionary
);
100 // Creates an ONC object from |shill_dictionary_| according to the signature
101 // associated to |onc_field_name| and adds it to |onc_object_| at
103 void TranslateAndAddNestedObject(const std::string
& onc_field_name
);
105 // Sets |onc_field_name| in dictionary |onc_dictionary_name| in |onc_object_|
106 // to |value| if the dictionary exists.
107 void SetNestedOncValue(const std::string
& onc_dictionary_name
,
108 const std::string
& onc_field_name
,
109 const base::Value
& value
);
111 // Translates a list of nested objects and adds the list to |onc_object_| at
112 // |onc_field_name|. If there are errors while parsing individual objects or
113 // if the resulting list contains no entries, the result will not be added to
115 void TranslateAndAddListOfObjects(const std::string
& onc_field_name
,
116 const base::ListValue
& list
);
118 // Applies function CopyProperty to each field of |value_signature| and its
120 void CopyPropertiesAccordingToSignature(
121 const OncValueSignature
* value_signature
);
123 // Applies function CopyProperty to each field of |onc_signature_| and its
125 void CopyPropertiesAccordingToSignature();
127 // If |shill_property_name| is defined in |field_signature|, copies this
128 // entry from |shill_dictionary_| to |onc_object_| if it exists.
129 void CopyProperty(const OncFieldSignature
* field_signature
);
131 // If existent, translates the entry at |shill_property_name| in
132 // |shill_dictionary_| using |table|. It is an error if no matching table
133 // entry is found. Writes the result as entry at |onc_field_name| in
135 void TranslateWithTableAndSet(const std::string
& shill_property_name
,
136 const StringTranslationEntry table
[],
137 const std::string
& onc_field_name
);
139 // Returns the name of the Shill service provided in |shill_dictionary_|
141 std::string
GetName();
143 const base::DictionaryValue
* shill_dictionary_
;
144 ::onc::ONCSource onc_source_
;
145 const OncValueSignature
* onc_signature_
;
146 const FieldTranslationEntry
* field_translation_table_
;
147 scoped_ptr
<base::DictionaryValue
> onc_object_
;
148 const NetworkState
* network_state_
;
150 DISALLOW_COPY_AND_ASSIGN(ShillToONCTranslator
);
153 scoped_ptr
<base::DictionaryValue
>
154 ShillToONCTranslator::CreateTranslatedONCObject() {
155 onc_object_
.reset(new base::DictionaryValue
);
156 if (onc_signature_
== &kNetworkWithStateSignature
) {
157 TranslateNetworkWithState();
158 } else if (onc_signature_
== &kEthernetSignature
) {
160 } else if (onc_signature_
== &kVPNSignature
) {
162 } else if (onc_signature_
== &kOpenVPNSignature
) {
164 } else if (onc_signature_
== &kIPsecSignature
) {
166 } else if (onc_signature_
== &kThirdPartyVPNSignature
) {
167 TranslateThirdPartyVPN();
168 } else if (onc_signature_
== &kWiFiWithStateSignature
) {
169 TranslateWiFiWithState();
170 } else if (onc_signature_
== &kWiMAXWithStateSignature
) {
171 TranslateWiMAXWithState();
172 } else if (onc_signature_
== &kCellularWithStateSignature
) {
173 if (field_translation_table_
== kCellularDeviceTable
)
174 TranslateCellularDevice();
176 TranslateCellularWithState();
177 } else if (onc_signature_
== &kIPConfigSignature
) {
179 } else if (onc_signature_
== &kSavedIPConfigSignature
) {
180 TranslateSavedIPConfig();
181 } else if (onc_signature_
== &kStaticIPConfigSignature
) {
182 TranslateStaticIPConfig();
184 CopyPropertiesAccordingToSignature();
186 return onc_object_
.Pass();
189 void ShillToONCTranslator::TranslateEthernet() {
190 std::string shill_network_type
;
191 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kTypeProperty
,
192 &shill_network_type
);
193 const char* onc_auth
= ::onc::ethernet::kAuthenticationNone
;
194 if (shill_network_type
== shill::kTypeEthernetEap
)
195 onc_auth
= ::onc::ethernet::k8021X
;
196 onc_object_
->SetStringWithoutPathExpansion(::onc::ethernet::kAuthentication
,
200 void ShillToONCTranslator::TranslateOpenVPN() {
201 if (shill_dictionary_
->HasKey(shill::kOpenVPNVerifyX509NameProperty
))
202 TranslateAndAddNestedObject(::onc::openvpn::kVerifyX509
);
204 // Shill supports only one RemoteCertKU but ONC requires a list. If existing,
205 // wraps the value into a list.
207 if (shill_dictionary_
->GetStringWithoutPathExpansion(
208 shill::kOpenVPNRemoteCertKUProperty
, &certKU
)) {
209 scoped_ptr
<base::ListValue
> certKUs(new base::ListValue
);
210 certKUs
->AppendString(certKU
);
211 onc_object_
->SetWithoutPathExpansion(::onc::openvpn::kRemoteCertKU
,
215 for (const OncFieldSignature
* field_signature
= onc_signature_
->fields
;
216 field_signature
->onc_field_name
!= NULL
; ++field_signature
) {
217 const std::string
& onc_field_name
= field_signature
->onc_field_name
;
218 if (onc_field_name
== ::onc::openvpn::kRemoteCertKU
||
219 onc_field_name
== ::onc::openvpn::kServerCAPEMs
) {
220 CopyProperty(field_signature
);
224 std::string shill_property_name
;
225 const base::Value
* shill_value
= NULL
;
226 if (!field_translation_table_
||
227 !GetShillPropertyName(field_signature
->onc_field_name
,
228 field_translation_table_
, &shill_property_name
) ||
229 !shill_dictionary_
->GetWithoutPathExpansion(shill_property_name
,
234 scoped_ptr
<base::Value
> translated
;
235 std::string shill_str
;
236 if (shill_value
->GetAsString(&shill_str
)) {
237 // Shill wants all Provider/VPN fields to be strings. Translates these
238 // strings back to the correct ONC type.
239 translated
= ConvertStringToValue(
240 shill_str
, field_signature
->value_signature
->onc_type
);
242 if (translated
.get() == NULL
) {
243 LOG(ERROR
) << "Shill property '" << shill_property_name
244 << "' with value " << *shill_value
245 << " couldn't be converted to base::Value::Type "
246 << field_signature
->value_signature
->onc_type
<< ": "
249 onc_object_
->SetWithoutPathExpansion(onc_field_name
,
250 translated
.release());
253 LOG(ERROR
) << "Shill property '" << shill_property_name
<< "' has value "
254 << *shill_value
<< ", but expected a string: " << GetName();
259 void ShillToONCTranslator::TranslateIPsec() {
260 CopyPropertiesAccordingToSignature();
261 if (shill_dictionary_
->HasKey(shill::kL2tpIpsecXauthUserProperty
))
262 TranslateAndAddNestedObject(::onc::ipsec::kXAUTH
);
263 std::string client_cert_id
;
264 shill_dictionary_
->GetStringWithoutPathExpansion(
265 shill::kL2tpIpsecClientCertIdProperty
, &client_cert_id
);
266 std::string authentication_type
=
267 client_cert_id
.empty() ? ::onc::ipsec::kPSK
: ::onc::ipsec::kCert
;
268 onc_object_
->SetStringWithoutPathExpansion(::onc::ipsec::kAuthenticationType
,
269 authentication_type
);
272 void ShillToONCTranslator::TranslateThirdPartyVPN() {
273 CopyPropertiesAccordingToSignature();
275 // For third-party VPNs, |shill::kProviderHostProperty| is used to store the
276 // provider's extension ID.
277 std::string shill_extension_id
;
278 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kHostProperty
,
279 &shill_extension_id
);
280 onc_object_
->SetStringWithoutPathExpansion(
281 ::onc::third_party_vpn::kExtensionID
, shill_extension_id
);
284 void ShillToONCTranslator::TranslateVPN() {
285 CopyPropertiesAccordingToSignature();
287 // Parse Shill Provider dictionary. Note, this may not exist, e.g. if we are
288 // just translating network state in network_util::TranslateNetworkStateToONC.
289 const base::DictionaryValue
* provider
= NULL
;
290 if (!shill_dictionary_
->GetDictionaryWithoutPathExpansion(
291 shill::kProviderProperty
, &provider
)) {
294 std::string shill_provider_type
, onc_provider_type
;
295 provider
->GetStringWithoutPathExpansion(shill::kTypeProperty
,
296 &shill_provider_type
);
297 if (!TranslateStringToONC(kVPNTypeTable
, shill_provider_type
,
298 &onc_provider_type
)) {
301 onc_object_
->SetStringWithoutPathExpansion(::onc::vpn::kType
,
303 std::string shill_provider_host
;
304 if (onc_provider_type
!= ::onc::vpn::kThirdPartyVpn
&&
305 provider
->GetStringWithoutPathExpansion(shill::kHostProperty
,
306 &shill_provider_host
)) {
307 onc_object_
->SetStringWithoutPathExpansion(::onc::vpn::kHost
,
308 shill_provider_host
);
311 // Translate the nested dictionary.
312 std::string provider_type_dictionary
;
313 if (onc_provider_type
== ::onc::vpn::kTypeL2TP_IPsec
) {
314 TranslateAndAddNestedObject(::onc::vpn::kIPsec
, *provider
);
315 TranslateAndAddNestedObject(::onc::vpn::kL2TP
, *provider
);
316 provider_type_dictionary
= ::onc::vpn::kIPsec
;
318 TranslateAndAddNestedObject(onc_provider_type
, *provider
);
319 provider_type_dictionary
= onc_provider_type
;
322 bool save_credentials
;
323 if (onc_provider_type
!= ::onc::vpn::kThirdPartyVpn
&&
324 shill_dictionary_
->GetBooleanWithoutPathExpansion(
325 shill::kSaveCredentialsProperty
, &save_credentials
)) {
326 SetNestedOncValue(provider_type_dictionary
, ::onc::vpn::kSaveCredentials
,
327 base::FundamentalValue(save_credentials
));
331 void ShillToONCTranslator::TranslateWiFiWithState() {
332 TranslateWithTableAndSet(shill::kSecurityClassProperty
, kWiFiSecurityTable
,
333 ::onc::wifi::kSecurity
);
334 bool unknown_encoding
= true;
335 std::string ssid
= shill_property_util::GetSSIDFromProperties(
336 *shill_dictionary_
, false /* verbose_logging */, &unknown_encoding
);
337 if (!unknown_encoding
&& !ssid
.empty())
338 onc_object_
->SetStringWithoutPathExpansion(::onc::wifi::kSSID
, ssid
);
340 bool link_monitor_disable
;
341 if (shill_dictionary_
->GetBooleanWithoutPathExpansion(
342 shill::kLinkMonitorDisableProperty
, &link_monitor_disable
)) {
343 onc_object_
->SetBooleanWithoutPathExpansion(
344 ::onc::wifi::kAllowGatewayARPPolling
, !link_monitor_disable
);
347 CopyPropertiesAccordingToSignature();
348 TranslateAndAddNestedObject(::onc::wifi::kEAP
);
351 void ShillToONCTranslator::TranslateWiMAXWithState() {
352 CopyPropertiesAccordingToSignature();
353 TranslateAndAddNestedObject(::onc::wimax::kEAP
);
356 void ShillToONCTranslator::TranslateCellularWithState() {
357 CopyPropertiesAccordingToSignature();
358 TranslateWithTableAndSet(shill::kActivationStateProperty
,
359 kActivationStateTable
,
360 ::onc::cellular::kActivationState
);
361 TranslateWithTableAndSet(shill::kNetworkTechnologyProperty
,
362 kNetworkTechnologyTable
,
363 ::onc::cellular::kNetworkTechnology
);
364 const base::DictionaryValue
* dictionary
= NULL
;
365 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
366 shill::kServingOperatorProperty
, &dictionary
)) {
367 TranslateAndAddNestedObject(::onc::cellular::kServingOperator
, *dictionary
);
369 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
370 shill::kCellularApnProperty
, &dictionary
)) {
371 TranslateAndAddNestedObject(::onc::cellular::kAPN
, *dictionary
);
373 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
374 shill::kCellularLastGoodApnProperty
, &dictionary
)) {
375 TranslateAndAddNestedObject(::onc::cellular::kLastGoodAPN
, *dictionary
);
377 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
378 shill::kPaymentPortalProperty
, &dictionary
)) {
379 TranslateAndAddNestedObject(::onc::cellular::kPaymentPortal
, *dictionary
);
382 const base::DictionaryValue
* device_dictionary
= NULL
;
383 bool requires_roaming
= false;
384 shill_dictionary_
->GetDictionaryWithoutPathExpansion(shill::kDeviceProperty
,
386 if (device_dictionary
) {
387 // Merge the Device dictionary with this one (Cellular) using the
388 // CellularDevice signature.
389 ShillToONCTranslator
nested_translator(
390 *device_dictionary
, onc_source_
, kCellularWithStateSignature
,
391 kCellularDeviceTable
, network_state_
);
392 scoped_ptr
<base::DictionaryValue
> nested_object
=
393 nested_translator
.CreateTranslatedONCObject();
394 onc_object_
->MergeDictionary(nested_object
.get());
396 /// Get the requires_roaming from the Device dictionary.
397 device_dictionary
->GetBooleanWithoutPathExpansion(
398 shill::kProviderRequiresRoamingProperty
, &requires_roaming
);
400 if (requires_roaming
) {
401 onc_object_
->SetStringWithoutPathExpansion(
402 ::onc::cellular::kRoamingState
, ::onc::cellular::kRoamingRequired
);
404 TranslateWithTableAndSet(shill::kRoamingStateProperty
, kRoamingStateTable
,
405 ::onc::cellular::kRoamingState
);
409 void ShillToONCTranslator::TranslateCellularDevice() {
410 CopyPropertiesAccordingToSignature();
411 const base::DictionaryValue
* shill_sim_lock_status
= NULL
;
412 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
413 shill::kSIMLockStatusProperty
, &shill_sim_lock_status
)) {
414 TranslateAndAddNestedObject(::onc::cellular::kSIMLockStatus
,
415 *shill_sim_lock_status
);
417 const base::DictionaryValue
* shill_home_provider
= NULL
;
418 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
419 shill::kHomeProviderProperty
, &shill_home_provider
)) {
420 TranslateAndAddNestedObject(::onc::cellular::kHomeProvider
,
421 *shill_home_provider
);
423 const base::ListValue
* shill_apns
= NULL
;
424 if (shill_dictionary_
->GetListWithoutPathExpansion(
425 shill::kCellularApnListProperty
, &shill_apns
)) {
426 TranslateAndAddListOfObjects(::onc::cellular::kAPNList
, *shill_apns
);
428 const base::ListValue
* shill_found_networks
= NULL
;
429 if (shill_dictionary_
->GetListWithoutPathExpansion(
430 shill::kFoundNetworksProperty
, &shill_found_networks
)) {
431 TranslateAndAddListOfObjects(::onc::cellular::kFoundNetworks
,
432 *shill_found_networks
);
436 void ShillToONCTranslator::TranslateNetworkWithState() {
437 CopyPropertiesAccordingToSignature();
439 std::string shill_network_type
;
440 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kTypeProperty
,
441 &shill_network_type
);
442 std::string onc_network_type
= ::onc::network_type::kEthernet
;
443 if (shill_network_type
!= shill::kTypeEthernet
&&
444 shill_network_type
!= shill::kTypeEthernetEap
) {
445 TranslateStringToONC(kNetworkTypeTable
, shill_network_type
,
448 // Translate nested Cellular, WiFi, etc. properties.
449 if (!onc_network_type
.empty()) {
450 onc_object_
->SetStringWithoutPathExpansion(::onc::network_config::kType
,
452 TranslateAndAddNestedObject(onc_network_type
);
455 // Since Name is a read only field in Shill unless it's a VPN, it is copied
456 // here, but not when going the other direction (if it's not a VPN).
458 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kNameProperty
, &name
);
459 onc_object_
->SetStringWithoutPathExpansion(::onc::network_config::kName
,
462 // Limit ONC state to "NotConnected", "Connected", or "Connecting".
464 if (shill_dictionary_
->GetStringWithoutPathExpansion(shill::kStateProperty
,
466 std::string onc_state
= ::onc::connection_state::kNotConnected
;
467 if (NetworkState::StateIsConnected(state
)) {
468 onc_state
= ::onc::connection_state::kConnected
;
469 } else if (NetworkState::StateIsConnecting(state
)) {
470 onc_state
= ::onc::connection_state::kConnecting
;
472 onc_object_
->SetStringWithoutPathExpansion(
473 ::onc::network_config::kConnectionState
, onc_state
);
474 // Only set 'RestrictedConnectivity' if captive portal state is true.
475 if (NetworkState::NetworkStateIsCaptivePortal(*shill_dictionary_
)) {
476 onc_object_
->SetBooleanWithoutPathExpansion(
477 ::onc::network_config::kRestrictedConnectivity
, true);
481 // 'ErrorState' reflects the most recent error maintained in NetworkState
482 // (which may not match Shill's Error or PreviousError properties). Non
483 // visible networks (with null network_state_) do not set ErrorState.
484 if (network_state_
) {
485 std::string error_state
= network_state_
->GetErrorState();
486 if (!error_state
.empty()) {
487 onc_object_
->SetStringWithoutPathExpansion(
488 ::onc::network_config::kErrorState
, error_state
);
492 std::string profile_path
;
493 if (onc_source_
!= ::onc::ONC_SOURCE_UNKNOWN
&&
494 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kProfileProperty
,
497 if (onc_source_
== ::onc::ONC_SOURCE_DEVICE_POLICY
)
498 source
= ::onc::network_config::kSourceDevicePolicy
;
499 else if (onc_source_
== ::onc::ONC_SOURCE_USER_POLICY
)
500 source
= ::onc::network_config::kSourceUserPolicy
;
501 else if (profile_path
== NetworkProfileHandler::GetSharedProfilePath())
502 source
= ::onc::network_config::kSourceDevice
;
503 else if (!profile_path
.empty())
504 source
= ::onc::network_config::kSourceUser
;
506 source
= ::onc::network_config::kSourceNone
;
507 onc_object_
->SetStringWithoutPathExpansion(::onc::network_config::kSource
,
511 // Use a human-readable aa:bb format for any hardware MAC address. Note:
512 // this property is provided by the caller but is not part of the Shill
513 // Service properties (it is copied from the Device properties).
515 if (shill_dictionary_
->GetStringWithoutPathExpansion(shill::kAddressProperty
,
517 onc_object_
->SetStringWithoutPathExpansion(
518 ::onc::network_config::kMacAddress
,
519 network_util::FormattedMacAddress(address
));
522 // Shill's Service has an IPConfig property (note the singular), not an
523 // IPConfigs property. However, we require the caller of the translation to
524 // patch the Shill dictionary before passing it to the translator.
525 const base::ListValue
* shill_ipconfigs
= NULL
;
526 if (shill_dictionary_
->GetListWithoutPathExpansion(shill::kIPConfigsProperty
,
528 TranslateAndAddListOfObjects(::onc::network_config::kIPConfigs
,
532 const base::DictionaryValue
* saved_ipconfig
= nullptr;
533 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
534 shill::kSavedIPConfigProperty
, &saved_ipconfig
)) {
535 TranslateAndAddNestedObject(::onc::network_config::kSavedIPConfig
,
539 // Translate the StaticIPConfig object and set the IP config types.
540 const base::DictionaryValue
* static_ipconfig
= nullptr;
541 if (shill_dictionary_
->GetDictionaryWithoutPathExpansion(
542 shill::kStaticIPConfigProperty
, &static_ipconfig
)) {
543 std::string ip_address
;
544 if (static_ipconfig
->GetStringWithoutPathExpansion(shill::kAddressProperty
,
546 !ip_address
.empty()) {
547 onc_object_
->SetStringWithoutPathExpansion(
548 ::onc::network_config::kIPAddressConfigType
,
549 ::onc::network_config::kIPConfigTypeStatic
);
551 const base::ListValue
* name_servers
= nullptr;
552 if (static_ipconfig
->GetListWithoutPathExpansion(
553 shill::kNameServersProperty
, &name_servers
) &&
554 !name_servers
->empty()) {
555 onc_object_
->SetStringWithoutPathExpansion(
556 ::onc::network_config::kNameServersConfigType
,
557 ::onc::network_config::kIPConfigTypeStatic
);
559 if (!ip_address
.empty() || (name_servers
&& !name_servers
->empty())) {
560 TranslateAndAddNestedObject(::onc::network_config::kStaticIPConfig
,
565 std::string proxy_config_str
;
566 if (shill_dictionary_
->GetStringWithoutPathExpansion(
567 shill::kProxyConfigProperty
, &proxy_config_str
) &&
568 !proxy_config_str
.empty()) {
569 scoped_ptr
<base::DictionaryValue
> proxy_config_value(
570 ReadDictionaryFromJson(proxy_config_str
));
571 if (proxy_config_value
) {
572 scoped_ptr
<base::DictionaryValue
> proxy_settings
=
573 ConvertProxyConfigToOncProxySettings(*proxy_config_value
);
574 if (proxy_settings
) {
575 onc_object_
->SetWithoutPathExpansion(
576 ::onc::network_config::kProxySettings
, proxy_settings
.release());
582 void ShillToONCTranslator::TranslateIPConfig() {
583 CopyPropertiesAccordingToSignature();
584 std::string shill_ip_method
;
585 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kMethodProperty
,
588 if (shill_ip_method
== shill::kTypeIPv4
||
589 shill_ip_method
== shill::kTypeDHCP
) {
590 type
= ::onc::ipconfig::kIPv4
;
591 } else if (shill_ip_method
== shill::kTypeIPv6
||
592 shill_ip_method
== shill::kTypeDHCP6
) {
593 type
= ::onc::ipconfig::kIPv6
;
595 return; // Ignore unhandled IPConfig types, e.g. bootp, zeroconf, ppp
598 onc_object_
->SetStringWithoutPathExpansion(::onc::ipconfig::kType
, type
);
601 void ShillToONCTranslator::TranslateSavedOrStaticIPConfig() {
602 CopyPropertiesAccordingToSignature();
604 // Static and Saved IPConfig in Shill are always of type IPv4. Set this type
605 // in ONC, but not if the object would be empty except the type.
606 if (!onc_object_
->empty()) {
607 onc_object_
->SetStringWithoutPathExpansion(::onc::ipconfig::kType
,
608 ::onc::ipconfig::kIPv4
);
612 void ShillToONCTranslator::TranslateSavedIPConfig() {
613 TranslateSavedOrStaticIPConfig();
616 void ShillToONCTranslator::TranslateStaticIPConfig() {
617 TranslateSavedOrStaticIPConfig();
620 void ShillToONCTranslator::TranslateAndAddNestedObject(
621 const std::string
& onc_field_name
) {
622 TranslateAndAddNestedObject(onc_field_name
, *shill_dictionary_
);
625 void ShillToONCTranslator::TranslateAndAddNestedObject(
626 const std::string
& onc_field_name
,
627 const base::DictionaryValue
& dictionary
) {
628 const OncFieldSignature
* field_signature
=
629 GetFieldSignature(*onc_signature_
, onc_field_name
);
630 if (!field_signature
) {
631 NOTREACHED() << "Unable to find signature for field: " << onc_field_name
;
634 ShillToONCTranslator
nested_translator(dictionary
, onc_source_
,
635 *field_signature
->value_signature
,
637 scoped_ptr
<base::DictionaryValue
> nested_object
=
638 nested_translator
.CreateTranslatedONCObject();
639 if (nested_object
->empty())
641 onc_object_
->SetWithoutPathExpansion(onc_field_name
, nested_object
.release());
644 void ShillToONCTranslator::SetNestedOncValue(
645 const std::string
& onc_dictionary_name
,
646 const std::string
& onc_field_name
,
647 const base::Value
& value
) {
648 base::DictionaryValue
* nested
;
649 if (!onc_object_
->GetDictionaryWithoutPathExpansion(onc_dictionary_name
,
651 nested
= new base::DictionaryValue
;
652 onc_object_
->SetWithoutPathExpansion(onc_dictionary_name
, nested
);
654 nested
->SetWithoutPathExpansion(onc_field_name
, value
.DeepCopy());
657 void ShillToONCTranslator::TranslateAndAddListOfObjects(
658 const std::string
& onc_field_name
,
659 const base::ListValue
& list
) {
660 const OncFieldSignature
* field_signature
=
661 GetFieldSignature(*onc_signature_
, onc_field_name
);
662 if (field_signature
->value_signature
->onc_type
!= base::Value::TYPE_LIST
) {
663 LOG(ERROR
) << "ONC Field name: '" << onc_field_name
<< "' has type '"
664 << field_signature
->value_signature
->onc_type
665 << "', expected: base::Value::TYPE_LIST: " << GetName();
668 DCHECK(field_signature
->value_signature
->onc_array_entry_signature
);
669 scoped_ptr
<base::ListValue
> result(new base::ListValue());
670 for (base::ListValue::const_iterator it
= list
.begin(); it
!= list
.end();
672 const base::DictionaryValue
* shill_value
= NULL
;
673 if (!(*it
)->GetAsDictionary(&shill_value
))
675 ShillToONCTranslator
nested_translator(
676 *shill_value
, onc_source_
,
677 *field_signature
->value_signature
->onc_array_entry_signature
,
679 scoped_ptr
<base::DictionaryValue
> nested_object
=
680 nested_translator
.CreateTranslatedONCObject();
681 // If the nested object couldn't be parsed, simply omit it.
682 if (nested_object
->empty())
684 result
->Append(nested_object
.release());
686 // If there are no entries in the list, there is no need to expose this field.
689 onc_object_
->SetWithoutPathExpansion(onc_field_name
, result
.release());
692 void ShillToONCTranslator::CopyPropertiesAccordingToSignature() {
693 CopyPropertiesAccordingToSignature(onc_signature_
);
696 void ShillToONCTranslator::CopyPropertiesAccordingToSignature(
697 const OncValueSignature
* value_signature
) {
698 if (value_signature
->base_signature
)
699 CopyPropertiesAccordingToSignature(value_signature
->base_signature
);
700 if (!value_signature
->fields
)
702 for (const OncFieldSignature
* field_signature
= value_signature
->fields
;
703 field_signature
->onc_field_name
!= NULL
; ++field_signature
) {
704 CopyProperty(field_signature
);
708 void ShillToONCTranslator::CopyProperty(
709 const OncFieldSignature
* field_signature
) {
710 std::string shill_property_name
;
711 const base::Value
* shill_value
= NULL
;
712 if (!field_translation_table_
||
713 !GetShillPropertyName(field_signature
->onc_field_name
,
714 field_translation_table_
, &shill_property_name
) ||
715 !shill_dictionary_
->GetWithoutPathExpansion(shill_property_name
,
720 if (shill_value
->GetType() != field_signature
->value_signature
->onc_type
) {
721 LOG(ERROR
) << "Shill property '" << shill_property_name
<< "' with value "
722 << *shill_value
<< " has base::Value::Type "
723 << shill_value
->GetType() << " but ONC field '"
724 << field_signature
->onc_field_name
<< "' requires type "
725 << field_signature
->value_signature
->onc_type
<< ": "
730 onc_object_
->SetWithoutPathExpansion(field_signature
->onc_field_name
,
731 shill_value
->DeepCopy());
734 void ShillToONCTranslator::TranslateWithTableAndSet(
735 const std::string
& shill_property_name
,
736 const StringTranslationEntry table
[],
737 const std::string
& onc_field_name
) {
738 std::string shill_value
;
739 if (!shill_dictionary_
->GetStringWithoutPathExpansion(shill_property_name
,
743 std::string onc_value
;
744 if (TranslateStringToONC(table
, shill_value
, &onc_value
)) {
745 onc_object_
->SetStringWithoutPathExpansion(onc_field_name
, onc_value
);
748 LOG(ERROR
) << "Shill property '" << shill_property_name
<< "' with value "
749 << shill_value
<< " couldn't be translated to ONC: " << GetName();
752 std::string
ShillToONCTranslator::GetName() {
753 DCHECK(shill_dictionary_
);
755 shill_dictionary_
->GetStringWithoutPathExpansion(shill::kNameProperty
, &name
);
761 scoped_ptr
<base::DictionaryValue
> TranslateShillServiceToONCPart(
762 const base::DictionaryValue
& shill_dictionary
,
763 ::onc::ONCSource onc_source
,
764 const OncValueSignature
* onc_signature
,
765 const NetworkState
* network_state
) {
766 CHECK(onc_signature
!= NULL
);
768 ShillToONCTranslator
translator(shill_dictionary
, onc_source
, *onc_signature
,
770 return translator
.CreateTranslatedONCObject();
774 } // namespace chromeos