OLD | NEW |
| (Empty) |
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 "chrome/browser/policy/schema_registry.h" | |
6 | |
7 #include "base/logging.h" | |
8 | |
9 namespace policy { | |
10 | |
11 SchemaRegistry::Observer::~Observer() {} | |
12 | |
13 SchemaRegistry::SchemaRegistry() : schema_map_(new SchemaMap) { | |
14 for (int i = 0; i < POLICY_DOMAIN_SIZE; ++i) | |
15 domains_ready_[i] = false; | |
16 #if !defined(ENABLE_EXTENSIONS) | |
17 domains_ready_[POLICY_DOMAIN_EXTENSIONS] = true; | |
18 #endif | |
19 } | |
20 | |
21 SchemaRegistry::~SchemaRegistry() {} | |
22 | |
23 void SchemaRegistry::RegisterComponent(const PolicyNamespace& ns, | |
24 const Schema& schema) { | |
25 ComponentMap map; | |
26 map[ns.component_id] = schema; | |
27 RegisterComponents(ns.domain, map); | |
28 } | |
29 | |
30 void SchemaRegistry::RegisterComponents(PolicyDomain domain, | |
31 const ComponentMap& components) { | |
32 // Assume that a schema was updated if the namespace was already registered | |
33 // before. | |
34 DomainMap map(schema_map_->GetDomains()); | |
35 for (ComponentMap::const_iterator it = components.begin(); | |
36 it != components.end(); ++it) { | |
37 map[domain][it->first] = it->second; | |
38 } | |
39 schema_map_ = new SchemaMap(map); | |
40 Notify(true); | |
41 } | |
42 | |
43 void SchemaRegistry::UnregisterComponent(const PolicyNamespace& ns) { | |
44 DomainMap map(schema_map_->GetDomains()); | |
45 if (map[ns.domain].erase(ns.component_id) != 0) { | |
46 schema_map_ = new SchemaMap(map); | |
47 Notify(false); | |
48 } else { | |
49 NOTREACHED(); | |
50 } | |
51 } | |
52 | |
53 bool SchemaRegistry::IsReady() const { | |
54 for (int i = 0; i < POLICY_DOMAIN_SIZE; ++i) { | |
55 if (!domains_ready_[i]) | |
56 return false; | |
57 } | |
58 return true; | |
59 } | |
60 | |
61 void SchemaRegistry::SetReady(PolicyDomain domain) { | |
62 if (domains_ready_[domain]) | |
63 return; | |
64 domains_ready_[domain] = true; | |
65 if (IsReady()) | |
66 FOR_EACH_OBSERVER(Observer, observers_, OnSchemaRegistryReady()); | |
67 } | |
68 | |
69 void SchemaRegistry::AddObserver(Observer* observer) { | |
70 observers_.AddObserver(observer); | |
71 } | |
72 | |
73 void SchemaRegistry::RemoveObserver(Observer* observer) { | |
74 observers_.RemoveObserver(observer); | |
75 } | |
76 | |
77 void SchemaRegistry::Notify(bool has_new_schemas) { | |
78 FOR_EACH_OBSERVER( | |
79 Observer, observers_, OnSchemaRegistryUpdated(has_new_schemas)); | |
80 } | |
81 | |
82 bool SchemaRegistry::HasObservers() const { | |
83 return observers_.might_have_observers(); | |
84 } | |
85 | |
86 CombinedSchemaRegistry::CombinedSchemaRegistry() | |
87 : own_schema_map_(new SchemaMap) { | |
88 // The combined registry is always ready, since it can always start tracking | |
89 // another registry that is not ready yet and going from "ready" to "not | |
90 // ready" is not allowed. | |
91 for (int i = 0; i < POLICY_DOMAIN_SIZE; ++i) | |
92 SetReady(static_cast<PolicyDomain>(i)); | |
93 } | |
94 | |
95 CombinedSchemaRegistry::~CombinedSchemaRegistry() {} | |
96 | |
97 void CombinedSchemaRegistry::Track(SchemaRegistry* registry) { | |
98 registries_.insert(registry); | |
99 registry->AddObserver(this); | |
100 // Recombine the maps only if the |registry| has any components other than | |
101 // POLICY_DOMAIN_CHROME. | |
102 if (registry->schema_map()->HasComponents()) | |
103 Combine(true); | |
104 } | |
105 | |
106 void CombinedSchemaRegistry::Untrack(SchemaRegistry* registry) { | |
107 registry->RemoveObserver(this); | |
108 if (registries_.erase(registry) != 0) { | |
109 if (registry->schema_map()->HasComponents()) | |
110 Combine(false); | |
111 } else { | |
112 NOTREACHED(); | |
113 } | |
114 } | |
115 | |
116 void CombinedSchemaRegistry::RegisterComponents( | |
117 PolicyDomain domain, | |
118 const ComponentMap& components) { | |
119 DomainMap map(own_schema_map_->GetDomains()); | |
120 for (ComponentMap::const_iterator it = components.begin(); | |
121 it != components.end(); ++it) { | |
122 map[domain][it->first] = it->second; | |
123 } | |
124 own_schema_map_ = new SchemaMap(map); | |
125 Combine(true); | |
126 } | |
127 | |
128 void CombinedSchemaRegistry::UnregisterComponent(const PolicyNamespace& ns) { | |
129 DomainMap map(own_schema_map_->GetDomains()); | |
130 if (map[ns.domain].erase(ns.component_id) != 0) { | |
131 own_schema_map_ = new SchemaMap(map); | |
132 Combine(false); | |
133 } else { | |
134 NOTREACHED(); | |
135 } | |
136 } | |
137 | |
138 void CombinedSchemaRegistry::OnSchemaRegistryUpdated(bool has_new_schemas) { | |
139 Combine(has_new_schemas); | |
140 } | |
141 | |
142 void CombinedSchemaRegistry::OnSchemaRegistryReady() { | |
143 // Ignore. | |
144 } | |
145 | |
146 void CombinedSchemaRegistry::Combine(bool has_new_schemas) { | |
147 // If two registries publish a Schema for the same component then it's | |
148 // undefined which version gets in the combined registry. | |
149 // | |
150 // The common case is that both registries want policy for the same component, | |
151 // and the Schemas should be the same; in that case this makes no difference. | |
152 // | |
153 // But if the Schemas are different then one of the components is out of date. | |
154 // In that case the policy loaded will be valid only for one of them, until | |
155 // the outdated components are updated. This is a known limitation of the | |
156 // way policies are loaded currently, but isn't a problem worth fixing for | |
157 // the time being. | |
158 DomainMap map(own_schema_map_->GetDomains()); | |
159 for (std::set<SchemaRegistry*>::const_iterator reg_it = registries_.begin(); | |
160 reg_it != registries_.end(); ++reg_it) { | |
161 const DomainMap& reg_domain_map = (*reg_it)->schema_map()->GetDomains(); | |
162 for (DomainMap::const_iterator domain_it = reg_domain_map.begin(); | |
163 domain_it != reg_domain_map.end(); ++domain_it) { | |
164 const ComponentMap& reg_component_map = domain_it->second; | |
165 for (ComponentMap::const_iterator comp_it = reg_component_map.begin(); | |
166 comp_it != reg_component_map.end(); ++comp_it) { | |
167 map[domain_it->first][comp_it->first] = comp_it->second; | |
168 } | |
169 } | |
170 } | |
171 schema_map_ = new SchemaMap(map); | |
172 Notify(has_new_schemas); | |
173 } | |
174 | |
175 } // namespace policy | |
OLD | NEW |