• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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