diff options
14 files changed, 727 insertions, 4 deletions
diff --git a/chrome/browser/chromeos/network_settings/onc_signature.cc b/chrome/browser/chromeos/network_settings/onc_signature.cc index 4d332cf..ee8cf52 100644 --- a/chrome/browser/chromeos/network_settings/onc_signature.cc +++ b/chrome/browser/chromeos/network_settings/onc_signature.cc @@ -124,8 +124,8 @@ const OncFieldSignature openvpn_fields[] = { &kBoolSignature }, { vpn::kRemoteCertEKU, flimflam::kOpenVPNRemoteCertEKUProperty, &kStringSignature }, - { vpn::kRemoteCertKU, flimflam::kOpenVPNRemoteCertKUProperty, - &kStringListSignature }, + // This field is converted during translation, see onc_translator_*. + { vpn::kRemoteCertKU, NULL, &kStringListSignature }, { vpn::kRemoteCertTLS, flimflam::kOpenVPNRemoteCertTLSProperty, &kStringSignature }, { vpn::kRenegSec, flimflam::kOpenVPNRenegSecProperty, &kIntegerSignature }, @@ -152,7 +152,8 @@ const OncFieldSignature vpn_fields[] = { { vpn::kIPsec, NULL, &kIPsecSignature }, { vpn::kL2TP, NULL, &kL2TPSignature }, { vpn::kOpenVPN, NULL, &kOpenVPNSignature }, - { kType, flimflam::kProviderTypeProperty, &kStringSignature }, + // This field is converted during translation, see onc_translator_*. + { kType, NULL, &kStringSignature }, { NULL } }; @@ -169,6 +170,7 @@ const OncFieldSignature ipconfig_fields[] = { { kNameServers, NULL, &kStringSignature }, { ipconfig::kRoutingPrefix, NULL, &kIntegerSignature }, { kSearchDomains, NULL, &kStringListSignature }, + // This field is converted during translation, see onc_translator_*. { kType, NULL, &kStringSignature }, { NULL } }; @@ -217,7 +219,8 @@ const OncFieldSignature network_configuration_fields[] = { { kProxySettings, NULL, &kProxySettingsSignature }, { kRemove, NULL, &kBoolSignature }, { kSearchDomains, NULL, &kStringListSignature }, - { kType, flimflam::kTypeProperty, &kStringSignature }, + // This field is converted during translation, see onc_translator_*. + { kType, NULL, &kStringSignature }, { kVPN, NULL, &kVPNSignature }, { kWiFi, NULL, &kWiFiSignature }, { NULL } diff --git a/chrome/browser/chromeos/network_settings/onc_translation_tables.cc b/chrome/browser/chromeos/network_settings/onc_translation_tables.cc new file mode 100644 index 0000000..59633c4 --- /dev/null +++ b/chrome/browser/chromeos/network_settings/onc_translation_tables.cc @@ -0,0 +1,30 @@ +// 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 "chrome/browser/chromeos/network_settings/onc_translation_tables.h" + +#include <cstddef> + +#include "chrome/browser/chromeos/cros/onc_constants.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { +namespace onc { + +const StringTranslationEntry kNetworkTypeTable[] = { + { kEthernet, flimflam::kTypeEthernet }, + { kWiFi, flimflam::kTypeWifi }, + { kCellular, flimflam::kTypeCellular }, + { kVPN, flimflam::kTypeVPN }, + { NULL } +}; + +const StringTranslationEntry kVPNTypeTable[] = { + { vpn::kTypeL2TP_IPsec, flimflam::kProviderL2tpIpsec }, + { vpn::kOpenVPN, flimflam::kProviderOpenVpn }, + { NULL } +}; + +} // namespace onc +} // namespace chromeos diff --git a/chrome/browser/chromeos/network_settings/onc_translation_tables.h b/chrome/browser/chromeos/network_settings/onc_translation_tables.h new file mode 100644 index 0000000..66594d8 --- /dev/null +++ b/chrome/browser/chromeos/network_settings/onc_translation_tables.h @@ -0,0 +1,24 @@ +// 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. + +#ifndef CHROME_BROWSER_CHROMEOS_NETWORK_SETTINGS_ONC_TRANSLATION_TABLES_H_ +#define CHROME_BROWSER_CHROMEOS_NETWORK_SETTINGS_ONC_TRANSLATION_TABLES_H_ + +namespace chromeos { +namespace onc { + +struct StringTranslationEntry { + const char* onc_value; + const char* shill_value; +}; + +// These tables contain the mapping from ONC strings to Shill strings. +// These are NULL-terminated arrays. +extern const StringTranslationEntry kNetworkTypeTable[]; +extern const StringTranslationEntry kVPNTypeTable[]; + +} // namespace onc +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_NETWORK_SETTINGS_ONC_TRANSLATION_TABLES_H_ diff --git a/chrome/browser/chromeos/network_settings/onc_translator.h b/chrome/browser/chromeos/network_settings/onc_translator.h new file mode 100644 index 0000000..900851f --- /dev/null +++ b/chrome/browser/chromeos/network_settings/onc_translator.h @@ -0,0 +1,45 @@ +// 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. + +#ifndef CHROME_BROWSER_CHROMEOS_NETWORK_SETTINGS_ONC_TRANSLATOR_H_ +#define CHROME_BROWSER_CHROMEOS_NETWORK_SETTINGS_ONC_TRANSLATOR_H_ + +#include "base/memory/scoped_ptr.h" + +namespace base { +class DictionaryValue; +} + +namespace chromeos { +namespace onc { + +struct OncValueSignature; + +// Translates a hierarchical ONC dictionary |onc_object| to a flat Shill +// dictionary. The |signature| declares the type of |onc_object| and must point +// to one of the signature objects in "onc_signature.h". The resulting Shill +// dictionary is returned. +// +// This function is used to translate network settings from ONC to Shill's +// format before sending them to Shill. +scoped_ptr<base::DictionaryValue> TranslateONCObjectToShill( + const OncValueSignature* signature, + const base::DictionaryValue& onc_object); + +// Translates a |shill_dictionary| to an ONC object according to the given +// |onc_signature|. |onc_signature| must point to a signature object in +// "onc_signature.h". The resulting ONC object is returned. +// +// This function is used to translate network settings coming from Shill to ONC +// before sending them to the UI. The result doesn't have to be valid ONC, but +// only a subset of it and includes only the values that are actually required +// by the UI. +scoped_ptr<base::DictionaryValue> TranslateShillServiceToONCPart( + const base::DictionaryValue& shill_dictionary, + const OncValueSignature* onc_signature); + +} // namespace onc +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_NETWORK_SETTINGS_ONC_TRANSLATOR_H_ diff --git a/chrome/browser/chromeos/network_settings/onc_translator_onc_to_shill.cc b/chrome/browser/chromeos/network_settings/onc_translator_onc_to_shill.cc new file mode 100644 index 0000000..2182dd5 --- /dev/null +++ b/chrome/browser/chromeos/network_settings/onc_translator_onc_to_shill.cc @@ -0,0 +1,210 @@ +// 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. + +// The implementation of TranslateONCObjectToShill is structured in two parts: +// - The recursion through the existing ONC hierarchy +// see TranslateONCHierarchy +// - The local translation of an object depending on the associated signature +// see LocalTranslator::TranslateFields + +#include "chrome/browser/chromeos/network_settings/onc_translator.h" + +#include <string> + +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/logging.h" +#include "base/values.h" +#include "chrome/browser/chromeos/cros/onc_constants.h" +#include "chrome/browser/chromeos/network_settings/onc_signature.h" +#include "chrome/browser/chromeos/network_settings/onc_translation_tables.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { +namespace onc { + +namespace { + +scoped_ptr<base::StringValue> ConvertValueToString(const base::Value& value) { + std::string str; + if (!value.GetAsString(&str)) + base::JSONWriter::Write(&value, &str); + return make_scoped_ptr(base::Value::CreateStringValue(str)); +} + +// This class is responsible to translate the local fields of the given +// |onc_object| according to |onc_signature| into |shill_dictionary|. This +// translation should consider (if possible) only fields of this ONC object and +// not nested objects because recursion is handled by the calling function +// TranslateONCHierarchy. +class LocalTranslator { + public: + LocalTranslator(const OncValueSignature& onc_signature, + const base::DictionaryValue& onc_object, + base::DictionaryValue* shill_dictionary) + : onc_signature_(&onc_signature), + onc_object_(&onc_object), + shill_dictionary_(shill_dictionary) { + } + + void TranslateFields(); + + private: + void TranslateOpenVPN(); + void TranslateVPN(); + void TranslateNetworkConfiguration(); + + // Copies all entries from |onc_object_| to |shill_dictionary_| for which a + // translation (shill_property_name) is defined by |onc_signature_|. + void CopyFieldsAccordingToSignature(); + + // Adds |value| to |shill_dictionary| at the field shill_property_name given + // by the associated signature. Takes ownership of |value|. Does nothing if + // |value| is NULL or the property name cannot be read from the signature. + void AddValueAccordingToSignature(const std::string& onc_field_name, + scoped_ptr<base::Value> value); + + // If existent, translates the entry at |onc_field_name| in |onc_object_| + // using |table|. It is an error if no matching table entry is found. Writes + // the result as entry at |shill_property_name| in |shill_dictionary_|. + void TranslateWithTableAndSet(const std::string& onc_field_name, + const StringTranslationEntry table[], + const std::string& shill_property_name); + + const OncValueSignature* onc_signature_; + const base::DictionaryValue* onc_object_; + base::DictionaryValue* shill_dictionary_; + + DISALLOW_COPY_AND_ASSIGN(LocalTranslator); +}; + +void LocalTranslator::TranslateFields() { + if (onc_signature_ == &kNetworkConfigurationSignature) + TranslateNetworkConfiguration(); + else if (onc_signature_ == &kVPNSignature) + TranslateVPN(); + else if (onc_signature_ == &kOpenVPNSignature) + TranslateOpenVPN(); + else + CopyFieldsAccordingToSignature(); +} + +void LocalTranslator::TranslateOpenVPN() { + // Shill supports only one RemoteCertKU but ONC a list. + // Copy only the first entry if existing. + const base::ListValue* certKUs; + std::string certKU; + if (onc_object_->GetListWithoutPathExpansion(vpn::kRemoteCertKU, &certKUs) && + certKUs->GetString(0, &certKU)) { + shill_dictionary_->SetStringWithoutPathExpansion( + flimflam::kOpenVPNRemoteCertKUProperty, certKU); + } + + for (base::DictionaryValue::Iterator it(*onc_object_); it.HasNext(); + it.Advance()) { + scoped_ptr<base::Value> translated; + if (it.key() == vpn::kSaveCredentials || it.key() == vpn::kRemoteCertKU) { + translated.reset(it.value().DeepCopy()); + } else { + // Shill wants all Provider/VPN fields to be strings. + translated = ConvertValueToString(it.value()); + } + AddValueAccordingToSignature(it.key(), translated.Pass()); + } +} + +void LocalTranslator::TranslateVPN() { + TranslateWithTableAndSet(kType, kVPNTypeTable, + flimflam::kProviderTypeProperty); + CopyFieldsAccordingToSignature(); +} + +void LocalTranslator::TranslateNetworkConfiguration() { + TranslateWithTableAndSet(kType, kNetworkTypeTable, flimflam::kTypeProperty); + CopyFieldsAccordingToSignature(); +} + +void LocalTranslator::CopyFieldsAccordingToSignature() { + for (base::DictionaryValue::Iterator it(*onc_object_); it.HasNext(); + it.Advance()) { + AddValueAccordingToSignature(it.key(), + make_scoped_ptr(it.value().DeepCopy())); + } +} + +void LocalTranslator::AddValueAccordingToSignature( + const std::string& onc_name, + scoped_ptr<base::Value> value) { + if (value.get() == NULL) + return; + const OncFieldSignature* field_signature = + GetFieldSignature(*onc_signature_, onc_name); + DCHECK(field_signature != NULL); + if (field_signature == NULL || field_signature->shill_property_name == NULL) + return; + + shill_dictionary_->SetWithoutPathExpansion( + field_signature->shill_property_name, value.release()); +} + +void LocalTranslator::TranslateWithTableAndSet( + const std::string& onc_field_name, + const StringTranslationEntry table[], + const std::string& shill_property_name) { + std::string onc_value; + if (!onc_object_->GetStringWithoutPathExpansion(onc_field_name, &onc_value)) + return; + + for (int i = 0; table[i].onc_value != NULL; ++i) { + if (onc_value != table[i].onc_value) + continue; + shill_dictionary_->SetStringWithoutPathExpansion(shill_property_name, + table[i].shill_value); + return; + } + // As we previously validate ONC, this case should never occur. If it still + // occurs, we should check here. Otherwise the failure will only show up much + // later in Shill. + LOG(ERROR) << "Value '" << onc_value << "' for field '" + << onc_field_name << "' cannot be translated to Shill"; +} + +// Iterates recursively over |onc_object| and its |signature|. At each object +// applies the local translation using LocalTranslator::TranslateFields. The +// results are written to |shill_dictionary|. +void TranslateONCHierarchy(const OncValueSignature& signature, + const base::DictionaryValue& onc_object, + base::DictionaryValue* shill_dictionary) { + // Translates fields of |onc_object| and writes them to |shill_dictionary_|. + LocalTranslator translator(signature, onc_object, shill_dictionary); + translator.TranslateFields(); + + // Recurse into nested objects. + for (base::DictionaryValue::Iterator it(onc_object); it.HasNext(); + it.Advance()) { + const base::DictionaryValue* inner_object; + if (!it.value().GetAsDictionary(&inner_object)) + continue; + + const OncFieldSignature* field_signature = + GetFieldSignature(signature, it.key()); + + TranslateONCHierarchy(*field_signature->value_signature, *inner_object, + shill_dictionary); + } +} + +} // namespace + +scoped_ptr<base::DictionaryValue> TranslateONCObjectToShill( + const OncValueSignature* onc_signature, + const base::DictionaryValue& onc_object) { + CHECK(onc_signature != NULL); + scoped_ptr<base::DictionaryValue> shill_dictionary(new base::DictionaryValue); + TranslateONCHierarchy(*onc_signature, onc_object, shill_dictionary.get()); + return shill_dictionary.Pass(); +} + +} // namespace onc +} // namespace chromeos diff --git a/chrome/browser/chromeos/network_settings/onc_translator_shill_to_onc.cc b/chrome/browser/chromeos/network_settings/onc_translator_shill_to_onc.cc new file mode 100644 index 0000000..b3c40de --- /dev/null +++ b/chrome/browser/chromeos/network_settings/onc_translator_shill_to_onc.cc @@ -0,0 +1,231 @@ +// 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 "chrome/browser/chromeos/network_settings/onc_translator.h" + +#include <string> + +#include "base/basictypes.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/logging.h" +#include "base/values.h" +#include "chrome/browser/chromeos/cros/onc_constants.h" +#include "chrome/browser/chromeos/network_settings/onc_signature.h" +#include "chrome/browser/chromeos/network_settings/onc_translation_tables.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { +namespace onc { + +namespace { + +// Converts |str| to a base::Value of the given |type|. If the conversion fails, +// returns NULL. +scoped_ptr<base::Value> ConvertStringToValue(const std::string& str, + base::Value::Type type) { + base::Value* value; + if (type == base::Value::TYPE_STRING) + value = base::Value::CreateStringValue(str); + else + value = base::JSONReader::Read(str); + + if (value == NULL || value->GetType() != type) { + delete value; + value = NULL; + } + return make_scoped_ptr(value); +} + +// 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 TranslateShillServiceToONCPart, nested objects are +// translated. +class ShillToONCTranslator { + public: + ShillToONCTranslator(const base::DictionaryValue& shill_dictionary, + const OncValueSignature& onc_signature) + : shill_dictionary_(&shill_dictionary), + onc_signature_(&onc_signature) { + } + + // Translates the associated Shill dictionary and creates an ONC object of the + // given signature. + scoped_ptr<base::DictionaryValue> CreateTranslatedONCObject(); + + private: + void TranslateOpenVPN(); + void TranslateVPN(); + void TranslateNetworkConfiguration(); + + // 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); + + // Copies all entries from |shill_dictionary_| to |onc_object_| for which a + // translation (shill_property_name) is defined by |onc_signature_|. + void CopyPropertiesAccordingToSignature(); + + // 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); + + const base::DictionaryValue* shill_dictionary_; + const OncValueSignature* onc_signature_; + scoped_ptr<base::DictionaryValue> onc_object_; + + DISALLOW_COPY_AND_ASSIGN(ShillToONCTranslator); +}; + +scoped_ptr<base::DictionaryValue> +ShillToONCTranslator::CreateTranslatedONCObject() { + onc_object_.reset(new base::DictionaryValue); + if (onc_signature_ == &kNetworkConfigurationSignature) + TranslateNetworkConfiguration(); + else if (onc_signature_ == &kVPNSignature) + TranslateVPN(); + else if (onc_signature_ == &kOpenVPNSignature) + TranslateOpenVPN(); + else + CopyPropertiesAccordingToSignature(); + return onc_object_.Pass(); +} + +void ShillToONCTranslator::TranslateOpenVPN() { + // Shill supports only one RemoteCertKU but ONC requires a list. If existing, + // wraps the value into a list. + std::string certKU; + if (shill_dictionary_->GetStringWithoutPathExpansion( + flimflam::kOpenVPNRemoteCertKUProperty, &certKU)) { + scoped_ptr<base::ListValue> certKUs(new base::ListValue); + certKUs->AppendString(certKU); + onc_object_->SetWithoutPathExpansion(vpn::kRemoteCertKU, certKUs.release()); + } + + for (const OncFieldSignature* field_signature = onc_signature_->fields; + field_signature->onc_field_name != NULL; ++field_signature) { + const base::Value* shill_value; + if (field_signature->shill_property_name == NULL || + !shill_dictionary_->GetWithoutPathExpansion( + field_signature->shill_property_name, &shill_value)) { + continue; + } + + scoped_ptr<base::Value> translated; + std::string shill_str; + const std::string& onc_field_name = field_signature->onc_field_name; + if (onc_field_name == vpn::kSaveCredentials || + onc_field_name == vpn::kRemoteCertKU) { + translated.reset(shill_value->DeepCopy()); + } else if (shill_value->GetAsString(&shill_str)) { + // Shill wants all Provider/VPN fields to be strings. Translates these + // strings back to the correct ONC type. + translated = ConvertStringToValue( + shill_str, + field_signature->value_signature->onc_type); + + if (translated.get() == NULL) { + LOG(ERROR) << "Shill property '" << field_signature->shill_property_name + << "' with value '" << shill_value + << "' couldn't be converted to base::Value::Type " + << field_signature->value_signature->onc_type; + } + } else { + LOG(ERROR) << "Shill property '" << field_signature->shill_property_name + << "' has value '" << shill_value + << "', but expected a string"; + } + onc_object_->SetWithoutPathExpansion(onc_field_name, translated.release()); + } +} + +void ShillToONCTranslator::TranslateVPN() { + TranslateWithTableAndSet(flimflam::kProviderTypeProperty, kVPNTypeTable, + kType); + CopyPropertiesAccordingToSignature(); + + std::string vpn_type; + if (onc_object_->GetStringWithoutPathExpansion(kType, &vpn_type)) { + if (vpn_type == vpn::kTypeL2TP_IPsec) { + TranslateAndAddNestedObject(vpn::kIPsec); + TranslateAndAddNestedObject(vpn::kL2TP); + } else { + TranslateAndAddNestedObject(vpn_type); + } + } +} + +void ShillToONCTranslator::TranslateAndAddNestedObject( + const std::string& onc_field_name) { + const OncFieldSignature* field_signature = + GetFieldSignature(*onc_signature_, onc_field_name); + ShillToONCTranslator nested_translator(*shill_dictionary_, + *field_signature->value_signature); + scoped_ptr<base::DictionaryValue> nested_object = + nested_translator.CreateTranslatedONCObject(); + onc_object_->SetWithoutPathExpansion(onc_field_name, nested_object.release()); +} + +void ShillToONCTranslator::TranslateNetworkConfiguration() { + TranslateWithTableAndSet(flimflam::kTypeProperty, kNetworkTypeTable, kType); + CopyPropertiesAccordingToSignature(); + + std::string network_type; + if (onc_object_->GetStringWithoutPathExpansion(kType, &network_type)) + TranslateAndAddNestedObject(network_type); +} + +void ShillToONCTranslator::CopyPropertiesAccordingToSignature() { + for (const OncFieldSignature* field_signature = onc_signature_->fields; + field_signature->onc_field_name != NULL; ++field_signature) { + const base::Value* shill_value; + if (field_signature->shill_property_name == NULL || + !shill_dictionary_->GetWithoutPathExpansion( + field_signature->shill_property_name, &shill_value)) { + continue; + } + onc_object_->SetWithoutPathExpansion( + field_signature->onc_field_name, shill_value->DeepCopy()); + } +} + +void ShillToONCTranslator::TranslateWithTableAndSet( + const std::string& shill_property_name, + const StringTranslationEntry table[], + const std::string& onc_field_name) { + std::string shill_value; + if (!shill_dictionary_->GetStringWithoutPathExpansion(shill_property_name, + &shill_value)) { + return; + } + + for (int i = 0; table[i].onc_value != NULL; ++i) { + if (shill_value != table[i].shill_value) + continue; + onc_object_->SetStringWithoutPathExpansion(onc_field_name, + table[i].onc_value); + return; + } + LOG(ERROR) << "Shill property '" << shill_property_name << "' with value '" + << shill_value << "' couldn't be translated to ONC"; +} + +} // namespace + +scoped_ptr<base::DictionaryValue> TranslateShillServiceToONCPart( + const base::DictionaryValue& shill_dictionary, + const OncValueSignature* onc_signature) { + CHECK(onc_signature != NULL); + + ShillToONCTranslator translator(shill_dictionary, *onc_signature); + return translator.CreateTranslatedONCObject(); +} + +} // namespace onc +} // namespace chromeos diff --git a/chrome/browser/chromeos/network_settings/onc_translator_unittest.cc b/chrome/browser/chromeos/network_settings/onc_translator_unittest.cc new file mode 100644 index 0000000..96a9f5c --- /dev/null +++ b/chrome/browser/chromeos/network_settings/onc_translator_unittest.cc @@ -0,0 +1,86 @@ +// 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 "chrome/browser/chromeos/network_settings/onc_translator.h" + +#include "base/memory/scoped_ptr.h" +#include "base/values.h" +#include "chrome/browser/chromeos/cros/onc_constants.h" +#include "chrome/browser/chromeos/network_settings/onc_signature.h" +#include "chrome/browser/chromeos/network_settings/onc_test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { +namespace onc { + +// First parameter: Filename of source ONC. +// Second parameter: Filename of expected translated Shill json. +class ONCTranslatorOncToShillTest + : public ::testing::TestWithParam<std::pair<std::string, std::string> > { +}; + +// Test the translation from ONC to Shill json. +TEST_P(ONCTranslatorOncToShillTest, Translate) { + std::string source_onc_filename = GetParam().first; + scoped_ptr<const base::DictionaryValue> onc_network( + test_utils::ReadTestDictionary(source_onc_filename)); + std::string result_json_filename = GetParam().second; + scoped_ptr<const base::DictionaryValue> shill_network( + test_utils::ReadTestDictionary(result_json_filename)); + + scoped_ptr<base::DictionaryValue> translation(TranslateONCObjectToShill( + &kNetworkConfigurationSignature, *onc_network)); + + EXPECT_TRUE(test_utils::Equals(shill_network.get(), translation.get())); +} + +// Test different network types, such that each ONC object type is tested at +// least once. +INSTANTIATE_TEST_CASE_P( + ONCTranslatorOncToShillTest, + ONCTranslatorOncToShillTest, + ::testing::Values( + std::make_pair("valid.onc", "shill_ethernet.json"), + std::make_pair("valid_l2tpipsec.onc", "shill_l2tpipsec.json"), + std::make_pair("valid_openvpn.onc", "shill_openvpn.json"))); + +// Test the translation from Shill json to ONC. +// +// Note: This translation direction doesn't have to reconstruct all of the ONC +// fields, as Chrome doesn't need all of a Service's properties. +TEST(ONCTranslatorShillToOncTest, L2TPIPsec) { + scoped_ptr<base::DictionaryValue> onc_network( + test_utils::ReadTestDictionary("valid_l2tpipsec.onc")); + + // These two fields are part of the ONC (and are required). However, they + // don't exist explicitly in the Shill dictionary. As there is no use-case + // yet, that requires to reconstruct these fields from a Shill dictionary, we + // don't require their translation. + onc_network->Remove("VPN.IPsec.AuthenticationType", NULL); + onc_network->Remove("VPN.IPsec.IKEVersion", NULL); + + scoped_ptr<const base::DictionaryValue> shill_network( + test_utils::ReadTestDictionary("shill_l2tpipsec.json")); + + scoped_ptr<base::DictionaryValue> translation(TranslateShillServiceToONCPart( + *shill_network, &kNetworkConfigurationSignature)); + + EXPECT_TRUE(test_utils::Equals(onc_network.get(), translation.get())); +} + +TEST(ONCTranslatorShillToOncTest, OpenVPN) { + scoped_ptr<const base::DictionaryValue> onc_network( + test_utils::ReadTestDictionary("valid_openvpn.onc")); + + scoped_ptr<const base::DictionaryValue> shill_network( + test_utils::ReadTestDictionary("shill_openvpn.json")); + + scoped_ptr<base::DictionaryValue> translation(TranslateShillServiceToONCPart( + *shill_network, &kNetworkConfigurationSignature)); + + EXPECT_TRUE(test_utils::Equals(onc_network.get(), translation.get())); +} + +} // namespace onc +} // namespace chromeos diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi index 629564b..31ad993 100644 --- a/chrome/chrome_browser_chromeos.gypi +++ b/chrome/chrome_browser_chromeos.gypi @@ -516,6 +516,11 @@ 'browser/chromeos/network_settings/onc_normalizer.h', 'browser/chromeos/network_settings/onc_signature.cc', 'browser/chromeos/network_settings/onc_signature.h', + 'browser/chromeos/network_settings/onc_translation_tables.cc', + 'browser/chromeos/network_settings/onc_translation_tables.h', + 'browser/chromeos/network_settings/onc_translator.h', + 'browser/chromeos/network_settings/onc_translator_shill_to_onc.cc', + 'browser/chromeos/network_settings/onc_translator_onc_to_shill.cc', 'browser/chromeos/network_settings/onc_validator.cc', 'browser/chromeos/network_settings/onc_validator.h', 'browser/chromeos/notifications/balloon_view_host_chromeos.cc', diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 5fc0ff2..fcc6f1b 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -613,6 +613,7 @@ 'browser/chromeos/network_settings/onc_normalizer_unittest.cc', 'browser/chromeos/network_settings/onc_test_utils.cc', 'browser/chromeos/network_settings/onc_test_utils.h', + 'browser/chromeos/network_settings/onc_translator_unittest.cc', 'browser/chromeos/network_settings/onc_validator_unittest.cc', 'browser/chromeos/offline/offline_load_page_unittest.cc', 'browser/chromeos/preferences_unittest.cc', diff --git a/chrome/test/data/chromeos/network_settings/shill_ethernet.json b/chrome/test/data/chromeos/network_settings/shill_ethernet.json new file mode 100644 index 0000000..7754932 --- /dev/null +++ b/chrome/test/data/chromeos/network_settings/shill_ethernet.json @@ -0,0 +1,4 @@ +{ "GUID": "guid", + "Type": "ethernet", + "Name": "name", +} diff --git a/chrome/test/data/chromeos/network_settings/shill_l2tpipsec.json b/chrome/test/data/chromeos/network_settings/shill_l2tpipsec.json new file mode 100644 index 0000000..f529a97 --- /dev/null +++ b/chrome/test/data/chromeos/network_settings/shill_l2tpipsec.json @@ -0,0 +1,10 @@ +{ "GUID": "guid", + "Type": "vpn", + "Name": "MyL2TPVPN", + "Provider.Host": "some.host.org", + "Provider.Type": "l2tpipsec", + "L2TPIPsec.PSK": "some_preshared_key", + "L2TPIPsec.User": "some username", + "L2TPIPsec.Password": "some password", + "SaveCredentials": true +} diff --git a/chrome/test/data/chromeos/network_settings/shill_openvpn.json b/chrome/test/data/chromeos/network_settings/shill_openvpn.json new file mode 100644 index 0000000..1bf84ef --- /dev/null +++ b/chrome/test/data/chromeos/network_settings/shill_openvpn.json @@ -0,0 +1,25 @@ +{ + "GUID": "{a3860e83-f03d-4cb1-bafa-b22c9e746950}", + "Type": "vpn", + "Name": "google-dogfood", + "SaveCredentials": false, + "Provider.Type": "openvpn", + "Provider.Host": "v.ext.google.com", + "OpenVPN.AuthRetry": "interact", + "OpenVPN.User": "some username", + "OpenVPN.Password": "some password", + "OpenVPN.StaticChallenge": "Please enter token OTP", + "OpenVPN.CompLZO": "true", + "OpenVPN.ServerPollTimeout": "10", + "OpenVPN.RemoteCertKU": "e0", + "OpenVPN.CACertNSS": "{14ff4d51-64c1-4c86-a622-054d8e55e750}", + "OpenVPN.RemoteCertTLS": "server", + "OpenVPN.Port": "443", + "OpenVPN.TLSRemote": "v.ext.google.com", + "OpenVPN.KeyDirection": "1", + "OpenVPN.RenegSec": "0", + "OpenVPN.RemoteCertEKU": "TLS Web Server Authentication", + "OpenVPN.Proto": "udp", + "OpenVPN.PushPeerInfo": "true", + "OpenVPN.TLSAuthContents": "-----BEGIN OpenVPN Static key V1-----\nf8a19b8fddda3a38e06b883c48c83474\n0d1dfe7e5cadb2891387ac2d85198cdf\ne14274d03d12c4128c6c8967f84b1b39\n22452fb869280cde868bcf3932615927\nab1948d951c19183276fa249fd6e1e5f\nfc1c41400b59493a39cad872f5c7e777\n310d685d9c30abff7f206afc09cc99d9\ne40b2091e29af5b37d191628fba6d86e\n3a239b45b1b5a6be3229663ee7a7dc67\n2fa5be59fe7ceb41d2c78f94237c2185\n0aea1b06d739bca83240671167ddd2c2\n9cfd931df468536bfd1be99cd05160d8\n09ebfe4b8da88fb1923b19ad1abfc45e\n0402321e41af54e7d19ac95b1a7cec9a\nbf60a8eabcd5eecc84773af211477ee9\n9c988269638f9f1bb668028bb688dea2\nEND OpenVPN Static key V1-----\n" +} diff --git a/chrome/test/data/chromeos/network_settings/valid_l2tpipsec.onc b/chrome/test/data/chromeos/network_settings/valid_l2tpipsec.onc new file mode 100644 index 0000000..0e0bc5f --- /dev/null +++ b/chrome/test/data/chromeos/network_settings/valid_l2tpipsec.onc @@ -0,0 +1,18 @@ +{ "GUID": "guid", + "Type": "VPN", + "Name": "MyL2TPVPN", + "VPN": { + "Type": "L2TP-IPsec", + "Host": "some.host.org", + "IPsec": { + "AuthenticationType": "PSK", + "IKEVersion": 1, + "PSK": "some_preshared_key", + "SaveCredentials": true + }, + "L2TP": { + "Username": "some username", + "Password": "some password" + } + } +} diff --git a/chrome/test/data/chromeos/network_settings/valid_openvpn.onc b/chrome/test/data/chromeos/network_settings/valid_openvpn.onc new file mode 100644 index 0000000..512cb0e --- /dev/null +++ b/chrome/test/data/chromeos/network_settings/valid_openvpn.onc @@ -0,0 +1,31 @@ +{ + "GUID": "{a3860e83-f03d-4cb1-bafa-b22c9e746950}", + "Name": "google-dogfood", + "Type": "VPN", + "VPN": { + "Host": "v.ext.google.com", + "Type": "OpenVPN", + "OpenVPN": { + "AuthRetry": "interact", + "CompLZO": "true", + "KeyDirection": "1", + "Password": "some password", + "Port": 443, + "Proto": "udp", + "PushPeerInfo": true, + "RemoteCertEKU": "TLS Web Server Authentication", + "RemoteCertKU": [ + "e0" + ], + "RemoteCertTLS": "server", + "RenegSec": 0, + "SaveCredentials": false, + "ServerCARef": "{14ff4d51-64c1-4c86-a622-054d8e55e750}", + "ServerPollTimeout": 10, + "StaticChallenge": "Please enter token OTP", + "TLSAuthContents": "-----BEGIN OpenVPN Static key V1-----\nf8a19b8fddda3a38e06b883c48c83474\n0d1dfe7e5cadb2891387ac2d85198cdf\ne14274d03d12c4128c6c8967f84b1b39\n22452fb869280cde868bcf3932615927\nab1948d951c19183276fa249fd6e1e5f\nfc1c41400b59493a39cad872f5c7e777\n310d685d9c30abff7f206afc09cc99d9\ne40b2091e29af5b37d191628fba6d86e\n3a239b45b1b5a6be3229663ee7a7dc67\n2fa5be59fe7ceb41d2c78f94237c2185\n0aea1b06d739bca83240671167ddd2c2\n9cfd931df468536bfd1be99cd05160d8\n09ebfe4b8da88fb1923b19ad1abfc45e\n0402321e41af54e7d19ac95b1a7cec9a\nbf60a8eabcd5eecc84773af211477ee9\n9c988269638f9f1bb668028bb688dea2\nEND OpenVPN Static key V1-----\n", + "TLSRemote": "v.ext.google.com", + "Username": "some username", + } + } +} |