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

Side by Side 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: addressed comments 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/policy/core/common/schema.h"
6
7 #include <algorithm>
8
9 #include "base/compiler_specific.h"
10 #include "base/logging.h"
11 #include "components/json_schema/json_schema_constants.h"
12 #include "components/json_schema/json_schema_validator.h"
13 #include "components/policy/core/common/schema_internal.h"
14
15 namespace policy {
16
17 namespace {
18
19 const char kJSONSchemaVersion[] = "http://json-schema.org/draft-03/schema#";
20
21 bool SchemaTypeToValueType(const std::string& type_string,
22 base::Value::Type* type) {
23 // Note: "any" is not an accepted type.
24 static const struct {
25 const char* schema_type;
26 base::Value::Type value_type;
27 } kSchemaToValueTypeMap[] = {
28 { json_schema_constants::kArray, base::Value::TYPE_LIST },
29 { json_schema_constants::kBoolean, base::Value::TYPE_BOOLEAN },
30 { json_schema_constants::kInteger, base::Value::TYPE_INTEGER },
31 { json_schema_constants::kNull, base::Value::TYPE_NULL },
32 { json_schema_constants::kNumber, base::Value::TYPE_DOUBLE },
33 { json_schema_constants::kObject, base::Value::TYPE_DICTIONARY },
34 { json_schema_constants::kString, base::Value::TYPE_STRING },
35 };
36 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSchemaToValueTypeMap); ++i) {
37 if (kSchemaToValueTypeMap[i].schema_type == type_string) {
38 *type = kSchemaToValueTypeMap[i].value_type;
39 return true;
40 }
41 }
42 return false;
43 }
44
45 } // namespace
46
47 Schema::Iterator::Iterator(const internal::PropertiesNode* properties)
48 : it_(properties->begin),
49 end_(properties->end) {}
50
51 Schema::Iterator::Iterator(const Iterator& iterator)
52 : it_(iterator.it_),
53 end_(iterator.end_) {}
54
55 Schema::Iterator::~Iterator() {}
56
57 Schema::Iterator& Schema::Iterator::operator=(const Iterator& iterator) {
58 it_ = iterator.it_;
59 end_ = iterator.end_;
60 return *this;
61 }
62
63 bool Schema::Iterator::IsAtEnd() const {
64 return it_ == end_;
65 }
66
67 void Schema::Iterator::Advance() {
68 ++it_;
69 }
70
71 const char* Schema::Iterator::key() const {
72 return it_->key;
73 }
74
75 Schema Schema::Iterator::schema() const {
76 return Schema(it_->schema);
77 }
78
79 Schema::Schema(const internal::SchemaNode* schema) : schema_(schema) {}
80
81 Schema::Schema(const Schema& schema) : schema_(schema.schema_) {}
82
83 Schema& Schema::operator=(const Schema& schema) {
84 schema_ = schema.schema_;
85 return *this;
86 }
87
88 base::Value::Type Schema::type() const {
89 CHECK(valid());
90 return schema_->type;
91 }
92
93 Schema::Iterator Schema::GetPropertiesIterator() const {
94 CHECK(valid());
95 CHECK_EQ(base::Value::TYPE_DICTIONARY, type());
96 return Iterator(
97 static_cast<const internal::PropertiesNode*>(schema_->extra));
98 }
99
100 namespace {
101
102 bool CompareKeys(const internal::PropertyNode& node, const std::string& key) {
103 return node.key < key;
104 }
105
106 } // namespace
107
108 Schema Schema::GetKnownProperty(const std::string& key) const {
109 CHECK(valid());
110 CHECK_EQ(base::Value::TYPE_DICTIONARY, type());
111 const internal::PropertiesNode* properties_node =
112 static_cast<const internal::PropertiesNode*>(schema_->extra);
113 const internal::PropertyNode* it = std::lower_bound(
114 properties_node->begin, properties_node->end, key, CompareKeys);
115 if (it != properties_node->end && it->key == key)
116 return Schema(it->schema);
117 return Schema(NULL);
118 }
119
120 Schema Schema::GetAdditionalProperties() const {
121 CHECK(valid());
122 CHECK_EQ(base::Value::TYPE_DICTIONARY, type());
123 return Schema(
124 static_cast<const internal::PropertiesNode*>(schema_->extra)->additional);
125 }
126
127 Schema Schema::GetProperty(const std::string& key) const {
128 Schema schema = GetKnownProperty(key);
129 return schema.valid() ? schema : GetAdditionalProperties();
130 }
131
132 Schema Schema::GetItems() const {
133 CHECK(valid());
134 CHECK_EQ(base::Value::TYPE_LIST, type());
135 return Schema(static_cast<const internal::SchemaNode*>(schema_->extra));
136 }
137
138 SchemaOwner::SchemaOwner(const internal::SchemaNode* root) : root_(root) {}
139
140 SchemaOwner::~SchemaOwner() {
141 for (size_t i = 0; i < property_nodes_.size(); ++i)
142 delete[] property_nodes_[i];
143 }
144
145 // static
146 scoped_ptr<SchemaOwner> SchemaOwner::Wrap(const internal::SchemaNode* schema) {
147 return scoped_ptr<SchemaOwner>(new SchemaOwner(schema));
148 }
149
150 // static
151 scoped_ptr<SchemaOwner> SchemaOwner::Parse(const std::string& content,
152 std::string* error) {
153 // Validate as a generic JSON schema.
154 scoped_ptr<base::DictionaryValue> dict =
155 JSONSchemaValidator::IsValidSchema(content, error);
156 if (!dict)
157 return scoped_ptr<SchemaOwner>();
158
159 // Validate the schema version.
160 std::string string_value;
161 if (!dict->GetString(json_schema_constants::kSchema, &string_value) ||
162 string_value != kJSONSchemaVersion) {
163 *error = "Must declare JSON Schema v3 version in \"$schema\".";
164 return scoped_ptr<SchemaOwner>();
165 }
166
167 // Validate the main type.
168 if (!dict->GetString(json_schema_constants::kType, &string_value) ||
169 string_value != json_schema_constants::kObject) {
170 *error =
171 "The main schema must have a type attribute with \"object\" value.";
172 return scoped_ptr<SchemaOwner>();
173 }
174
175 // Checks for invalid attributes at the top-level.
176 if (dict->HasKey(json_schema_constants::kAdditionalProperties) ||
177 dict->HasKey(json_schema_constants::kPatternProperties)) {
178 *error = "\"additionalProperties\" and \"patternProperties\" are not "
179 "supported at the main schema.";
180 return scoped_ptr<SchemaOwner>();
181 }
182
183 scoped_ptr<SchemaOwner> impl(new SchemaOwner(NULL));
184 impl->root_ = impl->Parse(*dict, error);
185 if (!impl->root_)
186 impl.reset();
187 return impl.PassAs<SchemaOwner>();
188 }
189
190 const internal::SchemaNode* SchemaOwner::Parse(
191 const base::DictionaryValue& schema,
192 std::string* error) {
193 std::string type_string;
194 if (!schema.GetString(json_schema_constants::kType, &type_string)) {
195 *error = "The schema type must be declared.";
196 return NULL;
197 }
198
199 base::Value::Type type = base::Value::TYPE_NULL;
200 if (!SchemaTypeToValueType(type_string, &type)) {
201 *error = "Type not supported: " + type_string;
202 return NULL;
203 }
204
205 if (type == base::Value::TYPE_DICTIONARY)
206 return ParseDictionary(schema, error);
207 if (type == base::Value::TYPE_LIST)
208 return ParseList(schema, error);
209
210 internal::SchemaNode* node = new internal::SchemaNode;
211 node->type = type;
212 node->extra = NULL;
213 schema_nodes_.push_back(node);
214 return node;
215 }
216
217 const internal::SchemaNode* SchemaOwner::ParseDictionary(
218 const base::DictionaryValue& schema,
219 std::string* error) {
220 internal::PropertiesNode* properties_node = new internal::PropertiesNode;
221 properties_node->begin = NULL;
222 properties_node->end = NULL;
223 properties_node->additional = NULL;
224 properties_nodes_.push_back(properties_node);
225
226 const base::DictionaryValue* dict = NULL;
227 const base::DictionaryValue* properties = NULL;
228 if (schema.GetDictionary(json_schema_constants::kProperties, &properties)) {
229 internal::PropertyNode* property_nodes =
230 new internal::PropertyNode[properties->size()];
231 property_nodes_.push_back(property_nodes);
232
233 size_t index = 0;
234 for (base::DictionaryValue::Iterator it(*properties);
235 !it.IsAtEnd(); it.Advance(), ++index) {
236 // This should have been verified by the JSONSchemaValidator.
237 CHECK(it.value().GetAsDictionary(&dict));
238 const internal::SchemaNode* sub_schema = Parse(*dict, error);
239 if (!sub_schema)
240 return NULL;
241 std::string* key = new std::string(it.key());
242 keys_.push_back(key);
243 property_nodes[index].key = key->c_str();
244 property_nodes[index].schema = sub_schema;
245 }
246 CHECK_EQ(properties->size(), index);
247 properties_node->begin = property_nodes;
248 properties_node->end = property_nodes + index;
249 }
250
251 if (schema.GetDictionary(json_schema_constants::kAdditionalProperties,
252 &dict)) {
253 const internal::SchemaNode* sub_schema = Parse(*dict, error);
254 if (!sub_schema)
255 return NULL;
256 properties_node->additional = sub_schema;
257 }
258
259 internal::SchemaNode* schema_node = new internal::SchemaNode;
260 schema_node->type = base::Value::TYPE_DICTIONARY;
261 schema_node->extra = properties_node;
262 schema_nodes_.push_back(schema_node);
263 return schema_node;
264 }
265
266 const internal::SchemaNode* SchemaOwner::ParseList(
267 const base::DictionaryValue& schema,
268 std::string* error) {
269 const base::DictionaryValue* dict = NULL;
270 if (!schema.GetDictionary(json_schema_constants::kItems, &dict)) {
271 *error = "Arrays must declare a single schema for their items.";
272 return NULL;
273 }
274 const internal::SchemaNode* items_schema_node = Parse(*dict, error);
275 if (!items_schema_node)
276 return NULL;
277
278 internal::SchemaNode* schema_node = new internal::SchemaNode;
279 schema_node->type = base::Value::TYPE_LIST;
280 schema_node->extra = items_schema_node;
281 schema_nodes_.push_back(schema_node);
282 return schema_node;
283 }
284
285 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698