// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <memory>
#include <string>
#include <utility>

#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "chromeos/network/network_profile_handler.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_util.h"
#include "chromeos/network/onc/onc_signature.h"
#include "chromeos/network/onc/onc_translation_tables.h"
#include "chromeos/network/onc/onc_translator.h"
#include "chromeos/network/onc/onc_utils.h"
#include "chromeos/network/shill_property_util.h"
#include "components/device_event_log/device_event_log.h"
#include "components/onc/onc_constants.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"

namespace chromeos {
namespace onc {

namespace {

// Converts a VPN string to a base::Value of the given |type|. If the conversion
// fails, returns a default value for |type|.
base::Value ConvertVpnStringToValue(const std::string& str,
                                    base::Value::Type type) {
  if (type == base::Value::Type::STRING)
    return base::Value(str);

  base::Optional<base::Value> value = base::JSONReader::Read(str);
  if (!value || value->type() != type)
    return base::Value(type);

  return std::move(*value);
}

// Returns the string value of |key| from |dict| if found, or the empty string
// otherwise.
std::string FindStringKeyOrEmpty(const base::Value* dict,
                                 base::StringPiece key) {
  const std::string* value = dict->FindStringKey(key);
  return value ? *value : std::string();
}

// If the network is configured with an installed certificate, a PKCS11 id will
// be set which is provided for the UI to display certificate information.
// Returns true if the PKCS11 id is available and set.
bool SetPKCS11Id(const base::Value* shill_dictionary,
                 const char* cert_id_property,
                 const char* cert_slot_property,
                 base::Value* onc_object) {
  const std::string* shill_cert_id =
      shill_dictionary->FindStringKey(cert_id_property);
  if (!shill_cert_id || shill_cert_id->empty()) {
    return false;
  }

  const std::string* shill_slot =
      shill_dictionary->FindStringKey(cert_slot_property);
  std::string pkcs11_id;
  if (shill_slot && !shill_slot->empty()) {
    pkcs11_id = *shill_slot + ":" + *shill_cert_id;
  } else {
    pkcs11_id = *shill_cert_id;
  }

  onc_object->SetKey(::onc::client_cert::kClientCertType,
                     base::Value(::onc::client_cert::kPKCS11Id));
  onc_object->SetKey(::onc::client_cert::kClientCertPKCS11Id,
                     base::Value(pkcs11_id));
  return true;
}

// This class implements the translation of properties from the given
// |shill_dictionary| to a new ONC object of signature |onc_signature|. Using
// recursive calls to CreateTranslatedONCObject of new instances, nested objects
// are translated.
class ShillToONCTranslator {
 public:
  ShillToONCTranslator(const base::Value& shill_dictionary,
                       ::onc::ONCSource onc_source,
                       const OncValueSignature& onc_signature,
                       const NetworkState* network_state)
      : shill_dictionary_(&shill_dictionary),
        onc_source_(onc_source),
        onc_signature_(&onc_signature),
        network_state_(network_state) {
    field_translation_table_ = GetFieldTranslationTable(onc_signature);
  }

  ShillToONCTranslator(const base::Value& shill_dictionary,
                       ::onc::ONCSource onc_source,
                       const OncValueSignature& onc_signature,
                       const FieldTranslationEntry* field_translation_table,
                       const NetworkState* network_state)
      : shill_dictionary_(&shill_dictionary),
        onc_source_(onc_source),
        onc_signature_(&onc_signature),
        field_translation_table_(field_translation_table),
        network_state_(network_state) {}

  // Translates the associated Shill dictionary and creates an ONC object of the
  // given signature.
  std::unique_ptr<base::DictionaryValue> CreateTranslatedONCObject();

 private:
  void TranslateEthernet();
  void TranslateOpenVPN();
  void TranslateIPsec();
  void TranslateL2TP();
  void TranslateThirdPartyVPN();
  void TranslateVPN();
  void TranslateWiFiWithState();
  void TranslateCellularWithState();
  void TranslateCellularDevice();
  void TranslateNetworkWithState();
  void TranslateIPConfig();
  void TranslateSavedOrStaticIPConfig();
  void TranslateSavedIPConfig();
  void TranslateStaticIPConfig();
  void TranslateEap();

  // Creates an ONC object from |dictionary| according to the signature
  // associated to |onc_field_name| and adds it to |onc_object_| at
  // |onc_field_name|.
  void TranslateAndAddNestedObject(const std::string& onc_field_name,
                                   const base::Value& dictionary);

  // Creates an ONC object from |shill_dictionary_| according to the signature
  // associated to |onc_field_name| and adds it to |onc_object_| at
  // |onc_field_name|.
  void TranslateAndAddNestedObject(const std::string& onc_field_name);

