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

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, 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
« 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
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>
12 11
13 #include "base/compiler_specific.h" 12 #include "base/compiler_specific.h"
14 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/memory/scoped_vector.h" 15 #include "base/memory/scoped_vector.h"
16 #include "base/stl_util.h"
16 #include "base/strings/stringprintf.h" 17 #include "base/strings/stringprintf.h"
17 #include "components/json_schema/json_schema_constants.h" 18 #include "components/json_schema/json_schema_constants.h"
18 #include "components/json_schema/json_schema_validator.h" 19 #include "components/json_schema/json_schema_validator.h"
19 #include "components/policy/core/common/schema_internal.h" 20 #include "components/policy/core/common/schema_internal.h"
21 #include "third_party/re2/re2/re2.h"
20 22
21 namespace schema = json_schema_constants; 23 namespace schema = json_schema_constants;
22 24
23 namespace policy { 25 namespace policy {
24 26
25 using internal::PropertiesNode; 27 using internal::PropertiesNode;
26 using internal::PropertyNode; 28 using internal::PropertyNode;
27 using internal::RestrictionNode; 29 using internal::RestrictionNode;
28 using internal::SchemaData; 30 using internal::SchemaData;
29 using internal::SchemaNode; 31 using internal::SchemaNode;
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 } 170 }
169 171
170 const int* int_enums(int index) const { 172 const int* int_enums(int index) const {
171 return schema_data_.int_enums + index; 173 return schema_data_.int_enums + index;
172 } 174 }
173 175
174 const char** string_enums(int index) const { 176 const char** string_enums(int index) const {
175 return schema_data_.string_enums + index; 177 return schema_data_.string_enums + index;
176 } 178 }
177 179
180 // Compiles regular expression |pattern|. The result is cached and will be
181 // returned directly next time.
182 re2::RE2* CompileRegex(const std::string& pattern) const;
183
178 private: 184 private:
179 friend class base::RefCountedThreadSafe<InternalStorage>; 185 friend class base::RefCountedThreadSafe<InternalStorage>;
180 186
181 InternalStorage(); 187 InternalStorage();
182 ~InternalStorage(); 188 ~InternalStorage();
183 189
184 // Determines the expected |sizes| of the storage for the representation 190 // Determines the expected |sizes| of the storage for the representation
185 // of |schema|. 191 // of |schema|.
186 static void DetermineStorageSizes(const base::DictionaryValue& schema, 192 static void DetermineStorageSizes(const base::DictionaryValue& schema,
187 StorageSizes* sizes); 193 StorageSizes* sizes);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 227
222 bool ParseEnum(const base::DictionaryValue& schema, 228 bool ParseEnum(const base::DictionaryValue& schema,
223 base::Value::Type type, 229 base::Value::Type type,
224 SchemaNode* schema_node, 230 SchemaNode* schema_node,
225 std::string* error); 231 std::string* error);
226 232
227 bool ParseRangedInt(const base::DictionaryValue& schema, 233 bool ParseRangedInt(const base::DictionaryValue& schema,
228 SchemaNode* schema_node, 234 SchemaNode* schema_node,
229 std::string* error); 235 std::string* error);
230 236
237 bool ParseStringPattern(const base::DictionaryValue& schema,
238 SchemaNode* schema_node,
239 std::string* error);
240
231 // Assigns the IDs in |id_map| to the pending references in the 241 // 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 242 // |reference_list|. If an ID is missing then |error| is set and false is
233 // returned; otherwise returns true. 243 // returned; otherwise returns true.
234 static bool ResolveReferences(const IdMap& id_map, 244 static bool ResolveReferences(const IdMap& id_map,
235 const ReferenceList& reference_list, 245 const ReferenceList& reference_list,
236 std::string* error); 246 std::string* error);
237 247
248 // Cache for CompileRegex(), will memorize return value of every call to
249 // CompileRegex() and return results directly next time.
250 mutable std::map<std::string, re2::RE2*> regex_cache_;
251 STLValueDeleter<std::map<std::string, re2::RE2*> > regex_cache_deleter_;
252
238 SchemaData schema_data_; 253 SchemaData schema_data_;
239 std::vector<std::string> strings_; 254 std::vector<std::string> strings_;
240 std::vector<SchemaNode> schema_nodes_; 255 std::vector<SchemaNode> schema_nodes_;
241 std::vector<PropertyNode> property_nodes_; 256 std::vector<PropertyNode> property_nodes_;
242 std::vector<PropertiesNode> properties_nodes_; 257 std::vector<PropertiesNode> properties_nodes_;
243 std::vector<RestrictionNode> restriction_nodes_; 258 std::vector<RestrictionNode> restriction_nodes_;
244 std::vector<int> int_enums_; 259 std::vector<int> int_enums_;
245 std::vector<const char*> string_enums_; 260 std::vector<const char*> string_enums_;
246 261
247 DISALLOW_COPY_AND_ASSIGN(InternalStorage); 262 DISALLOW_COPY_AND_ASSIGN(InternalStorage);
248 }; 263 };
249 264
250 Schema::InternalStorage::InternalStorage() {} 265 Schema::InternalStorage::InternalStorage()
266 : regex_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(); ++subschema) {
699 error)) { 810 if (!subschema->Validate(it.value(),
700 // Invalid property was detected. 811 StrategyForNextLevel(strategy),
701 AddDictKeyPrefixToPath(it.key(), error_path); 812 error_path,
702 if (!StrategyAllowInvalidOnTopLevel(strategy)) 813 error)) {
703 return false; 814 // Invalid property was detected.
815 AddDictKeyPrefixToPath(it.key(), error_path);
816 if (!StrategyAllowInvalidOnTopLevel(strategy))
817 return false;
818 }
819 }
704 } 820 }
705 } 821 }
706 } else if (value.GetAsList(&list)) { 822 } else if (value.GetAsList(&list)) {
707 for (base::ListValue::const_iterator it = list->begin(); it != list->end(); 823 for (base::ListValue::const_iterator it = list->begin(); it != list->end();
708 ++it) { 824 ++it) {
709 if (!*it || 825 if (!*it ||
710 !GetItems().Validate(**it, 826 !GetItems().Validate(**it,
711 StrategyForNextLevel(strategy), 827 StrategyForNextLevel(strategy),
712 error_path, 828 error_path,
713 error)) { 829 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."); 872 error_path, error, "The value type doesn't match the schema type.");
757 return false; 873 return false;
758 } 874 }
759 875
760 base::DictionaryValue* dict = NULL; 876 base::DictionaryValue* dict = NULL;
761 base::ListValue* list = NULL; 877 base::ListValue* list = NULL;
762 if (value->GetAsDictionary(&dict)) { 878 if (value->GetAsDictionary(&dict)) {
763 std::vector<std::string> drop_list; // Contains the keys to drop. 879 std::vector<std::string> drop_list; // Contains the keys to drop.
764 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); 880 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
765 it.Advance()) { 881 it.Advance()) {
766 Schema subschema = GetProperty(it.key()); 882 SchemaList schema_list = GetMatchingProperties(it.key());
767 if (!subschema.valid()) { 883 if (schema_list.empty()) {
768 // Unknown property was detected. 884 // Unknown property was detected.
769 SchemaErrorFound(error_path, error, "Unknown property: " + it.key()); 885 SchemaErrorFound(error_path, error, "Unknown property: " + it.key());
770 if (StrategyAllowUnknownOnTopLevel(strategy)) 886 if (StrategyAllowUnknownOnTopLevel(strategy))
771 drop_list.push_back(it.key()); 887 drop_list.push_back(it.key());
772 else 888 else
773 return false; 889 return false;
774 } else { 890 } else {
775 base::Value* sub_value = NULL; 891 for (SchemaList::iterator subschema = schema_list.begin();
776 dict->GetWithoutPathExpansion(it.key(), &sub_value); 892 subschema != schema_list.end(); ++subschema) {
777 if (!subschema.Normalize(sub_value, 893 base::Value* sub_value = NULL;
778 StrategyForNextLevel(strategy), 894 dict->GetWithoutPathExpansion(it.key(), &sub_value);
779 error_path, 895 if (!subschema->Normalize(sub_value,
780 error, 896 StrategyForNextLevel(strategy),
781 changed)) { 897 error_path,
782 // Invalid property was detected. 898 error,
783 AddDictKeyPrefixToPath(it.key(), error_path); 899 changed)) {
784 if (StrategyAllowInvalidOnTopLevel(strategy)) 900 // Invalid property was detected.
785 drop_list.push_back(it.key()); 901 AddDictKeyPrefixToPath(it.key(), error_path);
786 else 902 if (StrategyAllowInvalidOnTopLevel(strategy)) {
787 return false; 903 drop_list.push_back(it.key());
904 break;
905 } else {
906 return false;
907 }
908 }
788 } 909 }
789 } 910 }
790 } 911 }
791 if (changed && !drop_list.empty()) 912 if (changed && !drop_list.empty())
792 *changed = true; 913 *changed = true;
793 for (std::vector<std::string>::const_iterator it = drop_list.begin(); 914 for (std::vector<std::string>::const_iterator it = drop_list.begin();
794 it != drop_list.end(); 915 it != drop_list.end();
795 ++it) { 916 ++it) {
796 dict->RemoveWithoutPathExpansion(*it, NULL); 917 dict->RemoveWithoutPathExpansion(*it, NULL);
797 } 918 }
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
892 1013
893 Schema Schema::GetAdditionalProperties() const { 1014 Schema Schema::GetAdditionalProperties() const {
894 CHECK(valid()); 1015 CHECK(valid());
895 CHECK_EQ(base::Value::TYPE_DICTIONARY, type()); 1016 CHECK_EQ(base::Value::TYPE_DICTIONARY, type());
896 const PropertiesNode* node = storage_->properties(node_->extra); 1017 const PropertiesNode* node = storage_->properties(node_->extra);
897 if (node->additional == kInvalid) 1018 if (node->additional == kInvalid)
898 return Schema(); 1019 return Schema();
899 return Schema(storage_, storage_->schema(node->additional)); 1020 return Schema(storage_, storage_->schema(node->additional));
900 } 1021 }
901 1022
1023 SchemaList Schema::GetPatternProperties(const std::string& key) const {
1024 CHECK(valid());
1025 CHECK_EQ(base::Value::TYPE_DICTIONARY, type());
1026 const PropertiesNode* node = storage_->properties(node_->extra);
1027 const PropertyNode* begin = storage_->property(node->end);
1028 const PropertyNode* end = storage_->property(node->pattern_end);
1029 SchemaList matching_properties;
1030 for (const PropertyNode* it = begin; it != end; ++it) {
1031 if (re2::RE2::PartialMatch(key, *storage_->CompileRegex(it->key))) {
1032 matching_properties.push_back(
1033 Schema(storage_, storage_->schema(it->schema)));
1034 }
1035 }
1036 return matching_properties;
1037 }
1038
902 Schema Schema::GetProperty(const std::string& key) const { 1039 Schema Schema::GetProperty(const std::string& key) const {
903 Schema schema = GetKnownProperty(key); 1040 Schema schema = GetKnownProperty(key);
904 return schema.valid() ? schema : GetAdditionalProperties(); 1041 if (schema.valid())
1042 return schema;
1043 return GetAdditionalProperties();
1044 }
1045
1046 SchemaList Schema::GetMatchingProperties(const std::string& key) const {
1047 SchemaList schema_list;
1048
1049 Schema known_property = GetKnownProperty(key);
1050 if (known_property.valid())
1051 schema_list.push_back(known_property);
1052
1053 SchemaList pattern_properties = GetPatternProperties(key);
1054 schema_list.insert(
1055 schema_list.end(), pattern_properties.begin(), pattern_properties.end());
1056
1057 if (schema_list.empty()) {
1058 Schema additional_property = GetAdditionalProperties();
1059 if (additional_property.valid())
1060 schema_list.push_back(additional_property);
1061 }
1062
1063 return schema_list;
905 } 1064 }
906 1065
907 Schema Schema::GetItems() const { 1066 Schema Schema::GetItems() const {
908 CHECK(valid()); 1067 CHECK(valid());
909 CHECK_EQ(base::Value::TYPE_LIST, type()); 1068 CHECK_EQ(base::Value::TYPE_LIST, type());
910 if (node_->extra == kInvalid) 1069 if (node_->extra == kInvalid)
911 return Schema(); 1070 return Schema();
912 return Schema(storage_, storage_->schema(node_->extra)); 1071 return Schema(storage_, storage_->schema(node_->extra));
913 } 1072 }
914 1073
915 bool Schema::ValidateIntegerRestriction(int index, int value) const { 1074 bool Schema::ValidateIntegerRestriction(int index, int value) const {
916 const RestrictionNode* rnode = storage_->restriction(index); 1075 const RestrictionNode* rnode = storage_->restriction(index);
917 if (rnode->ranged_restriction.min_value <= 1076 if (rnode->ranged_restriction.min_value <=
918 rnode->ranged_restriction.max_value) { 1077 rnode->ranged_restriction.max_value) {
919 return rnode->ranged_restriction.min_value <= value && 1078 return rnode->ranged_restriction.min_value <= value &&
920 rnode->ranged_restriction.max_value >= value; 1079 rnode->ranged_restriction.max_value >= value;
921 } else { 1080 } else {
922 for (int i = rnode->enumeration_restriction.offset_begin; 1081 for (int i = rnode->enumeration_restriction.offset_begin;
923 i < rnode->enumeration_restriction.offset_end; i++) { 1082 i < rnode->enumeration_restriction.offset_end; ++i) {
924 if (*storage_->int_enums(i) == value) 1083 if (*storage_->int_enums(i) == value)
925 return true; 1084 return true;
926 } 1085 }
927 return false; 1086 return false;
928 } 1087 }
929 } 1088 }
930 1089
931 bool Schema::ValidateStringRestriction(int index, const char* str) const { 1090 bool Schema::ValidateStringRestriction(int index, const char* str) const {
932 const RestrictionNode* rnode = storage_->restriction(index); 1091 const RestrictionNode* rnode = storage_->restriction(index);
933 for (int i = rnode->enumeration_restriction.offset_begin; 1092 if (rnode->enumeration_restriction.offset_begin <
934 i < rnode->enumeration_restriction.offset_end; i++) { 1093 rnode->enumeration_restriction.offset_end) {
935 if (strcmp(*storage_->string_enums(i), str) == 0) 1094 for (int i = rnode->enumeration_restriction.offset_begin;
936 return true; 1095 i < rnode->enumeration_restriction.offset_end; ++i) {
1096 if (strcmp(*storage_->string_enums(i), str) == 0)
1097 return true;
1098 }
1099 return false;
1100 } else {
1101 int index = rnode->string_pattern_restriction.pattern_index;
1102 DCHECK(index == rnode->string_pattern_restriction.pattern_index_backup);
1103 re2::RE2* regex = storage_->CompileRegex(*storage_->string_enums(index));
1104 return re2::RE2::PartialMatch(str, *regex);
937 } 1105 }
938 return false;
939 } 1106 }
940 1107
941 } // namespace policy 1108 } // 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