| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/policy/core/common/schema.h" | 5 #include "components/policy/core/common/schema.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 if (kSchemaToValueTypeMap[i].schema_type == type_string) { | 44 if (kSchemaToValueTypeMap[i].schema_type == type_string) { |
| 45 *type = kSchemaToValueTypeMap[i].value_type; | 45 *type = kSchemaToValueTypeMap[i].value_type; |
| 46 return true; | 46 return true; |
| 47 } | 47 } |
| 48 } | 48 } |
| 49 return false; | 49 return false; |
| 50 } | 50 } |
| 51 | 51 |
| 52 } // namespace | 52 } // namespace |
| 53 | 53 |
| 54 // A SchemaOwner can either Wrap() a SchemaData owned elsewhere (currently used | 54 // Contains the internal data representation of a Schema. This can either wrap |
| 55 // to wrap the Chrome schema, which is generated at compile time), or it can | 55 // a SchemaData owned elsewhere (currently used to wrap the Chrome schema, which |
| 56 // own its own SchemaData. In that case, the InternalStorage class holds the | 56 // is generated at compile time), or it can own its own SchemaData. |
| 57 // data referenced by the SchemaData substructures. | 57 class Schema::InternalStorage |
| 58 class SchemaOwner::InternalStorage { | 58 : public base::RefCountedThreadSafe<InternalStorage> { |
| 59 public: | 59 public: |
| 60 ~InternalStorage() {} | 60 static scoped_refptr<const InternalStorage> Wrap(const SchemaData* data); |
| 61 | 61 |
| 62 static scoped_ptr<InternalStorage> ParseSchema( | 62 static scoped_refptr<const InternalStorage> ParseSchema( |
| 63 const base::DictionaryValue& schema, | 63 const base::DictionaryValue& schema, |
| 64 std::string* error); | 64 std::string* error); |
| 65 | 65 |
| 66 const SchemaData* schema_data() const { return &schema_data_; } | 66 const SchemaData* data() const { return &schema_data_; } |
| 67 |
| 68 const SchemaNode* root_node() const { |
| 69 return schema(0); |
| 70 } |
| 71 |
| 72 const SchemaNode* schema(int index) const { |
| 73 return schema_data_.schema_nodes + index; |
| 74 } |
| 75 |
| 76 const PropertiesNode* properties(int index) const { |
| 77 return schema_data_.properties_nodes + index; |
| 78 } |
| 79 |
| 80 const PropertyNode* property(int index) const { |
| 81 return schema_data_.property_nodes + index; |
| 82 } |
| 67 | 83 |
| 68 private: | 84 private: |
| 69 InternalStorage() {} | 85 friend class base::RefCountedThreadSafe<InternalStorage>; |
| 86 |
| 87 InternalStorage(); |
| 88 ~InternalStorage(); |
| 70 | 89 |
| 71 // Parses the JSON schema in |schema| and returns the index of the | 90 // Parses the JSON schema in |schema| and returns the index of the |
| 72 // corresponding SchemaNode in |schema_nodes_|, which gets populated with any | 91 // corresponding SchemaNode in |schema_nodes_|, which gets populated with any |
| 73 // necessary intermediate nodes. If |schema| is invalid then -1 is returned | 92 // necessary intermediate nodes. If |schema| is invalid then -1 is returned |
| 74 // and |error| is set to the error cause. | 93 // and |error| is set to the error cause. |
| 75 int Parse(const base::DictionaryValue& schema, std::string* error); | 94 int Parse(const base::DictionaryValue& schema, std::string* error); |
| 76 | 95 |
| 77 // Helper for Parse(). | 96 // Helper for Parse(). |
| 78 int ParseDictionary(const base::DictionaryValue& schema, std::string* error); | 97 int ParseDictionary(const base::DictionaryValue& schema, std::string* error); |
| 79 | 98 |
| 80 // Helper for Parse(). | 99 // Helper for Parse(). |
| 81 int ParseList(const base::DictionaryValue& schema, std::string* error); | 100 int ParseList(const base::DictionaryValue& schema, std::string* error); |
| 82 | 101 |
| 83 SchemaData schema_data_; | 102 SchemaData schema_data_; |
| 84 // TODO: compute the sizes of these arrays before filling them up to avoid | 103 // TODO: compute the sizes of these arrays before filling them up to avoid |
| 85 // having to resize them. | 104 // having to resize them. |
| 86 ScopedVector<std::string> strings_; | 105 ScopedVector<std::string> strings_; |
| 87 std::vector<SchemaNode> schema_nodes_; | 106 std::vector<SchemaNode> schema_nodes_; |
| 88 std::vector<PropertyNode> property_nodes_; | 107 std::vector<PropertyNode> property_nodes_; |
| 89 std::vector<PropertiesNode> properties_nodes_; | 108 std::vector<PropertiesNode> properties_nodes_; |
| 90 | 109 |
| 91 DISALLOW_COPY_AND_ASSIGN(InternalStorage); | 110 DISALLOW_COPY_AND_ASSIGN(InternalStorage); |
| 92 }; | 111 }; |
| 93 | 112 |
| 94 Schema::Iterator::Iterator(const SchemaData* data, const PropertiesNode* node) | 113 Schema::InternalStorage::InternalStorage() {} |
| 95 : data_(data), | |
| 96 it_(data->property_nodes + node->begin), | |
| 97 end_(data->property_nodes + node->end) {} | |
| 98 | 114 |
| 99 Schema::Iterator::Iterator(const Iterator& iterator) | 115 Schema::InternalStorage::~InternalStorage() {} |
| 100 : data_(iterator.data_), | |
| 101 it_(iterator.it_), | |
| 102 end_(iterator.end_) {} | |
| 103 | 116 |
| 104 Schema::Iterator::~Iterator() {} | 117 // static |
| 105 | 118 scoped_refptr<const Schema::InternalStorage> Schema::InternalStorage::Wrap( |
| 106 Schema::Iterator& Schema::Iterator::operator=(const Iterator& iterator) { | 119 const SchemaData* data) { |
| 107 data_ = iterator.data_; | 120 InternalStorage* storage = new InternalStorage(); |
| 108 it_ = iterator.it_; | 121 storage->schema_data_.schema_nodes = data->schema_nodes; |
| 109 end_ = iterator.end_; | 122 storage->schema_data_.property_nodes = data->property_nodes; |
| 110 return *this; | 123 storage->schema_data_.properties_nodes = data->properties_nodes; |
| 111 } | 124 return storage; |
| 112 | |
| 113 bool Schema::Iterator::IsAtEnd() const { | |
| 114 return it_ == end_; | |
| 115 } | |
| 116 | |
| 117 void Schema::Iterator::Advance() { | |
| 118 ++it_; | |
| 119 } | |
| 120 | |
| 121 const char* Schema::Iterator::key() const { | |
| 122 return it_->key; | |
| 123 } | |
| 124 | |
| 125 Schema Schema::Iterator::schema() const { | |
| 126 return Schema(data_, data_->schema_nodes + it_->schema); | |
| 127 } | |
| 128 | |
| 129 Schema::Schema() : data_(NULL), node_(NULL) {} | |
| 130 | |
| 131 Schema::Schema(const SchemaData* data, const SchemaNode* node) | |
| 132 : data_(data), node_(node) {} | |
| 133 | |
| 134 Schema::Schema(const Schema& schema) | |
| 135 : data_(schema.data_), node_(schema.node_) {} | |
| 136 | |
| 137 Schema& Schema::operator=(const Schema& schema) { | |
| 138 data_ = schema.data_; | |
| 139 node_ = schema.node_; | |
| 140 return *this; | |
| 141 } | |
| 142 | |
| 143 base::Value::Type Schema::type() const { | |
| 144 CHECK(valid()); | |
| 145 return node_->type; | |
| 146 } | |
| 147 | |
| 148 Schema::Iterator Schema::GetPropertiesIterator() const { | |
| 149 CHECK(valid()); | |
| 150 CHECK_EQ(base::Value::TYPE_DICTIONARY, type()); | |
| 151 return Iterator(data_, data_->properties_nodes + node_->extra); | |
| 152 } | |
| 153 | |
| 154 namespace { | |
| 155 | |
| 156 bool CompareKeys(const PropertyNode& node, const std::string& key) { | |
| 157 return node.key < key; | |
| 158 } | |
| 159 | |
| 160 } // namespace | |
| 161 | |
| 162 Schema Schema::GetKnownProperty(const std::string& key) const { | |
| 163 CHECK(valid()); | |
| 164 CHECK_EQ(base::Value::TYPE_DICTIONARY, type()); | |
| 165 const PropertiesNode* node = data_->properties_nodes + node_->extra; | |
| 166 const PropertyNode* begin = data_->property_nodes + node->begin; | |
| 167 const PropertyNode* end = data_->property_nodes + node->end; | |
| 168 const PropertyNode* it = std::lower_bound(begin, end, key, CompareKeys); | |
| 169 if (it != end && it->key == key) | |
| 170 return Schema(data_, data_->schema_nodes + it->schema); | |
| 171 return Schema(); | |
| 172 } | |
| 173 | |
| 174 Schema Schema::GetAdditionalProperties() const { | |
| 175 CHECK(valid()); | |
| 176 CHECK_EQ(base::Value::TYPE_DICTIONARY, type()); | |
| 177 const PropertiesNode* node = data_->properties_nodes + node_->extra; | |
| 178 if (node->additional == kInvalid) | |
| 179 return Schema(); | |
| 180 return Schema(data_, data_->schema_nodes + node->additional); | |
| 181 } | |
| 182 | |
| 183 Schema Schema::GetProperty(const std::string& key) const { | |
| 184 Schema schema = GetKnownProperty(key); | |
| 185 return schema.valid() ? schema : GetAdditionalProperties(); | |
| 186 } | |
| 187 | |
| 188 Schema Schema::GetItems() const { | |
| 189 CHECK(valid()); | |
| 190 CHECK_EQ(base::Value::TYPE_LIST, type()); | |
| 191 if (node_->extra == kInvalid) | |
| 192 return Schema(); | |
| 193 return Schema(data_, data_->schema_nodes + node_->extra); | |
| 194 } | |
| 195 | |
| 196 SchemaOwner::SchemaOwner(const SchemaData* data, | |
| 197 scoped_ptr<InternalStorage> storage) | |
| 198 : storage_(storage.Pass()), data_(data) {} | |
| 199 | |
| 200 SchemaOwner::~SchemaOwner() {} | |
| 201 | |
| 202 Schema SchemaOwner::schema() const { | |
| 203 // data_->schema_nodes[0] is the root node. | |
| 204 return Schema(data_, data_->schema_nodes); | |
| 205 } | 125 } |
| 206 | 126 |
| 207 // static | 127 // static |
| 208 scoped_ptr<SchemaOwner> SchemaOwner::Wrap(const SchemaData* data) { | 128 scoped_refptr<const Schema::InternalStorage> |
| 209 return make_scoped_ptr(new SchemaOwner(data, scoped_ptr<InternalStorage>())); | 129 Schema::InternalStorage::ParseSchema(const base::DictionaryValue& schema, |
| 210 } | 130 std::string* error) { |
| 211 | 131 scoped_refptr<InternalStorage> storage = new InternalStorage(); |
| 212 // static | |
| 213 scoped_ptr<SchemaOwner> SchemaOwner::Parse(const std::string& content, | |
| 214 std::string* error) { | |
| 215 // Validate as a generic JSON schema. | |
| 216 scoped_ptr<base::DictionaryValue> dict = | |
| 217 JSONSchemaValidator::IsValidSchema(content, error); | |
| 218 if (!dict) | |
| 219 return scoped_ptr<SchemaOwner>(); | |
| 220 | |
| 221 // Validate the main type. | |
| 222 std::string string_value; | |
| 223 if (!dict->GetString(json_schema_constants::kType, &string_value) || | |
| 224 string_value != json_schema_constants::kObject) { | |
| 225 *error = | |
| 226 "The main schema must have a type attribute with \"object\" value."; | |
| 227 return scoped_ptr<SchemaOwner>(); | |
| 228 } | |
| 229 | |
| 230 // Checks for invalid attributes at the top-level. | |
| 231 if (dict->HasKey(json_schema_constants::kAdditionalProperties) || | |
| 232 dict->HasKey(json_schema_constants::kPatternProperties)) { | |
| 233 *error = "\"additionalProperties\" and \"patternProperties\" are not " | |
| 234 "supported at the main schema."; | |
| 235 return scoped_ptr<SchemaOwner>(); | |
| 236 } | |
| 237 | |
| 238 scoped_ptr<InternalStorage> storage = | |
| 239 InternalStorage::ParseSchema(*dict, error); | |
| 240 if (!storage) | |
| 241 return scoped_ptr<SchemaOwner>(); | |
| 242 const SchemaData* data = storage->schema_data(); | |
| 243 return make_scoped_ptr(new SchemaOwner(data, storage.Pass())); | |
| 244 } | |
| 245 | |
| 246 // static | |
| 247 scoped_ptr<SchemaOwner::InternalStorage> | |
| 248 SchemaOwner::InternalStorage::ParseSchema(const base::DictionaryValue& schema, | |
| 249 std::string* error) { | |
| 250 scoped_ptr<InternalStorage> storage(new InternalStorage); | |
| 251 if (storage->Parse(schema, error) == kInvalid) | 132 if (storage->Parse(schema, error) == kInvalid) |
| 252 return scoped_ptr<InternalStorage>(); | 133 return NULL; |
| 253 SchemaData* data = &storage->schema_data_; | 134 SchemaData* data = &storage->schema_data_; |
| 254 data->schema_nodes = vector_as_array(&storage->schema_nodes_); | 135 data->schema_nodes = vector_as_array(&storage->schema_nodes_); |
| 255 data->property_nodes = vector_as_array(&storage->property_nodes_); | 136 data->property_nodes = vector_as_array(&storage->property_nodes_); |
| 256 data->properties_nodes = vector_as_array(&storage->properties_nodes_); | 137 data->properties_nodes = vector_as_array(&storage->properties_nodes_); |
| 257 return storage.Pass(); | 138 return storage; |
| 258 } | 139 } |
| 259 | 140 |
| 260 int SchemaOwner::InternalStorage::Parse(const base::DictionaryValue& schema, | 141 int Schema::InternalStorage::Parse(const base::DictionaryValue& schema, |
| 261 std::string* error) { | 142 std::string* error) { |
| 262 std::string type_string; | 143 std::string type_string; |
| 263 if (!schema.GetString(json_schema_constants::kType, &type_string)) { | 144 if (!schema.GetString(json_schema_constants::kType, &type_string)) { |
| 264 *error = "The schema type must be declared."; | 145 *error = "The schema type must be declared."; |
| 265 return kInvalid; | 146 return kInvalid; |
| 266 } | 147 } |
| 267 | 148 |
| 268 base::Value::Type type = base::Value::TYPE_NULL; | 149 base::Value::Type type = base::Value::TYPE_NULL; |
| 269 if (!SchemaTypeToValueType(type_string, &type)) { | 150 if (!SchemaTypeToValueType(type_string, &type)) { |
| 270 *error = "Type not supported: " + type_string; | 151 *error = "Type not supported: " + type_string; |
| 271 return kInvalid; | 152 return kInvalid; |
| 272 } | 153 } |
| 273 | 154 |
| 274 if (type == base::Value::TYPE_DICTIONARY) | 155 if (type == base::Value::TYPE_DICTIONARY) |
| 275 return ParseDictionary(schema, error); | 156 return ParseDictionary(schema, error); |
| 276 if (type == base::Value::TYPE_LIST) | 157 if (type == base::Value::TYPE_LIST) |
| 277 return ParseList(schema, error); | 158 return ParseList(schema, error); |
| 278 | 159 |
| 279 int index = static_cast<int>(schema_nodes_.size()); | 160 int index = static_cast<int>(schema_nodes_.size()); |
| 280 schema_nodes_.push_back(SchemaNode()); | 161 schema_nodes_.push_back(SchemaNode()); |
| 281 SchemaNode& node = schema_nodes_.back(); | 162 SchemaNode& node = schema_nodes_.back(); |
| 282 node.type = type; | 163 node.type = type; |
| 283 node.extra = kInvalid; | 164 node.extra = kInvalid; |
| 284 return index; | 165 return index; |
| 285 } | 166 } |
| 286 | 167 |
| 287 // static | 168 // static |
| 288 int SchemaOwner::InternalStorage::ParseDictionary( | 169 int Schema::InternalStorage::ParseDictionary( |
| 289 const base::DictionaryValue& schema, | 170 const base::DictionaryValue& schema, |
| 290 std::string* error) { | 171 std::string* error) { |
| 291 // Note: recursive calls to Parse() invalidate iterators and references into | 172 // Note: recursive calls to Parse() invalidate iterators and references into |
| 292 // the vectors. | 173 // the vectors. |
| 293 | 174 |
| 294 // Reserve an index for this dictionary at the front, so that the root node | 175 // Reserve an index for this dictionary at the front, so that the root node |
| 295 // is at index 0. | 176 // is at index 0. |
| 296 int schema_index = static_cast<int>(schema_nodes_.size()); | 177 int schema_index = static_cast<int>(schema_nodes_.size()); |
| 297 schema_nodes_.push_back(SchemaNode()); | 178 schema_nodes_.push_back(SchemaNode()); |
| 298 | 179 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 properties_nodes_[extra].begin = base_index; | 216 properties_nodes_[extra].begin = base_index; |
| 336 properties_nodes_[extra].end = index; | 217 properties_nodes_[extra].end = index; |
| 337 } | 218 } |
| 338 | 219 |
| 339 schema_nodes_[schema_index].type = base::Value::TYPE_DICTIONARY; | 220 schema_nodes_[schema_index].type = base::Value::TYPE_DICTIONARY; |
| 340 schema_nodes_[schema_index].extra = extra; | 221 schema_nodes_[schema_index].extra = extra; |
| 341 return schema_index; | 222 return schema_index; |
| 342 } | 223 } |
| 343 | 224 |
| 344 // static | 225 // static |
| 345 int SchemaOwner::InternalStorage::ParseList(const base::DictionaryValue& schema, | 226 int Schema::InternalStorage::ParseList(const base::DictionaryValue& schema, |
| 346 std::string* error) { | 227 std::string* error) { |
| 347 const base::DictionaryValue* dict = NULL; | 228 const base::DictionaryValue* dict = NULL; |
| 348 if (!schema.GetDictionary(json_schema_constants::kItems, &dict)) { | 229 if (!schema.GetDictionary(json_schema_constants::kItems, &dict)) { |
| 349 *error = "Arrays must declare a single schema for their items."; | 230 *error = "Arrays must declare a single schema for their items."; |
| 350 return kInvalid; | 231 return kInvalid; |
| 351 } | 232 } |
| 352 int extra = Parse(*dict, error); | 233 int extra = Parse(*dict, error); |
| 353 if (extra == kInvalid) | 234 if (extra == kInvalid) |
| 354 return kInvalid; | 235 return kInvalid; |
| 355 int index = static_cast<int>(schema_nodes_.size()); | 236 int index = static_cast<int>(schema_nodes_.size()); |
| 356 schema_nodes_.push_back(SchemaNode()); | 237 schema_nodes_.push_back(SchemaNode()); |
| 357 schema_nodes_[index].type = base::Value::TYPE_LIST; | 238 schema_nodes_[index].type = base::Value::TYPE_LIST; |
| 358 schema_nodes_[index].extra = extra; | 239 schema_nodes_[index].extra = extra; |
| 359 return index; | 240 return index; |
| 360 } | 241 } |
| 361 | 242 |
| 243 Schema::Iterator::Iterator(const scoped_refptr<const InternalStorage>& storage, |
| 244 const PropertiesNode* node) |
| 245 : storage_(storage), |
| 246 it_(storage->property(node->begin)), |
| 247 end_(storage->property(node->end)) {} |
| 248 |
| 249 Schema::Iterator::Iterator(const Iterator& iterator) |
| 250 : storage_(iterator.storage_), |
| 251 it_(iterator.it_), |
| 252 end_(iterator.end_) {} |
| 253 |
| 254 Schema::Iterator::~Iterator() {} |
| 255 |
| 256 Schema::Iterator& Schema::Iterator::operator=(const Iterator& iterator) { |
| 257 storage_ = iterator.storage_; |
| 258 it_ = iterator.it_; |
| 259 end_ = iterator.end_; |
| 260 return *this; |
| 261 } |
| 262 |
| 263 bool Schema::Iterator::IsAtEnd() const { |
| 264 return it_ == end_; |
| 265 } |
| 266 |
| 267 void Schema::Iterator::Advance() { |
| 268 ++it_; |
| 269 } |
| 270 |
| 271 const char* Schema::Iterator::key() const { |
| 272 return it_->key; |
| 273 } |
| 274 |
| 275 Schema Schema::Iterator::schema() const { |
| 276 return Schema(storage_, storage_->schema(it_->schema)); |
| 277 } |
| 278 |
| 279 Schema::Schema() : node_(NULL) {} |
| 280 |
| 281 Schema::Schema(const scoped_refptr<const InternalStorage>& storage, |
| 282 const SchemaNode* node) |
| 283 : storage_(storage), node_(node) {} |
| 284 |
| 285 Schema::Schema(const Schema& schema) |
| 286 : storage_(schema.storage_), node_(schema.node_) {} |
| 287 |
| 288 Schema::~Schema() {} |
| 289 |
| 290 Schema& Schema::operator=(const Schema& schema) { |
| 291 storage_ = schema.storage_; |
| 292 node_ = schema.node_; |
| 293 return *this; |
| 294 } |
| 295 |
| 296 // static |
| 297 Schema Schema::Wrap(const SchemaData* data) { |
| 298 scoped_refptr<const InternalStorage> storage = InternalStorage::Wrap(data); |
| 299 return Schema(storage, storage->root_node()); |
| 300 } |
| 301 |
| 302 // static |
| 303 Schema Schema::Parse(const std::string& content, std::string* error) { |
| 304 // Validate as a generic JSON schema. |
| 305 scoped_ptr<base::DictionaryValue> dict = |
| 306 JSONSchemaValidator::IsValidSchema(content, error); |
| 307 if (!dict) |
| 308 return Schema(); |
| 309 |
| 310 // Validate the main type. |
| 311 std::string string_value; |
| 312 if (!dict->GetString(json_schema_constants::kType, &string_value) || |
| 313 string_value != json_schema_constants::kObject) { |
| 314 *error = |
| 315 "The main schema must have a type attribute with \"object\" value."; |
| 316 return Schema(); |
| 317 } |
| 318 |
| 319 // Checks for invalid attributes at the top-level. |
| 320 if (dict->HasKey(json_schema_constants::kAdditionalProperties) || |
| 321 dict->HasKey(json_schema_constants::kPatternProperties)) { |
| 322 *error = "\"additionalProperties\" and \"patternProperties\" are not " |
| 323 "supported at the main schema."; |
| 324 return Schema(); |
| 325 } |
| 326 |
| 327 scoped_refptr<const InternalStorage> storage = |
| 328 InternalStorage::ParseSchema(*dict, error); |
| 329 if (!storage) |
| 330 return Schema(); |
| 331 return Schema(storage, storage->root_node()); |
| 332 } |
| 333 |
| 334 base::Value::Type Schema::type() const { |
| 335 CHECK(valid()); |
| 336 return node_->type; |
| 337 } |
| 338 |
| 339 Schema::Iterator Schema::GetPropertiesIterator() const { |
| 340 CHECK(valid()); |
| 341 CHECK_EQ(base::Value::TYPE_DICTIONARY, type()); |
| 342 return Iterator(storage_, storage_->properties(node_->extra)); |
| 343 } |
| 344 |
| 345 namespace { |
| 346 |
| 347 bool CompareKeys(const PropertyNode& node, const std::string& key) { |
| 348 return node.key < key; |
| 349 } |
| 350 |
| 351 } // namespace |
| 352 |
| 353 Schema Schema::GetKnownProperty(const std::string& key) const { |
| 354 CHECK(valid()); |
| 355 CHECK_EQ(base::Value::TYPE_DICTIONARY, type()); |
| 356 const PropertiesNode* node = storage_->properties(node_->extra); |
| 357 const PropertyNode* begin = storage_->property(node->begin); |
| 358 const PropertyNode* end = storage_->property(node->end); |
| 359 const PropertyNode* it = std::lower_bound(begin, end, key, CompareKeys); |
| 360 if (it != end && it->key == key) |
| 361 return Schema(storage_, storage_->schema(it->schema)); |
| 362 return Schema(); |
| 363 } |
| 364 |
| 365 Schema Schema::GetAdditionalProperties() const { |
| 366 CHECK(valid()); |
| 367 CHECK_EQ(base::Value::TYPE_DICTIONARY, type()); |
| 368 const PropertiesNode* node = storage_->properties(node_->extra); |
| 369 if (node->additional == kInvalid) |
| 370 return Schema(); |
| 371 return Schema(storage_, storage_->schema(node->additional)); |
| 372 } |
| 373 |
| 374 Schema Schema::GetProperty(const std::string& key) const { |
| 375 Schema schema = GetKnownProperty(key); |
| 376 return schema.valid() ? schema : GetAdditionalProperties(); |
| 377 } |
| 378 |
| 379 Schema Schema::GetItems() const { |
| 380 CHECK(valid()); |
| 381 CHECK_EQ(base::Value::TYPE_LIST, type()); |
| 382 if (node_->extra == kInvalid) |
| 383 return Schema(); |
| 384 return Schema(storage_, storage_->schema(node_->extra)); |
| 385 } |
| 386 |
| 362 } // namespace policy | 387 } // namespace policy |
| OLD | NEW |