|  | // Copyright 2013 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef COMPONENTS_JSON_SCHEMA_JSON_SCHEMA_VALIDATOR_H_ | 
|  | #define COMPONENTS_JSON_SCHEMA_JSON_SCHEMA_VALIDATOR_H_ | 
|  |  | 
|  | #include <map> | 
|  | #include <memory> | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/macros.h" | 
|  |  | 
|  | namespace base { | 
|  | class DictionaryValue; | 
|  | class ListValue; | 
|  | class Value; | 
|  | } | 
|  |  | 
|  | //============================================================================== | 
|  | // This class implements a subset of JSON Schema. | 
|  | // See: http://www.json.com/json-schema-proposal/ for more details. | 
|  | // | 
|  | // There is also an older JavaScript implementation of the same functionality in | 
|  | // chrome/renderer/resources/json_schema.js. | 
|  | // | 
|  | // The following features of JSON Schema are not implemented: | 
|  | // - requires | 
|  | // - unique | 
|  | // - disallow | 
|  | // - union types (but replaced with 'choices') | 
|  | // - number.maxDecimal | 
|  | // | 
|  | // The following properties are not applicable to the interface exposed by | 
|  | // this class: | 
|  | // - options | 
|  | // - readonly | 
|  | // - title | 
|  | // - description | 
|  | // - format | 
|  | // - default | 
|  | // - transient | 
|  | // - hidden | 
|  | // | 
|  | // There are also these departures from the JSON Schema proposal: | 
|  | // - null counts as 'unspecified' for optional values | 
|  | // - added the 'choices' property, to allow specifying a list of possible types | 
|  | //   for a value | 
|  | // - by default an "object" typed schema does not allow additional properties. | 
|  | //   if present, "additionalProperties" is to be a schema against which all | 
|  | //   additional properties will be validated. | 
|  | // - regular expression supports all syntaxes that re2 accepts. | 
|  | //   See https://github.com/google/re2/blob/master/doc/syntax.txt for details. | 
|  | //============================================================================== | 
|  | class JSONSchemaValidator { | 
|  | public: | 
|  | // Details about a validation error. | 
|  | struct Error { | 
|  | Error(); | 
|  |  | 
|  | explicit Error(const std::string& message); | 
|  |  | 
|  | Error(const std::string& path, const std::string& message); | 
|  |  | 
|  | // The path to the location of the error in the JSON structure. | 
|  | std::string path; | 
|  |  | 
|  | // An english message describing the error. | 
|  | std::string message; | 
|  | }; | 
|  |  | 
|  | enum Options { | 
|  | // Ignore unknown attributes. If this option is not set then unknown | 
|  | // attributes will make the schema validation fail. | 
|  | OPTIONS_IGNORE_UNKNOWN_ATTRIBUTES = 1 << 0, | 
|  | }; | 
|  |  | 
|  | // Error messages. | 
|  | static const char kUnknownTypeReference[]; | 
|  | static const char kInvalidChoice[]; | 
|  | static const char kInvalidEnum[]; | 
|  | static const char kObjectPropertyIsRequired[]; | 
|  | static const char kUnexpectedProperty[]; | 
|  | static const char kArrayMinItems[]; | 
|  | static const char kArrayMaxItems[]; | 
|  | static const char kArrayItemRequired[]; | 
|  | static const char kStringMinLength[]; | 
|  | static const char kStringMaxLength[]; | 
|  | static const char kStringPattern[]; | 
|  | static const char kNumberMinimum[]; | 
|  | static const char kNumberMaximum[]; | 
|  | static const char kInvalidType[]; | 
|  | static const char kInvalidTypeIntegerNumber[]; | 
|  | static const char kInvalidRegex[]; | 
|  |  | 
|  | // Classifies a Value as one of the JSON schema primitive types. | 
|  | static std::string GetJSONSchemaType(const base::Value* value); | 
|  |  | 
|  | // Utility methods to format error messages. The first method can have one | 
|  | // wildcard represented by '*', which is replaced with s1. The second method | 
|  | // can have two, which are replaced by s1 and s2. | 
|  | static std::string FormatErrorMessage(const std::string& format, | 
|  | const std::string& s1); | 
|  | static std::string FormatErrorMessage(const std::string& format, | 
|  | const std::string& s1, | 
|  | const std::string& s2); | 
|  |  | 
|  | // Verifies if |schema| is a valid JSON v3 schema. When this validation passes | 
|  | // then |schema| is valid JSON that can be parsed into a DictionaryValue, | 
|  | // and that DictionaryValue can be used to build a JSONSchemaValidator. | 
|  | // Returns the parsed DictionaryValue when |schema| validated, otherwise | 
|  | // returns NULL. In that case, |error| contains an error description. | 
|  | // For performance reasons, currently IsValidSchema() won't check the | 
|  | // correctness of regular expressions used in "pattern" and | 
|  | // "patternProperties" and in Validate() invalid regular expression don't | 
|  | // accept any strings. | 
|  | static std::unique_ptr<base::DictionaryValue> IsValidSchema( | 
|  | const std::string& schema, | 
|  | std::string* error); | 
|  |  | 
|  | // Same as above but with |options|, which is a bitwise-OR combination of the | 
|  | // Options above. | 
|  | static std::unique_ptr<base::DictionaryValue> | 
|  | IsValidSchema(const std::string& schema, int options, std::string* error); | 
|  |  | 
|  | // Creates a validator for the specified schema. | 
|  | // | 
|  | // NOTE: This constructor assumes that |schema| is well formed and valid. | 
|  | // Errors will result in CHECK at runtime; this constructor should not be used | 
|  | // with untrusted schemas. | 
|  | explicit JSONSchemaValidator(base::DictionaryValue* schema); | 
|  |  | 
|  | // Creates a validator for the specified schema and user-defined types. Each | 
|  | // type must be a valid JSONSchema type description with an additional "id" | 
|  | // field. Schema objects in |schema| can refer to these types with the "$ref" | 
|  | // property. | 
|  | // | 
|  | // NOTE: This constructor assumes that |schema| and |types| are well-formed | 
|  | // and valid. Errors will result in CHECK at runtime; this constructor should | 
|  | // not be used with untrusted schemas. | 
|  | JSONSchemaValidator(base::DictionaryValue* schema, base::ListValue* types); | 
|  |  | 
|  | ~JSONSchemaValidator(); | 
|  |  | 
|  | // Whether the validator allows additional items for objects and lists, beyond | 
|  | // those defined by their schema, by default. | 
|  | // | 
|  | // This setting defaults to false: all items in an instance list or object | 
|  | // must be defined by the corresponding schema. | 
|  | // | 
|  | // This setting can be overridden on individual object and list schemas by | 
|  | // setting the "additionalProperties" field. | 
|  | bool default_allow_additional_properties() const { | 
|  | return default_allow_additional_properties_; | 
|  | } | 
|  |  | 
|  | void set_default_allow_additional_properties(bool val) { | 
|  | default_allow_additional_properties_ = val; | 
|  | } | 
|  |  | 
|  | // Returns any errors from the last call to to Validate(). | 
|  | const std::vector<Error>& errors() const { | 
|  | return errors_; | 
|  | } | 
|  |  | 
|  | // Validates a JSON value. Returns true if the instance is valid, false | 
|  | // otherwise. If false is returned any errors are available from the errors() | 
|  | // getter. | 
|  | bool Validate(const base::Value* instance); | 
|  |  | 
|  | private: | 
|  | typedef std::map<std::string, const base::DictionaryValue*> TypeMap; | 
|  |  | 
|  | // Each of the below methods handle a subset of the validation process. The | 
|  | // path paramater is the path to |instance| from the root of the instance tree | 
|  | // and is used in error messages. | 
|  |  | 
|  | // Validates any instance node against any schema node. This is called for | 
|  | // every node in the instance tree, and it just decides which of the more | 
|  | // detailed methods to call. | 
|  | void Validate(const base::Value* instance, | 
|  | const base::DictionaryValue* schema, | 
|  | const std::string& path); | 
|  |  | 
|  | // Validates a node against a list of possible schemas. If any one of the | 
|  | // schemas match, the node is valid. | 
|  | void ValidateChoices(const base::Value* instance, | 
|  | const base::ListValue* choices, | 
|  | const std::string& path); | 
|  |  | 
|  | // Validates a node against a list of exact primitive values, eg 42, "foobar". | 
|  | void ValidateEnum(const base::Value* instance, | 
|  | const base::ListValue* choices, | 
|  | const std::string& path); | 
|  |  | 
|  | // Validates a JSON object against an object schema node. | 
|  | void ValidateObject(const base::DictionaryValue* instance, | 
|  | const base::DictionaryValue* schema, | 
|  | const std::string& path); | 
|  |  | 
|  | // Validates a JSON array against an array schema node. | 
|  | void ValidateArray(const base::ListValue* instance, | 
|  | const base::DictionaryValue* schema, | 
|  | const std::string& path); | 
|  |  | 
|  | // Validates a JSON array against an array schema node configured to be a | 
|  | // tuple. In a tuple, there is one schema node for each item expected in the | 
|  | // array. | 
|  | void ValidateTuple(const base::ListValue* instance, | 
|  | const base::DictionaryValue* schema, | 
|  | const std::string& path); | 
|  |  | 
|  | // Validate a JSON string against a string schema node. | 
|  | void ValidateString(const base::Value* instance, | 
|  | const base::DictionaryValue* schema, | 
|  | const std::string& path); | 
|  |  | 
|  | // Validate a JSON number against a number schema node. | 
|  | void ValidateNumber(const base::Value* instance, | 
|  | const base::DictionaryValue* schema, | 
|  | const std::string& path); | 
|  |  | 
|  | // Validates that the JSON node |instance| has |expected_type|. | 
|  | bool ValidateType(const base::Value* instance, | 
|  | const std::string& expected_type, | 
|  | const std::string& path); | 
|  |  | 
|  | // Returns true if |schema| will allow additional items of any type. | 
|  | bool SchemaAllowsAnyAdditionalItems( | 
|  | const base::DictionaryValue* schema, | 
|  | const base::DictionaryValue** addition_items_schema); | 
|  |  | 
|  | // The root schema node. | 
|  | base::DictionaryValue* schema_root_; | 
|  |  | 
|  | // Map of user-defined name to type. | 
|  | TypeMap types_; | 
|  |  | 
|  | // Whether we allow additional properties on objects by default. This can be | 
|  | // overridden by the allow_additional_properties flag on an Object schema. | 
|  | bool default_allow_additional_properties_; | 
|  |  | 
|  | // Errors accumulated since the last call to Validate(). | 
|  | std::vector<Error> errors_; | 
|  |  | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(JSONSchemaValidator); | 
|  | }; | 
|  |  | 
|  | #endif  // COMPONENTS_JSON_SCHEMA_JSON_SCHEMA_VALIDATOR_H_ |