schema_registry.cc revision f2477e01787aa58f445919b809d89e252beef54f
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_registry.h" 6 7#include "base/logging.h" 8 9namespace policy { 10 11SchemaRegistry::Observer::~Observer() {} 12 13SchemaRegistry::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 21SchemaRegistry::~SchemaRegistry() {} 22 23void 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 30void SchemaRegistry::RegisterComponents(PolicyDomain domain, 31 const ComponentMap& components) { 32 // Don't issue notifications if nothing is being registered. 33 if (components.empty()) 34 return; 35 // Assume that a schema was updated if the namespace was already registered 36 // before. 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; 41 } 42 schema_map_ = new SchemaMap(map); 43 Notify(true); 44} 45 46void 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); 50 Notify(false); 51 } else { 52 NOTREACHED(); 53 } 54} 55 56bool SchemaRegistry::IsReady() const { 57 for (int i = 0; i < POLICY_DOMAIN_SIZE; ++i) { 58 if (!domains_ready_[i]) 59 return false; 60 } 61 return true; 62} 63 64void SchemaRegistry::SetReady(PolicyDomain domain) { 65 if (domains_ready_[domain]) 66 return; 67 domains_ready_[domain] = true; 68 if (IsReady()) 69 FOR_EACH_OBSERVER(Observer, observers_, OnSchemaRegistryReady()); 70} 71 72void SchemaRegistry::AddObserver(Observer* observer) { 73 observers_.AddObserver(observer); 74} 75 76void SchemaRegistry::RemoveObserver(Observer* observer) { 77 observers_.RemoveObserver(observer); 78} 79 80void SchemaRegistry::Notify(bool has_new_schemas) { 81 FOR_EACH_OBSERVER( 82 Observer, observers_, OnSchemaRegistryUpdated(has_new_schemas)); 83} 84 85bool SchemaRegistry::HasObservers() const { 86 return observers_.might_have_observers(); 87} 88 89CombinedSchemaRegistry::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)); 96} 97 98CombinedSchemaRegistry::~CombinedSchemaRegistry() {} 99 100void 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()) 106 Combine(true); 107} 108 109void CombinedSchemaRegistry::Untrack(SchemaRegistry* registry) { 110 registry->RemoveObserver(this); 111 if (registries_.erase(registry) != 0) { 112 if (registry->schema_map()->HasComponents()) 113 Combine(false); 114 } else { 115 NOTREACHED(); 116 } 117} 118 119void CombinedSchemaRegistry::RegisterComponents( 120 PolicyDomain domain, 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; 126 } 127 own_schema_map_ = new SchemaMap(map); 128 Combine(true); 129} 130 131void 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); 135 Combine(false); 136 } else { 137 NOTREACHED(); 138 } 139} 140 141void CombinedSchemaRegistry::OnSchemaRegistryUpdated(bool has_new_schemas) { 142 Combine(has_new_schemas); 143} 144 145void CombinedSchemaRegistry::OnSchemaRegistryReady() { 146 // Ignore. 147} 148 149void 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. 152 // 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. 155 // 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 160 // the time being. 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; 171 } 172 } 173 } 174 schema_map_ = new SchemaMap(map); 175 Notify(has_new_schemas); 176} 177 178} // namespace policy 179