Index: chrome/browser/chromeos/network_settings/onc_validator.cc |
diff --git a/chrome/browser/chromeos/network_settings/onc_validator.cc b/chrome/browser/chromeos/network_settings/onc_validator.cc |
index ec4922797a060dbcef90e6a6490000da59e9260f..dbbc548db3c7bbdd2d0f9ba3bea60d8ea3a7658e 100644 |
--- a/chrome/browser/chromeos/network_settings/onc_validator.cc |
+++ b/chrome/browser/chromeos/network_settings/onc_validator.cc |
@@ -7,15 +7,47 @@ |
#include <algorithm> |
#include <string> |
+#include "base/json/json_writer.h" |
#include "base/logging.h" |
+#include "base/string_number_conversions.h" |
#include "base/string_util.h" |
+#include "base/utf_string_conversions.h" |
#include "base/values.h" |
#include "chrome/browser/chromeos/cros/onc_constants.h" |
#include "chrome/browser/chromeos/network_settings/onc_signature.h" |
+#include "grit/generated_resources.h" |
+#include "ui/base/l10n/l10n_util.h" |
namespace chromeos { |
namespace onc { |
+namespace { |
+ |
+string16 ValueToString(const base::Value& value) { |
+ std::string json; |
+ base::JSONWriter::Write(&value, &json); |
+ return UTF8ToUTF16(json); |
+} |
+ |
+// Copied from policy/configuration_policy_handler.cc. |
+// TODO(pneubeck): move to a common place like base/. |
+string16 ValueTypeToString(Value::Type type) { |
+ static const char* strings[] = { |
+ "null", |
+ "boolean", |
+ "integer", |
+ "double", |
+ "string", |
+ "binary", |
+ "dictionary", |
+ "list" |
+ }; |
+ DCHECK(static_cast<size_t>(type) < arraysize(strings)); |
+ return ASCIIToUTF16(strings[type]); |
+} |
+ |
+} // namespace |
+ |
Validator::Validator( |
bool error_on_unknown_field, |
bool error_on_wrong_recommended, |
@@ -32,29 +64,45 @@ Validator::~Validator() { |
scoped_ptr<base::DictionaryValue> Validator::ValidateAndRepairObject( |
const OncValueSignature* object_signature, |
- const base::DictionaryValue& onc_object) { |
+ const base::DictionaryValue& onc_object, |
+ std::string* messages) { |
CHECK(object_signature != NULL); |
+ messages_.clear(); |
+ bool error = false; |
scoped_ptr<base::Value> result_value = |
- MapValue(*object_signature, onc_object); |
+ MapValue(*object_signature, onc_object, &error); |
+ if (error) |
+ result_value.reset(); |
+ |
base::DictionaryValue* result_dict = NULL; |
if (result_value.get() != NULL) { |
result_value.release()->GetAsDictionary(&result_dict); |
CHECK(result_dict != NULL); |
} |
+ if (messages) |
+ *messages = JoinMessages(); |
+ |
return make_scoped_ptr(result_dict); |
} |
scoped_ptr<base::Value> Validator::MapValue( |
const OncValueSignature& signature, |
- const base::Value& onc_value) { |
+ const base::Value& onc_value, |
+ bool* error) { |
if (onc_value.GetType() != signature.onc_type) { |
DVLOG(1) << "Wrong type. Expected " << signature.onc_type |
<< ", but found " << onc_value.GetType(); |
+ AddError(l10n_util::GetStringFUTF8( |
+ IDS_NETWORK_CONFIG_ERROR_VALUE_HAS_WRONG_TYPE, |
+ ValueToString(onc_value), ValueTypeToString(signature.onc_type), |
+ ValueTypeToString(onc_value.GetType()))); |
+ *error = true; |
return scoped_ptr<base::Value>(); |
} |
- scoped_ptr<base::Value> repaired = Mapper::MapValue(signature, onc_value); |
+ scoped_ptr<base::Value> repaired = |
+ Mapper::MapValue(signature, onc_value, error); |
if (repaired.get() != NULL) |
CHECK_EQ(repaired->GetType(), signature.onc_type); |
return repaired.Pass(); |
@@ -62,11 +110,14 @@ scoped_ptr<base::Value> Validator::MapValue( |
scoped_ptr<base::DictionaryValue> Validator::MapObject( |
const OncValueSignature& signature, |
- const base::DictionaryValue& onc_object) { |
+ const base::DictionaryValue& onc_object, |
+ bool* error) { |
scoped_ptr<base::DictionaryValue> repaired(new base::DictionaryValue); |
bool valid; |
- if (&signature == &kNetworkConfigurationSignature) |
+ if (&signature == &kToplevelConfigurationSignature) |
+ valid = ValidateToplevelConfiguration(onc_object, repaired.get()); |
+ else if (&signature == &kNetworkConfigurationSignature) |
valid = ValidateNetworkConfiguration(onc_object, repaired.get()); |
else if (&signature == &kEthernetSignature) |
valid = ValidateEthernet(onc_object, repaired.get()); |
@@ -93,10 +144,51 @@ scoped_ptr<base::DictionaryValue> Validator::MapObject( |
else |
valid = ValidateObjectDefault(signature, onc_object, repaired.get()); |
- if (valid) |
+ if (valid) { |
return repaired.Pass(); |
- else |
+ } else { |
+ *error = true; |
return scoped_ptr<base::DictionaryValue>(); |
+ } |
+} |
+ |
+scoped_ptr<base::Value> Validator::MapField( |
+ const std::string& field_name, |
+ const OncValueSignature& object_signature, |
+ const base::Value& onc_value, |
+ bool* found_unknown_field, |
+ bool* error) { |
+ path_.push_back(field_name); |
+ bool current_field_unknown = false; |
+ scoped_ptr<base::Value> result = Mapper::MapField( |
+ field_name, object_signature, onc_value, ¤t_field_unknown, error); |
+ |
+ DCHECK_EQ(field_name, path_.back()); |
+ path_.pop_back(); |
+ |
+ if (current_field_unknown) { |
+ *found_unknown_field = true; |
+ DVLOG(1) << (error_on_unknown_field_ ? "Error" : "Warning") |
+ << ": Unknown field name '" << field_name << "'."; |
+ AddMessage(error_on_unknown_field_, l10n_util::GetStringFUTF8( |
+ IDS_NETWORK_CONFIG_ERROR_UNKNOWN_FIELD_NAME, |
+ UTF8ToUTF16(field_name))); |
+ } |
+ |
+ return result.Pass(); |
+} |
+ |
+scoped_ptr<base::Value> Validator::MapEntry(int index, |
+ const OncValueSignature& signature, |
+ const base::Value& onc_value, |
+ bool* error) { |
+ std::string str = base::IntToString(index); |
+ path_.push_back(str); |
+ scoped_ptr<base::Value> result = Mapper::MapEntry(index, signature, |
+ onc_value, error); |
+ DCHECK_EQ(str, path_.back()); |
+ path_.pop_back(); |
+ return result.Pass(); |
} |
bool Validator::ValidateObjectDefault( |
@@ -107,17 +199,15 @@ bool Validator::ValidateObjectDefault( |
bool nested_error_occured = false; |
MapFields(signature, onc_object, &found_unknown_field, &nested_error_occured, |
result); |
- if (nested_error_occured) |
- return false; |
- if (found_unknown_field) { |
- if (error_on_unknown_field_) { |
- DVLOG(1) << "Unknown field name. Aborting."; |
- return false; |
- } |
- DVLOG(1) << "Unknown field name. Ignoring."; |
+ if (found_unknown_field && error_on_unknown_field_) { |
+ DVLOG(1) << "Unknown field names are errors: Aborting."; |
+ return false; |
} |
+ if (nested_error_occured) |
+ return false; |
+ |
return ValidateRecommendedField(signature, result); |
} |
@@ -140,8 +230,11 @@ bool Validator::ValidateRecommendedField( |
recommended.reset(recommended_list); |
if (!managed_onc_) { |
+ AddWarning(l10n_util::GetStringFUTF8( |
+ IDS_NETWORK_CONFIG_ERROR_UNEXPECTED_FIELD_IN_UNMANAGED_CONFIG, |
+ ASCIIToUTF16(onc::kRecommended))); |
DVLOG(1) << "Found a " << onc::kRecommended |
- << " field in unmanaged ONC. Removing it."; |
+ << " field in an unmanaged ONC. Removing it."; |
return true; |
} |
@@ -169,8 +262,11 @@ bool Validator::ValidateRecommendedField( |
} |
if (found_error) { |
+ AddMessage(error_on_wrong_recommended_, l10n_util::GetStringFUTF8( |
+ IDS_NETWORK_CONFIG_ERROR_UNKNOWN_FIELD_RECOMMENDED, |
+ ASCIIToUTF16(field_name))); |
DVLOG(1) << "Found " << error_cause << " field name '" << field_name |
- << "' in kRecommended array. " |
+ << "' in a " << onc::kRecommended << " array. " |
<< (error_on_wrong_recommended_ ? "Aborting." : "Ignoring."); |
if (error_on_wrong_recommended_) |
return false; |
@@ -185,44 +281,42 @@ bool Validator::ValidateRecommendedField( |
return true; |
} |
-namespace { |
+bool Validator::ValidateToplevelConfiguration( |
+ const base::DictionaryValue& onc_object, |
+ base::DictionaryValue* result) { |
+ if (!ValidateObjectDefault(kToplevelConfigurationSignature, |
+ onc_object, result)) { |
+ return false; |
+ } |
-std::string JoinStringRange(const char** range_begin, |
- const char** range_end, |
- const std::string& separator) { |
- std::vector<std::string> string_vector; |
- std::copy(range_begin, range_end, std::back_inserter(string_vector)); |
- return JoinString(string_vector, separator); |
-} |
+ static const char* kValidTypes[] = |
+ { kUnencryptedConfiguration, kEncryptedConfiguration, NULL }; |
+ if (FieldExistsAndHasNoValueOf(*result, kType, kValidTypes)) |
+ return false; |
-bool RequireAnyOf(const std::string &actual, const char** valid_values) { |
- const char** it = valid_values; |
- for (; *it != NULL; ++it) { |
- if (actual == *it) |
- return true; |
- } |
- DVLOG(1) << "Found " << actual << ", but expected one of " |
- << JoinStringRange(valid_values, it, ", "); |
- return false; |
-} |
+ bool allRequiredExist = true; |
-bool IsInRange(int actual, int lower_bound, int upper_bound) { |
- if (lower_bound <= actual && actual <= upper_bound) |
- return true; |
- DVLOG(1) << "Found " << actual << ", which is out of range [" << lower_bound |
- << ", " << upper_bound << "]"; |
- return false; |
-} |
+ // Not part of the ONC spec yet: |
+ // We don't require the type field and default to UnencryptedConfiguration. |
+ std::string type = kUnencryptedConfiguration; |
+ result->GetStringWithoutPathExpansion(kType, &type); |
+ if (type == kUnencryptedConfiguration && |
+ !result->HasKey(kNetworkConfigurations) && |
+ !result->HasKey(kCertificates)) { |
+ DVLOG(1) << "Neither " << kNetworkConfigurations << " nor " |
+ << kCertificates << " present."; |
+ |
+ AddMessage(error_on_missing_field_, |
+ l10n_util::GetStringFUTF8( |
+ IDS_NETWORK_CONFIG_ERROR_NETWORKS_OR_CERTS_REQUIRED, |
+ ASCIIToUTF16(kNetworkConfigurations), |
+ ASCIIToUTF16(kCertificates))); |
+ allRequiredExist = false; |
+ } |
-bool RequireField(const base::DictionaryValue& dict, std::string key) { |
- if (dict.HasKey(key)) |
- return true; |
- DVLOG(1) << "Required field " << key << " missing."; |
- return false; |
+ return !error_on_missing_field_ || allRequiredExist; |
} |
-} // namespace |
- |
bool Validator::ValidateNetworkConfiguration( |
const base::DictionaryValue& onc_object, |
base::DictionaryValue* result) { |
@@ -231,12 +325,9 @@ bool Validator::ValidateNetworkConfiguration( |
return false; |
} |
- std::string type; |
static const char* kValidTypes[] = { kEthernet, kVPN, kWiFi, NULL }; |
- if (result->GetStringWithoutPathExpansion(kType, &type) && |
- !RequireAnyOf(type, kValidTypes)) { |
+ if (FieldExistsAndHasNoValueOf(*result, kType, kValidTypes)) |
return false; |
- } |
bool allRequiredExist = RequireField(*result, kGUID); |
@@ -245,6 +336,9 @@ bool Validator::ValidateNetworkConfiguration( |
if (!remove) { |
allRequiredExist &= RequireField(*result, kName); |
allRequiredExist &= RequireField(*result, kType); |
+ |
+ std::string type; |
+ result->GetStringWithoutPathExpansion(kType, &type); |
allRequiredExist &= type.empty() || RequireField(*result, type); |
} |
@@ -258,14 +352,15 @@ bool Validator::ValidateEthernet( |
if (!ValidateObjectDefault(kEthernetSignature, onc_object, result)) |
return false; |
- std::string auth; |
static const char* kValidAuthentications[] = { kNone, k8021X, NULL }; |
- if (result->GetStringWithoutPathExpansion(kAuthentication, &auth) && |
- !RequireAnyOf(auth, kValidAuthentications)) { |
+ if (FieldExistsAndHasNoValueOf(*result, kAuthentication, |
+ kValidAuthentications)) { |
return false; |
} |
bool allRequiredExist = true; |
+ std::string auth; |
+ result->GetStringWithoutPathExpansion(kAuthentication, &auth); |
if (auth == k8021X) |
allRequiredExist &= RequireField(*result, kEAP); |
@@ -279,19 +374,17 @@ bool Validator::ValidateIPConfig( |
if (!ValidateObjectDefault(kIPConfigSignature, onc_object, result)) |
return false; |
- std::string type; |
static const char* kValidTypes[] = { kIPv4, kIPv6, NULL }; |
- if (result->GetStringWithoutPathExpansion(ipconfig::kType, &type) && |
- !RequireAnyOf(type, kValidTypes)) { |
+ if (FieldExistsAndHasNoValueOf(*result, ipconfig::kType, kValidTypes)) |
return false; |
- } |
- int routing_prefix; |
+ std::string type; |
+ result->GetStringWithoutPathExpansion(ipconfig::kType, &type); |
int lower_bound = 1; |
// In case of missing type, choose higher upper_bound. |
int upper_bound = (type == kIPv4) ? 32 : 128; |
- if (result->GetIntegerWithoutPathExpansion(kRoutingPrefix, &routing_prefix) && |
- !IsInRange(routing_prefix, lower_bound, upper_bound)) { |
+ if (FieldExistsAndIsNotInRange(*result, kRoutingPrefix, |
+ lower_bound, upper_bound)) { |
return false; |
} |
@@ -309,16 +402,16 @@ bool Validator::ValidateWiFi( |
if (!ValidateObjectDefault(kWiFiSignature, onc_object, result)) |
return false; |
- std::string security; |
static const char* kValidSecurities[] = |
{ kNone, kWEP_PSK, kWEP_8021X, kWPA_PSK, kWPA_EAP, NULL }; |
- if (result->GetStringWithoutPathExpansion(kSecurity, &security) && |
- !RequireAnyOf(security, kValidSecurities)) { |
+ if (FieldExistsAndHasNoValueOf(*result, kSecurity, kValidSecurities)) |
return false; |
- } |
bool allRequiredExist = RequireField(*result, kSecurity) & |
RequireField(*result, kSSID); |
+ |
+ std::string security; |
+ result->GetStringWithoutPathExpansion(kSecurity, &security); |
if (security == kWEP_8021X || security == kWPA_EAP) |
allRequiredExist &= RequireField(*result, kEAP); |
else if (security == kWEP_PSK || security == kWPA_PSK) |
@@ -334,16 +427,14 @@ bool Validator::ValidateVPN( |
if (!ValidateObjectDefault(kVPNSignature, onc_object, result)) |
return false; |
- std::string type; |
static const char* kValidTypes[] = |
{ kIPsec, kTypeL2TP_IPsec, kOpenVPN, NULL }; |
- if (result->GetStringWithoutPathExpansion(vpn::kType, &type) && |
- !RequireAnyOf(type, kValidTypes)) { |
+ if (FieldExistsAndHasNoValueOf(*result, vpn::kType, kValidTypes)) |
return false; |
- } |
bool allRequiredExist = RequireField(*result, vpn::kType); |
- |
+ std::string type; |
+ result->GetStringWithoutPathExpansion(vpn::kType, &type); |
if (type == kOpenVPN) { |
allRequiredExist &= RequireField(*result, kOpenVPN); |
} else if (type == kIPsec) { |
@@ -364,26 +455,24 @@ bool Validator::ValidateIPsec( |
if (!ValidateObjectDefault(kIPsecSignature, onc_object, result)) |
return false; |
- std::string auth; |
static const char* kValidAuthentications[] = { kPSK, kCert, NULL }; |
- if (result->GetStringWithoutPathExpansion(kAuthenticationType, &auth) && |
- !RequireAnyOf(auth, kValidAuthentications)) { |
- return false; |
- } |
- |
- std::string cert_type; |
static const char* kValidCertTypes[] = { kRef, kPattern, NULL }; |
- if (result->GetStringWithoutPathExpansion(kClientCertType, &cert_type) && |
- !RequireAnyOf(cert_type, kValidCertTypes)) { |
+ if (FieldExistsAndHasNoValueOf(*result, kAuthenticationType, |
+ kValidAuthentications) | |
+ FieldExistsAndHasNoValueOf(*result, kClientCertType, kValidCertTypes)) { |
return false; |
} |
bool allRequiredExist = RequireField(*result, kAuthenticationType) & |
RequireField(*result, kIKEVersion); |
+ std::string auth; |
+ result->GetStringWithoutPathExpansion(kAuthenticationType, &auth); |
if (auth == kCert) { |
allRequiredExist &= RequireField(*result, kClientCertType) & |
RequireField(*result, kServerCARef); |
} |
+ std::string cert_type; |
+ result->GetStringWithoutPathExpansion(kClientCertType, &cert_type); |
if (cert_type == kPattern) |
allRequiredExist &= RequireField(*result, kClientCertPattern); |
else if (cert_type == kRef) |
@@ -401,31 +490,23 @@ bool Validator::ValidateOpenVPN( |
if (!ValidateObjectDefault(kOpenVPNSignature, onc_object, result)) |
return false; |
- std::string auth_retry; |
static const char* kValidAuthRetryValues[] = |
{ openvpn::kNone, kInteract, kNoInteract, NULL }; |
- if (result->GetStringWithoutPathExpansion(kAuthRetry, &auth_retry) && |
- !RequireAnyOf(auth_retry, kValidAuthRetryValues)) { |
- return false; |
- } |
- |
- std::string cert_type; |
static const char* kValidCertTypes[] = |
{ certificate::kNone, kRef, kPattern, NULL }; |
- if (result->GetStringWithoutPathExpansion(kClientCertType, &cert_type) && |
- !RequireAnyOf(cert_type, kValidCertTypes)) { |
- return false; |
- } |
- |
- std::string cert_tls; |
static const char* kValidCertTlsValues[] = |
{ openvpn::kNone, openvpn::kServer, NULL }; |
- if (result->GetStringWithoutPathExpansion(kRemoteCertTLS, &cert_tls) && |
- !RequireAnyOf(cert_tls, kValidCertTlsValues)) { |
+ |
+ if (FieldExistsAndHasNoValueOf(*result, kAuthRetry, kValidAuthRetryValues) | |
+ FieldExistsAndHasNoValueOf(*result, kClientCertType, kValidCertTypes) | |
+ FieldExistsAndHasNoValueOf(*result, kRemoteCertTLS, |
+ kValidCertTlsValues)) { |
return false; |
} |
bool allRequiredExist = RequireField(*result, kClientCertType); |
+ std::string cert_type; |
+ result->GetStringWithoutPathExpansion(kClientCertType, &cert_type); |
if (cert_type == kPattern) |
allRequiredExist &= RequireField(*result, kClientCertPattern); |
else if (cert_type == kRef) |
@@ -458,15 +539,13 @@ bool Validator::ValidateProxySettings(const base::DictionaryValue& onc_object, |
if (!ValidateObjectDefault(kProxySettingsSignature, onc_object, result)) |
return false; |
- std::string type; |
static const char* kValidTypes[] = { kDirect, kManual, kPAC, kWPAD, NULL }; |
- if (result->GetStringWithoutPathExpansion(proxy::kType, &type) && |
- !RequireAnyOf(type, kValidTypes)) { |
+ if (FieldExistsAndHasNoValueOf(*result, proxy::kType, kValidTypes)) |
return false; |
- } |
bool allRequiredExist = RequireField(*result, proxy::kType); |
- |
+ std::string type; |
+ result->GetStringWithoutPathExpansion(proxy::kType, &type); |
if (type == kManual) |
allRequiredExist &= RequireField(*result, kManual); |
else if (type == kPAC) |
@@ -494,32 +573,22 @@ bool Validator::ValidateEAP(const base::DictionaryValue& onc_object, |
if (!ValidateObjectDefault(kEAPSignature, onc_object, result)) |
return false; |
- std::string inner; |
static const char* kValidInnerValues[] = |
{ kAutomatic, kMD5, kMSCHAPv2, kPAP, NULL }; |
- if (result->GetStringWithoutPathExpansion(kInner, &inner) && |
- !RequireAnyOf(inner, kValidInnerValues)) { |
- return false; |
- } |
- |
- std::string outer; |
static const char* kValidOuterValues[] = |
{ kPEAP, kEAP_TLS, kEAP_TTLS, kLEAP, kEAP_SIM, kEAP_FAST, kEAP_AKA, |
NULL }; |
- if (result->GetStringWithoutPathExpansion(kOuter, &outer) && |
- !RequireAnyOf(outer, kValidOuterValues)) { |
- return false; |
- } |
- |
- std::string cert_type; |
static const char* kValidCertTypes[] = { kRef, kPattern, NULL }; |
- if (result->GetStringWithoutPathExpansion(kClientCertType, &cert_type) && |
- !RequireAnyOf(cert_type, kValidCertTypes )) { |
+ |
+ if (FieldExistsAndHasNoValueOf(*result, kInner, kValidInnerValues) | |
+ FieldExistsAndHasNoValueOf(*result, kOuter, kValidOuterValues) | |
+ FieldExistsAndHasNoValueOf(*result, kClientCertType, kValidCertTypes)) { |
return false; |
} |
bool allRequiredExist = RequireField(*result, kOuter); |
- |
+ std::string cert_type; |
+ result->GetStringWithoutPathExpansion(kClientCertType, &cert_type); |
if (cert_type == kPattern) |
allRequiredExist &= RequireField(*result, kClientCertPattern); |
else if (cert_type == kRef) |
@@ -535,12 +604,9 @@ bool Validator::ValidateCertificate( |
if (!ValidateObjectDefault(kCertificateSignature, onc_object, result)) |
return false; |
- std::string type; |
static const char* kValidTypes[] = { kClient, kServer, kAuthority, NULL }; |
- if (result->GetStringWithoutPathExpansion(certificate::kType, &type) && |
- !RequireAnyOf(type, kValidTypes)) { |
+ if (FieldExistsAndHasNoValueOf(*result, certificate::kType, kValidTypes)) |
return false; |
- } |
bool allRequiredExist = RequireField(*result, kGUID); |
@@ -549,6 +615,8 @@ bool Validator::ValidateCertificate( |
if (!remove) { |
allRequiredExist &= RequireField(*result, certificate::kType); |
+ std::string type; |
+ result->GetStringWithoutPathExpansion(certificate::kType, &type); |
if (type == kClient) |
allRequiredExist &= RequireField(*result, kPKCS12); |
else if (type == kServer || type == kAuthority) |
@@ -558,5 +626,105 @@ bool Validator::ValidateCertificate( |
return !error_on_missing_field_ || allRequiredExist; |
} |
+namespace { |
+ |
+std::string JoinStringRange(const char** range_begin, |
+ const char** range_end, |
+ const std::string& separator) { |
+ std::vector<std::string> string_vector; |
+ std::copy(range_begin, range_end, std::back_inserter(string_vector)); |
+ return JoinString(string_vector, separator); |
+} |
+ |
+} // namespace |
+ |
+bool Validator::FieldExistsAndHasNoValueOf(const base::DictionaryValue& object, |
+ const std::string &field_name, |
+ const char** valid_values) { |
+ std::string actual_value; |
+ if (!object.GetStringWithoutPathExpansion(field_name, &actual_value)) |
+ return false; |
+ |
+ const char** it = valid_values; |
+ for (; *it != NULL; ++it) { |
+ if (actual_value == *it) |
+ return false; |
+ } |
+ std::string valid_values_str = |
+ "[" + JoinStringRange(valid_values, it, ", ") + "]"; |
+ path_.push_back(field_name); |
+ AddError(l10n_util::GetStringFUTF8( |
+ IDS_NETWORK_CONFIG_ERROR_INVALID_VALUE, |
+ UTF8ToUTF16(actual_value), |
+ UTF8ToUTF16(valid_values_str))); |
+ path_.pop_back(); |
+ DVLOG(1) << "Found " << actual_value << ", but expected one of " |
+ << valid_values_str; |
+ return true; |
+} |
+ |
+bool Validator::FieldExistsAndIsNotInRange(const base::DictionaryValue& object, |
+ const std::string &field_name, |
+ int lower_bound, |
+ int upper_bound) { |
+ int actual_value; |
+ if (!object.GetIntegerWithoutPathExpansion(field_name, &actual_value)) |
+ return false; |
+ |
+ if (lower_bound <= actual_value && actual_value <= upper_bound) |
+ return false; |
+ path_.push_back(field_name); |
+ AddError(l10n_util::GetStringFUTF8( |
+ IDS_NETWORK_CONFIG_ERROR_VALUE_OUT_OF_RANGE, |
+ base::IntToString16(actual_value), |
+ base::IntToString16(lower_bound), |
+ base::IntToString16(upper_bound))); |
+ path_.pop_back(); |
+ DVLOG(1) << "Found " << actual_value << ", which is out of range [" |
+ << lower_bound << ", " << upper_bound << "]"; |
+ return true; |
+} |
+ |
+bool Validator::RequireField(const base::DictionaryValue& dict, |
+ const std::string& field_name) { |
+ if (dict.HasKey(field_name)) |
+ return true; |
+ AddError(l10n_util::GetStringFUTF8( |
+ IDS_NETWORK_CONFIG_ERROR_REQUIRED_FIELD_MISSING, |
+ UTF8ToUTF16(field_name))); |
+ DVLOG(1) << "Required field " << field_name << " missing."; |
+ return false; |
+} |
+ |
+void Validator::AddWarning(const std::string& msg) { |
+ AddMessage(false, msg); |
+} |
+ |
+void Validator::AddError(const std::string& msg) { |
+ AddMessage(true, msg); |
+} |
+ |
+void Validator::AddMessage(bool is_error, const std::string& sub_message) { |
+ std::string message; |
+ if (path_.empty()) { |
+ int message_id = is_error ? IDS_NETWORK_CONFIG_ERROR_AT_TOPLEVEL |
+ : IDS_NETWORK_CONFIG_WARNING_AT_TOPLEVEL; |
+ message = l10n_util::GetStringUTF8(message_id); |
+ } else { |
+ int message_id = is_error ? |
+ IDS_NETWORK_CONFIG_ERROR_AT_PATH : |
+ IDS_NETWORK_CONFIG_WARNING_AT_PATH; |
+ message = l10n_util::GetStringFUTF8(message_id, |
+ ASCIIToUTF16(JoinString(path_, "."))); |
+ } |
+ message.append(" "); |
+ message.append(sub_message); |
+ messages_.push_back(message); |
+} |
+ |
+std::string Validator::JoinMessages() { |
+ return JoinString(messages_, "\n"); |
+} |
+ |
} // namespace onc |
} // namespace chromeos |