Update V8 to version 4.6.62.
[chromium-blink-merge.git] / components / policy / core / common / schema_registry.cc
bloba0b41052ec8d8d38bb170007edb55a7a4ab484a0
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.
5 #include "components/policy/core/common/schema_registry.h"
7 #include "base/logging.h"
9 namespace policy {
11 SchemaRegistry::Observer::~Observer() {}
13 SchemaRegistry::InternalObserver::~InternalObserver() {}
15 SchemaRegistry::SchemaRegistry() : schema_map_(new SchemaMap) {
16 for (int i = 0; i < POLICY_DOMAIN_SIZE; ++i)
17 domains_ready_[i] = false;
18 #if !defined(ENABLE_EXTENSIONS)
19 domains_ready_[POLICY_DOMAIN_EXTENSIONS] = true;
20 #endif
23 SchemaRegistry::~SchemaRegistry() {
24 FOR_EACH_OBSERVER(InternalObserver,
25 internal_observers_,
26 OnSchemaRegistryShuttingDown(this));
29 void SchemaRegistry::RegisterComponent(const PolicyNamespace& ns,
30 const Schema& schema) {
31 ComponentMap map;
32 map[ns.component_id] = schema;
33 RegisterComponents(ns.domain, map);
36 void SchemaRegistry::RegisterComponents(PolicyDomain domain,
37 const ComponentMap& components) {
38 // Don't issue notifications if nothing is being registered.
39 if (components.empty())
40 return;
41 // Assume that a schema was updated if the namespace was already registered
42 // before.
43 DomainMap map(schema_map_->GetDomains());
44 for (ComponentMap::const_iterator it = components.begin();
45 it != components.end(); ++it) {
46 map[domain][it->first] = it->second;
48 schema_map_ = new SchemaMap(map);
49 Notify(true);
52 void SchemaRegistry::UnregisterComponent(const PolicyNamespace& ns) {
53 DomainMap map(schema_map_->GetDomains());
54 if (map[ns.domain].erase(ns.component_id) != 0) {
55 schema_map_ = new SchemaMap(map);
56 Notify(false);
57 } else {
58 NOTREACHED();
62 bool SchemaRegistry::IsReady() const {
63 for (int i = 0; i < POLICY_DOMAIN_SIZE; ++i) {
64 if (!domains_ready_[i])
65 return false;
67 return true;
70 void SchemaRegistry::SetReady(PolicyDomain domain) {
71 if (domains_ready_[domain])
72 return;
73 domains_ready_[domain] = true;
74 if (IsReady())
75 FOR_EACH_OBSERVER(Observer, observers_, OnSchemaRegistryReady());
78 void SchemaRegistry::AddObserver(Observer* observer) {
79 observers_.AddObserver(observer);
82 void SchemaRegistry::RemoveObserver(Observer* observer) {
83 observers_.RemoveObserver(observer);
86 void SchemaRegistry::AddInternalObserver(InternalObserver* observer) {
87 internal_observers_.AddObserver(observer);
90 void SchemaRegistry::RemoveInternalObserver(InternalObserver* observer) {
91 internal_observers_.RemoveObserver(observer);
94 void SchemaRegistry::Notify(bool has_new_schemas) {
95 FOR_EACH_OBSERVER(
96 Observer, observers_, OnSchemaRegistryUpdated(has_new_schemas));
99 CombinedSchemaRegistry::CombinedSchemaRegistry()
100 : own_schema_map_(new SchemaMap) {
101 // The combined registry is always ready, since it can always start tracking
102 // another registry that is not ready yet and going from "ready" to "not
103 // ready" is not allowed.
104 for (int i = 0; i < POLICY_DOMAIN_SIZE; ++i)
105 SetReady(static_cast<PolicyDomain>(i));
108 CombinedSchemaRegistry::~CombinedSchemaRegistry() {}
110 void CombinedSchemaRegistry::Track(SchemaRegistry* registry) {
111 registries_.insert(registry);
112 registry->AddObserver(this);
113 registry->AddInternalObserver(this);
114 // Recombine the maps only if the |registry| has any components other than
115 // POLICY_DOMAIN_CHROME.
116 if (registry->schema_map()->HasComponents())
117 Combine(true);
120 void CombinedSchemaRegistry::RegisterComponents(
121 PolicyDomain domain,
122 const ComponentMap& components) {
123 DomainMap map(own_schema_map_->GetDomains());
124 for (ComponentMap::const_iterator it = components.begin();
125 it != components.end(); ++it) {
126 map[domain][it->first] = it->second;
128 own_schema_map_ = new SchemaMap(map);
129 Combine(true);
132 void CombinedSchemaRegistry::UnregisterComponent(const PolicyNamespace& ns) {
133 DomainMap map(own_schema_map_->GetDomains());
134 if (map[ns.domain].erase(ns.component_id) != 0) {
135 own_schema_map_ = new SchemaMap(map);
136 Combine(false);
137 } else {
138 NOTREACHED();
142 void CombinedSchemaRegistry::OnSchemaRegistryUpdated(bool has_new_schemas) {
143 Combine(has_new_schemas);
146 void CombinedSchemaRegistry::OnSchemaRegistryShuttingDown(
147 SchemaRegistry* registry) {
148 registry->RemoveObserver(this);
149 registry->RemoveInternalObserver(this);
150 if (registries_.erase(registry) != 0) {
151 if (registry->schema_map()->HasComponents())
152 Combine(false);
153 } else {
154 NOTREACHED();
158 void CombinedSchemaRegistry::Combine(bool has_new_schemas) {
159 // If two registries publish a Schema for the same component then it's
160 // undefined which version gets in the combined registry.
162 // The common case is that both registries want policy for the same component,
163 // and the Schemas should be the same; in that case this makes no difference.
165 // But if the Schemas are different then one of the components is out of date.
166 // In that case the policy loaded will be valid only for one of them, until
167 // the outdated components are updated. This is a known limitation of the
168 // way policies are loaded currently, but isn't a problem worth fixing for
169 // the time being.
170 DomainMap map(own_schema_map_->GetDomains());
171 for (std::set<SchemaRegistry*>::const_iterator reg_it = registries_.begin();
172 reg_it != registries_.end(); ++reg_it) {
173 const DomainMap& reg_domain_map = (*reg_it)->schema_map()->GetDomains();
174 for (DomainMap::const_iterator domain_it = reg_domain_map.begin();
175 domain_it != reg_domain_map.end(); ++domain_it) {
176 const ComponentMap& reg_component_map = domain_it->second;
177 for (ComponentMap::const_iterator comp_it = reg_component_map.begin();
178 comp_it != reg_component_map.end(); ++comp_it) {
179 map[domain_it->first][comp_it->first] = comp_it->second;
183 schema_map_ = new SchemaMap(map);
184 Notify(has_new_schemas);
187 ForwardingSchemaRegistry::ForwardingSchemaRegistry(SchemaRegistry* wrapped)
188 : wrapped_(wrapped) {
189 schema_map_ = wrapped_->schema_map();
190 wrapped_->AddObserver(this);
191 wrapped_->AddInternalObserver(this);
194 ForwardingSchemaRegistry::~ForwardingSchemaRegistry() {
195 if (wrapped_) {
196 wrapped_->RemoveObserver(this);
197 wrapped_->RemoveInternalObserver(this);
201 void ForwardingSchemaRegistry::RegisterComponents(
202 PolicyDomain domain,
203 const ComponentMap& components) {
204 // POLICY_DOMAIN_CHROME is skipped to avoid spurious updates when a new
205 // Profile is created. If the ForwardingSchemaRegistry is used outside
206 // device-level accounts then this should become configurable.
207 if (wrapped_ && domain != POLICY_DOMAIN_CHROME)
208 wrapped_->RegisterComponents(domain, components);
209 // Ignore otherwise.
212 void ForwardingSchemaRegistry::UnregisterComponent(const PolicyNamespace& ns) {
213 if (wrapped_)
214 wrapped_->UnregisterComponent(ns);
215 // Ignore otherwise.
218 void ForwardingSchemaRegistry::OnSchemaRegistryUpdated(bool has_new_schemas) {
219 schema_map_ = wrapped_->schema_map();
220 Notify(has_new_schemas);
223 void ForwardingSchemaRegistry::OnSchemaRegistryShuttingDown(
224 SchemaRegistry* registry) {
225 DCHECK_EQ(wrapped_, registry);
226 wrapped_->RemoveObserver(this);
227 wrapped_->RemoveInternalObserver(this);
228 wrapped_ = NULL;
229 // Keep serving the same |schema_map_|.
232 } // namespace policy