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

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: Validate() against multiple properties Created 6 years, 8 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>
Joao da Silva 2014/04/02 09:51:11 This is already in the .h
binjin 2014/04/03 10:13:37 Done.
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;
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 // Cache for CompileRegex(), will memorize return value of every call to
250 // CompileRegex() and return results directly next time.
251 mutable std::map<std::string, re2::RE2*> regex_cache_;
252 STLValueDeleter<std::map<std::string, re2::RE2*> > cache_deleter_;
Joao da Silva 2014/04/02 09:51:11 regex_cache_deleter_
binjin 2014/04/03 10:13:37 Done.
253
238 SchemaData schema_data_; 254 SchemaData schema_data_;
239 std::vector<std::string> strings_; 255 std::vector<std::string> strings_;
240 std::vector<SchemaNode> schema_nodes_; 256 std::vector<SchemaNode> schema_nodes_;
241 std::vector<PropertyNode> property_nodes_; 257 std::vector<PropertyNode> property_nodes_;
242 std::vector<PropertiesNode> properties_nodes_; 258 std::vector<PropertiesNode> properties_nodes_;
243 std::vector<RestrictionNode> restriction_nodes_; 259 std::vector<RestrictionNode> restriction_nodes_;
244 std::vector<int> int_enums_; 260 std::vector<int> int_enums_;
245 std::vector<const char*> string_enums_; 261 std::vector<const char*> string_enums_;
246 262
247 DISALLOW_COPY_AND_ASSIGN(InternalStorage); 263 DISALLOW_COPY_AND_ASSIGN(InternalStorage);
248 }; 264 };
249 265
250 Schema::InternalStorage::InternalStorage() {} 266 Schema::InternalStorage::InternalStorage() : cache_deleter_(&regex_cache_) {}
251 267
252 Schema::InternalStorage::~InternalStorage() {} 268 Schema::InternalStorage::~InternalStorage() {}
253 269
254 // static 270 // static
255 scoped_refptr<const Schema::InternalStorage> Schema::InternalStorage::Wrap( 271 scoped_refptr<const Schema::InternalStorage> Schema::InternalStorage::Wrap(
256 const SchemaData* data) { 272 const SchemaData* data) {
257 InternalStorage* storage = new InternalStorage(); 273 InternalStorage* storage = new InternalStorage();
258 storage->schema_data_.schema_nodes = data->schema_nodes; 274 storage->schema_data_.schema_nodes = data->schema_nodes;
259 storage->schema_data_.property_nodes = data->property_nodes; 275 storage->schema_data_.property_nodes = data->property_nodes;
260 storage->schema_data_.properties_nodes = data->properties_nodes; 276 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_; 333 SchemaData* data = &storage->schema_data_;
318 data->schema_nodes = vector_as_array(&storage->schema_nodes_); 334 data->schema_nodes = vector_as_array(&storage->schema_nodes_);
319 data->property_nodes = vector_as_array(&storage->property_nodes_); 335 data->property_nodes = vector_as_array(&storage->property_nodes_);
320 data->properties_nodes = vector_as_array(&storage->properties_nodes_); 336 data->properties_nodes = vector_as_array(&storage->properties_nodes_);
321 data->restriction_nodes = vector_as_array(&storage->restriction_nodes_); 337 data->restriction_nodes = vector_as_array(&storage->restriction_nodes_);
322 data->int_enums = vector_as_array(&storage->int_enums_); 338 data->int_enums = vector_as_array(&storage->int_enums_);
323 data->string_enums = vector_as_array(&storage->string_enums_); 339 data->string_enums = vector_as_array(&storage->string_enums_);
324 return storage; 340 return storage;
325 } 341 }
326 342
343 re2::RE2* Schema::InternalStorage::CompileRegex(
344 const std::string& pattern) const {
345 std::map<std::string, re2::RE2*>::iterator it = regex_cache_.find(pattern);
346 if (it == regex_cache_.end()) {
347 re2::RE2* compiled = new re2::RE2(pattern);
348 regex_cache_[pattern] = compiled;
349 return compiled;
350 }
351 return it->second;
352 }
353
327 // static 354 // static
328 void Schema::InternalStorage::DetermineStorageSizes( 355 void Schema::InternalStorage::DetermineStorageSizes(
329 const base::DictionaryValue& schema, 356 const base::DictionaryValue& schema,
330 StorageSizes* sizes) { 357 StorageSizes* sizes) {
331 std::string ref_string; 358 std::string ref_string;
332 if (schema.GetString(schema::kRef, &ref_string)) { 359 if (schema.GetString(schema::kRef, &ref_string)) {
333 // Schemas with a "$ref" attribute don't take additional storage. 360 // Schemas with a "$ref" attribute don't take additional storage.
334 return; 361 return;
335 } 362 }
336 363
(...skipping 22 matching lines...) Expand all
359 if (schema.GetDictionary(schema::kProperties, &properties)) { 386 if (schema.GetDictionary(schema::kProperties, &properties)) {
360 for (base::DictionaryValue::Iterator it(*properties); 387 for (base::DictionaryValue::Iterator it(*properties);
361 !it.IsAtEnd(); it.Advance()) { 388 !it.IsAtEnd(); it.Advance()) {
362 // This should have been verified by the JSONSchemaValidator. 389 // This should have been verified by the JSONSchemaValidator.
363 CHECK(it.value().GetAsDictionary(&dict)); 390 CHECK(it.value().GetAsDictionary(&dict));
364 DetermineStorageSizes(*dict, sizes); 391 DetermineStorageSizes(*dict, sizes);
365 sizes->strings++; 392 sizes->strings++;
366 sizes->property_nodes++; 393 sizes->property_nodes++;
367 } 394 }
368 } 395 }
396
397 const base::DictionaryValue* pattern_properties = NULL;
398 if (schema.GetDictionary(schema::kPatternProperties, &pattern_properties)) {
399 for (base::DictionaryValue::Iterator it(*pattern_properties);
400 !it.IsAtEnd(); it.Advance()) {
401 CHECK(it.value().GetAsDictionary(&dict));
402 DetermineStorageSizes(*dict, sizes);
403 sizes->strings++;
404 sizes->property_nodes++;
405 }
406 }
369 } else if (schema.HasKey(schema::kEnum)) { 407 } else if (schema.HasKey(schema::kEnum)) {
370 const base::ListValue* possible_values = NULL; 408 const base::ListValue* possible_values = NULL;
371 if (schema.GetList(schema::kEnum, &possible_values)) { 409 if (schema.GetList(schema::kEnum, &possible_values)) {
372 if (type == base::Value::TYPE_INTEGER) { 410 if (type == base::Value::TYPE_INTEGER) {
373 sizes->int_enums += possible_values->GetSize(); 411 sizes->int_enums += possible_values->GetSize();
374 } else if (type == base::Value::TYPE_STRING) { 412 } else if (type == base::Value::TYPE_STRING) {
375 sizes->string_enums += possible_values->GetSize(); 413 sizes->string_enums += possible_values->GetSize();
376 sizes->strings += possible_values->GetSize(); 414 sizes->strings += possible_values->GetSize();
377 } 415 }
378 sizes->restriction_nodes++; 416 sizes->restriction_nodes++;
379 } 417 }
380 } else if (type == base::Value::TYPE_INTEGER) { 418 } else if (type == base::Value::TYPE_INTEGER) {
381 if (schema.HasKey(schema::kMinimum) || schema.HasKey(schema::kMaximum)) 419 if (schema.HasKey(schema::kMinimum) || schema.HasKey(schema::kMaximum))
382 sizes->restriction_nodes++; 420 sizes->restriction_nodes++;
421 } else if (type == base::Value::TYPE_STRING) {
422 if (schema.HasKey(schema::kPattern)) {
423 sizes->strings++;
424 sizes->string_enums++;
425 sizes->restriction_nodes++;
426 }
383 } 427 }
384 } 428 }
385 429
386 bool Schema::InternalStorage::Parse(const base::DictionaryValue& schema, 430 bool Schema::InternalStorage::Parse(const base::DictionaryValue& schema,
387 int* index, 431 int* index,
388 IdMap* id_map, 432 IdMap* id_map,
389 ReferenceList* reference_list, 433 ReferenceList* reference_list,
390 std::string* error) { 434 std::string* error) {
391 std::string ref_string; 435 std::string ref_string;
392 if (schema.GetString(schema::kRef, &ref_string)) { 436 if (schema.GetString(schema::kRef, &ref_string)) {
(...skipping 26 matching lines...) Expand all
419 463
420 if (type == base::Value::TYPE_DICTIONARY) { 464 if (type == base::Value::TYPE_DICTIONARY) {
421 if (!ParseDictionary(schema, schema_node, id_map, reference_list, error)) 465 if (!ParseDictionary(schema, schema_node, id_map, reference_list, error))
422 return false; 466 return false;
423 } else if (type == base::Value::TYPE_LIST) { 467 } else if (type == base::Value::TYPE_LIST) {
424 if (!ParseList(schema, schema_node, id_map, reference_list, error)) 468 if (!ParseList(schema, schema_node, id_map, reference_list, error))
425 return false; 469 return false;
426 } else if (schema.HasKey(schema::kEnum)) { 470 } else if (schema.HasKey(schema::kEnum)) {
427 if (!ParseEnum(schema, type, schema_node, error)) 471 if (!ParseEnum(schema, type, schema_node, error))
428 return false; 472 return false;
473 } else if (schema.HasKey(schema::kPattern)) {
474 if (!ParseStringPattern(schema, schema_node, error))
475 return false;
429 } else if (schema.HasKey(schema::kMinimum) || 476 } else if (schema.HasKey(schema::kMinimum) ||
430 schema.HasKey(schema::kMaximum)) { 477 schema.HasKey(schema::kMaximum)) {
431 if (type != base::Value::TYPE_INTEGER) { 478 if (type != base::Value::TYPE_INTEGER) {
432 *error = "Only integers can have minimum and maximum"; 479 *error = "Only integers can have minimum and maximum";
433 return false; 480 return false;
434 } 481 }
435 if (!ParseRangedInt(schema, schema_node, error)) 482 if (!ParseRangedInt(schema, schema_node, error))
436 return false; 483 return false;
437 } 484 }
438 std::string id_string; 485 std::string id_string;
439 if (schema.GetString(schema::kId, &id_string)) { 486 if (schema.GetString(schema::kId, &id_string)) {
440 if (ContainsKey(*id_map, id_string)) { 487 if (ContainsKey(*id_map, id_string)) {
441 *error = "Duplicated id: " + id_string; 488 *error = "Duplicated id: " + id_string;
442 return false; 489 return false;
443 } 490 }
444 (*id_map)[id_string] = *index; 491 (*id_map)[id_string] = *index;
445 } 492 }
446 493
447 return true; 494 return true;
448 } 495 }
449 496
450 bool Schema::InternalStorage::ParseDictionary( 497 bool Schema::InternalStorage::ParseDictionary(
451 const base::DictionaryValue& schema, 498 const base::DictionaryValue& schema,
452 SchemaNode* schema_node, 499 SchemaNode* schema_node,
453 IdMap* id_map, 500 IdMap* id_map,
454 ReferenceList* reference_list, 501 ReferenceList* reference_list,
455 std::string* error) { 502 std::string* error) {
456 int extra = static_cast<int>(properties_nodes_.size()); 503 int extra = static_cast<int>(properties_nodes_.size());
457 properties_nodes_.push_back(PropertiesNode()); 504 properties_nodes_.push_back(PropertiesNode());
458 properties_nodes_[extra].begin = kInvalid;
459 properties_nodes_[extra].end = kInvalid;
460 properties_nodes_[extra].additional = kInvalid; 505 properties_nodes_[extra].additional = kInvalid;
461 schema_node->extra = extra; 506 schema_node->extra = extra;
462 507
463 const base::DictionaryValue* dict = NULL; 508 const base::DictionaryValue* dict = NULL;
464 if (schema.GetDictionary(schema::kAdditionalProperties, &dict)) { 509 if (schema.GetDictionary(schema::kAdditionalProperties, &dict)) {
465 if (!Parse(*dict, &properties_nodes_[extra].additional, 510 if (!Parse(*dict, &properties_nodes_[extra].additional,
466 id_map, reference_list, error)) { 511 id_map, reference_list, error)) {
467 return false; 512 return false;
468 } 513 }
469 } 514 }
470 515
516 properties_nodes_[extra].begin = static_cast<int>(property_nodes_.size());
517
471 const base::DictionaryValue* properties = NULL; 518 const base::DictionaryValue* properties = NULL;
472 if (schema.GetDictionary(schema::kProperties, &properties)) { 519 if (schema.GetDictionary(schema::kProperties, &properties)) {
473 int base_index = static_cast<int>(property_nodes_.size()); 520 // This and below reserves nodes for all of the |properties|, and makes sure
474 // This reserves nodes for all of the |properties|, and makes sure they 521 // they are contiguous. Recursive calls to Parse() will append after these
475 // are contiguous. Recursive calls to Parse() will append after these
476 // elements. 522 // elements.
477 property_nodes_.resize(base_index + properties->size()); 523 property_nodes_.resize(property_nodes_.size() + properties->size());
524 }
478 525
526 properties_nodes_[extra].end = static_cast<int>(property_nodes_.size());
527
528 const base::DictionaryValue* pattern_properties = NULL;
529 if (schema.GetDictionary(schema::kPatternProperties, &pattern_properties))
530 property_nodes_.resize(property_nodes_.size() + pattern_properties->size());
531
532 properties_nodes_[extra].pattern_end =
533 static_cast<int>(property_nodes_.size());
534
535 if (properties != NULL) {
536 int base_index = properties_nodes_[extra].begin;
479 int index = base_index; 537 int index = base_index;
538
480 for (base::DictionaryValue::Iterator it(*properties); 539 for (base::DictionaryValue::Iterator it(*properties);
481 !it.IsAtEnd(); it.Advance(), ++index) { 540 !it.IsAtEnd(); it.Advance(), ++index) {
482 // This should have been verified by the JSONSchemaValidator. 541 // This should have been verified by the JSONSchemaValidator.
483 CHECK(it.value().GetAsDictionary(&dict)); 542 CHECK(it.value().GetAsDictionary(&dict));
484 strings_.push_back(it.key()); 543 strings_.push_back(it.key());
485 property_nodes_[index].key = strings_.back().c_str(); 544 property_nodes_[index].key = strings_.back().c_str();
486 if (!Parse(*dict, &property_nodes_[index].schema, 545 if (!Parse(*dict, &property_nodes_[index].schema,
487 id_map, reference_list, error)) { 546 id_map, reference_list, error)) {
488 return false; 547 return false;
489 } 548 }
490 } 549 }
491 CHECK_EQ(static_cast<int>(properties->size()), index - base_index); 550 CHECK_EQ(static_cast<int>(properties->size()), index - base_index);
492 properties_nodes_[extra].begin = base_index; 551 }
493 properties_nodes_[extra].end = index; 552
553 if (pattern_properties != NULL) {
554 int base_index = properties_nodes_[extra].end;
555 int index = base_index;
556
557 for (base::DictionaryValue::Iterator it(*pattern_properties);
558 !it.IsAtEnd(); it.Advance(), ++index) {
559 CHECK(it.value().GetAsDictionary(&dict));
560 re2::RE2* compiled_regex = CompileRegex(it.key());
561 if (!compiled_regex->ok()) {
562 *error =
563 "/" + it.key() + "/ is a invalid regex: " + compiled_regex->error();
564 return false;
565 }
566 strings_.push_back(it.key());
567 property_nodes_[index].key = strings_.back().c_str();
568 if (!Parse(*dict, &property_nodes_[index].schema,
569 id_map, reference_list, error)) {
570 return false;
571 }
572 }
573 CHECK_EQ(static_cast<int>(pattern_properties->size()), index - base_index);
574 }
575
576 if (properties_nodes_[extra].begin == properties_nodes_[extra].pattern_end) {
577 properties_nodes_[extra].begin = kInvalid;
578 properties_nodes_[extra].end = kInvalid;
579 properties_nodes_[extra].pattern_end = kInvalid;
494 } 580 }
495 581
496 return true; 582 return true;
497 } 583 }
498 584
499 bool Schema::InternalStorage::ParseList(const base::DictionaryValue& schema, 585 bool Schema::InternalStorage::ParseList(const base::DictionaryValue& schema,
500 SchemaNode* schema_node, 586 SchemaNode* schema_node,
501 IdMap* id_map, 587 IdMap* id_map,
502 ReferenceList* reference_list, 588 ReferenceList* reference_list,
503 std::string* error) { 589 std::string* error) {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 *error = "Invalid range restriction for int type."; 661 *error = "Invalid range restriction for int type.";
576 return false; 662 return false;
577 } 663 }
578 schema_node->extra = static_cast<int>(restriction_nodes_.size()); 664 schema_node->extra = static_cast<int>(restriction_nodes_.size());
579 restriction_nodes_.push_back(RestrictionNode()); 665 restriction_nodes_.push_back(RestrictionNode());
580 restriction_nodes_.back().ranged_restriction.max_value = max_value; 666 restriction_nodes_.back().ranged_restriction.max_value = max_value;
581 restriction_nodes_.back().ranged_restriction.min_value = min_value; 667 restriction_nodes_.back().ranged_restriction.min_value = min_value;
582 return true; 668 return true;
583 } 669 }
584 670
671 bool Schema::InternalStorage::ParseStringPattern(
672 const base::DictionaryValue& schema,
673 SchemaNode* schema_node,
674 std::string* error) {
675 std::string pattern;
676 if (!schema.GetString(schema::kPattern, &pattern)) {
677 *error = "Schema pattern must be a string.";
678 return false;
679 }
680 re2::RE2* compiled_regex = CompileRegex(pattern);
681 if (!compiled_regex->ok()) {
682 *error = "/" + pattern + "/ is invalid regex: " + compiled_regex->error();
683 return false;
684 }
685 int index = static_cast<int>(string_enums_.size());
686 strings_.push_back(pattern);
687 string_enums_.push_back(strings_.back().c_str());
688 schema_node->extra = static_cast<int>(restriction_nodes_.size());
689 restriction_nodes_.push_back(RestrictionNode());
690 restriction_nodes_.back().string_pattern_restriction.pattern_index = index;
691 restriction_nodes_.back().string_pattern_restriction.pattern_index_backup =
692 index;
693 return true;
694 }
695
585 // static 696 // static
586 bool Schema::InternalStorage::ResolveReferences( 697 bool Schema::InternalStorage::ResolveReferences(
587 const IdMap& id_map, 698 const IdMap& id_map,
588 const ReferenceList& reference_list, 699 const ReferenceList& reference_list,
589 std::string* error) { 700 std::string* error) {
590 for (ReferenceList::const_iterator ref = reference_list.begin(); 701 for (ReferenceList::const_iterator ref = reference_list.begin();
591 ref != reference_list.end(); ++ref) { 702 ref != reference_list.end(); ++ref) {
592 IdMap::const_iterator id = id_map.find(ref->first); 703 IdMap::const_iterator id = id_map.find(ref->first);
593 if (id == id_map.end()) { 704 if (id == id_map.end()) {
594 *error = "Invalid $ref: " + ref->first; 705 *error = "Invalid $ref: " + ref->first;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
680 return false; 791 return false;
681 } 792 }
682 793
683 const base::DictionaryValue* dict = NULL; 794 const base::DictionaryValue* dict = NULL;
684 const base::ListValue* list = NULL; 795 const base::ListValue* list = NULL;
685 int int_value; 796 int int_value;
686 std::string str_value; 797 std::string str_value;
687 if (value.GetAsDictionary(&dict)) { 798 if (value.GetAsDictionary(&dict)) {
688 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); 799 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
689 it.Advance()) { 800 it.Advance()) {
690 Schema subschema = GetProperty(it.key()); 801 SchemaList schema_list = GetMatchingProperties(it.key());
691 if (!subschema.valid()) { 802 if (schema_list.empty()) {
692 // Unknown property was detected. 803 // Unknown property was detected.
693 SchemaErrorFound(error_path, error, "Unknown property: " + it.key()); 804 SchemaErrorFound(error_path, error, "Unknown property: " + it.key());
694 if (!StrategyAllowUnknownOnTopLevel(strategy)) 805 if (!StrategyAllowUnknownOnTopLevel(strategy))
695 return false; 806 return false;
696 } else if (!subschema.Validate(it.value(), 807 } else {
697 StrategyForNextLevel(strategy), 808 for (SchemaList::iterator subschema = schema_list.begin();
698 error_path, 809 subschema != schema_list.end();
699 error)) { 810 ++subschema) {
Joao da Silva 2014/04/02 09:51:11 These 2 lines can be joined
binjin 2014/04/03 10:13:37 Done.
700 // Invalid property was detected. 811 if (!subschema->Validate(it.value(),
701 AddDictKeyPrefixToPath(it.key(), error_path); 812 StrategyForNextLevel(strategy),
702 if (!StrategyAllowInvalidOnTopLevel(strategy)) 813 error_path,
703 return false; 814 error)) {
815 // Invalid property was detected.
816 AddDictKeyPrefixToPath(it.key(), error_path);
817 if (!StrategyAllowInvalidOnTopLevel(strategy))
818 return false;
819 }
820 }
704 } 821 }
705 } 822 }
706 } else if (value.GetAsList(&list)) { 823 } else if (value.GetAsList(&list)) {
707 for (base::ListValue::const_iterator it = list->begin(); it != list->end(); 824 for (base::ListValue::const_iterator it = list->begin(); it != list->end();
708 ++it) { 825 ++it) {
709 if (!*it || 826 if (!*it ||
710 !GetItems().Validate(**it, 827 !GetItems().Validate(**it,
711 StrategyForNextLevel(strategy), 828 StrategyForNextLevel(strategy),
712 error_path, 829 error_path,
713 error)) { 830 error)) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
756 error_path, error, "The value type doesn't match the schema type."); 873 error_path, error, "The value type doesn't match the schema type.");
757 return false; 874 return false;
758 } 875 }
759 876
760 base::DictionaryValue* dict = NULL; 877 base::DictionaryValue* dict = NULL;
761 base::ListValue* list = NULL; 878 base::ListValue* list = NULL;
762 if (value->GetAsDictionary(&dict)) { 879 if (value->GetAsDictionary(&dict)) {
763 std::vector<std::string> drop_list; // Contains the keys to drop. 880 std::vector<std::string> drop_list; // Contains the keys to drop.
764 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); 881 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
765 it.Advance()) { 882 it.Advance()) {
766 Schema subschema = GetProperty(it.key()); 883 bool drop_it = false;
767 if (!subschema.valid()) { 884 SchemaList schema_list = GetMatchingProperties(it.key());
885 if (schema_list.empty()) {
768 // Unknown property was detected. 886 // Unknown property was detected.
769 SchemaErrorFound(error_path, error, "Unknown property: " + it.key()); 887 SchemaErrorFound(error_path, error, "Unknown property: " + it.key());
770 if (StrategyAllowUnknownOnTopLevel(strategy)) 888 if (StrategyAllowUnknownOnTopLevel(strategy))
771 drop_list.push_back(it.key()); 889 drop_it = true;
772 else 890 else
773 return false; 891 return false;
774 } else { 892 } else {
775 base::Value* sub_value = NULL; 893 for (SchemaList::iterator subschema = schema_list.begin();
776 dict->GetWithoutPathExpansion(it.key(), &sub_value); 894 subschema != schema_list.end();
777 if (!subschema.Normalize(sub_value, 895 ++subschema) {
Joao da Silva 2014/04/02 09:51:11 These 2 lines can be joined
binjin 2014/04/03 10:13:37 Done.
778 StrategyForNextLevel(strategy), 896 base::Value* sub_value = NULL;
779 error_path, 897 dict->GetWithoutPathExpansion(it.key(), &sub_value);
780 error, 898 if (!subschema->Normalize(sub_value,
781 changed)) { 899 StrategyForNextLevel(strategy),
782 // Invalid property was detected. 900 error_path,
783 AddDictKeyPrefixToPath(it.key(), error_path); 901 error,
784 if (StrategyAllowInvalidOnTopLevel(strategy)) 902 changed)) {
785 drop_list.push_back(it.key()); 903 // Invalid property was detected.
786 else 904 AddDictKeyPrefixToPath(it.key(), error_path);
787 return false; 905 if (StrategyAllowInvalidOnTopLevel(strategy))
906 drop_it = true;
Joao da Silva 2014/04/02 09:51:11 Why not just push it here and break from the inner
binjin 2014/04/03 10:13:37 Done.
907 else
908 return false;
909 }
788 } 910 }
789 } 911 }
912 if (drop_it)
913 drop_list.push_back(it.key());
790 } 914 }
791 if (changed && !drop_list.empty()) 915 if (changed && !drop_list.empty())
792 *changed = true; 916 *changed = true;
793 for (std::vector<std::string>::const_iterator it = drop_list.begin(); 917 for (std::vector<std::string>::const_iterator it = drop_list.begin();
794 it != drop_list.end(); 918 it != drop_list.end();
795 ++it) { 919 ++it) {
796 dict->RemoveWithoutPathExpansion(*it, NULL); 920 dict->RemoveWithoutPathExpansion(*it, NULL);
797 } 921 }
798 return true; 922 return true;
799 } else if (value->GetAsList(&list)) { 923 } else if (value->GetAsList(&list)) {
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
892 1016
893 Schema Schema::GetAdditionalProperties() const { 1017 Schema Schema::GetAdditionalProperties() const {
894 CHECK(valid()); 1018 CHECK(valid());
895 CHECK_EQ(base::Value::TYPE_DICTIONARY, type()); 1019 CHECK_EQ(base::Value::TYPE_DICTIONARY, type());
896 const PropertiesNode* node = storage_->properties(node_->extra); 1020 const PropertiesNode* node = storage_->properties(node_->extra);
897 if (node->additional == kInvalid) 1021 if (node->additional == kInvalid)
898 return Schema(); 1022 return Schema();
899 return Schema(storage_, storage_->schema(node->additional)); 1023 return Schema(storage_, storage_->schema(node->additional));
900 } 1024 }
901 1025
1026 Schema::SchemaList Schema::GetPatternProperties(const std::string& key) const {
1027 CHECK(valid());
1028 CHECK_EQ(base::Value::TYPE_DICTIONARY, type());
1029 const PropertiesNode* node = storage_->properties(node_->extra);
1030 const PropertyNode* begin = storage_->property(node->end);
1031 const PropertyNode* end = storage_->property(node->pattern_end);
1032 Schema::SchemaList matching_properties;
1033 for (const PropertyNode* it = begin; it != end; ++it) {
1034 if (re2::RE2::PartialMatch(key, *storage_->CompileRegex(it->key))) {
1035 matching_properties.push_back(
1036 Schema(storage_, storage_->schema(it->schema)));
1037 }
1038 }
1039 return matching_properties;
1040 }
1041
902 Schema Schema::GetProperty(const std::string& key) const { 1042 Schema Schema::GetProperty(const std::string& key) const {
903 Schema schema = GetKnownProperty(key); 1043 Schema schema = GetKnownProperty(key);
904 return schema.valid() ? schema : GetAdditionalProperties(); 1044 if (schema.valid())
1045 return schema;
1046 return GetAdditionalProperties();
1047 }
1048
1049 Schema::SchemaList Schema::GetMatchingProperties(const std::string& key) const {
1050 Schema::SchemaList schema_list;
1051
1052 Schema known_property = GetKnownProperty(key);
1053 if (known_property.valid())
1054 schema_list.push_back(known_property);
1055
1056 Schema::SchemaList pattern_properties = GetPatternProperties(key);
1057 schema_list.insert(
1058 schema_list.end(), pattern_properties.begin(), pattern_properties.end());
1059
1060 if (schema_list.empty()) {
1061 Schema additional_property = GetAdditionalProperties();
1062 if (additional_property.valid())
1063 schema_list.push_back(additional_property);
1064 }
1065
1066 return schema_list;
905 } 1067 }
906 1068
907 Schema Schema::GetItems() const { 1069 Schema Schema::GetItems() const {
908 CHECK(valid()); 1070 CHECK(valid());
909 CHECK_EQ(base::Value::TYPE_LIST, type()); 1071 CHECK_EQ(base::Value::TYPE_LIST, type());
910 if (node_->extra == kInvalid) 1072 if (node_->extra == kInvalid)
911 return Schema(); 1073 return Schema();
912 return Schema(storage_, storage_->schema(node_->extra)); 1074 return Schema(storage_, storage_->schema(node_->extra));
913 } 1075 }
914 1076
915 bool Schema::ValidateIntegerRestriction(int index, int value) const { 1077 bool Schema::ValidateIntegerRestriction(int index, int value) const {
916 const RestrictionNode* rnode = storage_->restriction(index); 1078 const RestrictionNode* rnode = storage_->restriction(index);
917 if (rnode->ranged_restriction.min_value <= 1079 if (rnode->ranged_restriction.min_value <=
918 rnode->ranged_restriction.max_value) { 1080 rnode->ranged_restriction.max_value) {
919 return rnode->ranged_restriction.min_value <= value && 1081 return rnode->ranged_restriction.min_value <= value &&
920 rnode->ranged_restriction.max_value >= value; 1082 rnode->ranged_restriction.max_value >= value;
921 } else { 1083 } else {
922 for (int i = rnode->enumeration_restriction.offset_begin; 1084 for (int i = rnode->enumeration_restriction.offset_begin;
923 i < rnode->enumeration_restriction.offset_end; i++) { 1085 i < rnode->enumeration_restriction.offset_end; i++) {
Joao da Silva 2014/04/02 09:51:11 ++i
binjin 2014/04/03 10:13:37 Done.
924 if (*storage_->int_enums(i) == value) 1086 if (*storage_->int_enums(i) == value)
925 return true; 1087 return true;
926 } 1088 }
927 return false; 1089 return false;
928 } 1090 }
929 } 1091 }
930 1092
931 bool Schema::ValidateStringRestriction(int index, const char* str) const { 1093 bool Schema::ValidateStringRestriction(int index, const char* str) const {
932 const RestrictionNode* rnode = storage_->restriction(index); 1094 const RestrictionNode* rnode = storage_->restriction(index);
933 for (int i = rnode->enumeration_restriction.offset_begin; 1095 if (rnode->enumeration_restriction.offset_begin <
934 i < rnode->enumeration_restriction.offset_end; i++) { 1096 rnode->enumeration_restriction.offset_end) {
935 if (strcmp(*storage_->string_enums(i), str) == 0) 1097 for (int i = rnode->enumeration_restriction.offset_begin;
936 return true; 1098 i < rnode->enumeration_restriction.offset_end; i++) {
Joao da Silva 2014/04/02 09:51:11 ++i
binjin 2014/04/03 10:13:37 Done.
1099 if (strcmp(*storage_->string_enums(i), str) == 0)
1100 return true;
1101 }
1102 return false;
1103 } else {
1104 int index = rnode->string_pattern_restriction.pattern_index;
1105 DCHECK(index == rnode->string_pattern_restriction.pattern_index_backup);
1106 re2::RE2* regex = storage_->CompileRegex(*storage_->string_enums(index));
1107 return re2::RE2::PartialMatch(str, *regex);
937 } 1108 }
938 return false;
939 } 1109 }
940 1110
941 } // namespace policy 1111 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698