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 #include "components/policy/core/common/schema_map.h"
6
7 #include "base/logging.h"
8 #include "base/values.h"
9 #include "components/policy/core/common/policy_bundle.h"
10 #include "components/policy/core/common/policy_map.h"
11
12 namespace policy {
13
SchemaMap()14 SchemaMap::SchemaMap() {}
15
SchemaMap(DomainMap & map)16 SchemaMap::SchemaMap(DomainMap& map) {
17 map_.swap(map);
18 }
19
~SchemaMap()20 SchemaMap::~SchemaMap() {}
21
GetDomains() const22 const DomainMap& SchemaMap::GetDomains() const {
23 return map_;
24 }
25
GetComponents(PolicyDomain domain) const26 const ComponentMap* SchemaMap::GetComponents(PolicyDomain domain) const {
27 const auto it = map_.find(domain);
28 return it == map_.end() ? nullptr : &it->second;
29 }
30
GetSchema(const PolicyNamespace & ns) const31 const Schema* SchemaMap::GetSchema(const PolicyNamespace& ns) const {
32 const ComponentMap* map = GetComponents(ns.domain);
33 if (!map)
34 return nullptr;
35 const auto it = map->find(ns.component_id);
36 return it == map->end() ? nullptr : &it->second;
37 }
38
FilterBundle(PolicyBundle * bundle) const39 void SchemaMap::FilterBundle(PolicyBundle* bundle) const {
40 for (const auto& bundle_item : *bundle) {
41 const PolicyNamespace& ns = bundle_item.first;
42 const std::unique_ptr<PolicyMap>& policy_map = bundle_item.second;
43
44 // Chrome policies are not filtered, so that typos appear in about:policy.
45 // Everything else gets filtered, so that components only see valid policy.
46 if (ns.domain == POLICY_DOMAIN_CHROME)
47 continue;
48
49 const Schema* schema = GetSchema(ns);
50
51 if (!schema) {
52 policy_map->Clear();
53 continue;
54 }
55
56 if (!schema->valid()) {
57 // Don't serve unknown policies.
58 policy_map->Clear();
59 continue;
60 }
61
62 for (auto it_map = policy_map->begin(); it_map != policy_map->end();) {
63 const std::string& policy_name = it_map->first;
64 const base::Value* policy_value = it_map->second.value.get();
65 Schema policy_schema = schema->GetProperty(policy_name);
66 ++it_map;
67 std::string error_path;
68 std::string error;
69 if (!policy_value ||
70 !policy_schema.Validate(*policy_value,
71 SCHEMA_STRICT,
72 &error_path,
73 &error)) {
74 LOG(ERROR) << "Dropping policy " << policy_name << " of component "
75 << ns.component_id << " due to error at "
76 << (error_path.empty() ? "root" : error_path) << ": "
77 << error;
78 policy_map->Erase(policy_name);
79 }
80 }
81 }
82 }
83
HasComponents() const84 bool SchemaMap::HasComponents() const {
85 for (const auto& item : map_) {
86 const PolicyDomain& domain = item.first;
87 const ComponentMap& component_map = item.second;
88 if (domain == POLICY_DOMAIN_CHROME)
89 continue;
90 if (!component_map.empty())
91 return true;
92 }
93 return false;
94 }
95
GetChanges(const scoped_refptr<SchemaMap> & older,PolicyNamespaceList * removed,PolicyNamespaceList * added) const96 void SchemaMap::GetChanges(const scoped_refptr<SchemaMap>& older,
97 PolicyNamespaceList* removed,
98 PolicyNamespaceList* added) const {
99 GetNamespacesNotInOther(older.get(), added);
100 older->GetNamespacesNotInOther(this, removed);
101 }
102
GetNamespacesNotInOther(const SchemaMap * other,PolicyNamespaceList * list) const103 void SchemaMap::GetNamespacesNotInOther(const SchemaMap* other,
104 PolicyNamespaceList* list) const {
105 list->clear();
106 for (const auto& item : map_) {
107 const PolicyDomain& domain = item.first;
108 const ComponentMap& component_map = item.second;
109 for (const auto& comp : component_map) {
110 const std::string& component_id = comp.first;
111 const PolicyNamespace ns(domain, component_id);
112 if (!other->GetSchema(ns))
113 list->push_back(ns);
114 }
115 }
116 }
117
118 } // namespace policy
119