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

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

Issue 109743002: Move policy code into components/policy. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: moar fixes Created 7 years 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/policy/policy_service_impl.h"
6
7 #include <algorithm>
8
9 #include "base/bind.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/stl_util.h"
12 #include "components/policy/core/common/policy_bundle.h"
13 #include "components/policy/core/common/policy_map.h"
14
15 namespace policy {
16
17 typedef PolicyServiceImpl::Providers::const_iterator Iterator;
18
19 PolicyServiceImpl::PolicyServiceImpl(
20 const Providers& providers,
21 const PreprocessCallback& preprocess_callback)
22 : preprocess_callback_(preprocess_callback),
23 update_task_ptr_factory_(this) {
24 for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain)
25 initialization_complete_[domain] = true;
26 providers_ = providers;
27 for (Iterator it = providers.begin(); it != providers.end(); ++it) {
28 ConfigurationPolicyProvider* provider = *it;
29 provider->AddObserver(this);
30 for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain) {
31 initialization_complete_[domain] &=
32 provider->IsInitializationComplete(static_cast<PolicyDomain>(domain));
33 }
34 }
35 // There are no observers yet, but calls to GetPolicies() should already get
36 // the processed policy values.
37 MergeAndTriggerUpdates();
38 }
39
40 PolicyServiceImpl::~PolicyServiceImpl() {
41 for (Iterator it = providers_.begin(); it != providers_.end(); ++it)
42 (*it)->RemoveObserver(this);
43 STLDeleteValues(&observers_);
44 }
45
46 void PolicyServiceImpl::AddObserver(PolicyDomain domain,
47 PolicyService::Observer* observer) {
48 Observers*& list = observers_[domain];
49 if (!list)
50 list = new Observers();
51 list->AddObserver(observer);
52 }
53
54 void PolicyServiceImpl::RemoveObserver(PolicyDomain domain,
55 PolicyService::Observer* observer) {
56 ObserverMap::iterator it = observers_.find(domain);
57 if (it == observers_.end()) {
58 NOTREACHED();
59 return;
60 }
61 it->second->RemoveObserver(observer);
62 if (!it->second->might_have_observers()) {
63 delete it->second;
64 observers_.erase(it);
65 }
66 }
67
68 const PolicyMap& PolicyServiceImpl::GetPolicies(
69 const PolicyNamespace& ns) const {
70 return policy_bundle_.Get(ns);
71 }
72
73 bool PolicyServiceImpl::IsInitializationComplete(PolicyDomain domain) const {
74 DCHECK(domain >= 0 && domain < POLICY_DOMAIN_SIZE);
75 return initialization_complete_[domain];
76 }
77
78 void PolicyServiceImpl::RefreshPolicies(const base::Closure& callback) {
79 if (!callback.is_null())
80 refresh_callbacks_.push_back(callback);
81
82 if (providers_.empty()) {
83 // Refresh is immediately complete if there are no providers. See the note
84 // on OnUpdatePolicy() about why this is a posted task.
85 update_task_ptr_factory_.InvalidateWeakPtrs();
86 base::MessageLoop::current()->PostTask(
87 FROM_HERE,
88 base::Bind(&PolicyServiceImpl::MergeAndTriggerUpdates,
89 update_task_ptr_factory_.GetWeakPtr()));
90 } else {
91 // Some providers might invoke OnUpdatePolicy synchronously while handling
92 // RefreshPolicies. Mark all as pending before refreshing.
93 for (Iterator it = providers_.begin(); it != providers_.end(); ++it)
94 refresh_pending_.insert(*it);
95 for (Iterator it = providers_.begin(); it != providers_.end(); ++it)
96 (*it)->RefreshPolicies();
97 }
98 }
99
100 void PolicyServiceImpl::OnUpdatePolicy(ConfigurationPolicyProvider* provider) {
101 DCHECK_EQ(1, std::count(providers_.begin(), providers_.end(), provider));
102 refresh_pending_.erase(provider);
103
104 // Note: a policy change may trigger further policy changes in some providers.
105 // For example, disabling SigninAllowed would cause the CloudPolicyManager to
106 // drop all its policies, which makes this method enter again for that
107 // provider.
108 //
109 // Therefore this update is posted asynchronously, to prevent reentrancy in
110 // MergeAndTriggerUpdates. Also, cancel a pending update if there is any,
111 // since both will produce the same PolicyBundle.
112 update_task_ptr_factory_.InvalidateWeakPtrs();
113 base::MessageLoop::current()->PostTask(
114 FROM_HERE,
115 base::Bind(&PolicyServiceImpl::MergeAndTriggerUpdates,
116 update_task_ptr_factory_.GetWeakPtr()));
117 }
118
119 void PolicyServiceImpl::NotifyNamespaceUpdated(
120 const PolicyNamespace& ns,
121 const PolicyMap& previous,
122 const PolicyMap& current) {
123 ObserverMap::iterator iterator = observers_.find(ns.domain);
124 if (iterator != observers_.end()) {
125 FOR_EACH_OBSERVER(PolicyService::Observer,
126 *iterator->second,
127 OnPolicyUpdated(ns, previous, current));
128 }
129 }
130
131 void PolicyServiceImpl::MergeAndTriggerUpdates() {
132 // Merge from each provider in their order of priority.
133 PolicyBundle bundle;
134 for (Iterator it = providers_.begin(); it != providers_.end(); ++it) {
135 PolicyBundle provided_bundle;
136 provided_bundle.CopyFrom((*it)->policies());
137 if (!preprocess_callback_.is_null())
138 preprocess_callback_.Run(&provided_bundle);
139 bundle.MergeFrom(provided_bundle);
140 }
141
142 // Swap first, so that observers that call GetPolicies() see the current
143 // values.
144 policy_bundle_.Swap(&bundle);
145
146 // Only notify observers of namespaces that have been modified.
147 const PolicyMap kEmpty;
148 PolicyBundle::const_iterator it_new = policy_bundle_.begin();
149 PolicyBundle::const_iterator end_new = policy_bundle_.end();
150 PolicyBundle::const_iterator it_old = bundle.begin();
151 PolicyBundle::const_iterator end_old = bundle.end();
152 while (it_new != end_new && it_old != end_old) {
153 if (it_new->first < it_old->first) {
154 // A new namespace is available.
155 NotifyNamespaceUpdated(it_new->first, kEmpty, *it_new->second);
156 ++it_new;
157 } else if (it_old->first < it_new->first) {
158 // A previously available namespace is now gone.
159 NotifyNamespaceUpdated(it_old->first, *it_old->second, kEmpty);
160 ++it_old;
161 } else {
162 if (!it_new->second->Equals(*it_old->second)) {
163 // An existing namespace's policies have changed.
164 NotifyNamespaceUpdated(it_new->first, *it_old->second, *it_new->second);
165 }
166 ++it_new;
167 ++it_old;
168 }
169 }
170
171 // Send updates for the remaining new namespaces, if any.
172 for (; it_new != end_new; ++it_new)
173 NotifyNamespaceUpdated(it_new->first, kEmpty, *it_new->second);
174
175 // Sends updates for the remaining removed namespaces, if any.
176 for (; it_old != end_old; ++it_old)
177 NotifyNamespaceUpdated(it_old->first, *it_old->second, kEmpty);
178
179 CheckInitializationComplete();
180 CheckRefreshComplete();
181 }
182
183 void PolicyServiceImpl::CheckInitializationComplete() {
184 // Check if all the providers just became initialized for each domain; if so,
185 // notify that domain's observers.
186 for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain) {
187 if (initialization_complete_[domain])
188 continue;
189
190 PolicyDomain policy_domain = static_cast<PolicyDomain>(domain);
191
192 bool all_complete = true;
193 for (Iterator it = providers_.begin(); it != providers_.end(); ++it) {
194 if (!(*it)->IsInitializationComplete(policy_domain)) {
195 all_complete = false;
196 break;
197 }
198 }
199 if (all_complete) {
200 initialization_complete_[domain] = true;
201 ObserverMap::iterator iter = observers_.find(policy_domain);
202 if (iter != observers_.end()) {
203 FOR_EACH_OBSERVER(PolicyService::Observer,
204 *iter->second,
205 OnPolicyServiceInitialized(policy_domain));
206 }
207 }
208 }
209 }
210
211 void PolicyServiceImpl::CheckRefreshComplete() {
212 // Invoke all the callbacks if a refresh has just fully completed.
213 if (refresh_pending_.empty() && !refresh_callbacks_.empty()) {
214 std::vector<base::Closure> callbacks;
215 callbacks.swap(refresh_callbacks_);
216 std::vector<base::Closure>::iterator it;
217 for (it = callbacks.begin(); it != callbacks.end(); ++it)
218 it->Run();
219 }
220 }
221
222 } // 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