Index: components/policy/core/common/schema.cc |
diff --git a/components/policy/core/common/schema.cc b/components/policy/core/common/schema.cc |
index 3830bc149bcf1cfbe95363db00a3e8f460e30606..325ec2a26e11fe5715937ba0d0c57e5931d7b42e 100644 |
--- a/components/policy/core/common/schema.cc |
+++ b/components/policy/core/common/schema.cc |
@@ -51,22 +51,41 @@ bool SchemaTypeToValueType(const std::string& type_string, |
} // namespace |
-// A SchemaOwner 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. In that case, the InternalStorage class holds the |
-// data referenced by the SchemaData substructures. |
-class SchemaOwner::InternalStorage { |
+// 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: |
- ~InternalStorage() {} |
+ static scoped_refptr<const InternalStorage> Wrap(const SchemaData* data); |
- static scoped_ptr<InternalStorage> ParseSchema( |
+ static scoped_refptr<const InternalStorage> ParseSchema( |
const base::DictionaryValue& schema, |
std::string* error); |
- const SchemaData* schema_data() const { return &schema_data_; } |
+ 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: |
- InternalStorage() {} |
+ friend class base::RefCountedThreadSafe<InternalStorage>; |
+ |
+ InternalStorage(); |
+ ~InternalStorage(); |
// Parses the JSON schema in |schema| and returns the index of the |
// corresponding SchemaNode in |schema_nodes_|, which gets populated with any |
@@ -91,174 +110,36 @@ class SchemaOwner::InternalStorage { |
DISALLOW_COPY_AND_ASSIGN(InternalStorage); |
}; |
-Schema::Iterator::Iterator(const SchemaData* data, const PropertiesNode* node) |
- : data_(data), |
- it_(data->property_nodes + node->begin), |
- end_(data->property_nodes + node->end) {} |
- |
-Schema::Iterator::Iterator(const Iterator& iterator) |
- : data_(iterator.data_), |
- it_(iterator.it_), |
- end_(iterator.end_) {} |
- |
-Schema::Iterator::~Iterator() {} |
- |
-Schema::Iterator& Schema::Iterator::operator=(const Iterator& iterator) { |
- data_ = iterator.data_; |
- it_ = iterator.it_; |
- end_ = iterator.end_; |
- return *this; |
-} |
+Schema::InternalStorage::InternalStorage() {} |
-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(data_, data_->schema_nodes + it_->schema); |
-} |
- |
-Schema::Schema() : data_(NULL), node_(NULL) {} |
- |
-Schema::Schema(const SchemaData* data, const SchemaNode* node) |
- : data_(data), node_(node) {} |
- |
-Schema::Schema(const Schema& schema) |
- : data_(schema.data_), node_(schema.node_) {} |
- |
-Schema& Schema::operator=(const Schema& schema) { |
- data_ = schema.data_; |
- node_ = schema.node_; |
- return *this; |
-} |
- |
-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(data_, data_->properties_nodes + 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 = data_->properties_nodes + node_->extra; |
- const PropertyNode* begin = data_->property_nodes + node->begin; |
- const PropertyNode* end = data_->property_nodes + node->end; |
- const PropertyNode* it = std::lower_bound(begin, end, key, CompareKeys); |
- if (it != end && it->key == key) |
- return Schema(data_, data_->schema_nodes + it->schema); |
- return Schema(); |
-} |
- |
-Schema Schema::GetAdditionalProperties() const { |
- CHECK(valid()); |
- CHECK_EQ(base::Value::TYPE_DICTIONARY, type()); |
- const PropertiesNode* node = data_->properties_nodes + node_->extra; |
- if (node->additional == kInvalid) |
- return Schema(); |
- return Schema(data_, data_->schema_nodes + 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(data_, data_->schema_nodes + node_->extra); |
-} |
- |
-SchemaOwner::SchemaOwner(const SchemaData* data, |
- scoped_ptr<InternalStorage> storage) |
- : storage_(storage.Pass()), data_(data) {} |
- |
-SchemaOwner::~SchemaOwner() {} |
- |
-Schema SchemaOwner::schema() const { |
- // data_->schema_nodes[0] is the root node. |
- return Schema(data_, data_->schema_nodes); |
-} |
+Schema::InternalStorage::~InternalStorage() {} |
// static |
-scoped_ptr<SchemaOwner> SchemaOwner::Wrap(const SchemaData* data) { |
- return make_scoped_ptr(new SchemaOwner(data, scoped_ptr<InternalStorage>())); |
+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_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<InternalStorage> storage = |
- InternalStorage::ParseSchema(*dict, error); |
- if (!storage) |
- return scoped_ptr<SchemaOwner>(); |
- const SchemaData* data = storage->schema_data(); |
- return make_scoped_ptr(new SchemaOwner(data, storage.Pass())); |
-} |
- |
-// static |
-scoped_ptr<SchemaOwner::InternalStorage> |
-SchemaOwner::InternalStorage::ParseSchema(const base::DictionaryValue& schema, |
- std::string* error) { |
- scoped_ptr<InternalStorage> storage(new InternalStorage); |
+scoped_refptr<const Schema::InternalStorage> |
+Schema::InternalStorage::ParseSchema(const base::DictionaryValue& schema, |
+ std::string* error) { |
+ scoped_refptr<InternalStorage> storage = new InternalStorage(); |
if (storage->Parse(schema, error) == kInvalid) |
- return scoped_ptr<InternalStorage>(); |
+ 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.Pass(); |
+ return storage; |
} |
-int SchemaOwner::InternalStorage::Parse(const base::DictionaryValue& schema, |
- std::string* error) { |
+int Schema::InternalStorage::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."; |
@@ -285,7 +166,7 @@ int SchemaOwner::InternalStorage::Parse(const base::DictionaryValue& schema, |
} |
// static |
-int SchemaOwner::InternalStorage::ParseDictionary( |
+int Schema::InternalStorage::ParseDictionary( |
const base::DictionaryValue& schema, |
std::string* error) { |
// Note: recursive calls to Parse() invalidate iterators and references into |
@@ -342,8 +223,8 @@ int SchemaOwner::InternalStorage::ParseDictionary( |
} |
// static |
-int SchemaOwner::InternalStorage::ParseList(const base::DictionaryValue& schema, |
- std::string* error) { |
+int Schema::InternalStorage::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."; |
@@ -359,4 +240,148 @@ int SchemaOwner::InternalStorage::ParseList(const base::DictionaryValue& schema, |
return index; |
} |
+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()); |
+} |
+ |
+// static |
+Schema Schema::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 Schema(); |
+ |
+ // 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 Schema(); |
+ } |
+ |
+ // 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 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 |