Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(239)

Side by Side Diff: chrome/browser/policy/policy_service_impl.cc

Issue 10386097: Refactored ConfigurationPolicyProvider to provide PolicyBundles instead of PolicyMaps. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/policy/policy_service_impl.h" 5 #include "chrome/browser/policy/policy_service_impl.h"
6 6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/observer_list.h"
10 #include "base/stl_util.h" 7 #include "base/stl_util.h"
11 #include "content/public/browser/browser_thread.h" 8 #include "chrome/browser/policy/policy_map.h"
12
13 using content::BrowserThread;
14 9
15 namespace policy { 10 namespace policy {
16 11
17 struct PolicyServiceImpl::Entry {
18 PolicyMap policies;
19 ObserverList<PolicyService::Observer, true> observers;
20 };
21
22 struct PolicyServiceImpl::ProviderData {
23 ConfigurationPolicyProvider* provider;
24 ConfigurationPolicyObserverRegistrar registrar;
25 PolicyMap policies;
26 bool refresh_pending;
27 };
28
29 PolicyServiceImpl::PolicyServiceImpl(const Providers& providers) { 12 PolicyServiceImpl::PolicyServiceImpl(const Providers& providers) {
30 initialization_complete_ = true; 13 initialization_complete_ = true;
31 for (size_t i = 0; i < providers.size(); ++i) { 14 for (size_t i = 0; i < providers.size(); ++i) {
32 ConfigurationPolicyProvider* provider = providers[i]; 15 ConfigurationPolicyProvider* provider = providers[i];
33 ProviderData* data = new ProviderData; 16 ConfigurationPolicyObserverRegistrar* registrar =
34 data->provider = provider; 17 new ConfigurationPolicyObserverRegistrar();
35 data->registrar.Init(provider, this); 18 registrar->Init(provider, this);
36 data->refresh_pending = false; 19 initialization_complete_ &= provider->IsInitializationComplete();
37 if (provider->IsInitializationComplete()) 20 registrars_.push_back(registrar);
38 provider->Provide(&data->policies);
39 else
40 initialization_complete_ = false;
41 providers_.push_back(data);
42 } 21 }
43 // There are no observers yet, but calls to GetPolicies() should already get 22 // There are no observers yet, but calls to GetPolicies() should already get
44 // the processed policy values. 23 // the processed policy values.
45 MergeAndTriggerUpdates(false); 24 MergeAndTriggerUpdates();
46 } 25 }
47 26
48 PolicyServiceImpl::~PolicyServiceImpl() { 27 PolicyServiceImpl::~PolicyServiceImpl() {
49 STLDeleteElements(&providers_); 28 STLDeleteElements(&registrars_);
50 STLDeleteValues(&entries_); 29 STLDeleteValues(&observers_);
51 } 30 }
52 31
53 void PolicyServiceImpl::AddObserver(PolicyDomain domain, 32 void PolicyServiceImpl::AddObserver(PolicyDomain domain,
54 const std::string& component_id, 33 const std::string& component_id,
55 PolicyService::Observer* observer) { 34 PolicyService::Observer* observer) {
56 PolicyNamespace ns = std::make_pair(domain, component_id); 35 PolicyBundle::PolicyNamespace ns(domain, component_id);
57 GetOrCreate(ns)->observers.AddObserver(observer); 36 Observers*& list = observers_[ns];
37 if (!list)
38 list = new Observers();
39 list->AddObserver(observer);
58 } 40 }
59 41
60 void PolicyServiceImpl::RemoveObserver(PolicyDomain domain, 42 void PolicyServiceImpl::RemoveObserver(PolicyDomain domain,
61 const std::string& component_id, 43 const std::string& component_id,
62 PolicyService::Observer* observer) { 44 PolicyService::Observer* observer) {
63 PolicyNamespace ns = std::make_pair(domain, component_id); 45 PolicyBundle::PolicyNamespace ns(domain, component_id);
64 EntryMap::const_iterator it = entries_.find(ns); 46 ObserverMap::iterator it = observers_.find(ns);
65 if (it == entries_.end()) { 47 if (it == observers_.end()) {
66 NOTREACHED(); 48 NOTREACHED();
67 return; 49 return;
68 } 50 }
69 it->second->observers.RemoveObserver(observer); 51 it->second->RemoveObserver(observer);
70 MaybeCleanup(ns); 52 if (it->second->size() == 0) {
53 delete it->second;
54 observers_.erase(it);
55 }
71 } 56 }
72 57
73 const PolicyMap* PolicyServiceImpl::GetPolicies( 58 const PolicyMap& PolicyServiceImpl::GetPolicies(
74 PolicyDomain domain, 59 PolicyDomain domain,
75 const std::string& component_id) const { 60 const std::string& component_id) const {
76 PolicyNamespace ns = std::make_pair(domain, component_id); 61 return policy_bundle_.Get(domain, component_id);
77 EntryMap::const_iterator it = entries_.find(ns);
78 return it == entries_.end() ? NULL : &it->second->policies;
79 } 62 }
80 63
81 bool PolicyServiceImpl::IsInitializationComplete() const { 64 bool PolicyServiceImpl::IsInitializationComplete() const {
82 return initialization_complete_; 65 return initialization_complete_;
83 } 66 }
84 67
85 void PolicyServiceImpl::RefreshPolicies(const base::Closure& callback) { 68 void PolicyServiceImpl::RefreshPolicies(const base::Closure& callback) {
86 if (!callback.is_null()) 69 if (!callback.is_null())
87 refresh_callbacks_.push_back(callback); 70 refresh_callbacks_.push_back(callback);
88 71
89 if (providers_.empty()) { 72 if (registrars_.empty()) {
90 // Refresh is immediately complete if there are no providers. 73 // Refresh is immediately complete if there are no providers.
91 MergeAndTriggerUpdates(true); 74 MergeAndTriggerUpdates();
92 } else { 75 } else {
93 // Some providers might invoke OnUpdatePolicy synchronously while handling 76 // Some providers might invoke OnUpdatePolicy synchronously while handling
94 // RefreshPolicies. Flag all with refresh_pending before refreshing. 77 // RefreshPolicies. Mark all as pending before refreshing.
95 ProviderList::iterator it; 78 RegistrarList::iterator it;
96 for (it = providers_.begin(); it != providers_.end(); ++it) 79 for (it = registrars_.begin(); it != registrars_.end(); ++it)
97 (*it)->refresh_pending = true; 80 refresh_pending_.insert((*it)->provider());
98 for (it = providers_.begin(); it != providers_.end(); ++it) 81 for (it = registrars_.begin(); it != registrars_.end(); ++it)
99 (*it)->provider->RefreshPolicies(); 82 (*it)->provider()->RefreshPolicies();
100 } 83 }
101 } 84 }
102 85
103 void PolicyServiceImpl::OnUpdatePolicy(ConfigurationPolicyProvider* provider) { 86 void PolicyServiceImpl::OnUpdatePolicy(ConfigurationPolicyProvider* provider) {
104 ProviderList::iterator it = GetProviderData(provider); 87 RegistrarList::iterator it = GetRegistrar(provider);
105 if (it == providers_.end()) 88 if (it == registrars_.end())
106 return; 89 return;
107 provider->Provide(&(*it)->policies); 90 refresh_pending_.erase(provider);
108 bool did_refresh = (*it)->refresh_pending; 91 MergeAndTriggerUpdates();
109 (*it)->refresh_pending = false;
110 MergeAndTriggerUpdates(did_refresh);
111 } 92 }
112 93
113 void PolicyServiceImpl::OnProviderGoingAway( 94 void PolicyServiceImpl::OnProviderGoingAway(
114 ConfigurationPolicyProvider* provider) { 95 ConfigurationPolicyProvider* provider) {
115 ProviderList::iterator it = GetProviderData(provider); 96 RegistrarList::iterator it = GetRegistrar(provider);
116 if (it == providers_.end()) 97 if (it == registrars_.end())
117 return; 98 return;
118 bool did_refresh = (*it)->refresh_pending; 99 refresh_pending_.erase(provider);
119 delete *it; 100 delete *it;
120 providers_.erase(it); 101 registrars_.erase(it);
121 MergeAndTriggerUpdates(did_refresh); 102 MergeAndTriggerUpdates();
122 } 103 }
123 104
124 PolicyServiceImpl::Entry* PolicyServiceImpl::GetOrCreate( 105 PolicyServiceImpl::RegistrarList::iterator PolicyServiceImpl::GetRegistrar(
125 const PolicyNamespace& ns) {
126 Entry*& entry = entries_[ns];
127 if (!entry)
128 entry = new Entry;
129 return entry;
130 }
131
132 PolicyServiceImpl::ProviderList::iterator PolicyServiceImpl::GetProviderData(
133 ConfigurationPolicyProvider* provider) { 106 ConfigurationPolicyProvider* provider) {
134 for (ProviderList::iterator it = providers_.begin(); 107 for (RegistrarList::iterator it = registrars_.begin();
135 it != providers_.end(); ++it) { 108 it != registrars_.end(); ++it) {
136 if ((*it)->provider == provider) 109 if ((*it)->provider() == provider)
137 return it; 110 return it;
138 } 111 }
139 NOTREACHED(); 112 NOTREACHED();
140 return providers_.end(); 113 return registrars_.end();
141 } 114 }
142 115
143 void PolicyServiceImpl::MaybeCleanup(const PolicyNamespace& ns) { 116 void PolicyServiceImpl::NotifyNamespaceUpdated(
144 EntryMap::iterator it = entries_.find(ns); 117 const PolicyBundle::PolicyNamespace& ns,
145 if (it != entries_.end() && 118 const PolicyMap& previous,
146 it->second->policies.empty() && 119 const PolicyMap& current) {
147 it->second->observers.size() == 0) { 120 ObserverMap::iterator iterator = observers_.find(ns);
148 delete it->second; 121 if (iterator != observers_.end()) {
149 entries_.erase(it); 122 FOR_EACH_OBSERVER(
123 PolicyService::Observer,
124 *iterator->second,
125 OnPolicyUpdated(ns.first, ns.second, previous, current));
150 } 126 }
151 } 127 }
152 128
153 void PolicyServiceImpl::MergeAndTriggerUpdates(bool is_refresh) { 129 void PolicyServiceImpl::MergeAndTriggerUpdates() {
154 // TODO(joaodasilva): do this for each namespace once the providers also 130 // Merge from each provider in their order of priority.
155 // provide policy for more namespaces. 131 PolicyBundle bundle;
156 132 for (RegistrarList::iterator it = registrars_.begin();
157 PolicyMap policies; 133 it != registrars_.end(); ++it) {
158 bool refresh_pending = false; 134 bundle.MergeFrom((*it)->provider()->policies());
159 for (ProviderList::iterator it = providers_.begin();
160 it != providers_.end(); ++it) {
161 policies.MergeFrom((*it)->policies);
162 refresh_pending |= (*it)->refresh_pending;
163 } 135 }
164 136
165 Entry* entry = GetOrCreate(std::make_pair(POLICY_DOMAIN_CHROME, "")); 137 // Swap first, so that observers that call GetPolicies() see the current
166 if (!policies.Equals(entry->policies)) { 138 // values.
167 // Swap first, so that observers that call GetPolicies() see the current 139 policy_bundle_.Swap(&bundle);
168 // values. 140
169 entry->policies.Swap(&policies); 141 // Only notify observers of namespaces that have been modified.
170 FOR_EACH_OBSERVER( 142 const PolicyMap kEmpty;
171 PolicyService::Observer, 143 PolicyBundle::const_iterator it_new = policy_bundle_.begin();
172 entry->observers, 144 PolicyBundle::const_iterator end_new = policy_bundle_.end();
173 OnPolicyUpdated(POLICY_DOMAIN_CHROME, "", policies, entry->policies)); 145 PolicyBundle::const_iterator it_old = bundle.begin();
146 PolicyBundle::const_iterator end_old = bundle.end();
147 while (it_new != end_new && it_old != end_old) {
148 if (it_new->first < it_old->first) {
149 // A new namespace is available.
150 NotifyNamespaceUpdated(it_new->first, kEmpty, *it_new->second);
151 ++it_new;
152 } else if (it_new->first > it_old->first) {
153 // A previously available namespace is now gone.
154 NotifyNamespaceUpdated(it_old->first, *it_old->second, kEmpty);
155 ++it_old;
156 } else {
157 if (!it_new->second->Equals(*it_old->second)) {
158 // An existing namespace's policies have changed.
159 NotifyNamespaceUpdated(it_new->first, *it_old->second, *it_new->second);
160 }
161 ++it_new;
162 ++it_old;
163 }
174 } 164 }
175 165
166 // Send updates for the remaining new namespaces, if any.
167 for (; it_new != end_new; ++it_new)
168 NotifyNamespaceUpdated(it_new->first, kEmpty, *it_new->second);
169
170 // Sends updates for the remaining removed namespaces, if any.
171 for (; it_old != end_old; ++it_old)
172 NotifyNamespaceUpdated(it_old->first, *it_old->second, kEmpty);
173
174 CheckInitializationComplete();
175 CheckRefreshComplete();
176 }
177
178 void PolicyServiceImpl::CheckInitializationComplete() {
176 // Check if all providers became initialized just now, if they weren't before. 179 // Check if all providers became initialized just now, if they weren't before.
177 if (!initialization_complete_) { 180 if (!initialization_complete_) {
178 initialization_complete_ = true; 181 initialization_complete_ = true;
179 for (ProviderList::iterator iter = providers_.begin(); 182 for (RegistrarList::iterator iter = registrars_.begin();
180 iter != providers_.end(); ++iter) { 183 iter != registrars_.end(); ++iter) {
181 if (!(*iter)->provider->IsInitializationComplete()) { 184 if (!(*iter)->provider()->IsInitializationComplete()) {
182 initialization_complete_ = false; 185 initialization_complete_ = false;
183 break; 186 break;
184 } 187 }
185 } 188 }
186 if (initialization_complete_) { 189 if (initialization_complete_) {
187 for (EntryMap::iterator i = entries_.begin(); i != entries_.end(); ++i) { 190 for (ObserverMap::iterator iter = observers_.begin();
191 iter != observers_.end(); ++iter) {
188 FOR_EACH_OBSERVER(PolicyService::Observer, 192 FOR_EACH_OBSERVER(PolicyService::Observer,
189 i->second->observers, 193 *iter->second,
190 OnPolicyServiceInitialized()); 194 OnPolicyServiceInitialized());
191 } 195 }
192 } 196 }
193 } 197 }
198 }
194 199
200 void PolicyServiceImpl::CheckRefreshComplete() {
195 // Invoke all the callbacks if a refresh has just fully completed. 201 // Invoke all the callbacks if a refresh has just fully completed.
196 if (is_refresh && !refresh_pending) { 202 if (refresh_pending_.empty() && !refresh_callbacks_.empty()) {
197 std::vector<base::Closure> callbacks; 203 std::vector<base::Closure> callbacks;
198 callbacks.swap(refresh_callbacks_); 204 callbacks.swap(refresh_callbacks_);
199 for (size_t i = 0; i < callbacks.size(); ++i) 205 for (size_t i = 0; i < callbacks.size(); ++i)
200 callbacks[i].Run(); 206 callbacks[i].Run();
201 } 207 }
202 } 208 }
203 209
204 } // namespace policy 210 } // namespace policy
OLDNEW
« no previous file with comments | « chrome/browser/policy/policy_service_impl.h ('k') | chrome/browser/policy/policy_service_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698