  // Sets |onc_field_name| in dictionary |onc_dictionary_name| in |onc_object_|
  // to |value| if the dictionary exists.
  void SetNestedOncValue(const std::string& onc_dictionary_name,
                         const std::string& onc_field_name,
                         const base::Value& value);

  // Translates a list of nested objects and adds the list to |onc_object_| at
  // |onc_field_name|. If there are errors while parsing individual objects or
  // if the resulting list contains no entries, the result will not be added to
  // |onc_object_|.
  void TranslateAndAddListOfObjects(const std::string& onc_field_name,
                                    const base::Value& list);

  // Applies function CopyProperty to each field of |value_signature| and its
  // base signatures.
  void CopyPropertiesAccordingToSignature(
      const OncValueSignature* value_signature);

  // Applies function CopyProperty to each field of |onc_signature_| and its
  // base signatures.
  void CopyPropertiesAccordingToSignature();

  // If |shill_property_name| is defined in |field_signature|, copies this
  // entry from |shill_dictionary_| to |onc_object_| if it exists.
  void CopyProperty(const OncFieldSignature* field_signature);

  // If existent, translates the entry at |shill_property_name| in
  // |shill_dictionary_| using |table|. It is an error if no matching table
  // entry is found. Writes the result as entry at |onc_field_name| in
  // |onc_object_|.
  void TranslateWithTableAndSet(const std::string& shill_property_name,
                                const StringTranslationEntry table[],
                                const std::string& onc_field_name);

  // Returns the name of the Shill service provided in |shill_dictionary_|
  // for debugging.
  std::string GetName();

  const base::Value* shill_dictionary_;
  ::onc::ONCSource onc_source_;
  const OncValueSignature* onc_signature_;
  const FieldTranslationEntry* field_translation_table_;
  std::unique_ptr<base::Value> onc_object_;
  const NetworkState* network_state_;

