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"
11 SchemaRegistry::Observer::~Observer() {}
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;
21 SchemaRegistry::~SchemaRegistry() {}
23 void SchemaRegistry::RegisterComponent(const PolicyNamespace
& ns
,
24 const Schema
& schema
) {
26 map
[ns
.component_id
] = schema
;
27 RegisterComponents(ns
.domain
, map
);
30 void SchemaRegistry::RegisterComponents(PolicyDomain domain
,
31 const ComponentMap
& components
) {
32 // Don't issue notifications if nothing is being registered.
33 if (components
.empty())
35 // Assume that a schema was updated if the namespace was already registered
37 DomainMap
map(schema_map_
->GetDomains());
38 for (ComponentMap::const_iterator it
= components
.begin();
39 it
!= components
.end(); ++it
) {
40 map
[domain
][it
->first
] = it
->second
;
42 schema_map_
= new SchemaMap(map
);
46 void SchemaRegistry::UnregisterComponent(const PolicyNamespace
& ns
) {
47 DomainMap
map(schema_map_
->GetDomains());
48 if (map
[ns
.domain
].erase(ns
.component_id
) != 0) {
49 schema_map_
= new SchemaMap(map
);
56 bool SchemaRegistry::IsReady() const {
57 for (int i
= 0; i
< POLICY_DOMAIN_SIZE
; ++i
) {
58 if (!domains_ready_
[i
])
64 void SchemaRegistry::SetReady(PolicyDomain domain
) {
65 if (domains_ready_
[domain
])
67 domains_ready_
[domain
] = true;
69 FOR_EACH_OBSERVER(Observer
, observers_
, OnSchemaRegistryReady());
72 void SchemaRegistry::AddObserver(Observer
* observer
) {
73 observers_
.AddObserver(observer
);
76 void SchemaRegistry::RemoveObserver(Observer
* observer
) {
77 observers_
.RemoveObserver(observer
);
80 void SchemaRegistry::Notify(bool has_new_schemas
) {
82 Observer
, observers_
, OnSchemaRegistryUpdated(has_new_schemas
));
85 bool SchemaRegistry::HasObservers() const {
86 return observers_
.might_have_observers();
89 CombinedSchemaRegistry::CombinedSchemaRegistry()
90 : own_schema_map_(new SchemaMap
) {
91 // The combined registry is always ready, since it can always start tracking
92 // another registry that is not ready yet and going from "ready" to "not
93 // ready" is not allowed.
94 for (int i
= 0; i
< POLICY_DOMAIN_SIZE
; ++i
)
95 SetReady(static_cast<PolicyDomain
>(i
));
98 CombinedSchemaRegistry::~CombinedSchemaRegistry() {}
100 void CombinedSchemaRegistry::Track(SchemaRegistry
* registry
) {
101 registries_
.insert(registry
);
102 registry
->AddObserver(this);
103 // Recombine the maps only if the |registry| has any components other than
104 // POLICY_DOMAIN_CHROME.
105 if (registry
->schema_map()->HasComponents())
109 void CombinedSchemaRegistry::Untrack(SchemaRegistry
* registry
) {
110 registry
->RemoveObserver(this);
111 if (registries_
.erase(registry
) != 0) {
112 if (registry
->schema_map()->HasComponents())
119 void CombinedSchemaRegistry::RegisterComponents(
121 const ComponentMap
& components
) {
122 DomainMap
map(own_schema_map_
->GetDomains());
123 for (ComponentMap::const_iterator it
= components
.begin();
124 it
!= components
.end(); ++it
) {
125 map
[domain
][it
->first
] = it
->second
;
127 own_schema_map_
= new SchemaMap(map
);
131 void CombinedSchemaRegistry::UnregisterComponent(const PolicyNamespace
& ns
) {
132 DomainMap
map(own_schema_map_
->GetDomains());
133 if (map
[ns
.domain
].erase(ns
.component_id
) != 0) {
134 own_schema_map_
= new SchemaMap(map
);
141 void CombinedSchemaRegistry::OnSchemaRegistryUpdated(bool has_new_schemas
) {
142 Combine(has_new_schemas
);
145 void CombinedSchemaRegistry::OnSchemaRegistryReady() {
149 void CombinedSchemaRegistry::Combine(bool has_new_schemas
) {
150 // If two registries publish a Schema for the same component then it's
151 // undefined which version gets in the combined registry.
153 // The common case is that both registries want policy for the same component,
154 // and the Schemas should be the same; in that case this makes no difference.
156 // But if the Schemas are different then one of the components is out of date.
157 // In that case the policy loaded will be valid only for one of them, until
158 // the outdated components are updated. This is a known limitation of the
159 // way policies are loaded currently, but isn't a problem worth fixing for
161 DomainMap
map(own_schema_map_
->GetDomains());
162 for (std::set
<SchemaRegistry
*>::const_iterator reg_it
= registries_
.begin();
163 reg_it
!= registries_
.end(); ++reg_it
) {
164 const DomainMap
& reg_domain_map
= (*reg_it
)->schema_map()->GetDomains();
165 for (DomainMap::const_iterator domain_it
= reg_domain_map
.begin();
166 domain_it
!= reg_domain_map
.end(); ++domain_it
) {
167 const ComponentMap
& reg_component_map
= domain_it
->second
;
168 for (ComponentMap::const_iterator comp_it
= reg_component_map
.begin();
169 comp_it
!= reg_component_map
.end(); ++comp_it
) {
170 map
[domain_it
->first
][comp_it
->first
] = comp_it
->second
;
174 schema_map_
= new SchemaMap(map
);
175 Notify(has_new_schemas
);
178 } // namespace policy