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

Side by Side Diff: components/policy/core/common/schema.cc

Issue 205923004: Add regex support in policy schema (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@json-schema-regex
Patch Set: Created 6 years, 9 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/policy/core/common/schema.h" 5 #include "components/policy/core/common/schema.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <climits> 8 #include <climits>
9 #include <map> 9 #include <map>
10 #include <utility> 10 #include <utility>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/compiler_specific.h" 13 #include "base/compiler_specific.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h"
15 #include "base/memory/scoped_vector.h" 16 #include "base/memory/scoped_vector.h"
17 #include "base/stl_util.h"
16 #include "base/strings/stringprintf.h" 18 #include "base/strings/stringprintf.h"
17 #include "components/json_schema/json_schema_constants.h" 19 #include "components/json_schema/json_schema_constants.h"
18 #include "components/json_schema/json_schema_validator.h" 20 #include "components/json_schema/json_schema_validator.h"
19 #include "components/policy/core/common/schema_internal.h" 21 #include "components/policy/core/common/schema_internal.h"
22 #include "third_party/re2/re2/re2.h"
20 23
21 namespace schema = json_schema_constants; 24 namespace schema = json_schema_constants;
22 25
23 namespace policy { 26 namespace policy {
24 27
25 using internal::PropertiesNode; 28 using internal::PropertiesNode;
26 using internal::PropertyNode; 29 using internal::PropertyNode;
27 using internal::RestrictionNode; 30 using internal::RestrictionNode;
28 using internal::SchemaData; 31 using internal::SchemaData;
29 using internal::SchemaNode; 32 using internal::SchemaNode;
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 } 171 }
169 172
170 const int* int_enums(int index) const { 173 const int* int_enums(int index) const {
171 return schema_data_.int_enums + index; 174 return schema_data_.int_enums + index;
172 } 175 }
173 176
174 const char** string_enums(int index) const { 177 const char** string_enums(int index) const {
175 return schema_data_.string_enums + index; 178 return schema_data_.string_enums + index;
176 } 179 }
177 180
181 // Compiles regular expression |pattern|. The result is cached and will be
182 // returned directly next time.
183 re2::RE2* CompileRegex(const std::string &pattern) const;
Joao da Silva 2014/03/21 12:58:12 const std::string& pattern
binjin 2014/03/27 17:57:47 Done.
184
178 private: 185 private:
179 friend class base::RefCountedThreadSafe<InternalStorage>; 186 friend class base::RefCountedThreadSafe<InternalStorage>;
180 187
181 InternalStorage(); 188 InternalStorage();
182 ~InternalStorage(); 189 ~InternalStorage();
183 190
184 // Determines the expected |sizes| of the storage for the representation 191 // Determines the expected |sizes| of the storage for the representation
185 // of |schema|. 192 // of |schema|.
186 static void DetermineStorageSizes(const base::DictionaryValue& schema, 193 static void DetermineStorageSizes(const base::DictionaryValue& schema,
187 StorageSizes* sizes); 194 StorageSizes* sizes);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 228
222 bool ParseEnum(const base::DictionaryValue& schema, 229 bool ParseEnum(const base::DictionaryValue& schema,
223 base::Value::Type type, 230 base::Value::Type type,
224 SchemaNode* schema_node, 231 SchemaNode* schema_node,
225 std::string* error); 232 std::string* error);
226 233
227 bool ParseRangedInt(const base::DictionaryValue& schema, 234 bool ParseRangedInt(const base::DictionaryValue& schema,
228 SchemaNode* schema_node, 235 SchemaNode* schema_node,
229 std::string* error); 236 std::string* error);
230 237
238 bool ParseStringPattern(const base::DictionaryValue& schema,
239 SchemaNode* schema_node,
240 std::string* error);
241
231 // Assigns the IDs in |id_map| to the pending references in the 242 // Assigns the IDs in |id_map| to the pending references in the
232 // |reference_list|. If an ID is missing then |error| is set and false is 243 // |reference_list|. If an ID is missing then |error| is set and false is
233 // returned; otherwise returns true. 244 // returned; otherwise returns true.
234 static bool ResolveReferences(const IdMap& id_map, 245 static bool ResolveReferences(const IdMap& id_map,
235 const ReferenceList& reference_list, 246 const ReferenceList& reference_list,
236 std::string* error); 247 std::string* error);
237 248
249 mutable std::map<std::string, re2::RE2*> regex_cache_;
Joao da Silva 2014/03/21 12:58:12 Argh, mutable. I think it's better than complicati
binjin 2014/03/27 17:57:47 Done.
250 STLValueDeleter<std::map<std::string, re2::RE2*> > cache_deleter_;
251
238 SchemaData schema_data_; 252 SchemaData schema_data_;
239 std::vector<std::string> strings_; 253 std::vector<std::string> strings_;
240 std::vector<SchemaNode> schema_nodes_; 254 std::vector<SchemaNode> schema_nodes_;
241 std::vector<PropertyNode> property_nodes_; 255 std::vector<PropertyNode> property_nodes_;
242 std::vector<PropertiesNode> properties_nodes_; 256 std::vector<PropertiesNode> properties_nodes_;
243 std::vector<RestrictionNode> restriction_nodes_; 257 std::vector<RestrictionNode> restriction_nodes_;
244 std::vector<int> int_enums_; 258 std::vector<int> int_enums_;
245 std::vector<const char*> string_enums_; 259 std::vector<const char*> string_enums_;
246 260
247 DISALLOW_COPY_AND_ASSIGN(InternalStorage); 261 DISALLOW_COPY_AND_ASSIGN(InternalStorage);
248 }; 262 };
249 263
250 Schema::InternalStorage::InternalStorage() {} 264 Schema::InternalStorage::InternalStorage() : cache_deleter_(&regex_cache_) {}
251 265
252 Schema::InternalStorage::~InternalStorage() {} 266 Schema::InternalStorage::~InternalStorage() {}
253 267
254 // static 268 // static
255 scoped_refptr<const Schema::InternalStorage> Schema::InternalStorage::Wrap( 269 scoped_refptr<const Schema::InternalStorage> Schema::InternalStorage::Wrap(
256 const SchemaData* data) { 270 const SchemaData* data) {
257 InternalStorage* storage = new InternalStorage(); 271 InternalStorage* storage = new InternalStorage();
258 storage->schema_data_.schema_nodes = data->schema_nodes; 272 storage->schema_data_.schema_nodes = data->schema_nodes;
259 storage->schema_data_.property_nodes = data->property_nodes; 273 storage->schema_data_.property_nodes = data->property_nodes;
260 storage->schema_data_.properties_nodes = data->properties_nodes; 274 storage->schema_data_.properties_nodes = data->properties_nodes;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 SchemaData* data = &storage->schema_data_; 331 SchemaData* data = &storage->schema_data_;
318 data->schema_nodes = vector_as_array(&storage->schema_nodes_); 332 data->schema_nodes = vector_as_array(&storage->schema_nodes_);
319 data->property_nodes = vector_as_array(&storage->property_nodes_); 333 data->property_nodes = vector_as_array(&storage->property_nodes_);
320 data->properties_nodes = vector_as_array(&storage->properties_nodes_); 334 data->properties_nodes = vector_as_array(&storage->properties_nodes_);
321 data->restriction_nodes = vector_as_array(&storage->restriction_nodes_); 335 data->restriction_nodes = vector_as_array(&storage->restriction_nodes_);
322 data->int_enums = vector_as_array(&storage->int_enums_); 336 data->int_enums = vector_as_array(&storage->int_enums_);
323 data->string_enums = vector_as_array(&storage->string_enums_); 337 data->string_enums = vector_as_array(&storage->string_enums_);
324 return storage; 338 return storage;
325 } 339 }
326 340
341 re2::RE2* Schema::InternalStorage::CompileRegex(
342 const std::string& pattern) const {
343 std::map<std::string, re2::RE2*>::iterator it = regex_cache_.find(pattern);
344 if (it == regex_cache_.end()) {
345 re2::RE2* compiled = new re2::RE2(pattern);
346 regex_cache_[pattern] = compiled;
347 return compiled;
348 }
349 return it->second;
350 }
351
327 // static 352 // static
328 void Schema::InternalStorage::DetermineStorageSizes( 353 void Schema::InternalStorage::DetermineStorageSizes(
329 const base::DictionaryValue& schema, 354 const base::DictionaryValue& schema,
330 StorageSizes* sizes) { 355 StorageSizes* sizes) {
331 std::string ref_string; 356 std::string ref_string;
332 if (schema.GetString(schema::kRef, &ref_string)) { 357 if (schema.GetString(schema::kRef, &ref_string)) {
333 // Schemas with a "$ref" attribute don't take additional storage. 358 // Schemas with a "$ref" attribute don't take additional storage.
334 return; 359 return;
335 } 360 }
336 361
(...skipping 22 matching lines...) Expand all
359 if (schema.GetDictionary(schema::kProperties, &properties)) { 384 if (schema.GetDictionary(schema::kProperties, &properties)) {
360 for (base::DictionaryValue::Iterator it(*properties); 385 for (base::DictionaryValue::Iterator it(*properties);
361 !it.IsAtEnd(); it.Advance()) { 386 !it.IsAtEnd(); it.Advance()) {
362 // This should have been verified by the JSONSchemaValidator. 387 // This should have been verified by the JSONSchemaValidator.
363 CHECK(it.value().GetAsDictionary(&dict)); 388 CHECK(it.value().GetAsDictionary(&dict));
364 DetermineStorageSizes(*dict, sizes); 389 DetermineStorageSizes(*dict, sizes);
365 sizes->strings++; 390 sizes->strings++;
366 sizes->property_nodes++; 391 sizes->property_nodes++;
367 } 392 }
368 } 393 }
394
395 const base::DictionaryValue* pattern_properties = NULL;
396 if (schema.GetDictionary(schema::kPatternProperties, &pattern_properties)) {
397 for (base::DictionaryValue::Iterator it(*pattern_properties);
398 !it.IsAtEnd(); it.Advance()) {
399 CHECK(it.value().GetAsDictionary(&dict));
400 DetermineStorageSizes(*dict, sizes);
401 sizes->strings++;
402 sizes->property_nodes++;
403 }
404 }
369 } else if (schema.HasKey(schema::kEnum)) { 405 } else if (schema.HasKey(schema::kEnum)) {
370 const base::ListValue* possible_values = NULL; 406 const base::ListValue* possible_values = NULL;
371 if (schema.GetList(schema::kEnum, &possible_values)) { 407 if (schema.GetList(schema::kEnum, &possible_values)) {
372 if (type == base::Value::TYPE_INTEGER) { 408 if (type == base::Value::TYPE_INTEGER) {
373 sizes->int_enums += possible_values->GetSize(); 409 sizes->int_enums += possible_values->GetSize();
374 } else if (type == base::Value::TYPE_STRING) { 410 } else if (type == base::Value::TYPE_STRING) {
375 sizes->string_enums += possible_values->GetSize(); 411 sizes->string_enums += possible_values->GetSize();
376 sizes->strings += possible_values->GetSize(); 412 sizes->strings += possible_values->GetSize();
377 } 413 }
378 sizes->restriction_nodes++; 414 sizes->restriction_nodes++;
379 } 415 }
380 } else if (type == base::Value::TYPE_INTEGER) { 416 } else if (type == base::Value::TYPE_INTEGER) {
381 if (schema.HasKey(schema::kMinimum) || schema.HasKey(schema::kMaximum)) 417 if (schema.HasKey(schema::kMinimum) || schema.HasKey(schema::kMaximum))
382 sizes->restriction_nodes++; 418 sizes->restriction_nodes++;
419 } else if (type == base::Value::TYPE_STRING) {
420 if (schema.HasKey(schema::kPattern)) {
421 sizes->strings++;
422 sizes->string_enums ++;
Joao da Silva 2014/03/21 12:58:12 nit: remove space before ++
binjin 2014/03/27 17:57:47 Done.
423 sizes->restriction_nodes++;
424 }
383 } 425 }
384 } 426 }
385 427
386 bool Schema::InternalStorage::Parse(const base::DictionaryValue& schema, 428 bool Schema::InternalStorage::Parse(const base::DictionaryValue& schema,
387 int* index, 429 int* index,
388 IdMap* id_map, 430 IdMap* id_map,
389 ReferenceList* reference_list, 431 ReferenceList* reference_list,
390 std::string* error) { 432 std::string* error) {
391 std::string ref_string; 433 std::string ref_string;
392 if (schema.GetString(schema::kRef, &ref_string)) { 434 if (schema.GetString(schema::kRef, &ref_string)) {
(...skipping 26 matching lines...) Expand all
419 461
420 if (type == base::Value::TYPE_DICTIONARY) { 462 if (type == base::Value::TYPE_DICTIONARY) {
421 if (!ParseDictionary(schema, schema_node, id_map, reference_list, error)) 463 if (!ParseDictionary(schema, schema_node, id_map, reference_list, error))
422 return false; 464 return false;
423 } else if (type == base::Value::TYPE_LIST) { 465 } else if (type == base::Value::TYPE_LIST) {
424 if (!ParseList(schema, schema_node, id_map, reference_list, error)) 466 if (!ParseList(schema, schema_node, id_map, reference_list, error))
425 return false; 467 return false;
426 } else if (schema.HasKey(schema::kEnum)) { 468 } else if (schema.HasKey(schema::kEnum)) {
427 if (!ParseEnum(schema, type, schema_node, error)) 469 if (!ParseEnum(schema, type, schema_node, error))
428 return false; 470 return false;
471 } else if (schema.HasKey(schema::kPattern)) {
472 if (!ParseStringPattern(schema, schema_node, error))
473 return false;
429 } else if (schema.HasKey(schema::kMinimum) || 474 } else if (schema.HasKey(schema::kMinimum) ||
430 schema.HasKey(schema::kMaximum)) { 475 schema.HasKey(schema::kMaximum)) {
431 if (type != base::Value::TYPE_INTEGER) { 476 if (type != base::Value::TYPE_INTEGER) {
432 *error = "Only integers can have minimum and maximum"; 477 *error = "Only integers can have minimum and maximum";
433 return false; 478 return false;
434 } 479 }
435 if (!ParseRangedInt(schema, schema_node, error)) 480 if (!ParseRangedInt(schema, schema_node, error))
436 return false; 481 return false;
437 } 482 }
438 std::string id_string; 483 std::string id_string;
439 if (schema.GetString(schema::kId, &id_string)) { 484 if (schema.GetString(schema::kId, &id_string)) {
440 if (ContainsKey(*id_map, id_string)) { 485 if (ContainsKey(*id_map, id_string)) {
441 *error = "Duplicated id: " + id_string; 486 *error = "Duplicated id: " + id_string;
442 return false; 487 return false;
443 } 488 }
444 (*id_map)[id_string] = *index; 489 (*id_map)[id_string] = *index;
445 } 490 }
446 491
447 return true; 492 return true;
448 } 493 }
449 494
450 bool Schema::InternalStorage::ParseDictionary( 495 bool Schema::InternalStorage::ParseDictionary(
451 const base::DictionaryValue& schema, 496 const base::DictionaryValue& schema,
452 SchemaNode* schema_node, 497 SchemaNode* schema_node,
453 IdMap* id_map, 498 IdMap* id_map,
454 ReferenceList* reference_list, 499 ReferenceList* reference_list,
455 std::string* error) { 500 std::string* error) {
456 int extra = static_cast<int>(properties_nodes_.size()); 501 int extra = static_cast<int>(properties_nodes_.size());
457 properties_nodes_.push_back(PropertiesNode()); 502 properties_nodes_.push_back(PropertiesNode());
458 properties_nodes_[extra].begin = kInvalid;
459 properties_nodes_[extra].end = kInvalid;
460 properties_nodes_[extra].additional = kInvalid; 503 properties_nodes_[extra].additional = kInvalid;
461 schema_node->extra = extra; 504 schema_node->extra = extra;
462 505
463 const base::DictionaryValue* dict = NULL; 506 const base::DictionaryValue* dict = NULL;
464 if (schema.GetDictionary(schema::kAdditionalProperties, &dict)) { 507 if (schema.GetDictionary(schema::kAdditionalProperties, &dict)) {
465 if (!Parse(*dict, &properties_nodes_[extra].additional, 508 if (!Parse(*dict, &properties_nodes_[extra].additional,
466 id_map, reference_list, error)) { 509 id_map, reference_list, error)) {
467 return false; 510 return false;
468 } 511 }
469 } 512 }
470 513
514 properties_nodes_[extra].begin = static_cast<int>(property_nodes_.size());
515
471 const base::DictionaryValue* properties = NULL; 516 const base::DictionaryValue* properties = NULL;
472 if (schema.GetDictionary(schema::kProperties, &properties)) { 517 if (schema.GetDictionary(schema::kProperties, &properties))
473 int base_index = static_cast<int>(property_nodes_.size()); 518 property_nodes_.resize(property_nodes_.size() + properties->size());
474 // This reserves nodes for all of the |properties|, and makes sure they
475 // are contiguous. Recursive calls to Parse() will append after these
476 // elements.
Joao da Silva 2014/03/21 12:58:12 Please leave this comment included.
binjin 2014/03/27 17:57:47 Done.
477 property_nodes_.resize(base_index + properties->size());
478 519
520 properties_nodes_[extra].end = static_cast<int>(property_nodes_.size());
521
522 const base::DictionaryValue* pattern_properties = NULL;
523 if (schema.GetDictionary(schema::kPatternProperties, &pattern_properties))
524 property_nodes_.resize(property_nodes_.size() + pattern_properties->size());
525
526 properties_nodes_[extra].pattern_end =
527 static_cast<int>(property_nodes_.size());
528
529 if (properties != NULL) {
530 int base_index = properties_nodes_[extra].begin;
479 int index = base_index; 531 int index = base_index;
532
480 for (base::DictionaryValue::Iterator it(*properties); 533 for (base::DictionaryValue::Iterator it(*properties);
481 !it.IsAtEnd(); it.Advance(), ++index) { 534 !it.IsAtEnd(); it.Advance(), ++index) {
482 // This should have been verified by the JSONSchemaValidator. 535 // This should have been verified by the JSONSchemaValidator.
483 CHECK(it.value().GetAsDictionary(&dict)); 536 CHECK(it.value().GetAsDictionary(&dict));
484 strings_.push_back(it.key()); 537 strings_.push_back(it.key());
485 property_nodes_[index].key = strings_.back().c_str(); 538 property_nodes_[index].key = strings_.back().c_str();
486 if (!Parse(*dict, &property_nodes_[index].schema, 539 if (!Parse(*dict, &property_nodes_[index].schema,
487 id_map, reference_list, error)) { 540 id_map, reference_list, error)) {
488 return false; 541 return false;
489 } 542 }
490 } 543 }
491 CHECK_EQ(static_cast<int>(properties->size()), index - base_index); 544 CHECK_EQ(static_cast<int>(properties->size()), index - base_index);
492 properties_nodes_[extra].begin = base_index; 545 }
493 properties_nodes_[extra].end = index; 546
547 if (pattern_properties != NULL) {
548 int base_index = properties_nodes_[extra].end;
549 int index = base_index;
550
551 for (base::DictionaryValue::Iterator it(*pattern_properties);
552 !it.IsAtEnd(); it.Advance(), ++index) {
553 CHECK(it.value().GetAsDictionary(&dict));
554 if (!CompileRegex(it.key())->ok()) {
555 *error = "Invalid regex: /" + it.key() + "/.";
Joao da Silva 2014/03/21 12:58:12 Include the ->error()
binjin 2014/03/27 17:57:47 Done.
556 return false;
557 }
558 strings_.push_back(it.key());
559 property_nodes_[index].key = strings_.back().c_str();
560 if (!Parse(*dict, &property_nodes_[index].schema,
561 id_map, reference_list, error)) {
562 return false;
563 }
564 }
565 CHECK_EQ(static_cast<int>(pattern_properties->size()), index - base_index);
566 }
567
568 if (properties_nodes_[extra].begin == properties_nodes_[extra].pattern_end) {
569 properties_nodes_[extra].begin = kInvalid;
570 properties_nodes_[extra].end = kInvalid;
571 properties_nodes_[extra].pattern_end = kInvalid;
494 } 572 }
495 573
496 return true; 574 return true;
497 } 575 }
498 576
499 bool Schema::InternalStorage::ParseList(const base::DictionaryValue& schema, 577 bool Schema::InternalStorage::ParseList(const base::DictionaryValue& schema,
500 SchemaNode* schema_node, 578 SchemaNode* schema_node,
501 IdMap* id_map, 579 IdMap* id_map,
502 ReferenceList* reference_list, 580 ReferenceList* reference_list,
503 std::string* error) { 581 std::string* error) {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 *error = "Invalid range restriction for int type."; 653 *error = "Invalid range restriction for int type.";
576 return false; 654 return false;
577 } 655 }
578 schema_node->extra = static_cast<int>(restriction_nodes_.size()); 656 schema_node->extra = static_cast<int>(restriction_nodes_.size());
579 restriction_nodes_.push_back(RestrictionNode()); 657 restriction_nodes_.push_back(RestrictionNode());
580 restriction_nodes_.back().ranged_restriction.max_value = max_value; 658 restriction_nodes_.back().ranged_restriction.max_value = max_value;
581 restriction_nodes_.back().ranged_restriction.min_value = min_value; 659 restriction_nodes_.back().ranged_restriction.min_value = min_value;
582 return true; 660 return true;
583 } 661 }
584 662
663 bool Schema::InternalStorage::ParseStringPattern(
664 const base::DictionaryValue& schema,
665 SchemaNode* schema_node,
666 std::string* error) {
667 std::string pattern;
668 if (!schema.GetString(schema::kPattern, &pattern)) {
669 *error = "Schema pattern must be a string.";
670 return false;
671 }
672 if (!CompileRegex(pattern)->ok()) {
673 *error = "Invalid regex: /" + pattern + "/.";
Joao da Silva 2014/03/21 12:58:12 Include the ->error() in this message too
binjin 2014/03/27 17:57:47 Done.
674 return false;
675 }
676 int index = static_cast<int>(string_enums_.size());
677 strings_.push_back(pattern);
678 string_enums_.push_back(strings_.back().c_str());
679 schema_node->extra = static_cast<int>(restriction_nodes_.size());
680 restriction_nodes_.push_back(RestrictionNode());
681 restriction_nodes_.back().string_pattern_restriction.pattern_index = index;
682 restriction_nodes_.back().string_pattern_restriction.pattern_index_backup =
683 index;
684 return true;
685 }
686
585 // static 687 // static
586 bool Schema::InternalStorage::ResolveReferences( 688 bool Schema::InternalStorage::ResolveReferences(
587 const IdMap& id_map, 689 const IdMap& id_map,
588 const ReferenceList& reference_list, 690 const ReferenceList& reference_list,
589 std::string* error) { 691 std::string* error) {
590 for (ReferenceList::const_iterator ref = reference_list.begin(); 692 for (ReferenceList::const_iterator ref = reference_list.begin();
591 ref != reference_list.end(); ++ref) { 693 ref != reference_list.end(); ++ref) {
592 IdMap::const_iterator id = id_map.find(ref->first); 694 IdMap::const_iterator id = id_map.find(ref->first);
593 if (id == id_map.end()) { 695 if (id == id_map.end()) {
594 *error = "Invalid $ref: " + ref->first; 696 *error = "Invalid $ref: " + ref->first;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
680 return false; 782 return false;
681 } 783 }
682 784
683 const base::DictionaryValue* dict = NULL; 785 const base::DictionaryValue* dict = NULL;
684 const base::ListValue* list = NULL; 786 const base::ListValue* list = NULL;
685 int int_value; 787 int int_value;
686 std::string str_value; 788 std::string str_value;
687 if (value.GetAsDictionary(&dict)) { 789 if (value.GetAsDictionary(&dict)) {
688 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); 790 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
689 it.Advance()) { 791 it.Advance()) {
690 Schema subschema = GetProperty(it.key()); 792 Schema subschema = GetProperty(it.key());
Joao da Silva 2014/03/21 12:58:12 This needs to be updated to validate against all p
binjin 2014/04/01 12:29:36 Done. But I think schema from pattern_properties a
691 if (!subschema.valid()) { 793 if (!subschema.valid()) {
692 // Unknown property was detected. 794 // Unknown property was detected.
693 SchemaErrorFound(error_path, error, "Unknown property: " + it.key()); 795 SchemaErrorFound(error_path, error, "Unknown property: " + it.key());
694 if (!StrategyAllowUnknownOnTopLevel(strategy)) 796 if (!StrategyAllowUnknownOnTopLevel(strategy))
695 return false; 797 return false;
696 } else if (!subschema.Validate(it.value(), 798 } else if (!subschema.Validate(it.value(),
697 StrategyForNextLevel(strategy), 799 StrategyForNextLevel(strategy),
698 error_path, 800 error_path,
699 error)) { 801 error)) {
700 // Invalid property was detected. 802 // Invalid property was detected.
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
756 error_path, error, "The value type doesn't match the schema type."); 858 error_path, error, "The value type doesn't match the schema type.");
757 return false; 859 return false;
758 } 860 }
759 861
760 base::DictionaryValue* dict = NULL; 862 base::DictionaryValue* dict = NULL;
761 base::ListValue* list = NULL; 863 base::ListValue* list = NULL;
762 if (value->GetAsDictionary(&dict)) { 864 if (value->GetAsDictionary(&dict)) {
763 std::vector<std::string> drop_list; // Contains the keys to drop. 865 std::vector<std::string> drop_list; // Contains the keys to drop.
764 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); 866 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
765 it.Advance()) { 867 it.Advance()) {
766 Schema subschema = GetProperty(it.key()); 868 Schema subschema = GetProperty(it.key());
Joao da Silva 2014/03/21 12:58:12 Similar fixes here to handle GetPatternProperties(
binjin 2014/04/01 12:29:36 Done.
767 if (!subschema.valid()) { 869 if (!subschema.valid()) {
768 // Unknown property was detected. 870 // Unknown property was detected.
769 SchemaErrorFound(error_path, error, "Unknown property: " + it.key()); 871 SchemaErrorFound(error_path, error, "Unknown property: " + it.key());
770 if (StrategyAllowUnknownOnTopLevel(strategy)) 872 if (StrategyAllowUnknownOnTopLevel(strategy))
771 drop_list.push_back(it.key()); 873 drop_list.push_back(it.key());
772 else 874 else
773 return false; 875 return false;
774 } else { 876 } else {
775 base::Value* sub_value = NULL; 877 base::Value* sub_value = NULL;
776 dict->GetWithoutPathExpansion(it.key(), &sub_value); 878 dict->GetWithoutPathExpansion(it.key(), &sub_value);
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
892 994
893 Schema Schema::GetAdditionalProperties() const { 995 Schema Schema::GetAdditionalProperties() const {
894 CHECK(valid()); 996 CHECK(valid());
895 CHECK_EQ(base::Value::TYPE_DICTIONARY, type()); 997 CHECK_EQ(base::Value::TYPE_DICTIONARY, type());
896 const PropertiesNode* node = storage_->properties(node_->extra); 998 const PropertiesNode* node = storage_->properties(node_->extra);
897 if (node->additional == kInvalid) 999 if (node->additional == kInvalid)
898 return Schema(); 1000 return Schema();
899 return Schema(storage_, storage_->schema(node->additional)); 1001 return Schema(storage_, storage_->schema(node->additional));
900 } 1002 }
901 1003
1004 Schema Schema::GetPatternProperty(const std::string& key) const {
1005 CHECK(valid());
1006 CHECK_EQ(base::Value::TYPE_DICTIONARY, type());
1007 const PropertiesNode* node = storage_->properties(node_->extra);
1008 const PropertyNode* begin = storage_->property(node->end);
1009 const PropertyNode* end = storage_->property(node->pattern_end);
1010 for (const PropertyNode* it = begin; it != end; ++it) {
1011 if (re2::RE2::PartialMatch(key, *storage_->CompileRegex(begin->key)))
Joao da Silva 2014/03/21 12:58:12 begin->key should be it->key
binjin 2014/03/27 17:57:47 Done.
1012 return Schema(storage_, storage_->schema(it->schema));
1013 }
1014 return Schema();
1015 }
1016
902 Schema Schema::GetProperty(const std::string& key) const { 1017 Schema Schema::GetProperty(const std::string& key) const {
Joao da Silva 2014/03/21 12:58:12 So this method is just a helper to mix GetKnownPro
binjin 2014/04/01 12:29:36 I deprecated this function, as it's a little bit c
903 Schema schema = GetKnownProperty(key); 1018 Schema schema = GetKnownProperty(key);
904 return schema.valid() ? schema : GetAdditionalProperties(); 1019 if (schema.valid())
1020 return schema;
1021 // This is slightly different from json schema standard. We won't match the
1022 // key against "patternProperty" regular expressions if it's already
1023 // presented by "property" attribute.
1024 schema = GetPatternProperty(key);
1025 if (schema.valid())
1026 return schema;
1027 return GetAdditionalProperties();
905 } 1028 }
906 1029
907 Schema Schema::GetItems() const { 1030 Schema Schema::GetItems() const {
908 CHECK(valid()); 1031 CHECK(valid());
909 CHECK_EQ(base::Value::TYPE_LIST, type()); 1032 CHECK_EQ(base::Value::TYPE_LIST, type());
910 if (node_->extra == kInvalid) 1033 if (node_->extra == kInvalid)
911 return Schema(); 1034 return Schema();
912 return Schema(storage_, storage_->schema(node_->extra)); 1035 return Schema(storage_, storage_->schema(node_->extra));
913 } 1036 }
914 1037
915 bool Schema::ValidateIntegerRestriction(int index, int value) const { 1038 bool Schema::ValidateIntegerRestriction(int index, int value) const {
916 const RestrictionNode* rnode = storage_->restriction(index); 1039 const RestrictionNode* rnode = storage_->restriction(index);
917 if (rnode->ranged_restriction.min_value <= 1040 if (rnode->ranged_restriction.min_value <=
918 rnode->ranged_restriction.max_value) { 1041 rnode->ranged_restriction.max_value) {
919 return rnode->ranged_restriction.min_value <= value && 1042 return rnode->ranged_restriction.min_value <= value &&
920 rnode->ranged_restriction.max_value >= value; 1043 rnode->ranged_restriction.max_value >= value;
921 } else { 1044 } else {
922 for (int i = rnode->enumeration_restriction.offset_begin; 1045 for (int i = rnode->enumeration_restriction.offset_begin;
923 i < rnode->enumeration_restriction.offset_end; i++) { 1046 i < rnode->enumeration_restriction.offset_end; i++) {
924 if (*storage_->int_enums(i) == value) 1047 if (*storage_->int_enums(i) == value)
925 return true; 1048 return true;
926 } 1049 }
927 return false; 1050 return false;
928 } 1051 }
929 } 1052 }
930 1053
931 bool Schema::ValidateStringRestriction(int index, const char* str) const { 1054 bool Schema::ValidateStringRestriction(int index, const char* str) const {
932 const RestrictionNode* rnode = storage_->restriction(index); 1055 const RestrictionNode* rnode = storage_->restriction(index);
933 for (int i = rnode->enumeration_restriction.offset_begin; 1056 if (rnode->enumeration_restriction.offset_begin <
934 i < rnode->enumeration_restriction.offset_end; i++) { 1057 rnode->enumeration_restriction.offset_end) {
935 if (strcmp(*storage_->string_enums(i), str) == 0) 1058 for (int i = rnode->enumeration_restriction.offset_begin;
936 return true; 1059 i < rnode->enumeration_restriction.offset_end; i++) {
Joao da Silva 2014/03/21 12:58:12 nit: add one space at the beginning of this line
binjin 2014/03/27 17:57:47 Done.
1060 if (strcmp(*storage_->string_enums(i), str) == 0)
1061 return true;
1062 }
1063 return false;
1064 } else {
1065 int index = rnode->string_pattern_restriction.pattern_index;
1066 DCHECK(index == rnode->string_pattern_restriction.pattern_index_backup);
1067 re2::RE2* regex = storage_->CompileRegex(*storage_->string_enums(index));
1068 return re2::RE2::PartialMatch(str, *regex);
937 } 1069 }
938 return false;
939 } 1070 }
940 1071
941 } // namespace policy 1072 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698