  DISALLOW_COPY_AND_ASSIGN(ShillToONCTranslator);
};

std::unique_ptr<base::DictionaryValue>
ShillToONCTranslator::CreateTranslatedONCObject() {
  onc_object_.reset(new base::Value(base::Value::Type::DICTIONARY));
  if (onc_signature_ == &kNetworkWithStateSignature) {
    TranslateNetworkWithState();
  } else if (onc_signature_ == &kEthernetSignature) {
    TranslateEthernet();
  } else if (onc_signature_ == &kVPNSignature) {
    TranslateVPN();
  } else if (onc_signature_ == &kOpenVPNSignature) {
    TranslateOpenVPN();
  } else if (onc_signature_ == &kIPsecSignature) {
    TranslateIPsec();
  } else if (onc_signature_ == &kL2TPSignature) {
    TranslateL2TP();
  } else if (onc_signature_ == &kThirdPartyVPNSignature) {
    TranslateThirdPartyVPN();
  } else if (onc_signature_ == &kWiFiWithStateSignature) {
    TranslateWiFiWithState();
  } else if (onc_signature_ == &kCellularWithStateSignature) {
    if (field_translation_table_ == kCellularDeviceTable)
      TranslateCellularDevice();
    else
      TranslateCellularWithState();
  } else if (onc_signature_ == &kIPConfigSignature) {
    TranslateIPConfig();
  } else if (onc_signature_ == &kSavedIPConfigSignature) {
    TranslateSavedIPConfig();
  } else if (onc_signature_ == &kStaticIPConfigSignature) {
    TranslateStaticIPConfig();
  } else if (onc_signature_ == &kEAPSignature) {
    TranslateEap();
  } else {
    CopyPropertiesAccordingToSignature();
  }
  return base::DictionaryValue::From(std::move(onc_object_));
}

void ShillToONCTranslator::TranslateEthernet() {
  const std::string* shill_network_type =
      shill_dictionary_->FindStringKey(shill::kTypeProperty);
  const char* onc_auth = ::onc::ethernet::kAuthenticationNone;
  if (shill_network_type && *shill_network_type == shill::kTypeEthernetEap)
    onc_auth = ::onc::ethernet::k8021X;
  onc_object_->SetKey(::onc::ethernet::kAuthentication, base::Value(onc_auth));

  if (shill_network_type && *shill_network_type == shill::kTypeEthernetEap)
    TranslateAndAddNestedObject(::onc::ethernet::kEAP);
}

void ShillToONCTranslator::TranslateOpenVPN() {
  if (shill_dictionary_->FindKey(shill::kOpenVPNVerifyX509NameProperty))
    TranslateAndAddNestedObject(::onc::openvpn::kVerifyX509);

  // Shill supports only one RemoteCertKU but ONC requires a list. If existing,
  // wraps the value into a list.
  const std::string* certKU =
      shill_dictionary_->FindStringKey(shill::kOpenVPNRemoteCertKUProperty);
  if (certKU) {
    base::Value certKUs(base::Value::Type::LIST);
    certKUs.Append(base::Value(*certKU));
    onc_object_->SetKey(::onc::openvpn::kRemoteCertKU, std::move(certKUs));
  }

  SetPKCS11Id(shill_dictionary_, shill::kOpenVPNClientCertIdProperty, "",
              onc_object_.get());

  TranslateWithTableAndSet(shill::kOpenVPNCompressProperty,
                           kOpenVpnCompressionAlgorithmTable,
                           ::onc::openvpn::kCompressionAlgorithm);

  for (const OncFieldSignature* field_signature = onc_signature_->fields;
       field_signature->onc_field_name != NULL; ++field_signature) {
    const std::string& onc_field_name = field_signature->onc_field_name;
    if (onc_field_name == ::onc::openvpn::kRemoteCertKU ||
        onc_field_name == ::onc::openvpn::kServerCAPEMs) {
      CopyProperty(field_signature);
      continue;
    }

    std::string shill_property_name;
    if (!field_translation_table_ ||
        !GetShillPropertyName(field_signature->onc_field_name,
                              field_translation_table_, &shill_property_name)) {
      continue;
    }
    const base::Value* shill_value =
        shill_dictionary_->FindKey(shill_property_name);
    if (!shill_value) {
      continue;
    }

    std::string shill_str;
    if (shill_value->GetAsString(&shill_str)) {
      // Shill wants all Provider/VPN fields to be strings. Translates these
      // strings back to the correct ONC type.
      base::Value translated = ConvertVpnStringToValue(
          shill_str, field_signature->value_signature->onc_type);

      if (translated.is_none()) {
        NET_LOG(ERROR) << "Shill property '" << shill_property_name
                       << "' with value " << *shill_value
                       << " couldn't be converted to base::Value::Type "
                       << field_signature->value_signature->onc_type << ": "
                       << GetName();
      } else {
        onc_object_->SetKey(onc_field_name, std::move(translated));
      }
    } else {
      NET_LOG(ERROR) << "Shill property '" << shill_property_name
                     << "' has value " << *shill_value
                     << ", but expected a string: " << GetName();
    }
  }
}

void ShillToONCTranslator::TranslateIPsec() {
  CopyPropertiesAccordingToSignature();
  if (shill_dictionary_->FindKey(shill::kL2tpIpsecXauthUserProperty))
    TranslateAndAddNestedObject(::onc::ipsec::kXAUTH);

  std::string authentication_type;
  if (SetPKCS11Id(shill_dictionary_, shill::kL2tpIpsecClientCertIdProperty,
                  shill::kL2tpIpsecClientCertSlotProperty, onc_object_.get())) {
    authentication_type = ::onc::ipsec::kCert;
  } else {
    authentication_type = ::onc::ipsec::kPSK;
  }
  onc_object_->SetKey(::onc::ipsec::kAuthenticationType,
                      base::Value(authentication_type));
}

void ShillToONCTranslator::TranslateL2TP() {
  CopyPropertiesAccordingToSignature();

  const base::Value* lcp_echo_disabled =
      shill_dictionary_->FindKey(shill::kL2tpIpsecLcpEchoDisabledProperty);
  if (lcp_echo_disabled && lcp_echo_disabled->is_string()) {
    base::Value lcp_echo_disabled_value = ConvertVpnStringToValue(
        lcp_echo_disabled->GetString(), base::Value::Type::BOOLEAN);
    onc_object_->SetKey(::onc::l2tp::kLcpEchoDisabled,
                        std::move(lcp_echo_disabled_value));
  }
}

void ShillToONCTranslator::TranslateThirdPartyVPN() {
  CopyPropertiesAccordingToSignature();

  // For third-party VPNs, |shill::kProviderHostProperty| is used to store the
  // provider's extension ID.
  const std::string* shill_extension_id =
      shill_dictionary_->FindStringKey(shill::kHostProperty);
  onc_object_->SetKey(
      ::onc::third_party_vpn::kExtensionID,
      base::Value(shill_extension_id ? *shill_extension_id : std::string()));
}

void ShillToONCTranslator::TranslateVPN() {
  CopyPropertiesAccordingToSignature();

  // Parse Shill Provider dictionary. Note, this may not exist, e.g. if we are
  // just translating network state in network_util::TranslateNetworkStateToONC.
  const base::Value* provider =
      shill_dictionary_->FindDictKey(shill::kProviderProperty);
  if (!provider) {
    return;
  }
  std::string shill_provider_type =
      FindStringKeyOrEmpty(provider, shill::kTypeProperty);
  std::string onc_provider_type;
  if (!TranslateStringToONC(kVPNTypeTable, shill_provider_type,
                            &onc_provider_type)) {
    return;
  }
  onc_object_->SetKey(::onc::vpn::kType, base::Value(onc_provider_type));
  const std::string* shill_provider_host =
      provider->FindStringKey(shill::kHostProperty);
  if (onc_provider_type != ::onc::vpn::kThirdPartyVpn && shill_provider_host) {
    onc_object_->SetKey(::onc::vpn::kHost, base::Value(*shill_provider_host));
  }

  // Translate the nested dictionary.
  std::string provider_type_dictionary;
  if (onc_provider_type == ::onc::vpn::kTypeL2TP_IPsec) {
    TranslateAndAddNestedObject(::onc::vpn::kIPsec, *provider);
    TranslateAndAddNestedObject(::onc::vpn::kL2TP, *provider);
    provider_type_dictionary = ::onc::vpn::kIPsec;
  } else {
    TranslateAndAddNestedObject(onc_provider_type, *provider);
    provider_type_dictionary = onc_provider_type;
  }

  base::Optional<bool> save_credentials =
      shill_dictionary_->FindBoolKey(shill::kSaveCredentialsProperty);
  if (onc_provider_type != ::onc::vpn::kThirdPartyVpn &&
      onc_provider_type != ::onc::vpn::kArcVpn && save_credentials) {
    SetNestedOncValue(provider_type_dictionary, ::onc::vpn::kSaveCredentials,
                      base::Value(*save_credentials));
  }
}

void ShillToONCTranslator::TranslateWiFiWithState() {
  const std::string* shill_security =
      shill_dictionary_->FindStringKey(shill::kSecurityClassProperty);
  const std::string* shill_key_mgmt =
      shill_dictionary_->FindStringKey(shill::kEapKeyMgmtProperty);
  if (shill_security && *shill_security == shill::kSecurityWep &&
      shill_key_mgmt && *shill_key_mgmt == shill::kKeyManagementIEEE8021X) {
    onc_object_->SetKey(::onc::wifi::kSecurity,
                        base::Value(::onc::wifi::kWEP_8021X));
  } else {
    TranslateWithTableAndSet(shill::kSecurityClassProperty, kWiFiSecurityTable,
                             ::onc::wifi::kSecurity);
  }

  bool unknown_encoding = true;
  std::string ssid = shill_property_util::GetSSIDFromProperties(
      *shill_dictionary_, false /* verbose_logging */, &unknown_encoding);
  if (!unknown_encoding && !ssid.empty())
    onc_object_->SetKey(::onc::wifi::kSSID, base::Value(ssid));

  base::Optional<bool> link_monitor_disable =
      shill_dictionary_->FindBoolKey(shill::kLinkMonitorDisableProperty);
  if (link_monitor_disable) {
    onc_object_->SetKey(::onc::wifi::kAllowGatewayARPPolling,
                        base::Value(!*link_monitor_disable));
  }

  CopyPropertiesAccordingToSignature();
  TranslateAndAddNestedObject(::onc::wifi::kEAP);
}

void ShillToONCTranslator::TranslateCellularWithState() {
  CopyPropertiesAccordingToSignature();
  TranslateWithTableAndSet(shill::kActivationStateProperty,
                           kActivationStateTable,
                           ::onc::cellular::kActivationState);
  TranslateWithTableAndSet(shill::kNetworkTechnologyProperty,
                           kNetworkTechnologyTable,
                           ::onc::cellular::kNetworkTechnology);
  const base::Value* dictionary =
      shill_dictionary_->FindDictKey(shill::kServingOperatorProperty);
  if (dictionary) {
    TranslateAndAddNestedObject(::onc::cellular::kServingOperator, *dictionary);
  }
  dictionary = shill_dictionary_->FindDictKey(shill::kCellularApnProperty);
  if (dictionary) {
    TranslateAndAddNestedObject(::onc::cellular::kAPN, *dictionary);
  }
  dictionary =
      shill_dictionary_->FindDictKey(shill::kCellularLastGoodApnProperty);
  if (dictionary) {
    TranslateAndAddNestedObject(::onc::cellular::kLastGoodAPN, *dictionary);
  }
  dictionary = shill_dictionary_->FindDictKey(shill::kPaymentPortalProperty);
  if (dictionary) {
    TranslateAndAddNestedObject(::onc::cellular::kPaymentPortal, *dictionary);
  }

  const base::Value* device_dictionary =
      shill_dictionary_->FindDictKey(shill::kDeviceProperty);
  bool requires_roaming = false;
  bool scanning = false;
  if (device_dictionary) {
    // Merge the Device dictionary with this one (Cellular) using the
    // CellularDevice signature.
    ShillToONCTranslator nested_translator(
        *device_dictionary, onc_source_, kCellularWithStateSignature,
        kCellularDeviceTable, network_state_);
    std::unique_ptr<base::DictionaryValue> nested_object =
        nested_translator.CreateTranslatedONCObject();
    onc_object_->MergeDictionary(nested_object.get());

    // Copy ICCID and IMSI from the Device dictionary only if not provied in the
    // Service properties.
    if (!onc_object_->FindKey(::onc::cellular::kICCID)) {
      const base::Value* iccid =
          device_dictionary->FindKey(shill::kIccidProperty);
      if (iccid)
        onc_object_->SetKey(::onc::cellular::kICCID, iccid->Clone());
    }
    if (!onc_object_->FindKey(::onc::cellular::kIMSI)) {
      const base::Value* imsi =
          device_dictionary->FindKey(shill::kImsiProperty);
      if (imsi)
        onc_object_->SetKey(::onc::cellular::kIMSI, imsi->Clone());
    }

    // Get requires_roaming and scanning from the Device dictionary.
    requires_roaming =
        device_dictionary->FindBoolKey(shill::kProviderRequiresRoamingProperty)
            .value_or(false);
    scanning = device_dictionary->FindBoolKey(shill::kScanningProperty)
                   .value_or(false);
  }
  if (requires_roaming) {
    onc_object_->SetKey(::onc::cellular::kRoamingState,
                        base::Value(::onc::cellular::kRoamingRequired));
  } else {
    TranslateWithTableAndSet(shill::kRoamingStateProperty, kRoamingStateTable,
                             ::onc::cellular::kRoamingState);
  }
  onc_object_->SetKey(::onc::cellular::kScanning, base::Value(scanning));
}

void ShillToONCTranslator::TranslateCellularDevice() {
  CopyPropertiesAccordingToSignature();
  const base::Value* shill_sim_lock_status =
      shill_dictionary_->FindDictKey(shill::kSIMLockStatusProperty);
  if (shill_sim_lock_status) {
    TranslateAndAddNestedObject(::onc::cellular::kSIMLockStatus,
                                *shill_sim_lock_status);
  }
  const base::Value* shill_home_provider =
      shill_dictionary_->FindDictKey(shill::kHomeProviderProperty);
  if (shill_home_provider) {
    TranslateAndAddNestedObject(::onc::cellular::kHomeProvider,
                                *shill_home_provider);
  }
  const base::Value* shill_apns =
      shill_dictionary_->FindListKey(shill::kCellularApnListProperty);
  if (shill_apns) {
    TranslateAndAddListOfObjects(::onc::cellular::kAPNList, *shill_apns);
  }
  const base::Value* shill_found_networks =
      shill_dictionary_->FindListKey(shill::kFoundNetworksProperty);
  if (shill_found_networks) {
    TranslateAndAddListOfObjects(::onc::cellular::kFoundNetworks,
                                 *shill_found_networks);
  }
}

void ShillToONCTranslator::TranslateNetworkWithState() {
  CopyPropertiesAccordingToSignature();

  std::string shill_network_type =
      FindStringKeyOrEmpty(shill_dictionary_, shill::kTypeProperty);
  std::string onc_network_type = ::onc::network_type::kEthernet;
  if (shill_network_type != shill::kTypeEthernet &&
      shill_network_type != shill::kTypeEthernetEap) {
    TranslateStringToONC(kNetworkTypeTable, shill_network_type,
                         &onc_network_type);
  }
  // Translate nested Cellular, WiFi, etc. properties.
  if (!onc_network_type.empty()) {
    onc_object_->SetKey(::onc::network_config::kType,
                        base::Value(onc_network_type));
    TranslateAndAddNestedObject(onc_network_type);
  }

  // Since Name is a read only field in Shill unless it's a VPN, it is copied
  // here, but not when going the other direction (if it's not a VPN).
  std::string name =
      FindStringKeyOrEmpty(shill_dictionary_, shill::kNameProperty);
  onc_object_->SetKey(::onc::network_config::kName, base::Value(name));

  // Limit ONC state to "NotConnected", "Connected", or "Connecting".
  const std::string* state =
      shill_dictionary_->FindStringKey(shill::kStateProperty);
  if (state) {
    std::string onc_state = ::onc::connection_state::kNotConnected;
    if (NetworkState::StateIsConnected(*state)) {
      onc_state = ::onc::connection_state::kConnected;
    } else if (NetworkState::StateIsConnecting(*state)) {
      onc_state = ::onc::connection_state::kConnecting;
    }
    onc_object_->SetKey(::onc::network_config::kConnectionState,
                        base::Value(onc_state));
    // Only set 'RestrictedConnectivity' if captive portal state is true.
    if (NetworkState::NetworkStateIsCaptivePortal(*shill_dictionary_)) {
      onc_object_->SetKey(::onc::network_config::kRestrictedConnectivity,
                          base::Value(true));
    }
  }

  // Non-visible networks (with null network_state_) do not set ErrorState.
  if (network_state_) {
    if (!network_state_->GetError().empty()) {
      onc_object_->SetKey(::onc::network_config::kErrorState,
                          base::Value(network_state_->GetError()));
    }
  }

  const std::string* profile_path =
      shill_dictionary_->FindStringKey(shill::kProfileProperty);
  if (onc_source_ != ::onc::ONC_SOURCE_UNKNOWN && profile_path) {
    std::string source;
    if (onc_source_ == ::onc::ONC_SOURCE_DEVICE_POLICY)
      source = ::onc::network_config::kSourceDevicePolicy;
    else if (onc_source_ == ::onc::ONC_SOURCE_USER_POLICY)
      source = ::onc::network_config::kSourceUserPolicy;
    else if (*profile_path == NetworkProfileHandler::GetSharedProfilePath())
      source = ::onc::network_config::kSourceDevice;
    else if (!profile_path->empty())
      source = ::onc::network_config::kSourceUser;
    else
      source = ::onc::network_config::kSourceNone;
    onc_object_->SetKey(::onc::network_config::kSource, base::Value(source));
  }

  // Use a human-readable aa:bb format for any hardware MAC address. Note:
  // this property is provided by the caller but is not part of the Shill
  // Service properties (it is copied from the Device properties).
  const std::string* address =
      shill_dictionary_->FindStringKey(shill::kAddressProperty);
  if (address) {
    onc_object_->SetKey(
        ::onc::network_config::kMacAddress,
        base::Value(network_util::FormattedMacAddress(*address)));
  }

  // Shill's Service has an IPConfig property (note the singular), not an
  // IPConfigs property. However, we require the caller of the translation to
  // patch the Shill dictionary before passing it to the translator.
  const base::Value* shill_ipconfigs =
      shill_dictionary_->FindListKey(shill::kIPConfigsProperty);
  if (shill_ipconfigs) {
    TranslateAndAddListOfObjects(::onc::network_config::kIPConfigs,
                                 *shill_ipconfigs);
  }

  const base::Value* saved_ipconfig =
      shill_dictionary_->FindDictKey(shill::kSavedIPConfigProperty);
  if (saved_ipconfig) {
    TranslateAndAddNestedObject(::onc::network_config::kSavedIPConfig,
                                *saved_ipconfig);
  }

  // Translate the StaticIPConfig object and set the IP config types.
  const base::Value* static_ipconfig =
      shill_dictionary_->FindDictKey(shill::kStaticIPConfigProperty);
  if (static_ipconfig) {
    const std::string* ip_address =
        static_ipconfig->FindStringKey(shill::kAddressProperty);
    if (ip_address && !ip_address->empty()) {
      onc_object_->SetKey(
          ::onc::network_config::kIPAddressConfigType,
          base::Value(::onc::network_config::kIPConfigTypeStatic));
    }
    const base::Value* name_servers =
        static_ipconfig->FindListKey(shill::kNameServersProperty);
    if (name_servers && !name_servers->GetList().empty()) {
      onc_object_->SetKey(
          ::onc::network_config::kNameServersConfigType,
          base::Value(::onc::network_config::kIPConfigTypeStatic));
    }
    if ((ip_address && !ip_address->empty()) ||
        (name_servers && !name_servers->GetList().empty())) {
      TranslateAndAddNestedObject(::onc::network_config::kStaticIPConfig,
                                  *static_ipconfig);
    }
  }

  const std::string* proxy_config_str =
      shill_dictionary_->FindStringKey(shill::kProxyConfigProperty);
  if (proxy_config_str && !proxy_config_str->empty()) {
    base::Value proxy_config_value = ReadDictionaryFromJson(*proxy_config_str);
    if (!proxy_config_value.is_none()) {
      base::Value proxy_settings =
          ConvertProxyConfigToOncProxySettings(proxy_config_value);
      if (!proxy_settings.is_none()) {
        onc_object_->SetKey(::onc::network_config::kProxySettings,
                            std::move(proxy_settings));
      }
    }
  }
}

void ShillToONCTranslator::TranslateIPConfig() {
  CopyPropertiesAccordingToSignature();
  std::string shill_ip_method =
      FindStringKeyOrEmpty(shill_dictionary_, shill::kMethodProperty);
  std::string type;
  if (shill_ip_method == shill::kTypeIPv4 ||
      shill_ip_method == shill::kTypeDHCP) {
    type = ::onc::ipconfig::kIPv4;
  } else if (shill_ip_method == shill::kTypeIPv6 ||
             shill_ip_method == shill::kTypeDHCP6) {
    type = ::onc::ipconfig::kIPv6;
  } else {
    return;  // Ignore unhandled IPConfig types, e.g. bootp, zeroconf, ppp
  }

  onc_object_->SetKey(::onc::ipconfig::kType, base::Value(type));
}

void ShillToONCTranslator::TranslateSavedOrStaticIPConfig() {
  CopyPropertiesAccordingToSignature();

  // Static and Saved IPConfig in Shill are always of type IPv4. Set this type
  // in ONC, but not if the object would be empty except the type.
  if (!onc_object_->DictEmpty()) {
    onc_object_->SetKey(::onc::ipconfig::kType,
                        base::Value(::onc::ipconfig::kIPv4));
  }
}

void ShillToONCTranslator::TranslateSavedIPConfig() {
  TranslateSavedOrStaticIPConfig();
}

void ShillToONCTranslator::TranslateStaticIPConfig() {
  TranslateSavedOrStaticIPConfig();
}

void ShillToONCTranslator::TranslateEap() {
  CopyPropertiesAccordingToSignature();

  // Translate EAP Outer and Inner values if EAP.EAP exists and is not empty.
  const std::string* shill_eap_method =
      shill_dictionary_->FindStringKey(shill::kEapMethodProperty);
  if (shill_eap_method && !shill_eap_method->empty()) {
    TranslateWithTableAndSet(shill::kEapMethodProperty, kEAPOuterTable,
                             ::onc::eap::kOuter);
    const std::string* shill_phase2_auth =
        shill_dictionary_->FindStringKey(shill::kEapPhase2AuthProperty);
    if (shill_phase2_auth && !shill_phase2_auth->empty()) {
      TranslateWithTableAndSet(shill::kEapPhase2AuthProperty,
                               kEAP_TTLS_InnerTable, ::onc::eap::kInner);
    }
  }

  const std::string* shill_cert_id =
      shill_dictionary_->FindStringKey(shill::kEapCertIdProperty);
  if (shill_cert_id) {
    onc_object_->SetKey(::onc::client_cert::kClientCertType,
                        base::Value(::onc::client_cert::kPKCS11Id));
    // Note: shill::kEapCertIdProperty is already in the format slot:key_id.
    // Note: shill::kEapKeyIdProperty has the same value as
    //       shill::kEapCertIdProperty and is ignored.
    onc_object_->SetKey(::onc::client_cert::kClientCertPKCS11Id,
                        base::Value(*shill_cert_id));
  }

  bool use_login_password =
      shill_dictionary_->FindBoolKey(shill::kEapUseLoginPasswordProperty)
          .value_or(false);
  if (use_login_password) {
    onc_object_->SetKey(
        ::onc::eap::kPassword,
        base::Value(::onc::substitutes::kPasswordPlaceholderVerbatim));
  }
}

void ShillToONCTranslator::TranslateAndAddNestedObject(
    const std::string& onc_field_name) {
  TranslateAndAddNestedObject(onc_field_name, *shill_dictionary_);
}

void ShillToONCTranslator::TranslateAndAddNestedObject(
    const std::string& onc_field_name,
    const base::Value& dictionary) {
  const OncFieldSignature* field_signature =
      GetFieldSignature(*onc_signature_, onc_field_name);
  if (!field_signature) {
    NET_LOG(ERROR) << "Unable to find signature for field: " << onc_field_name;
    return;
  }
  ShillToONCTranslator nested_translator(dictionary, onc_source_,
                                         *field_signature->value_signature,
                                         network_state_);
  std::unique_ptr<base::DictionaryValue> nested_object =
      nested_translator.CreateTranslatedONCObject();
  if (nested_object->empty())
    return;
  onc_object_->SetKey(onc_field_name, std::move(*nested_object));
}

void ShillToONCTranslator::SetNestedOncValue(
    const std::string& onc_dictionary_name,
    const std::string& onc_field_name,
    const base::Value& value) {
  onc_object_->SetPath({onc_dictionary_name, onc_field_name}, value.Clone());
}

void ShillToONCTranslator::TranslateAndAddListOfObjects(
    const std::string& onc_field_name,
    const base::Value& list) {
  const OncFieldSignature* field_signature =
      GetFieldSignature(*onc_signature_, onc_field_name);
  if (field_signature->value_signature->onc_type != base::Value::Type::LIST) {
    NET_LOG(ERROR) << "ONC Field name: '" << onc_field_name << "' has type '"
                   << field_signature->value_signature->onc_type
                   << "', expected: base::Value::Type::LIST: " << GetName();
    return;
  }
  DCHECK(field_signature->value_signature->onc_array_entry_signature);
  base::Value result(base::Value::Type::LIST);
  for (const auto& it : list.GetList()) {
    if (!it.is_dict())
      continue;
    ShillToONCTranslator nested_translator(
        it, onc_source_,
        *field_signature->value_signature->onc_array_entry_signature,
        network_state_);
    std::unique_ptr<base::DictionaryValue> nested_object =
        nested_translator.CreateTranslatedONCObject();
    // If the nested object couldn't be parsed, simply omit it.
    if (nested_object->empty())
      continue;
    result.Append(std::move(*nested_object));
  }
  // If there are no entries in the list, there is no need to expose this field.
  if (result.GetList().empty())
    return;
  onc_object_->SetKey(onc_field_name, std::move(result));
}

void ShillToONCTranslator::CopyPropertiesAccordingToSignature() {
  CopyPropertiesAccordingToSignature(onc_signature_);
}

void ShillToONCTranslator::CopyPropertiesAccordingToSignature(
    const OncValueSignature* value_signature) {
  if (value_signature->base_signature)
    CopyPropertiesAccordingToSignature(value_signature->base_signature);
  if (!value_signature->fields)
    return;
  for (const OncFieldSignature* field_signature = value_signature->fields;
       field_signature->onc_field_name != NULL; ++field_signature) {
    CopyProperty(field_signature);
  }
}

void ShillToONCTranslator::CopyProperty(
    const OncFieldSignature* field_signature) {
  std::string shill_property_name;
  if (!field_translation_table_ ||
      !GetShillPropertyName(field_signature->onc_field_name,
                            field_translation_table_, &shill_property_name)) {
    return;
  }
  const base::Value* shill_value =
      shill_dictionary_->FindKey(shill_property_name);
  if (!shill_value) {
    return;
  }

  if (shill_value->type() != field_signature->value_signature->onc_type) {
    NET_LOG(ERROR) << "Shill property '" << shill_property_name
                   << "' with value " << *shill_value
                   << " has base::Value::Type " << shill_value->type()
                   << " but ONC field '" << field_signature->onc_field_name
                   << "' requires type "
                   << field_signature->value_signature->onc_type << ": "
                   << GetName();
    return;
  }

  onc_object_->SetKey(field_signature->onc_field_name, shill_value->Clone());
}

void ShillToONCTranslator::TranslateWithTableAndSet(
    const std::string& shill_property_name,
    const StringTranslationEntry table[],
    const std::string& onc_field_name) {
  const std::string* shill_value =
      shill_dictionary_->FindStringKey(shill_property_name);
  if (!shill_value || shill_value->empty()) {
    return;
  }
  std::string onc_value;
  if (TranslateStringToONC(table, *shill_value, &onc_value)) {
    onc_object_->SetKey(onc_field_name, base::Value(onc_value));
    return;
  }
  NET_LOG(ERROR) << "Shill property '" << shill_property_name << "' with value "
                 << *shill_value
                 << " couldn't be translated to ONC: " << GetName();
}

std::string ShillToONCTranslator::GetName() {
  DCHECK(shill_dictionary_);
  const std::string* name =
      shill_dictionary_->FindStringKey(shill::kNameProperty);
  return name ? *name : std::string();
}

}  // namespace

std::unique_ptr<base::DictionaryValue> TranslateShillServiceToONCPart(
    const base::Value& shill_dictionary,
    ::onc::ONCSource onc_source,
    const OncValueSignature* onc_signature,
    const NetworkState* network_state) {
  CHECK(onc_signature != NULL);

  ShillToONCTranslator translator(shill_dictionary, onc_source, *onc_signature,
                                  network_state);
  return translator.CreateTranslatedONCObject();
}

}  // namespace onc
}  // namespace chromeos
