Home | History | Annotate | Download | only in common
      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.
     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