OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/policy_loader_win.h" | 5 #include "chrome/browser/policy/policy_loader_win.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include <string.h> | 9 #include <string.h> |
10 | 10 |
(...skipping 16 matching lines...) Expand all Loading... | |
27 #include "policy/policy_constants.h" | 27 #include "policy/policy_constants.h" |
28 | 28 |
29 using base::win::RegKey; | 29 using base::win::RegKey; |
30 using base::win::RegistryKeyIterator; | 30 using base::win::RegistryKeyIterator; |
31 using base::win::RegistryValueIterator; | 31 using base::win::RegistryValueIterator; |
32 | 32 |
33 namespace policy { | 33 namespace policy { |
34 | 34 |
35 namespace { | 35 namespace { |
36 | 36 |
37 // Path separator for registry keys. | |
38 const wchar_t kPathSep[] = L"\\"; | |
39 | |
37 // Suffix of kRegistryMandatorySubKey where 3rd party policies are stored. | 40 // Suffix of kRegistryMandatorySubKey where 3rd party policies are stored. |
38 const char k3rdPartyPolicySubKey[] = "\\3rdparty\\"; | 41 const char k3rdPartyPolicySubKey[] = "\\3rdparty\\"; |
39 | 42 |
40 // Path separator for registry keys. | 43 // Registry value that contains a component's schema. |
41 const wchar_t kPathSep[] = L"\\"; | 44 const wchar_t kSchema[] = L"schema"; |
45 | |
46 // Entry in a JSON schema that contains the expected type of an entry. | |
47 const char kType[] = "type"; | |
48 | |
49 // Entry in a JSON schema that describes the expected properties of an object. | |
50 const char kProperties[] = "properties"; | |
51 | |
52 // Entry in a JSON schema that describes the expected type of array elements. | |
53 const char kItems[] = "items"; | |
42 | 54 |
43 // Map of registry hives to their corresponding policy scope, in decreasing | 55 // Map of registry hives to their corresponding policy scope, in decreasing |
44 // order of priority. | 56 // order of priority. |
45 const struct { | 57 const struct { |
46 HKEY hive; | 58 HKEY hive; |
47 PolicyScope scope; | 59 PolicyScope scope; |
48 } kHives[] = { | 60 } kHives[] = { |
49 { HKEY_LOCAL_MACHINE, POLICY_SCOPE_MACHINE }, | 61 { HKEY_LOCAL_MACHINE, POLICY_SCOPE_MACHINE }, |
50 { HKEY_CURRENT_USER, POLICY_SCOPE_USER }, | 62 { HKEY_CURRENT_USER, POLICY_SCOPE_USER }, |
51 }; | 63 }; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
126 uint32* result) { | 138 uint32* result) { |
127 DWORD dword; | 139 DWORD dword; |
128 if (key->ReadValueDW(name.c_str(), &dword) != ERROR_SUCCESS) | 140 if (key->ReadValueDW(name.c_str(), &dword) != ERROR_SUCCESS) |
129 return false; | 141 return false; |
130 *result = dword; | 142 *result = dword; |
131 return true; | 143 return true; |
132 } | 144 } |
133 | 145 |
134 // Returns the Value for a Chrome string policy named |name|, or NULL if | 146 // Returns the Value for a Chrome string policy named |name|, or NULL if |
135 // it wasn't found. The caller owns the returned value. | 147 // it wasn't found. The caller owns the returned value. |
136 base::Value* ReadStringValue(const string16& name, | 148 base::Value* ReadChromeStringValue(const string16& name, |
137 PolicyLevel* level, | 149 PolicyLevel* level, |
138 PolicyScope* scope) { | 150 PolicyScope* scope) { |
139 RegKey key; | 151 RegKey key; |
140 if (!LoadHighestPriorityKey(string16(), name, &key, level, scope)) | 152 if (!LoadHighestPriorityKey(string16(), name, &key, level, scope)) |
141 return NULL; | 153 return NULL; |
142 string16 value; | 154 string16 value; |
143 if (!ReadRegistryString(&key, name, &value)) | 155 if (!ReadRegistryString(&key, name, &value)) |
144 return NULL; | 156 return NULL; |
145 return base::Value::CreateStringValue(value); | 157 return base::Value::CreateStringValue(value); |
146 } | 158 } |
147 | 159 |
148 // Returns the Value for a Chrome string list policy named |name|, | 160 // Returns the Value for a Chrome string list policy named |name|, |
149 // or NULL if it wasn't found. The caller owns the returned value. | 161 // or NULL if it wasn't found. The caller owns the returned value. |
150 base::Value* ReadStringListValue(const string16& name, | 162 base::Value* ReadChromeStringListValue(const string16& name, |
151 PolicyLevel* level, | 163 PolicyLevel* level, |
152 PolicyScope* scope) { | 164 PolicyScope* scope) { |
153 RegKey key; | 165 RegKey key; |
154 if (!LoadHighestPriorityKey(name, string16(), &key, level, scope)) | 166 if (!LoadHighestPriorityKey(name, string16(), &key, level, scope)) |
155 return NULL; | 167 return NULL; |
156 base::ListValue* result = new base::ListValue(); | 168 base::ListValue* result = new base::ListValue(); |
157 string16 value; | 169 string16 value; |
158 int index = 0; | 170 int index = 0; |
159 while (ReadRegistryString(&key, base::IntToString16(++index), &value)) | 171 while (ReadRegistryString(&key, base::IntToString16(++index), &value)) |
160 result->Append(base::Value::CreateStringValue(value)); | 172 result->Append(base::Value::CreateStringValue(value)); |
161 return result; | 173 return result; |
162 } | 174 } |
163 | 175 |
164 // Returns the Value for a Chrome boolean policy named |name|, | 176 // Returns the Value for a Chrome boolean policy named |name|, |
165 // or NULL if it wasn't found. The caller owns the returned value. | 177 // or NULL if it wasn't found. The caller owns the returned value. |
166 base::Value* ReadBooleanValue(const string16& name, | 178 base::Value* ReadChromeBooleanValue(const string16& name, |
167 PolicyLevel* level, | 179 PolicyLevel* level, |
168 PolicyScope* scope) { | 180 PolicyScope* scope) { |
169 RegKey key; | 181 RegKey key; |
170 if (!LoadHighestPriorityKey(string16(), name, &key, level, scope)) | 182 if (!LoadHighestPriorityKey(string16(), name, &key, level, scope)) |
171 return NULL; | 183 return NULL; |
172 uint32 value; | 184 uint32 value; |
173 if (!ReadRegistryInteger(&key, name, &value)) | 185 if (!ReadRegistryInteger(&key, name, &value)) |
174 return NULL; | 186 return NULL; |
175 return base::Value::CreateBooleanValue(value != 0u); | 187 return base::Value::CreateBooleanValue(value != 0u); |
176 } | 188 } |
177 | 189 |
178 // Returns the Value for a Chrome integer policy named |name|, | 190 // Returns the Value for a Chrome integer policy named |name|, |
179 // or NULL if it wasn't found. The caller owns the returned value. | 191 // or NULL if it wasn't found. The caller owns the returned value. |
180 base::Value* ReadIntegerValue(const string16& name, | 192 base::Value* ReadChromeIntegerValue(const string16& name, |
181 PolicyLevel* level, | 193 PolicyLevel* level, |
182 PolicyScope* scope) { | 194 PolicyScope* scope) { |
183 RegKey key; | 195 RegKey key; |
184 if (!LoadHighestPriorityKey(string16(), name, &key, level, scope)) | 196 if (!LoadHighestPriorityKey(string16(), name, &key, level, scope)) |
185 return NULL; | 197 return NULL; |
186 uint32 value; | 198 uint32 value; |
187 if (!ReadRegistryInteger(&key, name, &value)) | 199 if (!ReadRegistryInteger(&key, name, &value)) |
188 return NULL; | 200 return NULL; |
189 return base::Value::CreateIntegerValue(value); | 201 return base::Value::CreateIntegerValue(value); |
190 } | 202 } |
191 | 203 |
192 // Returns the Value for a Chrome dictionary policy named |name|, | 204 // Returns the Value for a Chrome dictionary policy named |name|, |
193 // or NULL if it wasn't found. The caller owns the returned value. | 205 // or NULL if it wasn't found. The caller owns the returned value. |
194 base::Value* ReadDictionaryValue(const string16& name, | 206 base::Value* ReadChromeDictionaryValue(const string16& name, |
195 PolicyLevel* level, | 207 PolicyLevel* level, |
196 PolicyScope* scope) { | 208 PolicyScope* scope) { |
197 // Dictionaries are encoded as JSON strings on Windows. | 209 // Dictionaries are encoded as JSON strings on Windows. |
198 // | 210 // |
199 // A dictionary could be stored as a subkey, with each of its entries | 211 // A dictionary could be stored as a subkey, with each of its entries |
200 // within that subkey. However, it would be impossible to recover the | 212 // within that subkey. However, it would be impossible to recover the |
201 // type for some of those entries: | 213 // type for some of those entries: |
202 // - Booleans are stored as DWORDS and are indistinguishable from | 214 // - Booleans are stored as DWORDS and are indistinguishable from |
203 // integers; | 215 // integers; |
204 // - Lists are stored as a subkey, with entries mapping 0 to N-1 to | 216 // - Lists are stored as a subkey, with entries mapping 0 to N-1 to |
205 // their value. This is indistinguishable from a Dictionary with | 217 // their value. This is indistinguishable from a Dictionary with |
206 // integer keys. | 218 // integer keys. |
207 // | 219 // |
208 // The GPO policy editor also has a limited data entry form that doesn't | 220 // The GPO policy editor also has a limited data entry form that doesn't |
209 // support dictionaries. | 221 // support dictionaries. |
210 RegKey key; | 222 RegKey key; |
211 if (!LoadHighestPriorityKey(string16(), name, &key, level, scope)) | 223 if (!LoadHighestPriorityKey(string16(), name, &key, level, scope)) |
212 return NULL; | 224 return NULL; |
213 string16 value; | 225 string16 value; |
214 if (!ReadRegistryString(&key, name, &value)) | 226 if (!ReadRegistryString(&key, name, &value)) |
215 return NULL; | 227 return NULL; |
216 return base::JSONReader::Read(UTF16ToUTF8(value)); | 228 return base::JSONReader::Read(UTF16ToUTF8(value)); |
217 } | 229 } |
218 | 230 |
219 // Loads the dictionary at |path| in the given |hive|. Ownership is transferred | 231 // Returns the Value type described in |schema|, or |default_type| if not found. |
220 // to the caller. | 232 base::Value::Type GetType(const base::DictionaryValue* schema, |
221 base::DictionaryValue* ReadRegistryDictionaryValue(HKEY hive, | 233 base::Value::Type default_type) { |
222 const string16& path) { | 234 // JSON-schema types to base::Value::Type mapping. |
235 static const struct { | |
236 // JSON schema type. | |
237 const char* schema_type; | |
238 // Correspondent value type. | |
239 base::Value::Type value_type; | |
240 } kSchemaToValueTypeMap[] = { | |
241 { "array", base::Value::TYPE_LIST }, | |
242 { "boolean", base::Value::TYPE_BOOLEAN }, | |
243 { "integer", base::Value::TYPE_INTEGER }, | |
244 { "null", base::Value::TYPE_NULL }, | |
245 { "number", base::Value::TYPE_DOUBLE }, | |
246 { "object", base::Value::TYPE_DICTIONARY }, | |
247 { "string", base::Value::TYPE_STRING }, | |
248 }; | |
249 | |
250 if (!schema) | |
251 return default_type; | |
252 std::string type; | |
253 if (!schema->GetString(kType, &type)) | |
254 return default_type; | |
255 for (size_t i = 0; i < arraysize(kSchemaToValueTypeMap); ++i) { | |
256 if (type == kSchemaToValueTypeMap[i].schema_type) | |
257 return kSchemaToValueTypeMap[i].value_type; | |
258 } | |
259 return default_type; | |
260 } | |
261 | |
262 // Returns the default type for registry entries of |reg_type|, when there is | |
263 // no schema defined type for a policy. | |
264 base::Value::Type GetDefaultFor(DWORD reg_type) { | |
265 return reg_type == REG_DWORD ? base::Value::TYPE_INTEGER : | |
266 base::Value::TYPE_STRING; | |
267 } | |
268 | |
269 // Returns the entry with key |name| in |dictionary| (can be NULL), or NULL. | |
270 base::DictionaryValue* GetEntry(const base::DictionaryValue* dictionary, | |
271 const std::string& name) { | |
272 if (!dictionary) | |
273 return NULL; | |
274 base::DictionaryValue* entry = NULL; | |
275 dictionary->GetDictionary(name, &entry); | |
276 return entry; | |
277 } | |
278 | |
279 // Converts string |value| to another |type|, if possible. | |
280 base::Value* ConvertComponentStringValue(const string16& value, | |
281 base::Value::Type type) { | |
282 switch (type) { | |
283 case base::Value::TYPE_DICTIONARY: | |
284 return base::JSONReader::Read(UTF16ToUTF8(value)); | |
285 | |
286 case base::Value::TYPE_NULL: | |
287 return base::Value::CreateNullValue(); | |
288 | |
289 case base::Value::TYPE_DOUBLE: { | |
290 double double_value; | |
291 if (base::StringToDouble(UTF16ToUTF8(value), &double_value)) | |
292 return base::Value::CreateDoubleValue(double_value); | |
293 DLOG(WARNING) << "Failed to read policy value as double: " << value; | |
294 return NULL; | |
295 } | |
296 | |
297 case base::Value::TYPE_STRING: | |
298 return base::Value::CreateStringValue(value); | |
299 | |
Mattias Nissler (ping if slow)
2012/06/27 12:07:17
what about TYPE_LIST and TYPE_INTEGER? Should they
Joao da Silva
2012/06/27 14:31:15
Sure, done. Also added a conversion to TYPE_BOOLEA
| |
300 default: | |
Mattias Nissler (ping if slow)
2012/06/27 12:07:17
I'd list the remaining enum constants here and rem
Joao da Silva
2012/06/27 14:31:15
Done.
| |
301 DLOG(WARNING) << "Cannot convert REG_SZ entry to type " << type; | |
302 return NULL; | |
303 } | |
304 } | |
305 | |
306 // Converts an integer |value| to another |type|, if possible. | |
307 base::Value* ConvertComponentIntegerValue(uint32 value, | |
308 base::Value::Type type) { | |
309 switch (type) { | |
310 case base::Value::TYPE_BOOLEAN: | |
311 return base::Value::CreateBooleanValue(value != 0); | |
312 | |
313 case base::Value::TYPE_DOUBLE: | |
314 return base::Value::CreateDoubleValue(value); | |
315 | |
316 case base::Value::TYPE_INTEGER: | |
317 return base::Value::CreateIntegerValue(value); | |
318 | |
319 default: | |
Mattias Nissler (ping if slow)
2012/06/27 12:07:17
same comment regarding remaining constants, defaul
Joao da Silva
2012/06/27 14:31:15
Done.
| |
320 DLOG(WARNING) << "Cannot convert REG_DWORD entry to type " << type; | |
321 return NULL; | |
322 } | |
323 } | |
324 | |
325 // Reads a simple (non-Dictionary, non-Array) value from the registry |key| | |
326 // named |name| with registry type |reg_type| as a value of type |type|. | |
327 // Returns NULL if the value could not be loaded or converted. | |
328 base::Value* ReadComponentSimpleValue(RegKey* key, | |
329 const string16& name, | |
330 DWORD reg_type, | |
331 base::Value::Type type) { | |
332 switch (reg_type) { | |
333 case REG_SZ: { | |
334 string16 value; | |
335 if (ReadRegistryString(key, name, &value)) | |
336 return ConvertComponentStringValue(value, type); | |
337 break; | |
338 } | |
339 | |
340 case REG_DWORD: { | |
341 uint32 value; | |
342 if (ReadRegistryInteger(key, name, &value)) | |
343 return ConvertComponentIntegerValue(value, type); | |
344 break; | |
345 } | |
346 | |
347 default: | |
348 DLOG(WARNING) << "Registry type not supported for key " << name; | |
349 break; | |
350 } | |
351 NOTREACHED(); | |
352 return NULL; | |
353 } | |
354 | |
355 // Forward declaration for ReadComponentListValue(). | |
356 base::DictionaryValue* ReadComponentDictionaryValue( | |
357 HKEY hive, | |
358 const string16& path, | |
359 const base::DictionaryValue* schema); | |
360 | |
361 // Loads the list at |path| in the given |hive|. |schema| is a JSON schema | |
362 // (http://json-schema.org/) that describes the expected type of the list's | |
363 // elements. Ownership of the result is transferred to the caller. | |
364 base::ListValue* ReadComponentListValue(HKEY hive, | |
365 const string16& path, | |
366 const base::DictionaryValue* schema) { | |
367 // The sub-elements are indexed from 1 to N. They can be represented as | |
368 // registry values or registry keys though; use |schema| first to try to | |
369 // determine the right type, and if that fails default to STRING. | |
370 | |
371 RegKey key(hive, path.c_str(), KEY_READ); | |
372 if (!key.Valid()) | |
373 return NULL; | |
374 | |
375 base::Value::Type type = GetType(schema, base::Value::TYPE_STRING); | |
376 base::ListValue* list = new base::ListValue(); | |
377 for (int i = 1; ; ++i) { | |
378 string16 name = base::IntToString16(i); | |
379 base::Value* value = NULL; | |
380 base::DictionaryValue* sub_schema = NULL; | |
381 if (type == base::Value::TYPE_DICTIONARY) { | |
382 value = ReadComponentDictionaryValue(hive, path + kPathSep + name, | |
383 GetEntry(schema, kProperties)); | |
384 } else if (type == base::Value::TYPE_LIST) { | |
385 value = ReadComponentListValue(hive, path + kPathSep + name, | |
386 GetEntry(schema, kItems)); | |
387 } else { | |
388 DWORD reg_type; | |
389 key.ReadValue(name.c_str(), NULL, NULL, ®_type); | |
390 value = ReadComponentSimpleValue(&key, name, reg_type, type); | |
391 } | |
392 if (!value) | |
393 break; | |
394 list->Append(value); | |
395 } | |
396 return list; | |
397 } | |
398 | |
399 // Loads the dictionary at |path| in the given |hive|. |schema| is a JSON | |
400 // schema (http://json-schema.org/) that describes the expected types for the | |
401 // dictionary entries. When the type for a certain entry isn't described in the | |
402 // schema, a default conversion takes place. |schema| can be NULL. | |
403 // Ownership of the result is transferred to the caller. | |
404 base::DictionaryValue* ReadComponentDictionaryValue( | |
405 HKEY hive, | |
406 const string16& path, | |
407 const base::DictionaryValue* schema) { | |
223 // A "value" in the registry is like a file in a filesystem, and a "key" is | 408 // A "value" in the registry is like a file in a filesystem, and a "key" is |
224 // like a directory, that contains other "values" and "keys". | 409 // like a directory, that contains other "values" and "keys". |
225 // Unfortunately it is possible to have a name both as a "value" and a "key". | 410 // Unfortunately it is possible to have a name both as a "value" and a "key". |
226 // In those cases, the sub "key" will be ignored; this choice is arbitrary. | 411 // In those cases, the sub "key" will be ignored; this choice is arbitrary. |
227 | 412 |
228 // First iterate over all the "values" in |path| and convert them; then | 413 // First iterate over all the "values" in |path| and convert them; then |
229 // recurse into each "key" in |path| and convert them as dictionaries. | 414 // recurse into each "key" in |path| and convert them as dictionaries. |
230 | 415 |
416 RegKey key(hive, path.c_str(), KEY_READ); | |
417 if (!key.Valid()) | |
418 return NULL; | |
419 | |
231 base::DictionaryValue* dict = new base::DictionaryValue(); | 420 base::DictionaryValue* dict = new base::DictionaryValue(); |
232 RegKey key(hive, path.c_str(), KEY_READ); | |
233 | |
234 for (RegistryValueIterator it(hive, path.c_str()); it.Valid(); ++it) { | 421 for (RegistryValueIterator it(hive, path.c_str()); it.Valid(); ++it) { |
235 string16 name(it.Name()); | 422 string16 name16(it.Name()); |
236 switch (it.Type()) { | 423 std::string name(UTF16ToUTF8(name16)); |
237 case REG_SZ: { | 424 const base::DictionaryValue* sub_schema = GetEntry(schema, name); |
Mattias Nissler (ping if slow)
2012/06/27 12:07:17
What about the case of a dictionary with arbitrary
Joao da Silva
2012/06/27 14:31:15
Great idea, and json-schema even has something for
| |
238 string16 value; | 425 base::Value::Type type = GetType(sub_schema, GetDefaultFor(it.Type())); |
239 if (ReadRegistryString(&key, name, &value)) | 426 base::Value* value = |
240 dict->SetString(UTF16ToUTF8(name), value); | 427 ReadComponentSimpleValue(&key, name16, it.Type(), type); |
Mattias Nissler (ping if slow)
2012/06/27 12:07:17
Why can't this be an encoded dictionary or list?
Joao da Silva
2012/06/27 14:31:15
Because we're using a RegistryValueIterator, so th
| |
241 break; | 428 if (value) |
242 } | 429 dict->Set(name, value); |
243 | |
244 case REG_DWORD: { | |
245 uint32 value; | |
246 if (ReadRegistryInteger(&key, name, &value)) | |
247 dict->SetInteger(UTF16ToUTF8(name), value); | |
248 break; | |
249 } | |
250 | |
251 default: | |
252 // TODO(joaodasilva): use a schema to determine the correct types. | |
253 LOG(WARNING) << "Ignoring registry value with unsupported type: " | |
254 << path << kPathSep << name; | |
255 } | |
256 } | 430 } |
257 | 431 |
258 for (RegistryKeyIterator it(hive, path.c_str()); it.Valid(); ++it) { | 432 for (RegistryKeyIterator it(hive, path.c_str()); it.Valid(); ++it) { |
259 string16 name16(it.Name()); | 433 string16 name16(it.Name()); |
260 std::string name(UTF16ToUTF8(name16)); | 434 std::string name(UTF16ToUTF8(name16)); |
261 if (dict->HasKey(name)) { | 435 if (dict->HasKey(name)) { |
262 LOG(WARNING) << "Ignoring registry key because a value exists with the " | 436 DLOG(WARNING) << "Ignoring registry key because a value exists with the " |
263 "same name: " << path << kPathSep << name; | 437 "same name: " << path << kPathSep << name; |
264 continue; | 438 continue; |
265 } | 439 } |
266 base::DictionaryValue* value = | 440 |
267 ReadRegistryDictionaryValue(hive, path + kPathSep + name16); | 441 base::DictionaryValue* sub_schema = GetEntry(schema, name); |
442 base::Value::Type type = GetType(sub_schema, base::Value::TYPE_DICTIONARY); | |
443 base::Value* value = NULL; | |
444 const string16 sub_path = path + kPathSep + name16; | |
445 if (type == base::Value::TYPE_DICTIONARY) { | |
446 sub_schema = GetEntry(sub_schema, kProperties); | |
447 value = ReadComponentDictionaryValue(hive, sub_path, sub_schema); | |
448 } else if (type == base::Value::TYPE_LIST) { | |
449 sub_schema = GetEntry(sub_schema, kItems); | |
450 value = ReadComponentListValue(hive, sub_path, sub_schema); | |
451 } else { | |
452 DLOG(WARNING) << "Can't read a simple type in registry key at " << path; | |
453 } | |
268 if (value) | 454 if (value) |
269 dict->Set(name, value); | 455 dict->Set(name, value); |
270 } | 456 } |
271 | 457 |
272 return dict; | 458 return dict; |
273 } | 459 } |
274 | 460 |
461 // Reads a JSON schema from the given |registry_value|, at the given | |
462 // |registry_key| in |hive|. |registry_value| must be a string (REG_SZ), and | |
463 // is decoded as JSON data. Returns NULL on failure. Ownership is transferred | |
464 // to the caller. | |
465 base::DictionaryValue* ReadRegistrySchema(HKEY hive, | |
466 const string16& registry_key, | |
467 const string16& registry_value) { | |
468 RegKey key(hive, registry_key.c_str(), KEY_READ); | |
469 string16 schema; | |
470 if (!ReadRegistryString(&key, registry_value, &schema)) | |
471 return NULL; | |
472 // A JSON schema is represented in JSON too. | |
473 scoped_ptr<base::Value> value(base::JSONReader::Read(UTF16ToUTF8(schema))); | |
474 if (!value.get()) | |
475 return NULL; | |
476 base::DictionaryValue* dict = NULL; | |
477 if (!value->GetAsDictionary(&dict)) | |
478 return NULL; | |
479 // The top-level entry must be an object, and each of its properties maps | |
480 // a policy name to its schema. | |
481 if (GetType(dict, base::Value::TYPE_DICTIONARY) != | |
482 base::Value::TYPE_DICTIONARY) { | |
483 DLOG(WARNING) << "schema top-level type isn't \"object\""; | |
484 return NULL; | |
485 } | |
486 base::DictionaryValue* properties = GetEntry(dict, kProperties); | |
487 if (!properties) | |
488 return NULL; | |
489 value.release(); | |
490 return properties; | |
491 } | |
492 | |
275 } // namespace | 493 } // namespace |
276 | 494 |
277 PolicyLoaderWin::PolicyLoaderWin(const PolicyDefinitionList* policy_list) | 495 PolicyLoaderWin::PolicyLoaderWin(const PolicyDefinitionList* policy_list) |
278 : is_initialized_(false), | 496 : is_initialized_(false), |
279 policy_list_(policy_list), | 497 policy_list_(policy_list), |
280 user_policy_changed_event_(false, false), | 498 user_policy_changed_event_(false, false), |
281 machine_policy_changed_event_(false, false), | 499 machine_policy_changed_event_(false, false), |
282 user_policy_watcher_failed_(false), | 500 user_policy_watcher_failed_(false), |
283 machine_policy_watcher_failed_(false) { | 501 machine_policy_watcher_failed_(false) { |
284 if (!RegisterGPNotification(user_policy_changed_event_.handle(), false)) { | 502 if (!RegisterGPNotification(user_policy_changed_event_.handle(), false)) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
316 | 534 |
317 const PolicyDefinitionList::Entry* current; | 535 const PolicyDefinitionList::Entry* current; |
318 for (current = policy_list_->begin; current != policy_list_->end; ++current) { | 536 for (current = policy_list_->begin; current != policy_list_->end; ++current) { |
319 const string16 name(ASCIIToUTF16(current->name)); | 537 const string16 name(ASCIIToUTF16(current->name)); |
320 PolicyLevel level = POLICY_LEVEL_MANDATORY; | 538 PolicyLevel level = POLICY_LEVEL_MANDATORY; |
321 PolicyScope scope = POLICY_SCOPE_MACHINE; | 539 PolicyScope scope = POLICY_SCOPE_MACHINE; |
322 base::Value* value = NULL; | 540 base::Value* value = NULL; |
323 | 541 |
324 switch (current->value_type) { | 542 switch (current->value_type) { |
325 case base::Value::TYPE_STRING: | 543 case base::Value::TYPE_STRING: |
326 value = ReadStringValue(name, &level, &scope); | 544 value = ReadChromeStringValue(name, &level, &scope); |
327 break; | 545 break; |
328 | 546 |
329 case base::Value::TYPE_LIST: | 547 case base::Value::TYPE_LIST: |
330 value = ReadStringListValue(name, &level, &scope); | 548 value = ReadChromeStringListValue(name, &level, &scope); |
331 break; | 549 break; |
332 | 550 |
333 case base::Value::TYPE_BOOLEAN: | 551 case base::Value::TYPE_BOOLEAN: |
334 value = ReadBooleanValue(name, &level, &scope); | 552 value = ReadChromeBooleanValue(name, &level, &scope); |
335 break; | 553 break; |
336 | 554 |
337 case base::Value::TYPE_INTEGER: | 555 case base::Value::TYPE_INTEGER: |
338 value = ReadIntegerValue(name, &level, &scope); | 556 value = ReadChromeIntegerValue(name, &level, &scope); |
339 break; | 557 break; |
340 | 558 |
341 case base::Value::TYPE_DICTIONARY: | 559 case base::Value::TYPE_DICTIONARY: |
342 value = ReadDictionaryValue(name, &level, &scope); | 560 value = ReadChromeDictionaryValue(name, &level, &scope); |
343 break; | 561 break; |
344 | 562 |
345 default: | 563 default: |
346 NOTREACHED(); | 564 NOTREACHED(); |
347 } | 565 } |
348 | 566 |
349 if (value) | 567 if (value) |
350 chrome_policies->Set(current->name, level, scope, value); | 568 chrome_policies->Set(current->name, level, scope, value); |
351 } | 569 } |
352 } | 570 } |
(...skipping 30 matching lines...) Expand all Loading... | |
383 for (size_t d = 0; d < arraysize(kDomains); ++d) { | 601 for (size_t d = 0; d < arraysize(kDomains); ++d) { |
384 // Each subkey under this domain is a component of that domain. | 602 // Each subkey under this domain is a component of that domain. |
385 // |domain_path| == SOFTWARE\Policies\Chromium\3rdparty\<domain> | 603 // |domain_path| == SOFTWARE\Policies\Chromium\3rdparty\<domain> |
386 string16 domain_path = kPathPrefix + ASCIIToUTF16(kDomains[d].name); | 604 string16 domain_path = kPathPrefix + ASCIIToUTF16(kDomains[d].name); |
387 | 605 |
388 for (RegistryKeyIterator domain_iterator(hkey, domain_path.c_str()); | 606 for (RegistryKeyIterator domain_iterator(hkey, domain_path.c_str()); |
389 domain_iterator.Valid(); ++domain_iterator) { | 607 domain_iterator.Valid(); ++domain_iterator) { |
390 string16 component(domain_iterator.Name()); | 608 string16 component(domain_iterator.Name()); |
391 string16 component_path = domain_path + kPathSep + component; | 609 string16 component_path = domain_path + kPathSep + component; |
392 | 610 |
611 // Load the schema for this component's policy, if present. | |
612 scoped_ptr<base::DictionaryValue> schema( | |
613 ReadRegistrySchema(hkey, component_path, kSchema)); | |
614 | |
393 for (size_t k = 0; k < arraysize(kKeyPaths); ++k) { | 615 for (size_t k = 0; k < arraysize(kKeyPaths); ++k) { |
394 string16 path = | 616 string16 path = |
395 component_path + kPathSep + ASCIIToUTF16(kKeyPaths[k].path); | 617 component_path + kPathSep + ASCIIToUTF16(kKeyPaths[k].path); |
396 | 618 |
397 scoped_ptr<base::DictionaryValue> dictionary( | 619 scoped_ptr<base::DictionaryValue> dictionary( |
398 ReadRegistryDictionaryValue(hkey, path)); | 620 ReadComponentDictionaryValue(hkey, path, schema.get())); |
399 if (dictionary.get()) { | 621 if (dictionary.get()) { |
400 PolicyMap policies; | 622 PolicyMap policies; |
401 policies.LoadFrom( | 623 policies.LoadFrom( |
402 dictionary.get(), kKeyPaths[k].level, kHives[h].scope); | 624 dictionary.get(), kKeyPaths[k].level, kHives[h].scope); |
403 // LoadFrom() overwrites any existing values. Use a temporary map | 625 // LoadFrom() overwrites any existing values. Use a temporary map |
404 // and then use MergeFrom(), that only overwrites values with lower | 626 // and then use MergeFrom(), that only overwrites values with lower |
405 // priority. | 627 // priority. |
406 bundle->Get(kDomains[d].domain, UTF16ToUTF8(component)) | 628 bundle->Get(kDomains[d].domain, UTF16ToUTF8(component)) |
407 .MergeFrom(policies); | 629 .MergeFrom(policies); |
408 } | 630 } |
(...skipping 23 matching lines...) Expand all Loading... | |
432 | 654 |
433 void PolicyLoaderWin::OnObjectSignaled(HANDLE object) { | 655 void PolicyLoaderWin::OnObjectSignaled(HANDLE object) { |
434 DCHECK(object == user_policy_changed_event_.handle() || | 656 DCHECK(object == user_policy_changed_event_.handle() || |
435 object == machine_policy_changed_event_.handle()) | 657 object == machine_policy_changed_event_.handle()) |
436 << "unexpected object signaled policy reload, obj = " | 658 << "unexpected object signaled policy reload, obj = " |
437 << std::showbase << std::hex << object; | 659 << std::showbase << std::hex << object; |
438 Reload(false); | 660 Reload(false); |
439 } | 661 } |
440 | 662 |
441 } // namespace policy | 663 } // namespace policy |
OLD | NEW |