Revert of Roll src/third_party/WebKit e0eac24:489c548 (svn 193311:193320) (patchset...
[chromium-blink-merge.git] / chromeos / network / onc / onc_translator_shill_to_onc.cc
bloba97d51e778fe88447e1323aafca65e56d6c11344
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chromeos/network/onc/onc_translator.h"
7 #include <string>
9 #include "base/basictypes.h"
10 #include "base/json/json_reader.h"
11 #include "base/json/json_writer.h"
12 #include "base/logging.h"
13 #include "base/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"
24 namespace chromeos {
25 namespace onc {
27 namespace {
29 // Converts |str| to a base::Value of the given |type|. If the conversion fails,
30 // returns NULL.
31 scoped_ptr<base::Value> ConvertStringToValue(const std::string& str,
32 base::Value::Type type) {
33 base::Value* value;
34 if (type == base::Value::TYPE_STRING) {
35 value = new base::StringValue(str);
36 } else {
37 value = base::JSONReader::Read(str);
40 if (value == NULL || value->GetType() != type) {
41 delete value;
42 value = NULL;
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
50 // are translated.
51 class ShillToONCTranslator {
52 public:
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) {}
71 // Translates the associated Shill dictionary and creates an ONC object of the
72 // given signature.
73 scoped_ptr<base::DictionaryValue> CreateTranslatedONCObject();
75 private:
76 void TranslateEthernet();
77 void TranslateOpenVPN();
78 void TranslateIPsec();
79 void TranslateThirdPartyVPN();
80 void TranslateVPN();
81 void TranslateWiFiWithState();
82 void TranslateWiMAXWithState();
83 void TranslateCellularWithState();
84 void TranslateCellularDevice();
85 void TranslateNetworkWithState();
86 void TranslateIPConfig();
87 void TranslateSavedOrStaticIPConfig();
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
93 // |onc_field_name|.
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
99 // |onc_field_name|.
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
111 // |onc_object_|.
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
116 // base signatures.
117 void CopyPropertiesAccordingToSignature(
118 const OncValueSignature* value_signature);
120 // Applies function CopyProperty to each field of |onc_signature_| and its
121 // base signatures.
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
131 // |onc_object_|.
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_|
137 // for debugging.
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) {
155 TranslateEthernet();
156 } else if (onc_signature_ == &kVPNSignature) {
157 TranslateVPN();
158 } else if (onc_signature_ == &kOpenVPNSignature) {
159 TranslateOpenVPN();
160 } else if (onc_signature_ == &kIPsecSignature) {
161 TranslateIPsec();
162 } else if (onc_signature_ == &kThirdPartyVPNSignature) {
163 TranslateThirdPartyVPN();
164 } else if (onc_signature_ == &kWiFiWithStateSignature) {
165 TranslateWiFiWithState();
166 } else if (onc_signature_ == &kWiMAXWithStateSignature) {
167 TranslateWiMAXWithState();
168 } else if (onc_signature_ == &kCellularWithStateSignature) {
169 if (field_translation_table_ == kCellularDeviceTable)
170 TranslateCellularDevice();
171 else
172 TranslateCellularWithState();
173 } else if (onc_signature_ == &kIPConfigSignature) {
174 TranslateIPConfig();
175 } else if (onc_signature_ == &kSavedIPConfigSignature) {
176 TranslateSavedIPConfig();
177 } else if (onc_signature_ == &kStaticIPConfigSignature) {
178 TranslateStaticIPConfig();
179 } else {
180 CopyPropertiesAccordingToSignature();
182 return onc_object_.Pass();
185 void ShillToONCTranslator::TranslateEthernet() {
186 std::string shill_network_type;
187 shill_dictionary_->GetStringWithoutPathExpansion(shill::kTypeProperty,
188 &shill_network_type);
189 const char* onc_auth = ::onc::ethernet::kAuthenticationNone;
190 if (shill_network_type == shill::kTypeEthernetEap)
191 onc_auth = ::onc::ethernet::k8021X;
192 onc_object_->SetStringWithoutPathExpansion(::onc::ethernet::kAuthentication,
193 onc_auth);
196 void ShillToONCTranslator::TranslateOpenVPN() {
197 if (shill_dictionary_->HasKey(shill::kOpenVPNVerifyX509NameProperty))
198 TranslateAndAddNestedObject(::onc::openvpn::kVerifyX509);
200 // Shill supports only one RemoteCertKU but ONC requires a list. If existing,
201 // wraps the value into a list.
202 std::string certKU;
203 if (shill_dictionary_->GetStringWithoutPathExpansion(
204 shill::kOpenVPNRemoteCertKUProperty, &certKU)) {
205 scoped_ptr<base::ListValue> certKUs(new base::ListValue);
206 certKUs->AppendString(certKU);
207 onc_object_->SetWithoutPathExpansion(::onc::openvpn::kRemoteCertKU,
208 certKUs.release());
211 for (const OncFieldSignature* field_signature = onc_signature_->fields;
212 field_signature->onc_field_name != NULL; ++field_signature) {
213 const std::string& onc_field_name = field_signature->onc_field_name;
214 if (onc_field_name == ::onc::openvpn::kRemoteCertKU ||
215 onc_field_name == ::onc::openvpn::kServerCAPEMs) {
216 CopyProperty(field_signature);
217 continue;
220 std::string shill_property_name;
221 const base::Value* shill_value = NULL;
222 if (!field_translation_table_ ||
223 !GetShillPropertyName(field_signature->onc_field_name,
224 field_translation_table_, &shill_property_name) ||
225 !shill_dictionary_->GetWithoutPathExpansion(shill_property_name,
226 &shill_value)) {
227 continue;
230 scoped_ptr<base::Value> translated;
231 std::string shill_str;
232 if (shill_value->GetAsString(&shill_str)) {
233 // Shill wants all Provider/VPN fields to be strings. Translates these
234 // strings back to the correct ONC type.
235 translated = ConvertStringToValue(
236 shill_str, 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();
244 } else {
245 onc_object_->SetWithoutPathExpansion(onc_field_name,
246 translated.release());
248 } else {
249 LOG(ERROR) << "Shill property '" << shill_property_name << "' has value "
250 << *shill_value << ", but expected a string: " << GetName();
255 void ShillToONCTranslator::TranslateIPsec() {
256 CopyPropertiesAccordingToSignature();
257 if (shill_dictionary_->HasKey(shill::kL2tpIpsecXauthUserProperty))
258 TranslateAndAddNestedObject(::onc::ipsec::kXAUTH);
259 std::string client_cert_id;
260 shill_dictionary_->GetStringWithoutPathExpansion(
261 shill::kL2tpIpsecClientCertIdProperty, &client_cert_id);
262 std::string authentication_type =
263 client_cert_id.empty() ? ::onc::ipsec::kPSK : ::onc::ipsec::kCert;
264 onc_object_->SetStringWithoutPathExpansion(::onc::ipsec::kAuthenticationType,
265 authentication_type);
268 void ShillToONCTranslator::TranslateThirdPartyVPN() {
269 CopyPropertiesAccordingToSignature();
271 // For third-party VPNs, |shill::kProviderHostProperty| is used to store the
272 // provider's extension ID.
273 std::string shill_extension_id;
274 shill_dictionary_->GetStringWithoutPathExpansion(shill::kHostProperty,
275 &shill_extension_id);
276 onc_object_->SetStringWithoutPathExpansion(
277 ::onc::third_party_vpn::kExtensionID, shill_extension_id);
280 void ShillToONCTranslator::TranslateVPN() {
281 CopyPropertiesAccordingToSignature();
283 // Parse Shill Provider dictionary. Note, this may not exist, e.g. if we are
284 // just translating network state in network_util::TranslateNetworkStateToONC.
285 const base::DictionaryValue* provider = NULL;
286 if (!shill_dictionary_->GetDictionaryWithoutPathExpansion(
287 shill::kProviderProperty, &provider)) {
288 return;
290 std::string shill_provider_type, onc_provider_type;
291 provider->GetStringWithoutPathExpansion(shill::kTypeProperty,
292 &shill_provider_type);
293 if (!TranslateStringToONC(kVPNTypeTable, shill_provider_type,
294 &onc_provider_type)) {
295 return;
297 onc_object_->SetStringWithoutPathExpansion(::onc::vpn::kType,
298 onc_provider_type);
299 std::string shill_provider_host;
300 if (onc_provider_type != ::onc::vpn::kThirdPartyVpn &&
301 provider->GetStringWithoutPathExpansion(shill::kHostProperty,
302 &shill_provider_host)) {
303 onc_object_->SetStringWithoutPathExpansion(::onc::vpn::kHost,
304 shill_provider_host);
307 // Translate the nested dictionary.
308 std::string provider_type_dictionary;
309 if (onc_provider_type == ::onc::vpn::kTypeL2TP_IPsec) {
310 TranslateAndAddNestedObject(::onc::vpn::kIPsec, *provider);
311 TranslateAndAddNestedObject(::onc::vpn::kL2TP, *provider);
312 provider_type_dictionary = ::onc::vpn::kIPsec;
313 } else {
314 TranslateAndAddNestedObject(onc_provider_type, *provider);
315 provider_type_dictionary = onc_provider_type;
318 bool save_credentials;
319 if (onc_provider_type != ::onc::vpn::kThirdPartyVpn &&
320 shill_dictionary_->GetBooleanWithoutPathExpansion(
321 shill::kSaveCredentialsProperty, &save_credentials)) {
322 SetNestedOncValue(provider_type_dictionary, ::onc::vpn::kSaveCredentials,
323 base::FundamentalValue(save_credentials));
327 void ShillToONCTranslator::TranslateWiFiWithState() {
328 TranslateWithTableAndSet(shill::kSecurityClassProperty, kWiFiSecurityTable,
329 ::onc::wifi::kSecurity);
330 bool unknown_encoding = true;
331 std::string ssid = shill_property_util::GetSSIDFromProperties(
332 *shill_dictionary_, false /* verbose_logging */, &unknown_encoding);
333 if (!unknown_encoding && !ssid.empty())
334 onc_object_->SetStringWithoutPathExpansion(::onc::wifi::kSSID, ssid);
336 bool link_monitor_disable;
337 if (shill_dictionary_->GetBooleanWithoutPathExpansion(
338 shill::kLinkMonitorDisableProperty, &link_monitor_disable)) {
339 onc_object_->SetBooleanWithoutPathExpansion(
340 ::onc::wifi::kAllowGatewayARPPolling, !link_monitor_disable);
343 CopyPropertiesAccordingToSignature();
344 TranslateAndAddNestedObject(::onc::wifi::kEAP);
347 void ShillToONCTranslator::TranslateWiMAXWithState() {
348 CopyPropertiesAccordingToSignature();
349 TranslateAndAddNestedObject(::onc::wimax::kEAP);
352 void ShillToONCTranslator::TranslateCellularWithState() {
353 CopyPropertiesAccordingToSignature();
354 TranslateWithTableAndSet(shill::kActivationStateProperty,
355 kActivationStateTable,
356 ::onc::cellular::kActivationState);
357 TranslateWithTableAndSet(shill::kNetworkTechnologyProperty,
358 kNetworkTechnologyTable,
359 ::onc::cellular::kNetworkTechnology);
360 const base::DictionaryValue* dictionary = NULL;
361 if (shill_dictionary_->GetDictionaryWithoutPathExpansion(
362 shill::kServingOperatorProperty, &dictionary)) {
363 TranslateAndAddNestedObject(::onc::cellular::kServingOperator, *dictionary);
365 if (shill_dictionary_->GetDictionaryWithoutPathExpansion(
366 shill::kCellularApnProperty, &dictionary)) {
367 TranslateAndAddNestedObject(::onc::cellular::kAPN, *dictionary);
369 if (shill_dictionary_->GetDictionaryWithoutPathExpansion(
370 shill::kCellularLastGoodApnProperty, &dictionary)) {
371 TranslateAndAddNestedObject(::onc::cellular::kLastGoodAPN, *dictionary);
373 const base::DictionaryValue* device_dictionary = NULL;
374 bool requires_roaming = false;
375 shill_dictionary_->GetDictionaryWithoutPathExpansion(shill::kDeviceProperty,
376 &device_dictionary);
377 if (device_dictionary) {
378 // Merge the Device dictionary with this one (Cellular) using the
379 // CellularDevice signature.
380 ShillToONCTranslator nested_translator(*device_dictionary, onc_source_,
381 kCellularWithStateSignature,
382 kCellularDeviceTable);
383 scoped_ptr<base::DictionaryValue> nested_object =
384 nested_translator.CreateTranslatedONCObject();
385 onc_object_->MergeDictionary(nested_object.get());
387 /// Get the requires_roaming from the Device dictionary.
388 device_dictionary->GetBooleanWithoutPathExpansion(
389 shill::kProviderRequiresRoamingProperty, &requires_roaming);
391 if (requires_roaming) {
392 onc_object_->SetStringWithoutPathExpansion(
393 ::onc::cellular::kRoamingState, ::onc::cellular::kRoamingRequired);
394 } else {
395 TranslateWithTableAndSet(shill::kRoamingStateProperty, kRoamingStateTable,
396 ::onc::cellular::kRoamingState);
400 void ShillToONCTranslator::TranslateCellularDevice() {
401 CopyPropertiesAccordingToSignature();
402 const base::DictionaryValue* shill_sim_lock_status = NULL;
403 if (shill_dictionary_->GetDictionaryWithoutPathExpansion(
404 shill::kSIMLockStatusProperty, &shill_sim_lock_status)) {
405 TranslateAndAddNestedObject(::onc::cellular::kSIMLockStatus,
406 *shill_sim_lock_status);
408 const base::DictionaryValue* shill_home_provider = NULL;
409 if (shill_dictionary_->GetDictionaryWithoutPathExpansion(
410 shill::kHomeProviderProperty, &shill_home_provider)) {
411 TranslateAndAddNestedObject(::onc::cellular::kHomeProvider,
412 *shill_home_provider);
414 const base::ListValue* shill_apns = NULL;
415 if (shill_dictionary_->GetListWithoutPathExpansion(
416 shill::kCellularApnListProperty, &shill_apns)) {
417 TranslateAndAddListOfObjects(::onc::cellular::kAPNList, *shill_apns);
419 const base::ListValue* shill_found_networks = NULL;
420 if (shill_dictionary_->GetListWithoutPathExpansion(
421 shill::kFoundNetworksProperty, &shill_found_networks)) {
422 TranslateAndAddListOfObjects(::onc::cellular::kFoundNetworks,
423 *shill_found_networks);
427 void ShillToONCTranslator::TranslateNetworkWithState() {
428 CopyPropertiesAccordingToSignature();
430 std::string shill_network_type;
431 shill_dictionary_->GetStringWithoutPathExpansion(shill::kTypeProperty,
432 &shill_network_type);
433 std::string onc_network_type = ::onc::network_type::kEthernet;
434 if (shill_network_type != shill::kTypeEthernet &&
435 shill_network_type != shill::kTypeEthernetEap) {
436 TranslateStringToONC(kNetworkTypeTable, shill_network_type,
437 &onc_network_type);
439 // Translate nested Cellular, WiFi, etc. properties.
440 if (!onc_network_type.empty()) {
441 onc_object_->SetStringWithoutPathExpansion(::onc::network_config::kType,
442 onc_network_type);
443 TranslateAndAddNestedObject(onc_network_type);
446 // Since Name is a read only field in Shill unless it's a VPN, it is copied
447 // here, but not when going the other direction (if it's not a VPN).
448 std::string name;
449 shill_dictionary_->GetStringWithoutPathExpansion(shill::kNameProperty, &name);
450 onc_object_->SetStringWithoutPathExpansion(::onc::network_config::kName,
451 name);
453 // Limit ONC state to "NotConnected", "Connected", or "Connecting".
454 std::string state;
455 if (shill_dictionary_->GetStringWithoutPathExpansion(shill::kStateProperty,
456 &state)) {
457 std::string onc_state = ::onc::connection_state::kNotConnected;
458 if (NetworkState::StateIsConnected(state)) {
459 onc_state = ::onc::connection_state::kConnected;
460 } else if (NetworkState::StateIsConnecting(state)) {
461 onc_state = ::onc::connection_state::kConnecting;
463 onc_object_->SetStringWithoutPathExpansion(
464 ::onc::network_config::kConnectionState, onc_state);
465 // Only set 'RestrictedConnectivity' if captive portal state is true.
466 if (NetworkState::NetworkStateIsCaptivePortal(*shill_dictionary_)) {
467 onc_object_->SetBooleanWithoutPathExpansion(
468 ::onc::network_config::kRestrictedConnectivity, true);
472 std::string profile_path;
473 if (onc_source_ != ::onc::ONC_SOURCE_UNKNOWN &&
474 shill_dictionary_->GetStringWithoutPathExpansion(shill::kProfileProperty,
475 &profile_path)) {
476 std::string source;
477 if (onc_source_ == ::onc::ONC_SOURCE_DEVICE_POLICY)
478 source = ::onc::network_config::kSourceDevicePolicy;
479 else if (onc_source_ == ::onc::ONC_SOURCE_USER_POLICY)
480 source = ::onc::network_config::kSourceUserPolicy;
481 else if (profile_path == NetworkProfileHandler::GetSharedProfilePath())
482 source = ::onc::network_config::kSourceDevice;
483 else if (!profile_path.empty())
484 source = ::onc::network_config::kSourceUser;
485 else
486 source = ::onc::network_config::kSourceNone;
487 onc_object_->SetStringWithoutPathExpansion(::onc::network_config::kSource,
488 source);
491 // Use a human-readable aa:bb format for any hardware MAC address. Note:
492 // this property is provided by the caller but is not part of the Shill
493 // Service properties (it is copied from the Device properties).
494 std::string address;
495 if (shill_dictionary_->GetStringWithoutPathExpansion(shill::kAddressProperty,
496 &address)) {
497 onc_object_->SetStringWithoutPathExpansion(
498 ::onc::network_config::kMacAddress,
499 network_util::FormattedMacAddress(address));
502 // Shill's Service has an IPConfig property (note the singular), not an
503 // IPConfigs property. However, we require the caller of the translation to
504 // patch the Shill dictionary before passing it to the translator.
505 const base::ListValue* shill_ipconfigs = NULL;
506 if (shill_dictionary_->GetListWithoutPathExpansion(shill::kIPConfigsProperty,
507 &shill_ipconfigs)) {
508 TranslateAndAddListOfObjects(::onc::network_config::kIPConfigs,
509 *shill_ipconfigs);
512 const base::DictionaryValue* saved_ipconfig = nullptr;
513 if (shill_dictionary_->GetDictionaryWithoutPathExpansion(
514 shill::kSavedIPConfigProperty, &saved_ipconfig)) {
515 TranslateAndAddNestedObject(::onc::network_config::kSavedIPConfig,
516 *saved_ipconfig);
519 // Translate the StaticIPConfig object and set the IP config types.
520 const base::DictionaryValue* static_ipconfig = nullptr;
521 if (shill_dictionary_->GetDictionaryWithoutPathExpansion(
522 shill::kStaticIPConfigProperty, &static_ipconfig)) {
523 std::string ip_address;
524 if (static_ipconfig->GetStringWithoutPathExpansion(shill::kAddressProperty,
525 &ip_address) &&
526 !ip_address.empty()) {
527 onc_object_->SetStringWithoutPathExpansion(
528 ::onc::network_config::kIPAddressConfigType,
529 ::onc::network_config::kIPConfigTypeStatic);
531 const base::ListValue* name_servers = nullptr;
532 if (static_ipconfig->GetListWithoutPathExpansion(
533 shill::kNameServersProperty, &name_servers) &&
534 !name_servers->empty()) {
535 onc_object_->SetStringWithoutPathExpansion(
536 ::onc::network_config::kNameServersConfigType,
537 ::onc::network_config::kIPConfigTypeStatic);
539 if (!ip_address.empty() || (name_servers && !name_servers->empty())) {
540 TranslateAndAddNestedObject(::onc::network_config::kStaticIPConfig,
541 *static_ipconfig);
546 void ShillToONCTranslator::TranslateIPConfig() {
547 CopyPropertiesAccordingToSignature();
548 std::string shill_ip_method;
549 shill_dictionary_->GetStringWithoutPathExpansion(shill::kMethodProperty,
550 &shill_ip_method);
551 std::string type;
552 if (shill_ip_method == shill::kTypeIPv4 ||
553 shill_ip_method == shill::kTypeDHCP) {
554 type = ::onc::ipconfig::kIPv4;
555 } else if (shill_ip_method == shill::kTypeIPv6 ||
556 shill_ip_method == shill::kTypeDHCP6) {
557 type = ::onc::ipconfig::kIPv6;
558 } else {
559 return; // Ignore unhandled IPConfig types, e.g. bootp, zeroconf, ppp
562 onc_object_->SetStringWithoutPathExpansion(::onc::ipconfig::kType, type);
565 void ShillToONCTranslator::TranslateSavedOrStaticIPConfig() {
566 CopyPropertiesAccordingToSignature();
568 // Static and Saved IPConfig in Shill are always of type IPv4. Set this type
569 // in ONC, but not if the object would be empty except the type.
570 if (!onc_object_->empty()) {
571 onc_object_->SetStringWithoutPathExpansion(::onc::ipconfig::kType,
572 ::onc::ipconfig::kIPv4);
576 void ShillToONCTranslator::TranslateSavedIPConfig() {
577 TranslateSavedOrStaticIPConfig();
580 void ShillToONCTranslator::TranslateStaticIPConfig() {
581 TranslateSavedOrStaticIPConfig();
584 void ShillToONCTranslator::TranslateAndAddNestedObject(
585 const std::string& onc_field_name) {
586 TranslateAndAddNestedObject(onc_field_name, *shill_dictionary_);
589 void ShillToONCTranslator::TranslateAndAddNestedObject(
590 const std::string& onc_field_name,
591 const base::DictionaryValue& dictionary) {
592 const OncFieldSignature* field_signature =
593 GetFieldSignature(*onc_signature_, onc_field_name);
594 if (!field_signature) {
595 NOTREACHED() << "Unable to find signature for field: " << onc_field_name;
596 return;
598 ShillToONCTranslator nested_translator(dictionary, onc_source_,
599 *field_signature->value_signature);
600 scoped_ptr<base::DictionaryValue> nested_object =
601 nested_translator.CreateTranslatedONCObject();
602 if (nested_object->empty())
603 return;
604 onc_object_->SetWithoutPathExpansion(onc_field_name, nested_object.release());
607 void ShillToONCTranslator::SetNestedOncValue(
608 const std::string& onc_dictionary_name,
609 const std::string& onc_field_name,
610 const base::Value& value) {
611 base::DictionaryValue* nested;
612 if (!onc_object_->GetDictionaryWithoutPathExpansion(onc_dictionary_name,
613 &nested)) {
614 nested = new base::DictionaryValue;
615 onc_object_->SetWithoutPathExpansion(onc_dictionary_name, nested);
617 nested->SetWithoutPathExpansion(onc_field_name, value.DeepCopy());
620 void ShillToONCTranslator::TranslateAndAddListOfObjects(
621 const std::string& onc_field_name,
622 const base::ListValue& list) {
623 const OncFieldSignature* field_signature =
624 GetFieldSignature(*onc_signature_, onc_field_name);
625 if (field_signature->value_signature->onc_type != base::Value::TYPE_LIST) {
626 LOG(ERROR) << "ONC Field name: '" << onc_field_name << "' has type '"
627 << field_signature->value_signature->onc_type
628 << "', expected: base::Value::TYPE_LIST: " << GetName();
629 return;
631 DCHECK(field_signature->value_signature->onc_array_entry_signature);
632 scoped_ptr<base::ListValue> result(new base::ListValue());
633 for (base::ListValue::const_iterator it = list.begin(); it != list.end();
634 ++it) {
635 const base::DictionaryValue* shill_value = NULL;
636 if (!(*it)->GetAsDictionary(&shill_value))
637 continue;
638 ShillToONCTranslator nested_translator(
639 *shill_value, onc_source_,
640 *field_signature->value_signature->onc_array_entry_signature);
641 scoped_ptr<base::DictionaryValue> nested_object =
642 nested_translator.CreateTranslatedONCObject();
643 // If the nested object couldn't be parsed, simply omit it.
644 if (nested_object->empty())
645 continue;
646 result->Append(nested_object.release());
648 // If there are no entries in the list, there is no need to expose this field.
649 if (result->empty())
650 return;
651 onc_object_->SetWithoutPathExpansion(onc_field_name, result.release());
654 void ShillToONCTranslator::CopyPropertiesAccordingToSignature() {
655 CopyPropertiesAccordingToSignature(onc_signature_);
658 void ShillToONCTranslator::CopyPropertiesAccordingToSignature(
659 const OncValueSignature* value_signature) {
660 if (value_signature->base_signature)
661 CopyPropertiesAccordingToSignature(value_signature->base_signature);
662 if (!value_signature->fields)
663 return;
664 for (const OncFieldSignature* field_signature = value_signature->fields;
665 field_signature->onc_field_name != NULL; ++field_signature) {
666 CopyProperty(field_signature);
670 void ShillToONCTranslator::CopyProperty(
671 const OncFieldSignature* field_signature) {
672 std::string shill_property_name;
673 const base::Value* shill_value = NULL;
674 if (!field_translation_table_ ||
675 !GetShillPropertyName(field_signature->onc_field_name,
676 field_translation_table_, &shill_property_name) ||
677 !shill_dictionary_->GetWithoutPathExpansion(shill_property_name,
678 &shill_value)) {
679 return;
682 if (shill_value->GetType() != field_signature->value_signature->onc_type) {
683 LOG(ERROR) << "Shill property '" << shill_property_name << "' with value "
684 << *shill_value << " has base::Value::Type "
685 << shill_value->GetType() << " but ONC field '"
686 << field_signature->onc_field_name << "' requires type "
687 << field_signature->value_signature->onc_type << ": "
688 << GetName();
689 return;
692 onc_object_->SetWithoutPathExpansion(field_signature->onc_field_name,
693 shill_value->DeepCopy());
696 void ShillToONCTranslator::TranslateWithTableAndSet(
697 const std::string& shill_property_name,
698 const StringTranslationEntry table[],
699 const std::string& onc_field_name) {
700 std::string shill_value;
701 if (!shill_dictionary_->GetStringWithoutPathExpansion(shill_property_name,
702 &shill_value)) {
703 return;
705 std::string onc_value;
706 if (TranslateStringToONC(table, shill_value, &onc_value)) {
707 onc_object_->SetStringWithoutPathExpansion(onc_field_name, onc_value);
708 return;
710 LOG(ERROR) << "Shill property '" << shill_property_name << "' with value "
711 << shill_value << " couldn't be translated to ONC: " << GetName();
714 std::string ShillToONCTranslator::GetName() {
715 DCHECK(shill_dictionary_);
716 std::string name;
717 shill_dictionary_->GetStringWithoutPathExpansion(shill::kNameProperty, &name);
718 return name;
721 } // namespace
723 scoped_ptr<base::DictionaryValue> TranslateShillServiceToONCPart(
724 const base::DictionaryValue& shill_dictionary,
725 ::onc::ONCSource onc_source,
726 const OncValueSignature* onc_signature) {
727 CHECK(onc_signature != NULL);
729 ShillToONCTranslator translator(shill_dictionary, onc_source, *onc_signature);
730 return translator.CreateTranslatedONCObject();
733 } // namespace onc
734 } // namespace chromeos