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

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

Issue 10236003: Added RefreshPolicies to PolicyService. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 8 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"
7 #include "base/observer_list.h" 9 #include "base/observer_list.h"
8 #include "base/stl_util.h" 10 #include "base/stl_util.h"
11 #include "content/public/browser/browser_thread.h"
12
13 using content::BrowserThread;
9 14
10 namespace policy { 15 namespace policy {
11 16
17 namespace {
18
19 // Helper to invoke |callbacks| asynchronously.
20 void InvokeCallbacks(std::vector<base::Closure>* callbacks) {
21 for (std::vector<base::Closure>::iterator it = callbacks->begin();
22 it != callbacks->end(); ++it) {
23 it->Run();
24 }
25 }
26
27 // Helper to resolve the overloading of PostTask.
28 void PostTask(BrowserThread::ID id, const base::Closure& callback) {
29 BrowserThread::PostTask(id, FROM_HERE, callback);
30 }
31
32 } // namespace
33
12 struct PolicyServiceImpl::Entry { 34 struct PolicyServiceImpl::Entry {
13 PolicyMap policies; 35 PolicyMap policies;
14 ObserverList<PolicyService::Observer, true> observers; 36 ObserverList<PolicyService::Observer, true> observers;
15 }; 37 };
16 38
17 struct PolicyServiceImpl::ProviderData { 39 struct PolicyServiceImpl::ProviderData {
18 ConfigurationPolicyProvider* provider; 40 ConfigurationPolicyProvider* provider;
19 ConfigurationPolicyObserverRegistrar registrar; 41 ConfigurationPolicyObserverRegistrar registrar;
20 PolicyMap policies; 42 PolicyMap policies;
43 bool refresh_pending;
21 }; 44 };
22 45
23 PolicyServiceImpl::PolicyServiceImpl(const Providers& providers) { 46 PolicyServiceImpl::PolicyServiceImpl(const Providers& providers) {
24 initialization_complete_ = true; 47 initialization_complete_ = true;
25 for (size_t i = 0; i < providers.size(); ++i) { 48 for (size_t i = 0; i < providers.size(); ++i) {
26 ConfigurationPolicyProvider* provider = providers[i]; 49 ConfigurationPolicyProvider* provider = providers[i];
27 ProviderData* data = new ProviderData; 50 ProviderData* data = new ProviderData;
28 data->provider = provider; 51 data->provider = provider;
29 data->registrar.Init(provider, this); 52 data->registrar.Init(provider, this);
53 data->refresh_pending = false;
30 if (provider->IsInitializationComplete()) 54 if (provider->IsInitializationComplete())
31 provider->Provide(&data->policies); 55 provider->Provide(&data->policies);
32 else 56 else
33 initialization_complete_ = false; 57 initialization_complete_ = false;
34 providers_.push_back(data); 58 providers_.push_back(data);
35 } 59 }
36 // There are no observers yet, but calls to GetPolicies() should already get 60 // There are no observers yet, but calls to GetPolicies() should already get
37 // the processed policy values. 61 // the processed policy values.
38 MergeAndTriggerUpdates(); 62 MergeAndTriggerUpdates(false);
39 } 63 }
40 64
41 PolicyServiceImpl::~PolicyServiceImpl() { 65 PolicyServiceImpl::~PolicyServiceImpl() {
42 STLDeleteElements(&providers_); 66 STLDeleteElements(&providers_);
43 STLDeleteValues(&entries_); 67 STLDeleteValues(&entries_);
44 } 68 }
45 69
46 void PolicyServiceImpl::AddObserver(PolicyDomain domain, 70 void PolicyServiceImpl::AddObserver(PolicyDomain domain,
47 const std::string& component_id, 71 const std::string& component_id,
48 PolicyService::Observer* observer) { 72 PolicyService::Observer* observer) {
(...skipping 19 matching lines...) Expand all
68 const std::string& component_id) const { 92 const std::string& component_id) const {
69 PolicyNamespace ns = std::make_pair(domain, component_id); 93 PolicyNamespace ns = std::make_pair(domain, component_id);
70 EntryMap::const_iterator it = entries_.find(ns); 94 EntryMap::const_iterator it = entries_.find(ns);
71 return it == entries_.end() ? NULL : &it->second->policies; 95 return it == entries_.end() ? NULL : &it->second->policies;
72 } 96 }
73 97
74 bool PolicyServiceImpl::IsInitializationComplete() const { 98 bool PolicyServiceImpl::IsInitializationComplete() const {
75 return initialization_complete_; 99 return initialization_complete_;
76 } 100 }
77 101
102 void PolicyServiceImpl::RefreshPolicies(const base::Closure& callback) {
103 refresh_callbacks_.push_back(callback);
104
105 // Some providers might invoke OnUpdatePolicy synchronously while handling
106 // RefreshPolicies. Flag all with refresh_pending before starting to refresh.
107 ProviderList::iterator it;
108 for (it = providers_.begin(); it != providers_.end(); ++it)
109 (*it)->refresh_pending = true;
110 for (it = providers_.begin(); it != providers_.end(); ++it)
111 (*it)->provider->RefreshPolicies();
112 }
113
78 void PolicyServiceImpl::OnUpdatePolicy(ConfigurationPolicyProvider* provider) { 114 void PolicyServiceImpl::OnUpdatePolicy(ConfigurationPolicyProvider* provider) {
79 ProviderList::iterator it = GetProviderData(provider); 115 ProviderList::iterator it = GetProviderData(provider);
80 if (it == providers_.end()) 116 if (it == providers_.end())
81 return; 117 return;
82 provider->Provide(&(*it)->policies); 118 provider->Provide(&(*it)->policies);
83 MergeAndTriggerUpdates(); 119 bool did_refresh = (*it)->refresh_pending;
120 (*it)->refresh_pending = false;
121 MergeAndTriggerUpdates(did_refresh);
84 } 122 }
85 123
86 void PolicyServiceImpl::OnProviderGoingAway( 124 void PolicyServiceImpl::OnProviderGoingAway(
87 ConfigurationPolicyProvider* provider) { 125 ConfigurationPolicyProvider* provider) {
88 ProviderList::iterator it = GetProviderData(provider); 126 ProviderList::iterator it = GetProviderData(provider);
89 if (it == providers_.end()) 127 if (it == providers_.end())
90 return; 128 return;
129 bool did_refresh = (*it)->refresh_pending;
91 delete *it; 130 delete *it;
92 providers_.erase(it); 131 providers_.erase(it);
93 MergeAndTriggerUpdates(); 132 MergeAndTriggerUpdates(did_refresh);
94 } 133 }
95 134
96 PolicyServiceImpl::Entry* PolicyServiceImpl::GetOrCreate( 135 PolicyServiceImpl::Entry* PolicyServiceImpl::GetOrCreate(
97 const PolicyNamespace& ns) { 136 const PolicyNamespace& ns) {
98 Entry*& entry = entries_[ns]; 137 Entry*& entry = entries_[ns];
99 if (!entry) 138 if (!entry)
100 entry = new Entry; 139 entry = new Entry;
101 return entry; 140 return entry;
102 } 141 }
103 142
(...skipping 11 matching lines...) Expand all
115 void PolicyServiceImpl::MaybeCleanup(const PolicyNamespace& ns) { 154 void PolicyServiceImpl::MaybeCleanup(const PolicyNamespace& ns) {
116 EntryMap::iterator it = entries_.find(ns); 155 EntryMap::iterator it = entries_.find(ns);
117 if (it != entries_.end() && 156 if (it != entries_.end() &&
118 it->second->policies.empty() && 157 it->second->policies.empty() &&
119 it->second->observers.size() == 0) { 158 it->second->observers.size() == 0) {
120 delete it->second; 159 delete it->second;
121 entries_.erase(it); 160 entries_.erase(it);
122 } 161 }
123 } 162 }
124 163
125 void PolicyServiceImpl::MergeAndTriggerUpdates() { 164 void PolicyServiceImpl::MergeAndTriggerUpdates(bool is_refresh) {
126 // TODO(joaodasilva): do this for each namespace once the providers also 165 // TODO(joaodasilva): do this for each namespace once the providers also
127 // provide policy for more namespaces. 166 // provide policy for more namespaces.
167
128 PolicyMap policies; 168 PolicyMap policies;
169 bool refresh_pending = false;
129 for (ProviderList::iterator it = providers_.begin(); 170 for (ProviderList::iterator it = providers_.begin();
130 it != providers_.end(); ++it) { 171 it != providers_.end(); ++it) {
131 policies.MergeFrom((*it)->policies); 172 policies.MergeFrom((*it)->policies);
173 refresh_pending |= (*it)->refresh_pending;
132 } 174 }
133 175
176 if (refresh_pending)
Mattias Nissler (ping if slow) 2012/04/26 11:08:52 This results in all updates being blocked until th
Joao da Silva 2012/04/26 14:43:58 Done.
177 return;
178
134 Entry* entry = GetOrCreate(std::make_pair(POLICY_DOMAIN_CHROME, "")); 179 Entry* entry = GetOrCreate(std::make_pair(POLICY_DOMAIN_CHROME, ""));
135 if (!policies.Equals(entry->policies)) { 180 if (!policies.Equals(entry->policies)) {
136 // Swap first, so that observers that call GetPolicies() see the current 181 // Swap first, so that observers that call GetPolicies() see the current
137 // values. 182 // values.
138 entry->policies.Swap(&policies); 183 entry->policies.Swap(&policies);
139 FOR_EACH_OBSERVER( 184 FOR_EACH_OBSERVER(
140 PolicyService::Observer, 185 PolicyService::Observer,
141 entry->observers, 186 entry->observers,
142 OnPolicyUpdated(POLICY_DOMAIN_CHROME, "", policies, entry->policies)); 187 OnPolicyUpdated(POLICY_DOMAIN_CHROME, "", policies, entry->policies));
143 } 188 }
144 189
145 // Check if all providers became initialized just now, if they weren't before. 190 // Check if all providers became initialized just now, if they weren't before.
146 if (!initialization_complete_) { 191 if (!initialization_complete_) {
147 initialization_complete_ = true; 192 initialization_complete_ = true;
148 for (ProviderList::iterator iter = providers_.begin(); 193 for (ProviderList::iterator iter = providers_.begin();
149 iter != providers_.end(); ++iter) { 194 iter != providers_.end(); ++iter) {
150 if (!(*iter)->provider->IsInitializationComplete()) { 195 if (!(*iter)->provider->IsInitializationComplete()) {
151 initialization_complete_ = false; 196 initialization_complete_ = false;
152 break; 197 break;
153 } 198 }
154 } 199 }
155 if (initialization_complete_) { 200 if (initialization_complete_) {
156 for (EntryMap::iterator i = entries_.begin(); i != entries_.end(); ++i) { 201 for (EntryMap::iterator i = entries_.begin(); i != entries_.end(); ++i) {
157 FOR_EACH_OBSERVER(PolicyService::Observer, 202 FOR_EACH_OBSERVER(PolicyService::Observer,
158 i->second->observers, 203 i->second->observers,
159 OnPolicyServiceInitialized()); 204 OnPolicyServiceInitialized());
160 } 205 }
161 } 206 }
162 } 207 }
208
209 // Invoke all the callbacks if a refresh has just fully completed.
210 if (is_refresh && !refresh_pending) {
211 // Some policies (e.g. URLBlacklist) post tasks to other message loops
212 // before they start enforcing updated policy values; make sure those tasks
213 // have finished after a policy update.
214 // Updates of the URLBlacklist are done on IO, after building the blacklist
215 // on FILE, which is initiated from IO.
Mattias Nissler (ping if slow) 2012/04/26 11:08:52 This doesn't belong here. Policies might trigger v
Joao da Silva 2012/04/26 14:43:58 Right; this was introduced to fix automation tests
216 std::vector<base::Closure>* callbacks = new std::vector<base::Closure>();
217 callbacks->swap(refresh_callbacks_);
218 PostTask(BrowserThread::IO,
219 base::Bind(&PostTask, BrowserThread::FILE,
220 base::Bind(&PostTask, BrowserThread::IO,
221 base::Bind(&PostTask, BrowserThread::UI,
222 base::Bind(InvokeCallbacks, base::Owned(callbacks))))));
223 }
163 } 224 }
164 225
165 } // namespace policy 226 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698