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