summaryrefslogtreecommitdiffstats
path: root/chromium/components/policy/core/common/schema.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/policy/core/common/schema.cc')
-rw-r--r--chromium/components/policy/core/common/schema.cc587
1 files changed, 0 insertions, 587 deletions
diff --git a/chromium/components/policy/core/common/schema.cc b/chromium/components/policy/core/common/schema.cc
deleted file mode 100644
index 5f0cc18db87..00000000000
--- a/chromium/components/policy/core/common/schema.cc
+++ /dev/null
@@ -1,587 +0,0 @@
-// 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 <map>
-#include <utility>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "base/memory/scoped_vector.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 schema = json_schema_constants;
-
-namespace policy {
-
-using internal::PropertiesNode;
-using internal::PropertyNode;
-using internal::SchemaData;
-using internal::SchemaNode;
-
-namespace {
-
-// Maps schema "id" attributes to the corresponding SchemaNode index.
-typedef std::map<std::string, int> IdMap;
-
-// List of pairs of references to be assigned later. The string is the "id"
-// whose corresponding index should be stored in the pointer, once all the IDs
-// are available.
-typedef std::vector<std::pair<std::string, int*> > ReferenceList;
-
-// Sizes for the storage arrays. These are calculated in advance so that the
-// arrays don't have to be resized during parsing, which would invalidate
-// pointers into their contents (i.e. string's c_str() and address of indices
-// for "$ref" attributes).
-struct StorageSizes {
- StorageSizes()
- : strings(0), schema_nodes(0), property_nodes(0), properties_nodes(0) {}
- size_t strings;
- size_t schema_nodes;
- size_t property_nodes;
- size_t properties_nodes;
-};
-
-// An invalid index, indicating that a node is not present; similar to a NULL
-// pointer.
-const int kInvalid = -1;
-
-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[] = {
- { schema::kArray, base::Value::TYPE_LIST },
- { schema::kBoolean, base::Value::TYPE_BOOLEAN },
- { schema::kInteger, base::Value::TYPE_INTEGER },
- { schema::kNull, base::Value::TYPE_NULL },
- { schema::kNumber, base::Value::TYPE_DOUBLE },
- { schema::kObject, base::Value::TYPE_DICTIONARY },
- { schema::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
-
-// Contains the internal data representation of a Schema. This can either wrap
-// a SchemaData owned elsewhere (currently used to wrap the Chrome schema, which
-// is generated at compile time), or it can own its own SchemaData.
-class Schema::InternalStorage
- : public base::RefCountedThreadSafe<InternalStorage> {
- public:
- static scoped_refptr<const InternalStorage> Wrap(const SchemaData* data);
-
- static scoped_refptr<const InternalStorage> ParseSchema(
- const base::DictionaryValue& schema,
- std::string* error);
-
- const SchemaData* data() const { return &schema_data_; }
-
- const SchemaNode* root_node() const {
- return schema(0);
- }
-
- const SchemaNode* schema(int index) const {
- return schema_data_.schema_nodes + index;
- }
-
- const PropertiesNode* properties(int index) const {
- return schema_data_.properties_nodes + index;
- }
-
- const PropertyNode* property(int index) const {
- return schema_data_.property_nodes + index;
- }
-
- private:
- friend class base::RefCountedThreadSafe<InternalStorage>;
-
- InternalStorage();
- ~InternalStorage();
-
- // Determines the expected |sizes| of the storage for the representation
- // of |schema|.
- static void DetermineStorageSizes(const base::DictionaryValue& schema,
- StorageSizes* sizes);
-
- // Parses the JSON schema in |schema|.
- //
- // If |schema| has a "$ref" attribute then a pending reference is appended
- // to the |reference_list|, and nothing else is done.
- //
- // Otherwise, |index| gets assigned the index of the corresponding SchemaNode
- // in |schema_nodes_|. If the |schema| contains an "id" then that ID is mapped
- // to the |index| in the |id_map|.
- //
- // If |schema| is invalid then |error| gets the error reason and false is
- // returned. Otherwise returns true.
- bool Parse(const base::DictionaryValue& schema,
- int* index,
- IdMap* id_map,
- ReferenceList* reference_list,
- std::string* error);
-
- // Helper for Parse() that gets an already assigned |schema_node| instead of
- // an |index| pointer.
- bool ParseDictionary(const base::DictionaryValue& schema,
- SchemaNode* schema_node,
- IdMap* id_map,
- ReferenceList* reference_list,
- std::string* error);
-
- // Helper for Parse() that gets an already assigned |schema_node| instead of
- // an |index| pointer.
- bool ParseList(const base::DictionaryValue& schema,
- SchemaNode* schema_node,
- IdMap* id_map,
- ReferenceList* reference_list,
- std::string* error);
-
- // Assigns the IDs in |id_map| to the pending references in the
- // |reference_list|. If an ID is missing then |error| is set and false is
- // returned; otherwise returns true.
- static bool ResolveReferences(const IdMap& id_map,
- const ReferenceList& reference_list,
- std::string* error);
-
- SchemaData schema_data_;
- std::vector<std::string> strings_;
- std::vector<SchemaNode> schema_nodes_;
- std::vector<PropertyNode> property_nodes_;
- std::vector<PropertiesNode> properties_nodes_;
-
- DISALLOW_COPY_AND_ASSIGN(InternalStorage);
-};
-
-Schema::InternalStorage::InternalStorage() {}
-
-Schema::InternalStorage::~InternalStorage() {}
-
-// static
-scoped_refptr<const Schema::InternalStorage> Schema::InternalStorage::Wrap(
- const SchemaData* data) {
- InternalStorage* storage = new InternalStorage();
- storage->schema_data_.schema_nodes = data->schema_nodes;
- storage->schema_data_.property_nodes = data->property_nodes;
- storage->schema_data_.properties_nodes = data->properties_nodes;
- return storage;
-}
-
-// static
-scoped_refptr<const Schema::InternalStorage>
-Schema::InternalStorage::ParseSchema(const base::DictionaryValue& schema,
- std::string* error) {
- // Determine the sizes of the storage arrays and reserve the capacity before
- // starting to append nodes and strings. This is important to prevent the
- // arrays from being reallocated, which would invalidate the c_str() pointers
- // and the addresses of indices to fix.
- StorageSizes sizes;
- DetermineStorageSizes(schema, &sizes);
-
- scoped_refptr<InternalStorage> storage = new InternalStorage();
- storage->strings_.reserve(sizes.strings);
- storage->schema_nodes_.reserve(sizes.schema_nodes);
- storage->property_nodes_.reserve(sizes.property_nodes);
- storage->properties_nodes_.reserve(sizes.properties_nodes);
-
- int root_index = kInvalid;
- IdMap id_map;
- ReferenceList reference_list;
- if (!storage->Parse(schema, &root_index, &id_map, &reference_list, error))
- return NULL;
-
- if (root_index == kInvalid) {
- *error = "The main schema can't have a $ref";
- return NULL;
- }
-
- // None of this should ever happen without having been already detected.
- // But, if it does happen, then it will lead to corrupted memory; drop
- // everything in that case.
- if (root_index != 0 ||
- sizes.strings != storage->strings_.size() ||
- sizes.schema_nodes != storage->schema_nodes_.size() ||
- sizes.property_nodes != storage->property_nodes_.size() ||
- sizes.properties_nodes != storage->properties_nodes_.size()) {
- *error = "Failed to parse the schema due to a Chrome bug. Please file a "
- "new issue at http://crbug.com";
- return NULL;
- }
-
- if (!ResolveReferences(id_map, reference_list, error))
- return NULL;
-
- SchemaData* data = &storage->schema_data_;
- data->schema_nodes = vector_as_array(&storage->schema_nodes_);
- data->property_nodes = vector_as_array(&storage->property_nodes_);
- data->properties_nodes = vector_as_array(&storage->properties_nodes_);
- return storage;
-}
-
-// static
-void Schema::InternalStorage::DetermineStorageSizes(
- const base::DictionaryValue& schema,
- StorageSizes* sizes) {
- std::string ref_string;
- if (schema.GetString(schema::kRef, &ref_string)) {
- // Schemas with a "$ref" attribute don't take additional storage.
- return;
- }
-
- std::string type_string;
- base::Value::Type type = base::Value::TYPE_NULL;
- if (!schema.GetString(schema::kType, &type_string) ||
- !SchemaTypeToValueType(type_string, &type)) {
- // This schema is invalid.
- return;
- }
-
- sizes->schema_nodes++;
-
- if (type == base::Value::TYPE_LIST) {
- const base::DictionaryValue* items = NULL;
- if (schema.GetDictionary(schema::kItems, &items))
- DetermineStorageSizes(*items, sizes);
- } else if (type == base::Value::TYPE_DICTIONARY) {
- sizes->properties_nodes++;
-
- const base::DictionaryValue* dict = NULL;
- if (schema.GetDictionary(schema::kAdditionalProperties, &dict))
- DetermineStorageSizes(*dict, sizes);
-
- const base::DictionaryValue* properties = NULL;
- if (schema.GetDictionary(schema::kProperties, &properties)) {
- for (base::DictionaryValue::Iterator it(*properties);
- !it.IsAtEnd(); it.Advance()) {
- // This should have been verified by the JSONSchemaValidator.
- CHECK(it.value().GetAsDictionary(&dict));
- DetermineStorageSizes(*dict, sizes);
- sizes->strings++;
- sizes->property_nodes++;
- }
- }
- }
-}
-
-bool Schema::InternalStorage::Parse(const base::DictionaryValue& schema,
- int* index,
- IdMap* id_map,
- ReferenceList* reference_list,
- std::string* error) {
- std::string ref_string;
- if (schema.GetString(schema::kRef, &ref_string)) {
- std::string id_string;
- if (schema.GetString(schema::kId, &id_string)) {
- *error = "Schemas with a $ref can't have an id";
- return false;
- }
- reference_list->push_back(std::make_pair(ref_string, index));
- return true;
- }
-
- std::string type_string;
- if (!schema.GetString(schema::kType, &type_string)) {
- *error = "The schema type must be declared.";
- return false;
- }
-
- base::Value::Type type = base::Value::TYPE_NULL;
- if (!SchemaTypeToValueType(type_string, &type)) {
- *error = "Type not supported: " + type_string;
- return false;
- }
-
- *index = static_cast<int>(schema_nodes_.size());
- schema_nodes_.push_back(SchemaNode());
- SchemaNode* schema_node = &schema_nodes_.back();
- schema_node->type = type;
- schema_node->extra = kInvalid;
-
- if (type == base::Value::TYPE_DICTIONARY) {
- if (!ParseDictionary(schema, schema_node, id_map, reference_list, error))
- return false;
- } else if (type == base::Value::TYPE_LIST) {
- if (!ParseList(schema, schema_node, id_map, reference_list, error))
- return false;
- }
-
- std::string id_string;
- if (schema.GetString(schema::kId, &id_string)) {
- if (ContainsKey(*id_map, id_string)) {
- *error = "Duplicated id: " + id_string;
- return false;
- }
- (*id_map)[id_string] = *index;
- }
-
- return true;
-}
-
-bool Schema::InternalStorage::ParseDictionary(
- const base::DictionaryValue& schema,
- SchemaNode* schema_node,
- IdMap* id_map,
- ReferenceList* reference_list,
- std::string* error) {
- int extra = static_cast<int>(properties_nodes_.size());
- properties_nodes_.push_back(PropertiesNode());
- properties_nodes_[extra].begin = kInvalid;
- properties_nodes_[extra].end = kInvalid;
- properties_nodes_[extra].additional = kInvalid;
- schema_node->extra = extra;
-
- const base::DictionaryValue* dict = NULL;
- if (schema.GetDictionary(schema::kAdditionalProperties, &dict)) {
- if (!Parse(*dict, &properties_nodes_[extra].additional,
- id_map, reference_list, error)) {
- return false;
- }
- }
-
- const base::DictionaryValue* properties = NULL;
- if (schema.GetDictionary(schema::kProperties, &properties)) {
- int base_index = static_cast<int>(property_nodes_.size());
- // This reserves nodes for all of the |properties|, and makes sure they
- // are contiguous. Recursive calls to Parse() will append after these
- // elements.
- property_nodes_.resize(base_index + properties->size());
-
- int index = base_index;
- for (base::DictionaryValue::Iterator it(*properties);
- !it.IsAtEnd(); it.Advance(), ++index) {
- // This should have been verified by the JSONSchemaValidator.
- CHECK(it.value().GetAsDictionary(&dict));
- strings_.push_back(it.key());
- property_nodes_[index].key = strings_.back().c_str();
- if (!Parse(*dict, &property_nodes_[index].schema,
- id_map, reference_list, error)) {
- return false;
- }
- }
- CHECK_EQ(static_cast<int>(properties->size()), index - base_index);
- properties_nodes_[extra].begin = base_index;
- properties_nodes_[extra].end = index;
- }
-
- return true;
-}
-
-bool Schema::InternalStorage::ParseList(const base::DictionaryValue& schema,
- SchemaNode* schema_node,
- IdMap* id_map,
- ReferenceList* reference_list,
- std::string* error) {
- const base::DictionaryValue* dict = NULL;
- if (!schema.GetDictionary(schema::kItems, &dict)) {
- *error = "Arrays must declare a single schema for their items.";
- return false;
- }
- return Parse(*dict, &schema_node->extra, id_map, reference_list, error);
-}
-
-// static
-bool Schema::InternalStorage::ResolveReferences(
- const IdMap& id_map,
- const ReferenceList& reference_list,
- std::string* error) {
- for (ReferenceList::const_iterator ref = reference_list.begin();
- ref != reference_list.end(); ++ref) {
- IdMap::const_iterator id = id_map.find(ref->first);
- if (id == id_map.end()) {
- *error = "Invalid $ref: " + ref->first;
- return false;
- }
- *ref->second = id->second;
- }
- return true;
-}
-
-Schema::Iterator::Iterator(const scoped_refptr<const InternalStorage>& storage,
- const PropertiesNode* node)
- : storage_(storage),
- it_(storage->property(node->begin)),
- end_(storage->property(node->end)) {}
-
-Schema::Iterator::Iterator(const Iterator& iterator)
- : storage_(iterator.storage_),
- it_(iterator.it_),
- end_(iterator.end_) {}
-
-Schema::Iterator::~Iterator() {}
-
-Schema::Iterator& Schema::Iterator::operator=(const Iterator& iterator) {
- storage_ = iterator.storage_;
- 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(storage_, storage_->schema(it_->schema));
-}
-
-Schema::Schema() : node_(NULL) {}
-
-Schema::Schema(const scoped_refptr<const InternalStorage>& storage,
- const SchemaNode* node)
- : storage_(storage), node_(node) {}
-
-Schema::Schema(const Schema& schema)
- : storage_(schema.storage_), node_(schema.node_) {}
-
-Schema::~Schema() {}
-
-Schema& Schema::operator=(const Schema& schema) {
- storage_ = schema.storage_;
- node_ = schema.node_;
- return *this;
-}
-
-// static
-Schema Schema::Wrap(const SchemaData* data) {
- scoped_refptr<const InternalStorage> storage = InternalStorage::Wrap(data);
- return Schema(storage, storage->root_node());
-}
-
-bool Schema::Validate(const base::Value& value) const {
- if (!valid()) {
- // Schema not found, invalid entry.
- return false;
- }
-
- if (!value.IsType(type()))
- return false;
-
- const base::DictionaryValue* dict = NULL;
- const base::ListValue* list = NULL;
- if (value.GetAsDictionary(&dict)) {
- for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
- it.Advance()) {
- if (!GetProperty(it.key()).Validate(it.value()))
- return false;
- }
- } else if (value.GetAsList(&list)) {
- for (base::ListValue::const_iterator it = list->begin();
- it != list->end(); ++it) {
- if (!*it || !GetItems().Validate(**it))
- return false;
- }
- }
-
- return true;
-}
-
-// static
-Schema Schema::Parse(const std::string& content, std::string* error) {
- // Validate as a generic JSON schema, and ignore unknown attributes; they
- // may become used in a future version of the schema format.
- scoped_ptr<base::DictionaryValue> dict = JSONSchemaValidator::IsValidSchema(
- content, JSONSchemaValidator::OPTIONS_IGNORE_UNKNOWN_ATTRIBUTES, error);
- if (!dict)
- return Schema();
-
- // Validate the main type.
- std::string string_value;
- if (!dict->GetString(schema::kType, &string_value) ||
- string_value != schema::kObject) {
- *error =
- "The main schema must have a type attribute with \"object\" value.";
- return Schema();
- }
-
- // Checks for invalid attributes at the top-level.
- if (dict->HasKey(schema::kAdditionalProperties) ||
- dict->HasKey(schema::kPatternProperties)) {
- *error = "\"additionalProperties\" and \"patternProperties\" are not "
- "supported at the main schema.";
- return Schema();
- }
-
- scoped_refptr<const InternalStorage> storage =
- InternalStorage::ParseSchema(*dict, error);
- if (!storage)
- return Schema();
- return Schema(storage, storage->root_node());
-}
-
-base::Value::Type Schema::type() const {
- CHECK(valid());
- return node_->type;
-}
-
-Schema::Iterator Schema::GetPropertiesIterator() const {
- CHECK(valid());
- CHECK_EQ(base::Value::TYPE_DICTIONARY, type());
- return Iterator(storage_, storage_->properties(node_->extra));
-}
-
-namespace {
-
-bool CompareKeys(const 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 PropertiesNode* node = storage_->properties(node_->extra);
- const PropertyNode* begin = storage_->property(node->begin);
- const PropertyNode* end = storage_->property(node->end);
- const PropertyNode* it = std::lower_bound(begin, end, key, CompareKeys);
- if (it != end && it->key == key)
- return Schema(storage_, storage_->schema(it->schema));
- return Schema();
-}
-
-Schema Schema::GetAdditionalProperties() const {
- CHECK(valid());
- CHECK_EQ(base::Value::TYPE_DICTIONARY, type());
- const PropertiesNode* node = storage_->properties(node_->extra);
- if (node->additional == kInvalid)
- return Schema();
- return Schema(storage_, storage_->schema(node->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());
- if (node_->extra == kInvalid)
- return Schema();
- return Schema(storage_, storage_->schema(node_->extra));
-}
-
-} // namespace policy