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

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