1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef COMPONENTS_POLICY_CORE_COMMON_SCHEMA_H_ 6 #define COMPONENTS_POLICY_CORE_COMMON_SCHEMA_H_ 7 8 #include <string> 9 #include <vector> 10 11 #include "base/memory/ref_counted.h" 12 #include "base/values.h" 13 #include "components/policy/policy_export.h" 14 15 namespace policy { 16 namespace internal { 17 18 struct POLICY_EXPORT SchemaData; 19 struct POLICY_EXPORT SchemaNode; 20 struct POLICY_EXPORT PropertyNode; 21 struct POLICY_EXPORT PropertiesNode; 22 23 } // namespace internal 24 25 // Option flags passed to Schema::Validate() and Schema::Normalize(), describing 26 // the strategy to handle unknown properties or invalid values for dict type. 27 // Note that in Schema::Normalize() allowed errors will be dropped and thus 28 // ignored. 29 // Unknown error indicates that some value in a dictionary (may or may not be 30 // the one in root) have unknown property name according to schema. 31 // Invalid error indicates a validation failure against the schema. As 32 // validation is done recursively, a validation failure of dict properties or 33 // list items might be ignored (or dropped in Normalize()) or trigger whole 34 // dictionary/list validation failure. 35 enum SchemaOnErrorStrategy { 36 // No errors will be allowed. 37 SCHEMA_STRICT = 0, 38 // Unknown properties in the top-level dictionary will be ignored. 39 SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, 40 // Unknown properties in any dictionary will be ignored. 41 SCHEMA_ALLOW_UNKNOWN, 42 // Mismatched values will be ignored at the toplevel. 43 SCHEMA_ALLOW_INVALID_TOPLEVEL, 44 // Mismatched values will be ignored at the top-level value. 45 // Unknown properties in any dictionary will be ignored. 46 SCHEMA_ALLOW_INVALID_TOPLEVEL_AND_ALLOW_UNKNOWN, 47 // Mismatched values will be ignored. 48 SCHEMA_ALLOW_INVALID, 49 }; 50 51 class Schema; 52 53 typedef std::vector<Schema> SchemaList; 54 55 // Describes the expected type of one policy. Also recursively describes the 56 // types of inner elements, for structured types. 57 // Objects of this class refer to external, immutable data and are cheap to 58 // copy. 59 // 60 // Schema validation is based on a subset of the JSON Schema standard. 61 // TODO(crbug.com/856901): Document the supported subset of the JSON Schema 62 // standard. 63 class POLICY_EXPORT Schema { 64 public: 65 // Used internally to store shared data. 66 class InternalStorage; 67 68 // Builds an empty, invalid schema. 69 Schema(); 70 71 // Makes a copy of |schema| that shares the same internal storage. 72 Schema(const Schema& schema); 73 74 ~Schema(); 75 76 Schema& operator=(const Schema& schema); 77 78 // Returns a Schema that references static data. This can be used by 79 // the embedder to pass structures generated at compile time, which can then 80 // be quickly loaded at runtime. 81 static Schema Wrap(const internal::SchemaData* data); 82 83 // Parses the JSON schema in |schema| and returns a Schema that owns 84 // the internal representation. If |schema| is invalid then an invalid Schema 85 // is returned and |error| contains a reason for the failure. 86 static Schema Parse(const std::string& schema, std::string* error); 87 88 // Returns true if this Schema is valid. Schemas returned by the methods below 89 // may be invalid, and in those cases the other methods must not be used. valid()90 bool valid() const { return node_ != NULL; } 91 92 base::Value::Type type() const; 93 94 // Validate |value| against current schema, |strategy| is the strategy to 95 // handle unknown properties or invalid values. Allowed errors will be 96 // ignored. |error_path| and |error| will contain the last error location and 97 // detailed message if |value| doesn't strictly conform to the schema. If 98 // |value| doesn't conform to the schema even within the allowance of 99 // |strategy|, false will be returned and |error_path| and |error| will 100 // contain the corresponding error that caused the failure. |error_path| can 101 // be NULL and in that case no error path will be returned. 102 bool Validate(const base::Value& value, 103 SchemaOnErrorStrategy strategy, 104 std::string* error_path, 105 std::string* error) const; 106 107 // Similar to Validate() but drop values with errors instead of ignoring them. 108 // |changed| is a pointer to a boolean value, and indicate whether |value| 109 // is changed or not (probably dropped properties or items). Be sure to set 110 // the bool that |changed| pointed to to false before calling Normalize(). 111 // |changed| can be NULL and in that case no boolean will be set. 112 // This function will also take the ownership of dropped base::Value and 113 // destroy them. 114 bool Normalize(base::Value* value, 115 SchemaOnErrorStrategy strategy, 116 std::string* error_path, 117 std::string* error, 118 bool* changed) const; 119 120 // Used to iterate over the known properties of Type::DICTIONARY schemas. 121 class POLICY_EXPORT Iterator { 122 public: 123 Iterator(const scoped_refptr<const InternalStorage>& storage, 124 const internal::PropertiesNode* node); 125 Iterator(const Iterator& iterator); 126 ~Iterator(); 127 128 Iterator& operator=(const Iterator& iterator); 129 130 // The other methods must not be called if the iterator is at the end. 131 bool IsAtEnd() const; 132 133 // Advances the iterator to the next property. 134 void Advance(); 135 136 // Returns the name of the current property. 137 const char* key() const; 138 139 // Returns the Schema for the current property. This Schema is always valid. 140 Schema schema() const; 141 142 private: 143 scoped_refptr<const InternalStorage> storage_; 144 const internal::PropertyNode* it_; 145 const internal::PropertyNode* end_; 146 }; 147 148 // These methods should be called only if type() == Type::DICTIONARY, 149 // otherwise invalid memory will be read. A CHECK is currently enforcing this. 150 151 // Returns an iterator that goes over the named properties of this schema. 152 // The returned iterator is at the beginning. 153 Iterator GetPropertiesIterator() const; 154 155 // Returns the Schema for the property named |key|. If |key| is not a known 156 // property name then the returned Schema is not valid. 157 Schema GetKnownProperty(const std::string& key) const; 158 159 // Returns all Schemas from pattern properties that match |key|. May be empty. 160 SchemaList GetPatternProperties(const std::string& key) const; 161 162 // Returns this Schema's required properties. May be empty if the Schema has 163 // no required properties. 164 std::vector<std::string> GetRequiredProperties() const; 165 166 // Returns the Schema for additional properties. If additional properties are 167 // not allowed for this Schema then the Schema returned is not valid. 168 Schema GetAdditionalProperties() const; 169 170 // Returns the Schema for |key| if it is a known property, otherwise returns 171 // the Schema for additional properties. 172 // DEPRECATED: This function didn't consider patternProperties, use 173 // GetMatchingProperties() instead. 174 // TODO(binjin): Replace calls to this function with GetKnownProperty() or 175 // GetMatchingProperties() and remove this later. 176 Schema GetProperty(const std::string& key) const; 177 178 // Returns all Schemas that are supposed to be validated against for |key|. 179 // May be empty. 180 SchemaList GetMatchingProperties(const std::string& key) const; 181 182 // Returns the Schema for items of an array. 183 // This method should be called only if type() == Type::LIST, 184 // otherwise invalid memory will be read. A CHECK is currently enforcing this. 185 Schema GetItems() const; 186 187 // Gets the validation schema associated with this |schema| - or if there 188 // isn't one, returns an empty invalid schema. There are a few policies that 189 // contain embedded JSON - these policies have a schema for validating that 190 // JSON that is more complicated than the regular schema. For other policies 191 // it is not defined. To get the validation schema for a policy, call 192 // |chrome_schema.GetValidationSchema().GetKnownProperty(policy_name)|, where 193 // |chrome_schema| is the root schema that has all policies as children. 194 Schema GetValidationSchema() const; 195 196 private: 197 // Builds a schema pointing to the inner structure of |storage|, 198 // rooted at |node|. 199 Schema(const scoped_refptr<const InternalStorage>& storage, 200 const internal::SchemaNode* node); 201 202 bool ValidateIntegerRestriction(int index, int value) const; 203 bool ValidateStringRestriction(int index, const char* str) const; 204 205 scoped_refptr<const InternalStorage> storage_; 206 const internal::SchemaNode* node_; 207 }; 208 209 } // namespace policy 210 211 #endif // COMPONENTS_POLICY_CORE_COMMON_SCHEMA_H_ 212