Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1811)

Unified Diff: chrome/browser/chromeos/network_settings/onc_validator.cc

Issue 10944009: Implementation of ONC signature, validator and normalizer. (Closed) Base URL: http://git.chromium.org/chromium/src.git@gperffix
Patch Set: Addressed comments (formatting, sorting). Minor change in policy.onc. Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
new file mode 100644
index 0000000000000000000000000000000000000000..f3f98db78229e05397e6423925eeb00235f3a0dd
--- /dev/null
+++ b/chrome/browser/chromeos/network_settings/onc_validator.cc
@@ -0,0 +1,238 @@
+// 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_validator.h"
+
+#include <string>
+
+#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"
+
+namespace chromeos {
+namespace onc {
+
+Validator::Validator(
+ bool error_on_unknown_field,
+ bool error_on_wrong_recommended,
+ bool error_on_missing_field,
+ bool managed_onc)
+ : error_on_unknown_field_(error_on_unknown_field),
+ error_on_wrong_recommended_(error_on_wrong_recommended),
+ error_on_missing_field_(error_on_missing_field),
+ managed_onc_(managed_onc) {
+}
+
+// static
+scoped_ptr<Validator> Validator::CreateStrictValidator(bool managed_onc) {
+ return make_scoped_ptr(new Validator(true, true, true, managed_onc));
+}
+
+// static
+scoped_ptr<Validator> Validator::CreateLiberalValidator(bool managed_onc) {
+ return make_scoped_ptr(new Validator(false, false, false, managed_onc));
+}
+
+scoped_ptr<base::DictionaryValue> Validator::ValidateAndRepairObject(
+ const OncValueSignature* object_signature,
+ const base::DictionaryValue& onc_object) {
+ CHECK(object_signature != NULL);
+ scoped_ptr<base::Value> result_value =
+ MapValue(*object_signature, onc_object);
+ base::DictionaryValue* result_dict = NULL;
+ if (result_value.get()) {
+ result_value.release()->GetAsDictionary(&result_dict);
+ CHECK(result_dict != NULL);
+ }
+
+ return make_scoped_ptr(result_dict);
+}
+
+scoped_ptr<base::Value> Validator::MapValue(
+ const OncValueSignature& signature,
+ const base::Value& onc_value) {
+ if (onc_value.GetType() != signature.onc_type) {
+ LOG(WARNING) << "Wrong type. Expected " << signature.onc_type
+ << ", but found " << onc_value.GetType();
+ return scoped_ptr<base::Value>();
+ }
+
+ scoped_ptr<base::Value> repaired = Mapper::MapValue(signature, onc_value);
+ if (repaired.get())
+ CHECK_EQ(repaired->GetType(), signature.onc_type);
+ return repaired.Pass();
+}
+
+scoped_ptr<base::DictionaryValue> Validator::MapObject(
+ const OncValueSignature& signature,
+ const base::DictionaryValue& onc_object) {
+ scoped_ptr<base::DictionaryValue> repaired(new base::DictionaryValue);
+
+ bool valid;
+ if (&signature == &network_configuration_signature)
+ valid = ValidateNetworkConfiguration(onc_object, repaired.get());
+ else if (&signature == &vpn_signature)
+ valid = ValidateVpn(onc_object, repaired.get());
+ else if (&signature == &ipsec_signature)
+ valid = ValidateIpsec(onc_object, repaired.get());
+ else
+ valid = ValidateObjectDefault(signature, onc_object, repaired.get());
+
+ if (valid)
+ return repaired.Pass();
+ else
+ return scoped_ptr<base::DictionaryValue>();
+}
+
+bool Validator::ValidateObjectDefault(
+ const OncValueSignature& signature,
+ const base::DictionaryValue& onc_object,
+ base::DictionaryValue* result) {
+ bool found_unknown_fieldname = false;
+ if (!MapFields(signature, onc_object, &found_unknown_fieldname, result))
+ return false;
+
+ if (found_unknown_fieldname) {
+ if (error_on_unknown_field_) {
+ LOG(WARNING) << "Unknown field name. Aborting.";
+ return false;
+ } else {
stevenjb 2012/10/11 19:54:00 nit: else unnecessary after early exit
pneubeck (no reviews) 2012/10/15 13:57:44 Done.
+ LOG(WARNING) << "Unknown field name. Ignoring.";
+ }
+ }
+
+ return ValidateRecommendedField(signature, result);
+}
+
+bool Validator::ValidateRecommendedField(
+ const OncValueSignature& object_signature,
+ base::DictionaryValue* result) {
+ CHECK(result != NULL);
+
+ scoped_ptr<base::ListValue> recommended;
+ {
+ base::Value* recommended_value;
+ // This remove passes ownership to |recommended_value|.
+ if (!result->RemoveWithoutPathExpansion(onc::kRecommended,
+ &recommended_value)) {
+ return true;
+ }
+ base::ListValue* recommended_list;
+ if (!recommended_value->GetAsList(&recommended_list))
+ NOTREACHED();
+ recommended.reset(recommended_list);
+ }
+
+ if (!managed_onc_) {
+ LOG(WARNING) << "Found kRecommended field in unmanaged ONC."
+ << (error_on_wrong_recommended_ ? " Aborting." : " Ignoring.");
+ return !error_on_wrong_recommended_;
+ }
+
+ scoped_ptr<base::ListValue> repaired_recommended(new base::ListValue);
+ for (base::ListValue::iterator it = recommended->begin();
+ it != recommended->end(); ++it) {
+ std::string field_name;
+ if (!(*it)->GetAsString(&field_name))
+ NOTREACHED();
+
+ const OncFieldSignature* field_signature =
+ object_signature.GetFieldSignature(field_name);
+
+ bool found_error = false;
+ std::string error_cause = "";
stevenjb 2012/10/11 19:54:00 nit: = "" unnecessary
pneubeck (no reviews) 2012/10/15 13:57:44 Done.
+ if (!field_signature) {
+ found_error = true;
+ error_cause = "unknown";
+ } else if (field_signature->value_signature->onc_type ==
+ base::Value::TYPE_DICTIONARY) {
+ found_error = true;
+ error_cause = "dictionary-typed";
+ }
+
+ if (found_error) {
+ LOG(WARNING) << "Found " << error_cause << " field name '" << field_name
+ << "' in kRecommended array. "
+ << (error_on_wrong_recommended_ ? "Aborting." : "Ignoring.");
+ if (error_on_wrong_recommended_)
+ return false;
+ else
+ continue;
+ }
+
+ repaired_recommended->Append((*it)->DeepCopy());
+ }
+
+ result->Set(onc::kRecommended, repaired_recommended.release());
+ return true;
+}
+
+namespace {
+
+template<class T>
+bool IsAnyOf(const T &actual, const T &v1, const T &v2) {
+ if (actual == v1 || actual == v2)
+ return true;
+ LOG(WARNING) << "Found " << actual << ", but expected one of "
+ << v1 << ", " << v2;
+ return false;
+}
stevenjb 2012/10/11 19:54:00 nit: empty line between templates / classes
pneubeck (no reviews) 2012/10/15 13:57:44 Done.
+template<class T>
+bool IsAnyOf(const T &actual, const T &v1, const T &v2, const T &v3) {
+ if (actual == v1 || actual == v2 || actual == v3)
+ return true;
+ LOG(WARNING) << "Found " << actual << ", but expected one of "
+ << v1 << ", " << v2 << ", " << v3;
+ return false;
+}
+bool RequiredField(const base::DictionaryValue& dict, std::string key) {
+ if (dict.HasKey(key))
+ return true;
+ LOG(WARNING) << "Required field " << key << " missing.";
+ return false;
+}
+
+} // namespace
+
+bool Validator::ValidateNetworkConfiguration(
+ const base::DictionaryValue& onc_object,
+ base::DictionaryValue* result) {
+ if (!ValidateObjectDefault(network_configuration_signature,
+ onc_object, result)) {
+ return false;
+ }
+
+ std::string type = "";
stevenjb 2012/10/11 19:54:00 nit: = "" unnecessary
pneubeck (no reviews) 2012/10/15 13:57:44 Done.
+ if (result->GetStringWithoutPathExpansion(kType, &type) &&
+ !IsAnyOf<std::string>(type, "Ethernet", "VPN", "WiFi"))
stevenjb 2012/10/11 19:54:00 These should be consts declared somewhere
pneubeck (no reviews) 2012/10/15 13:57:44 Done.
+ return false;
+
+ bool allRequiredExist =
+ RequiredField(*result, kGUID) &&
+ RequiredField(*result, kName) &&
+ RequiredField(*result, kType) &&
+ (type != "Ethernet" || RequiredField(*result, kEthernet)) &&
+ (type != "VPN" || RequiredField(*result, kVPN)) &&
+ (type != "WiFi" || RequiredField(*result, kWiFi));
+ if (error_on_missing_field_ && !allRequiredExist)
+ return false;
+
+ return true;
+}
+
+bool Validator::ValidateVpn(
+ const base::DictionaryValue& onc_object,
+ base::DictionaryValue* result) {
+ return ValidateObjectDefault(vpn_signature, onc_object, result);
+}
+
+bool Validator::ValidateIpsec(
+ const base::DictionaryValue& onc_object,
+ base::DictionaryValue* result) {
+ return ValidateObjectDefault(ipsec_signature, onc_object, result);
+}
+
+} // namespace onc
+} // namespace chromeos

Powered by Google App Engine
This is Rietveld 408576698