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

Unified Diff: components/policy/core/common/schema.cc

Issue 23851022: Added new policy Schema classes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 3 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
« no previous file with comments | « components/policy/core/common/schema.h ('k') | components/policy/core/common/schema_internal.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/policy/core/common/schema.cc
diff --git a/components/policy/core/common/schema.cc b/components/policy/core/common/schema.cc
new file mode 100644
index 0000000000000000000000000000000000000000..cbfde46faf3374115c91a4ec670873c2cf43d7c5
--- /dev/null
+++ b/components/policy/core/common/schema.cc
@@ -0,0 +1,276 @@
+// Copyright 2013 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 "components/policy/core/common/schema.h"
+
+#include <algorithm>
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "components/json_schema/json_schema_constants.h"
+#include "components/json_schema/json_schema_validator.h"
+#include "components/policy/core/common/schema_internal.h"
+
+namespace policy {
+
+namespace {
+
+bool SchemaTypeToValueType(const std::string& type_string,
+ base::Value::Type* type) {
+ // Note: "any" is not an accepted type.
+ static const struct {
+ const char* schema_type;
+ base::Value::Type value_type;
+ } kSchemaToValueTypeMap[] = {
+ { json_schema_constants::kArray, base::Value::TYPE_LIST },
+ { json_schema_constants::kBoolean, base::Value::TYPE_BOOLEAN },
+ { json_schema_constants::kInteger, base::Value::TYPE_INTEGER },
+ { json_schema_constants::kNull, base::Value::TYPE_NULL },
+ { json_schema_constants::kNumber, base::Value::TYPE_DOUBLE },
+ { json_schema_constants::kObject, base::Value::TYPE_DICTIONARY },
+ { json_schema_constants::kString, base::Value::TYPE_STRING },
+ };
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSchemaToValueTypeMap); ++i) {
+ if (kSchemaToValueTypeMap[i].schema_type == type_string) {
+ *type = kSchemaToValueTypeMap[i].value_type;
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
+
+Schema::Iterator::Iterator(const internal::PropertiesNode* properties)
+ : it_(properties->begin),
+ end_(properties->end) {}
+
+Schema::Iterator::Iterator(const Iterator& iterator)
+ : it_(iterator.it_),
+ end_(iterator.end_) {}
+
+Schema::Iterator::~Iterator() {}
+
+Schema::Iterator& Schema::Iterator::operator=(const Iterator& iterator) {
+ it_ = iterator.it_;
+ end_ = iterator.end_;
+ return *this;
+}
+
+bool Schema::Iterator::IsAtEnd() const {
+ return it_ == end_;
+}
+
+void Schema::Iterator::Advance() {
+ ++it_;
+}
+
+const char* Schema::Iterator::key() const {
+ return it_->key;
+}
+
+Schema Schema::Iterator::schema() const {
+ return Schema(it_->schema);
+}
+
+Schema::Schema(const internal::SchemaNode* schema) : schema_(schema) {}
+
+Schema::Schema(const Schema& schema) : schema_(schema.schema_) {}
+
+Schema& Schema::operator=(const Schema& schema) {
+ schema_ = schema.schema_;
+ return *this;
+}
+
+base::Value::Type Schema::type() const {
+ CHECK(valid());
+ return schema_->type;
+}
+
+Schema::Iterator Schema::GetPropertiesIterator() const {
+ CHECK(valid());
+ CHECK_EQ(base::Value::TYPE_DICTIONARY, type());
+ return Iterator(
+ static_cast<const internal::PropertiesNode*>(schema_->extra));
+}
+
+namespace {
+
+bool CompareKeys(const internal::PropertyNode& node, const std::string& key) {
+ return node.key < key;
+}
+
+} // namespace
+
+Schema Schema::GetKnownProperty(const std::string& key) const {
+ CHECK(valid());
+ CHECK_EQ(base::Value::TYPE_DICTIONARY, type());
+ const internal::PropertiesNode* properties_node =
+ static_cast<const internal::PropertiesNode*>(schema_->extra);
+ const internal::PropertyNode* it = std::lower_bound(
+ properties_node->begin, properties_node->end, key, CompareKeys);
+ if (it != properties_node->end && it->key == key)
+ return Schema(it->schema);
+ return Schema(NULL);
+}
+
+Schema Schema::GetAdditionalProperties() const {
+ CHECK(valid());
+ CHECK_EQ(base::Value::TYPE_DICTIONARY, type());
+ return Schema(
+ static_cast<const internal::PropertiesNode*>(schema_->extra)->additional);
+}
+
+Schema Schema::GetProperty(const std::string& key) const {
+ Schema schema = GetKnownProperty(key);
+ return schema.valid() ? schema : GetAdditionalProperties();
+}
+
+Schema Schema::GetItems() const {
+ CHECK(valid());
+ CHECK_EQ(base::Value::TYPE_LIST, type());
+ return Schema(static_cast<const internal::SchemaNode*>(schema_->extra));
+}
+
+SchemaOwner::SchemaOwner(const internal::SchemaNode* root) : root_(root) {}
+
+SchemaOwner::~SchemaOwner() {
+ for (size_t i = 0; i < property_nodes_.size(); ++i)
+ delete[] property_nodes_[i];
+}
+
+// static
+scoped_ptr<SchemaOwner> SchemaOwner::Wrap(const internal::SchemaNode* schema) {
+ return scoped_ptr<SchemaOwner>(new SchemaOwner(schema));
+}
+
+// static
+scoped_ptr<SchemaOwner> SchemaOwner::Parse(const std::string& content,
+ std::string* error) {
+ // Validate as a generic JSON schema.
+ scoped_ptr<base::DictionaryValue> dict =
+ JSONSchemaValidator::IsValidSchema(content, error);
+ if (!dict)
+ return scoped_ptr<SchemaOwner>();
+
+ // Validate the main type.
+ std::string string_value;
+ if (!dict->GetString(json_schema_constants::kType, &string_value) ||
+ string_value != json_schema_constants::kObject) {
+ *error =
+ "The main schema must have a type attribute with \"object\" value.";
+ return scoped_ptr<SchemaOwner>();
+ }
+
+ // Checks for invalid attributes at the top-level.
+ if (dict->HasKey(json_schema_constants::kAdditionalProperties) ||
+ dict->HasKey(json_schema_constants::kPatternProperties)) {
+ *error = "\"additionalProperties\" and \"patternProperties\" are not "
+ "supported at the main schema.";
+ return scoped_ptr<SchemaOwner>();
+ }
+
+ scoped_ptr<SchemaOwner> impl(new SchemaOwner(NULL));
+ impl->root_ = impl->Parse(*dict, error);
+ if (!impl->root_)
+ impl.reset();
+ return impl.PassAs<SchemaOwner>();
+}
+
+const internal::SchemaNode* SchemaOwner::Parse(
+ const base::DictionaryValue& schema,
+ std::string* error) {
+ std::string type_string;
+ if (!schema.GetString(json_schema_constants::kType, &type_string)) {
+ *error = "The schema type must be declared.";
+ return NULL;
+ }
+
+ base::Value::Type type = base::Value::TYPE_NULL;
+ if (!SchemaTypeToValueType(type_string, &type)) {
+ *error = "Type not supported: " + type_string;
+ return NULL;
+ }
+
+ if (type == base::Value::TYPE_DICTIONARY)
+ return ParseDictionary(schema, error);
+ if (type == base::Value::TYPE_LIST)
+ return ParseList(schema, error);
+
+ internal::SchemaNode* node = new internal::SchemaNode;
+ node->type = type;
+ node->extra = NULL;
+ schema_nodes_.push_back(node);
+ return node;
+}
+
+const internal::SchemaNode* SchemaOwner::ParseDictionary(
+ const base::DictionaryValue& schema,
+ std::string* error) {
+ internal::PropertiesNode* properties_node = new internal::PropertiesNode;
+ properties_node->begin = NULL;
+ properties_node->end = NULL;
+ properties_node->additional = NULL;
+ properties_nodes_.push_back(properties_node);
+
+ const base::DictionaryValue* dict = NULL;
+ const base::DictionaryValue* properties = NULL;
+ if (schema.GetDictionary(json_schema_constants::kProperties, &properties)) {
+ internal::PropertyNode* property_nodes =
+ new internal::PropertyNode[properties->size()];
+ property_nodes_.push_back(property_nodes);
+
+ size_t index = 0;
+ for (base::DictionaryValue::Iterator it(*properties);
+ !it.IsAtEnd(); it.Advance(), ++index) {
+ // This should have been verified by the JSONSchemaValidator.
+ CHECK(it.value().GetAsDictionary(&dict));
+ const internal::SchemaNode* sub_schema = Parse(*dict, error);
+ if (!sub_schema)
+ return NULL;
+ std::string* key = new std::string(it.key());
+ keys_.push_back(key);
+ property_nodes[index].key = key->c_str();
+ property_nodes[index].schema = sub_schema;
+ }
+ CHECK_EQ(properties->size(), index);
+ properties_node->begin = property_nodes;
+ properties_node->end = property_nodes + index;
+ }
+
+ if (schema.GetDictionary(json_schema_constants::kAdditionalProperties,
+ &dict)) {
+ const internal::SchemaNode* sub_schema = Parse(*dict, error);
+ if (!sub_schema)
+ return NULL;
+ properties_node->additional = sub_schema;
+ }
+
+ internal::SchemaNode* schema_node = new internal::SchemaNode;
+ schema_node->type = base::Value::TYPE_DICTIONARY;
+ schema_node->extra = properties_node;
+ schema_nodes_.push_back(schema_node);
+ return schema_node;
+}
+
+const internal::SchemaNode* SchemaOwner::ParseList(
+ const base::DictionaryValue& schema,
+ std::string* error) {
+ const base::DictionaryValue* dict = NULL;
+ if (!schema.GetDictionary(json_schema_constants::kItems, &dict)) {
+ *error = "Arrays must declare a single schema for their items.";
+ return NULL;
+ }
+ const internal::SchemaNode* items_schema_node = Parse(*dict, error);
+ if (!items_schema_node)
+ return NULL;
+
+ internal::SchemaNode* schema_node = new internal::SchemaNode;
+ schema_node->type = base::Value::TYPE_LIST;
+ schema_node->extra = items_schema_node;
+ schema_nodes_.push_back(schema_node);
+ return schema_node;
+}
+
+} // namespace policy
« no previous file with comments | « components/policy/core/common/schema.h ('k') | components/policy/core/common/schema_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698