Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: chrome/browser/policy/policy_loader_win.cc

Issue 22645011: policy: use JSON schema to deserialize entries from Windows registry. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix 3rd party policy unit tests Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <rpc.h> // For struct GUID 7 #include <rpc.h> // For struct GUID
8 #include <shlwapi.h> // For PathIsUNC() 8 #include <shlwapi.h> // For PathIsUNC()
9 #include <userenv.h> // For GPO functions 9 #include <userenv.h> // For GPO functions
10 #include <windows.h> 10 #include <windows.h>
11 11
12 #include <string> 12 #include <string>
13 #include <vector> 13 #include <vector>
14 14
15 // shlwapi.dll is required for PathIsUNC(). 15 // shlwapi.dll is required for PathIsUNC().
16 #pragma comment(lib, "shlwapi.lib") 16 #pragma comment(lib, "shlwapi.lib")
17 // userenv.dll is required for various GPO functions. 17 // userenv.dll is required for various GPO functions.
18 #pragma comment(lib, "userenv.lib") 18 #pragma comment(lib, "userenv.lib")
19 19
20 #include "base/basictypes.h" 20 #include "base/basictypes.h"
21 #include "base/file_util.h" 21 #include "base/file_util.h"
22 #include "base/json/json_reader.h" 22 #include "base/json/json_reader.h"
23 #include "base/lazy_instance.h" 23 #include "base/lazy_instance.h"
24 #include "base/logging.h" 24 #include "base/logging.h"
25 #include "base/message_loop/message_loop.h"
25 #include "base/scoped_native_library.h" 26 #include "base/scoped_native_library.h"
26 #include "base/sequenced_task_runner.h" 27 #include "base/sequenced_task_runner.h"
27 #include "base/stl_util.h" 28 #include "base/stl_util.h"
28 #include "base/strings/string16.h" 29 #include "base/strings/string16.h"
29 #include "base/strings/string_util.h" 30 #include "base/strings/string_util.h"
31 #include "chrome/browser/policy/browser_policy_connector.h"
30 #include "chrome/browser/policy/policy_bundle.h" 32 #include "chrome/browser/policy/policy_bundle.h"
33 #include "chrome/browser/policy/policy_domain_descriptor.h"
31 #include "chrome/browser/policy/policy_load_status.h" 34 #include "chrome/browser/policy/policy_load_status.h"
32 #include "chrome/browser/policy/policy_map.h" 35 #include "chrome/browser/policy/policy_map.h"
36 #include "chrome/browser/policy/policy_service.h"
33 #include "chrome/browser/policy/preg_parser_win.h" 37 #include "chrome/browser/policy/preg_parser_win.h"
34 #include "chrome/browser/policy/registry_dict_win.h" 38 #include "chrome/browser/policy/registry_dict_win.h"
35 #include "components/json_schema/json_schema_constants.h" 39 #include "components/json_schema/json_schema_constants.h"
36 #include "policy/policy_constants.h" 40 #include "policy/policy_constants.h"
37 41
38 namespace schema = json_schema_constants; 42 namespace schema = json_schema_constants;
39 43
40 namespace policy { 44 namespace policy {
41 45
42 namespace { 46 namespace {
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 185
182 NOTREACHED() << "Unsupported policy value type " << value_type; 186 NOTREACHED() << "Unsupported policy value type " << value_type;
183 return json_schema_constants::kNull; 187 return json_schema_constants::kNull;
184 } 188 }
185 189
186 // Parses |gpo_dict| according to |schema| and writes the resulting policy 190 // Parses |gpo_dict| according to |schema| and writes the resulting policy
187 // settings to |policy| for the given |scope| and |level|. 191 // settings to |policy| for the given |scope| and |level|.
188 void ParsePolicy(const RegistryDict* gpo_dict, 192 void ParsePolicy(const RegistryDict* gpo_dict,
189 PolicyLevel level, 193 PolicyLevel level,
190 PolicyScope scope, 194 PolicyScope scope,
191 const base::DictionaryValue* schema, 195 const PolicySchema* schema,
192 PolicyMap* policy) { 196 PolicyMap* policy) {
193 if (!gpo_dict) 197 if (!gpo_dict)
194 return; 198 return;
195 199
196 scoped_ptr<base::Value> policy_value(gpo_dict->ConvertToJSON(schema)); 200 scoped_ptr<base::Value> policy_value(gpo_dict->ConvertToJSON(schema));
197 const base::DictionaryValue* policy_dict = NULL; 201 const base::DictionaryValue* policy_dict = NULL;
198 if (!policy_value->GetAsDictionary(&policy_dict) || !policy_dict) { 202 if (!policy_value->GetAsDictionary(&policy_dict) || !policy_dict) {
199 LOG(WARNING) << "Root policy object is not a dictionary!"; 203 LOG(WARNING) << "Root policy object is not a dictionary!";
200 return; 204 return;
201 } 205 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 is_initialized_ = true; 254 is_initialized_ = true;
251 SetupWatches(); 255 SetupWatches();
252 } 256 }
253 257
254 scoped_ptr<PolicyBundle> PolicyLoaderWin::Load() { 258 scoped_ptr<PolicyBundle> PolicyLoaderWin::Load() {
255 // Reset the watches BEFORE reading the individual policies to avoid 259 // Reset the watches BEFORE reading the individual policies to avoid
256 // missing a change notification. 260 // missing a change notification.
257 if (is_initialized_) 261 if (is_initialized_)
258 SetupWatches(); 262 SetupWatches();
259 263
260 if (chrome_policy_schema_.empty())
261 BuildChromePolicySchema();
262
263 // Policy scope and corresponding hive. 264 // Policy scope and corresponding hive.
264 static const struct { 265 static const struct {
265 PolicyScope scope; 266 PolicyScope scope;
266 HKEY hive; 267 HKEY hive;
267 } kScopes[] = { 268 } kScopes[] = {
268 { POLICY_SCOPE_MACHINE, HKEY_LOCAL_MACHINE }, 269 { POLICY_SCOPE_MACHINE, HKEY_LOCAL_MACHINE },
269 { POLICY_SCOPE_USER, HKEY_CURRENT_USER }, 270 { POLICY_SCOPE_USER, HKEY_CURRENT_USER },
270 }; 271 };
271 272
272 // Load policy data for the different scopes/levels and merge them. 273 // Load policy data for the different scopes/levels and merge them.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 chrome_policy); 314 chrome_policy);
314 315
315 // Load 3rd-party policy. 316 // Load 3rd-party policy.
316 if (third_party_dict) 317 if (third_party_dict)
317 Load3rdPartyPolicy(third_party_dict.get(), scope, bundle.get()); 318 Load3rdPartyPolicy(third_party_dict.get(), scope, bundle.get());
318 } 319 }
319 320
320 return bundle.Pass(); 321 return bundle.Pass();
321 } 322 }
322 323
323 void PolicyLoaderWin::BuildChromePolicySchema() {
324 scoped_ptr<base::DictionaryValue> properties(new base::DictionaryValue());
325 for (const PolicyDefinitionList::Entry* e = policy_list_->begin;
326 e != policy_list_->end; ++e) {
327 const std::string schema_type = GetSchemaTypeForValueType(e->value_type);
328 scoped_ptr<base::DictionaryValue> entry_schema(new base::DictionaryValue());
329 entry_schema->SetStringWithoutPathExpansion(json_schema_constants::kType,
330 schema_type);
331
332 if (e->value_type == base::Value::TYPE_LIST) {
333 scoped_ptr<base::DictionaryValue> items_schema(
334 new base::DictionaryValue());
335 items_schema->SetStringWithoutPathExpansion(
336 json_schema_constants::kType, json_schema_constants::kString);
337 entry_schema->SetWithoutPathExpansion(json_schema_constants::kItems,
338 items_schema.release());
339 }
340 properties->SetWithoutPathExpansion(e->name, entry_schema.release());
341 }
342 chrome_policy_schema_.SetStringWithoutPathExpansion(
343 json_schema_constants::kType, json_schema_constants::kObject);
344 chrome_policy_schema_.SetWithoutPathExpansion(
345 json_schema_constants::kProperties, properties.release());
346 }
347
348 bool PolicyLoaderWin::ReadPRegFile(const base::FilePath& preg_file, 324 bool PolicyLoaderWin::ReadPRegFile(const base::FilePath& preg_file,
349 RegistryDict* policy, 325 RegistryDict* policy,
350 PolicyLoadStatusSample* status) { 326 PolicyLoadStatusSample* status) {
351 // The following deals with the minor annoyance that Wow64 FS redirection 327 // The following deals with the minor annoyance that Wow64 FS redirection
352 // might need to be turned off: This is the case if running as a 32-bit 328 // might need to be turned off: This is the case if running as a 32-bit
353 // process on a 64-bit system, in which case Wow64 FS redirection redirects 329 // process on a 64-bit system, in which case Wow64 FS redirection redirects
354 // access to the %WINDIR%/System32/GroupPolicy directory to 330 // access to the %WINDIR%/System32/GroupPolicy directory to
355 // %WINDIR%/SysWOW64/GroupPolicy, but the file is actually in the 331 // %WINDIR%/SysWOW64/GroupPolicy, but the file is actually in the
356 // system-native directory. 332 // system-native directory.
357 if (base::PathExists(preg_file)) { 333 if (base::PathExists(preg_file)) {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
438 } 414 }
439 415
440 return result; 416 return result;
441 } 417 }
442 418
443 void PolicyLoaderWin::LoadChromePolicy(const RegistryDict* gpo_dict, 419 void PolicyLoaderWin::LoadChromePolicy(const RegistryDict* gpo_dict,
444 PolicyLevel level, 420 PolicyLevel level,
445 PolicyScope scope, 421 PolicyScope scope,
446 PolicyMap* chrome_policy_map) { 422 PolicyMap* chrome_policy_map) {
447 PolicyMap policy; 423 PolicyMap policy;
448 ParsePolicy(gpo_dict, level, scope, &chrome_policy_schema_, &policy); 424 const PolicySchema* schema = NULL;
425 scoped_refptr<const PolicyDomainDescriptor> descriptor =
426 get_descriptor(POLICY_DOMAIN_CHROME);
427 if (descriptor)
428 schema = descriptor->get_schema("");
429 ParsePolicy(gpo_dict, level, scope, schema, &policy);
449 chrome_policy_map->MergeFrom(policy); 430 chrome_policy_map->MergeFrom(policy);
450 } 431 }
451 432
433 const PolicySchema* PolicyLoaderWin::Load3rdPartyPolicySchema(
434 PolicyDomain domain,
435 const std::string& component_key,
436 RegistryDict* component_dict) {
437
438 // Try to find the schema in the domain descriptor, if it exists.
439 scoped_refptr<const PolicyDomainDescriptor> descriptor =
440 get_descriptor(domain);
441 if (descriptor) {
442 const PolicySchema* schema =
443 descriptor->get_schema(domain + "//" + component_key);
444 if (schema)
445 return schema;
446 }
447
448 // Next, look in the registry entry.
449 // TODO(joaodasilva): Remove this for M31. http://crbug.com/240704
450 std::string schema_json;
451 const base::Value* schema_value = component_dict->GetValue(kKeySchema);
452 if (schema_value && schema_value->GetAsString(&schema_json)) {
453 std::string err;
454 PolicySchema* parsed_schema =
455 PolicySchema::Parse(schema_json, &err).release();
456 if (!parsed_schema) {
457 LOG(ERROR) << "Failed to parse 3rd-party policy schema for "
458 << domain << "/" << component_key << ": "
459 << err;
460 return NULL;
461 }
462 // We don't want to own the schema, but we need it around for the
463 // rest of this task to parse the policy value.
464 base::MessageLoop::current()->DeleteSoon(FROM_HERE, parsed_schema);
465 return parsed_schema;
466 }
467
468 return NULL;
469 }
470
452 void PolicyLoaderWin::Load3rdPartyPolicy(const RegistryDict* gpo_dict, 471 void PolicyLoaderWin::Load3rdPartyPolicy(const RegistryDict* gpo_dict,
453 PolicyScope scope, 472 PolicyScope scope,
454 PolicyBundle* bundle) { 473 PolicyBundle* bundle) {
455 // Map of known 3rd party policy domain name to their enum values. 474 // Map of known 3rd party policy domain name to their enum values.
456 static const struct { 475 static const struct {
457 const char* name; 476 const char* name;
458 PolicyDomain domain; 477 PolicyDomain domain;
459 } k3rdPartyDomains[] = { 478 } k3rdPartyDomains[] = {
460 { "extensions", POLICY_DOMAIN_EXTENSIONS }, 479 { "extensions", POLICY_DOMAIN_EXTENSIONS },
461 }; 480 };
(...skipping 12 matching lines...) Expand all
474 const PolicyDomain domain = k3rdPartyDomains[i].domain; 493 const PolicyDomain domain = k3rdPartyDomains[i].domain;
475 const RegistryDict* domain_dict = gpo_dict->GetKey(name); 494 const RegistryDict* domain_dict = gpo_dict->GetKey(name);
476 if (!domain_dict) 495 if (!domain_dict)
477 continue; 496 continue;
478 497
479 for (RegistryDict::KeyMap::const_iterator component( 498 for (RegistryDict::KeyMap::const_iterator component(
480 domain_dict->keys().begin()); 499 domain_dict->keys().begin());
481 component != domain_dict->keys().end(); 500 component != domain_dict->keys().end();
482 ++component) { 501 ++component) {
483 // Load the schema. 502 // Load the schema.
484 const base::DictionaryValue* schema_dict = NULL; 503 const PolicySchema* schema =
485 scoped_ptr<base::Value> schema; 504 Load3rdPartyPolicySchema(domain, component->first, component->second);
486 std::string schema_json;
487 const base::Value* schema_value = component->second->GetValue(kKeySchema);
488 if (schema_value && schema_value->GetAsString(&schema_json)) {
489 schema.reset(base::JSONReader::Read(schema_json));
490 if (!schema || !schema->GetAsDictionary(&schema_dict)) {
491 LOG(WARNING) << "Failed to parse 3rd-part policy schema for "
492 << domain << "/" << component->first;
493 }
494 }
495 505
496 // Parse policy. 506 // Parse policy.
497 for (size_t j = 0; j < arraysize(kLevels); j++) { 507 for (size_t j = 0; j < arraysize(kLevels); j++) {
498 const RegistryDict* policy_dict = 508 const RegistryDict* policy_dict =
499 component->second->GetKey(kLevels[j].path); 509 component->second->GetKey(kLevels[j].path);
500 if (!policy_dict) 510 if (!policy_dict)
501 continue; 511 continue;
502 512
503 PolicyMap policy; 513 PolicyMap policy;
504 ParsePolicy(policy_dict, kLevels[j].level, scope, schema_dict, &policy); 514 ParsePolicy(policy_dict, kLevels[j].level, scope, schema, &policy);
505 PolicyNamespace policy_namespace(domain, component->first); 515 PolicyNamespace policy_namespace(domain, component->first);
506 bundle->Get(policy_namespace).MergeFrom(policy); 516 bundle->Get(policy_namespace).MergeFrom(policy);
507 } 517 }
508 } 518 }
509 } 519 }
510 } 520 }
511 521
512 void PolicyLoaderWin::SetupWatches() { 522 void PolicyLoaderWin::SetupWatches() {
513 DCHECK(is_initialized_); 523 DCHECK(is_initialized_);
514 if (!user_policy_watcher_failed_ && 524 if (!user_policy_watcher_failed_ &&
(...skipping 14 matching lines...) Expand all
529 539
530 void PolicyLoaderWin::OnObjectSignaled(HANDLE object) { 540 void PolicyLoaderWin::OnObjectSignaled(HANDLE object) {
531 DCHECK(object == user_policy_changed_event_.handle() || 541 DCHECK(object == user_policy_changed_event_.handle() ||
532 object == machine_policy_changed_event_.handle()) 542 object == machine_policy_changed_event_.handle())
533 << "unexpected object signaled policy reload, obj = " 543 << "unexpected object signaled policy reload, obj = "
534 << std::showbase << std::hex << object; 544 << std::showbase << std::hex << object;
535 Reload(false); 545 Reload(false);
536 } 546 }
537 547
538 } // namespace policy 548 } // namespace policy
OLDNEW
« no previous file with comments | « chrome/browser/policy/policy_loader_win.h ('k') | chrome/browser/policy/policy_loader_win_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698