| 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 "chrome/browser/policy/registry_dict_win.h" | 5 #include "chrome/browser/policy/registry_dict_win.h" |
| 6 | 6 |
| 7 #include "base/json/json_reader.h" | 7 #include "base/json/json_reader.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| 11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 12 #include "base/sys_byteorder.h" | 12 #include "base/sys_byteorder.h" |
| 13 #include "base/values.h" | 13 #include "base/values.h" |
| 14 #include "base/win/registry.h" | 14 #include "base/win/registry.h" |
| 15 #include "components/json_schema/json_schema_constants.h" | 15 #include "components/json_schema/json_schema_constants.h" |
| 16 | 16 |
| 17 namespace schema = json_schema_constants; | 17 namespace schema = json_schema_constants; |
| 18 | 18 |
| 19 using base::win::RegistryKeyIterator; | 19 using base::win::RegistryKeyIterator; |
| 20 using base::win::RegistryValueIterator; | 20 using base::win::RegistryValueIterator; |
| 21 | 21 |
| 22 namespace policy { | 22 namespace policy { |
| 23 | 23 |
| 24 namespace { | 24 namespace { |
| 25 | 25 |
| 26 // Returns the entry with key |name| in |dictionary| (can be NULL), or NULL. | |
| 27 const base::DictionaryValue* GetEntry(const base::DictionaryValue* dictionary, | |
| 28 const std::string& name) { | |
| 29 if (!dictionary) | |
| 30 return NULL; | |
| 31 const base::DictionaryValue* entry = NULL; | |
| 32 dictionary->GetDictionaryWithoutPathExpansion(name, &entry); | |
| 33 return entry; | |
| 34 } | |
| 35 | |
| 36 // Returns the Value type described in |schema|, or |default_type| if not found. | 26 // Returns the Value type described in |schema|, or |default_type| if not found. |
| 37 base::Value::Type GetValueTypeForSchema(const base::DictionaryValue* schema, | 27 base::Value::Type GetValueTypeForSchema(const PolicySchema* schema, |
| 38 base::Value::Type default_type) { | 28 base::Value::Type default_type) { |
| 39 // JSON-schema types to base::Value::Type mapping. | |
| 40 static const struct { | |
| 41 // JSON schema type. | |
| 42 const char* schema_type; | |
| 43 // Correspondent value type. | |
| 44 base::Value::Type value_type; | |
| 45 } kSchemaToValueTypeMap[] = { | |
| 46 { schema::kArray, base::Value::TYPE_LIST }, | |
| 47 { schema::kBoolean, base::Value::TYPE_BOOLEAN }, | |
| 48 { schema::kInteger, base::Value::TYPE_INTEGER }, | |
| 49 { schema::kNull, base::Value::TYPE_NULL }, | |
| 50 { schema::kNumber, base::Value::TYPE_DOUBLE }, | |
| 51 { schema::kObject, base::Value::TYPE_DICTIONARY }, | |
| 52 { schema::kString, base::Value::TYPE_STRING }, | |
| 53 }; | |
| 54 | |
| 55 if (!schema) | 29 if (!schema) |
| 56 return default_type; | 30 return default_type; |
| 57 std::string type; | 31 return schema->type(); |
| 58 if (!schema->GetStringWithoutPathExpansion(schema::kType, &type)) | |
| 59 return default_type; | |
| 60 for (size_t i = 0; i < arraysize(kSchemaToValueTypeMap); ++i) { | |
| 61 if (type == kSchemaToValueTypeMap[i].schema_type) | |
| 62 return kSchemaToValueTypeMap[i].value_type; | |
| 63 } | |
| 64 return default_type; | |
| 65 } | 32 } |
| 66 | 33 |
| 67 // Returns the schema for property |name| given the |schema| of an object. | 34 // Returns the schema for property |name| given the |schema| of an object. |
| 68 // Returns the "additionalProperties" schema if no specific schema for | 35 // Returns the "additionalProperties" schema if no specific schema for |
| 69 // |name| is present. Returns NULL if no schema is found. | 36 // |name| is present. Returns NULL if no schema is found. |
| 70 const base::DictionaryValue* GetSchemaFor(const base::DictionaryValue* schema, | 37 const PolicySchema* GetSchemaFor(const PolicySchema* schema, |
| 71 const std::string& name) { | 38 const std::string& name) { |
| 72 const base::DictionaryValue* properties = | 39 if (!schema) |
| 73 GetEntry(schema, schema::kProperties); | 40 return NULL; |
| 74 const base::DictionaryValue* sub_schema = GetEntry(properties, name); | 41 const PolicySchema* sub_schema = schema->GetSchemaForProperty(name); |
| 75 if (sub_schema) | 42 if (sub_schema) |
| 76 return sub_schema; | 43 return sub_schema; |
| 77 // "additionalProperties" can be a boolean, but that case is ignored. | 44 // "additionalProperties" can be a boolean, but that case is ignored. |
| 78 return GetEntry(schema, schema::kAdditionalProperties); | 45 return schema->GetSchemaForAdditionalProperties(); |
| 79 } | 46 } |
| 80 | 47 |
| 81 // Converts a value (as read from the registry) to meet |schema|, converting | 48 // Converts a value (as read from the registry) to meet |schema|, converting |
| 82 // types as necessary. Unconvertible types will show up as NULL values in the | 49 // types as necessary. Unconvertible types will show up as NULL values in the |
| 83 // result. | 50 // result. |
| 84 scoped_ptr<base::Value> ConvertValue(const base::Value& value, | 51 scoped_ptr<base::Value> ConvertValue(const base::Value& value, |
| 85 const base::DictionaryValue* schema) { | 52 const PolicySchema* schema) { |
| 86 // Figure out the type to convert to from the schema. | 53 // Figure out the type to convert to from the schema. |
| 87 const base::Value::Type result_type( | 54 const base::Value::Type result_type( |
| 88 GetValueTypeForSchema(schema, value.GetType())); | 55 GetValueTypeForSchema(schema, value.GetType())); |
| 89 | 56 |
| 90 // If the type is good already, go with it. | 57 // If the type is good already, go with it. |
| 91 if (value.IsType(result_type)) { | 58 if (value.IsType(result_type)) { |
| 92 // Recurse for complex types if there is a schema. | 59 // Recurse for complex types if there is a schema. |
| 93 if (schema) { | 60 if (schema) { |
| 94 const base::DictionaryValue* dict = NULL; | 61 const base::DictionaryValue* dict = NULL; |
| 95 const base::ListValue* list = NULL; | 62 const base::ListValue* list = NULL; |
| 96 if (value.GetAsDictionary(&dict)) { | 63 if (value.GetAsDictionary(&dict)) { |
| 97 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue()); | 64 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue()); |
| 98 for (base::DictionaryValue::Iterator entry(*dict); !entry.IsAtEnd(); | 65 for (base::DictionaryValue::Iterator entry(*dict); !entry.IsAtEnd(); |
| 99 entry.Advance()) { | 66 entry.Advance()) { |
| 100 scoped_ptr<base::Value> converted_value( | 67 scoped_ptr<base::Value> converted_value( |
| 101 ConvertValue(entry.value(), GetSchemaFor(schema, entry.key()))); | 68 ConvertValue(entry.value(), GetSchemaFor(schema, entry.key()))); |
| 102 result->SetWithoutPathExpansion(entry.key(), | 69 result->SetWithoutPathExpansion(entry.key(), |
| 103 converted_value.release()); | 70 converted_value.release()); |
| 104 } | 71 } |
| 105 return result.Pass(); | 72 return result.Pass(); |
| 106 } else if (value.GetAsList(&list)) { | 73 } else if (value.GetAsList(&list)) { |
| 107 scoped_ptr<base::ListValue> result(new base::ListValue()); | 74 scoped_ptr<base::ListValue> result(new base::ListValue()); |
| 108 const base::DictionaryValue* item_schema = | 75 const PolicySchema* item_schema = schema->GetSchemaForItems(); |
| 109 GetEntry(schema, schema::kItems); | |
| 110 for (base::ListValue::const_iterator entry(list->begin()); | 76 for (base::ListValue::const_iterator entry(list->begin()); |
| 111 entry != list->end(); ++entry) { | 77 entry != list->end(); ++entry) { |
| 112 result->Append(ConvertValue(**entry, item_schema).release()); | 78 result->Append(ConvertValue(**entry, item_schema).release()); |
| 113 } | 79 } |
| 114 return result.Pass(); | 80 return result.Pass(); |
| 115 } | 81 } |
| 116 } | 82 } |
| 117 return make_scoped_ptr(value.DeepCopy()); | 83 return make_scoped_ptr(value.DeepCopy()); |
| 118 } | 84 } |
| 119 | 85 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 150 base::StringToDouble(string_value, &double_value)) { | 116 base::StringToDouble(string_value, &double_value)) { |
| 151 return make_scoped_ptr(base::Value::CreateDoubleValue(double_value)); | 117 return make_scoped_ptr(base::Value::CreateDoubleValue(double_value)); |
| 152 } | 118 } |
| 153 break; | 119 break; |
| 154 } | 120 } |
| 155 case base::Value::TYPE_LIST: { | 121 case base::Value::TYPE_LIST: { |
| 156 // Lists are encoded as subkeys with numbered value in the registry. | 122 // Lists are encoded as subkeys with numbered value in the registry. |
| 157 const base::DictionaryValue* dict = NULL; | 123 const base::DictionaryValue* dict = NULL; |
| 158 if (value.GetAsDictionary(&dict)) { | 124 if (value.GetAsDictionary(&dict)) { |
| 159 scoped_ptr<base::ListValue> result(new base::ListValue()); | 125 scoped_ptr<base::ListValue> result(new base::ListValue()); |
| 160 const base::DictionaryValue* item_schema = | 126 const PolicySchema* item_schema = schema->GetSchemaForItems(); |
| 161 GetEntry(schema, schema::kItems); | |
| 162 for (int i = 1; ; ++i) { | 127 for (int i = 1; ; ++i) { |
| 163 const base::Value* entry = NULL; | 128 const base::Value* entry = NULL; |
| 164 if (!dict->Get(base::IntToString(i), &entry)) | 129 if (!dict->Get(base::IntToString(i), &entry)) |
| 165 break; | 130 break; |
| 166 result->Append(ConvertValue(*entry, item_schema).release()); | 131 result->Append(ConvertValue(*entry, item_schema).release()); |
| 167 } | 132 } |
| 168 return result.Pass(); | 133 return result.Pass(); |
| 169 } | 134 } |
| 170 // Fall through in order to accept lists encoded as JSON strings. | 135 // Fall through in order to accept lists encoded as JSON strings. |
| 171 } | 136 } |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 // Recurse for all subkeys. | 306 // Recurse for all subkeys. |
| 342 for (RegistryKeyIterator it(hive, root.c_str()); it.Valid(); ++it) { | 307 for (RegistryKeyIterator it(hive, root.c_str()); it.Valid(); ++it) { |
| 343 std::string name(UTF16ToUTF8(it.Name())); | 308 std::string name(UTF16ToUTF8(it.Name())); |
| 344 scoped_ptr<RegistryDict> subdict(new RegistryDict()); | 309 scoped_ptr<RegistryDict> subdict(new RegistryDict()); |
| 345 subdict->ReadRegistry(hive, root + L"\\" + it.Name()); | 310 subdict->ReadRegistry(hive, root + L"\\" + it.Name()); |
| 346 SetKey(name, subdict.Pass()); | 311 SetKey(name, subdict.Pass()); |
| 347 } | 312 } |
| 348 } | 313 } |
| 349 | 314 |
| 350 scoped_ptr<base::Value> RegistryDict::ConvertToJSON( | 315 scoped_ptr<base::Value> RegistryDict::ConvertToJSON( |
| 351 const base::DictionaryValue* schema) const { | 316 const PolicySchema* schema) const { |
| 352 base::Value::Type type = | 317 base::Value::Type type = |
| 353 GetValueTypeForSchema(schema, base::Value::TYPE_DICTIONARY); | 318 GetValueTypeForSchema(schema, base::Value::TYPE_DICTIONARY); |
| 354 switch (type) { | 319 switch (type) { |
| 355 case base::Value::TYPE_DICTIONARY: { | 320 case base::Value::TYPE_DICTIONARY: { |
| 356 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue()); | 321 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue()); |
| 357 for (RegistryDict::ValueMap::const_iterator entry(values_.begin()); | 322 for (RegistryDict::ValueMap::const_iterator entry(values_.begin()); |
| 358 entry != values_.end(); ++entry) { | 323 entry != values_.end(); ++entry) { |
| 359 result->SetWithoutPathExpansion( | 324 result->SetWithoutPathExpansion( |
| 360 entry->first, | 325 entry->first, |
| 361 ConvertValue(*entry->second, | 326 ConvertValue(*entry->second, |
| 362 GetSchemaFor(schema, entry->first)).release()); | 327 GetSchemaFor(schema, entry->first)).release()); |
| 363 } | 328 } |
| 364 for (RegistryDict::KeyMap::const_iterator entry(keys_.begin()); | 329 for (RegistryDict::KeyMap::const_iterator entry(keys_.begin()); |
| 365 entry != keys_.end(); ++entry) { | 330 entry != keys_.end(); ++entry) { |
| 366 result->SetWithoutPathExpansion( | 331 result->SetWithoutPathExpansion( |
| 367 entry->first, | 332 entry->first, |
| 368 entry->second->ConvertToJSON( | 333 entry->second->ConvertToJSON( |
| 369 GetSchemaFor(schema, entry->first)).release()); | 334 GetSchemaFor(schema, entry->first)).release()); |
| 370 } | 335 } |
| 371 return result.Pass(); | 336 return result.Pass(); |
| 372 } | 337 } |
| 373 case base::Value::TYPE_LIST: { | 338 case base::Value::TYPE_LIST: { |
| 374 scoped_ptr<base::ListValue> result(new base::ListValue()); | 339 scoped_ptr<base::ListValue> result(new base::ListValue()); |
| 375 const base::DictionaryValue* item_schema = | 340 const PolicySchema* item_schema = schema->GetSchemaForItems(); |
| 376 GetEntry(schema, schema::kItems); | |
| 377 for (int i = 1; ; ++i) { | 341 for (int i = 1; ; ++i) { |
| 378 const std::string name(base::IntToString(i)); | 342 const std::string name(base::IntToString(i)); |
| 379 const RegistryDict* key = GetKey(name); | 343 const RegistryDict* key = GetKey(name); |
| 380 if (key) { | 344 if (key) { |
| 381 result->Append(key->ConvertToJSON(item_schema).release()); | 345 result->Append(key->ConvertToJSON(item_schema).release()); |
| 382 continue; | 346 continue; |
| 383 } | 347 } |
| 384 const base::Value* value = GetValue(name); | 348 const base::Value* value = GetValue(name); |
| 385 if (value) { | 349 if (value) { |
| 386 result->Append(ConvertValue(*value, item_schema).release()); | 350 result->Append(ConvertValue(*value, item_schema).release()); |
| 387 continue; | 351 continue; |
| 388 } | 352 } |
| 389 break; | 353 break; |
| 390 } | 354 } |
| 391 return result.Pass(); | 355 return result.Pass(); |
| 392 } | 356 } |
| 393 default: | 357 default: |
| 394 LOG(WARNING) << "Can't convert registry key to schema type " << type; | 358 LOG(WARNING) << "Can't convert registry key to schema type " << type; |
| 395 } | 359 } |
| 396 | 360 |
| 397 return make_scoped_ptr(base::Value::CreateNullValue()); | 361 return make_scoped_ptr(base::Value::CreateNullValue()); |
| 398 } | 362 } |
| 399 | 363 |
| 400 } // namespace policy | 364 } // namespace policy |
| OLD | NEW |