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

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

Issue 11667006: Create a list of policy changes before notifying observers (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix lint error/merge to ToT Created 7 years, 12 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 <algorithm> 7 #include <algorithm>
8 8
9 #include "base/memory/scoped_vector.h"
9 #include "base/stl_util.h" 10 #include "base/stl_util.h"
10 #include "chrome/browser/policy/policy_map.h" 11 #include "chrome/browser/policy/policy_map.h"
11 12
12 namespace policy { 13 namespace policy {
13 14
14 typedef PolicyServiceImpl::Providers::const_iterator Iterator; 15 typedef PolicyServiceImpl::Providers::const_iterator Iterator;
15 16
16 PolicyServiceImpl::PolicyServiceImpl(const Providers& providers) { 17 PolicyServiceImpl::PolicyServiceImpl(const Providers& providers) {
17 initialization_complete_ = true; 18 initialization_complete_ = true;
18 providers_ = providers; 19 providers_ = providers;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 const PolicyMap& current) { 94 const PolicyMap& current) {
94 ObserverMap::iterator iterator = observers_.find(ns.first); 95 ObserverMap::iterator iterator = observers_.find(ns.first);
95 if (iterator != observers_.end()) { 96 if (iterator != observers_.end()) {
96 FOR_EACH_OBSERVER( 97 FOR_EACH_OBSERVER(
97 PolicyService::Observer, 98 PolicyService::Observer,
98 *iterator->second, 99 *iterator->second,
99 OnPolicyUpdated(ns.first, ns.second, previous, current)); 100 OnPolicyUpdated(ns.first, ns.second, previous, current));
100 } 101 }
101 } 102 }
102 103
104 namespace {
105
106 // Information we batch up for pending policy changes before sending updates to
107 // observers.
108 class PolicyChangeInfo {
109 public:
110 PolicyChangeInfo(const PolicyBundle::PolicyNamespace& policy_namespace,
111 const PolicyMap& previous, const PolicyMap& current)
112 : policy_namespace_(policy_namespace) {
113 previous_.CopyFrom(previous);
114 current_.CopyFrom(current);
115 }
116
117 PolicyBundle::PolicyNamespace policy_namespace_;
118 PolicyMap previous_;
119 PolicyMap current_;
120 };
121
122 } // namespace
123
103 void PolicyServiceImpl::MergeAndTriggerUpdates() { 124 void PolicyServiceImpl::MergeAndTriggerUpdates() {
104 // Merge from each provider in their order of priority. 125 // Merge from each provider in their order of priority.
105 PolicyBundle bundle; 126 PolicyBundle bundle;
106 for (Iterator it = providers_.begin(); it != providers_.end(); ++it) 127 for (Iterator it = providers_.begin(); it != providers_.end(); ++it)
107 bundle.MergeFrom((*it)->policies()); 128 bundle.MergeFrom((*it)->policies());
108 129
109 // Swap first, so that observers that call GetPolicies() see the current 130 // Swap first, so that observers that call GetPolicies() see the current
110 // values. 131 // values.
111 policy_bundle_.Swap(&bundle); 132 policy_bundle_.Swap(&bundle);
112 133
113 // Only notify observers of namespaces that have been modified. 134 // Walk the changes and create a list of updates - otherwise, activities
135 // taken by observers that modify the underlying policy store (like signing
136 // out and deleting policy) can cause crashes.
114 const PolicyMap kEmpty; 137 const PolicyMap kEmpty;
138 ScopedVector<PolicyChangeInfo> changes;
115 PolicyBundle::const_iterator it_new = policy_bundle_.begin(); 139 PolicyBundle::const_iterator it_new = policy_bundle_.begin();
116 PolicyBundle::const_iterator end_new = policy_bundle_.end(); 140 PolicyBundle::const_iterator end_new = policy_bundle_.end();
117 PolicyBundle::const_iterator it_old = bundle.begin(); 141 PolicyBundle::const_iterator it_old = bundle.begin();
118 PolicyBundle::const_iterator end_old = bundle.end(); 142 PolicyBundle::const_iterator end_old = bundle.end();
119 while (it_new != end_new && it_old != end_old) { 143 while (it_new != end_new && it_old != end_old) {
120 if (it_new->first < it_old->first) { 144 if (it_new->first < it_old->first) {
121 // A new namespace is available. 145 // A new namespace is available.
122 NotifyNamespaceUpdated(it_new->first, kEmpty, *it_new->second); 146 changes.push_back(
147 new PolicyChangeInfo(it_new->first, kEmpty, *it_new->second));
123 ++it_new; 148 ++it_new;
124 } else if (it_new->first > it_old->first) { 149 } else if (it_new->first > it_old->first) {
125 // A previously available namespace is now gone. 150 // A previously available namespace is now gone.
126 NotifyNamespaceUpdated(it_old->first, *it_old->second, kEmpty); 151 changes.push_back(
152 new PolicyChangeInfo(it_old->first, *it_old->second, kEmpty));
127 ++it_old; 153 ++it_old;
128 } else { 154 } else {
129 if (!it_new->second->Equals(*it_old->second)) { 155 if (!it_new->second->Equals(*it_old->second)) {
130 // An existing namespace's policies have changed. 156 // An existing namespace's policies have changed.
131 NotifyNamespaceUpdated(it_new->first, *it_old->second, *it_new->second); 157 changes.push_back(
158 new PolicyChangeInfo(it_new->first, *it_old->second,
159 *it_new->second));
132 } 160 }
133 ++it_new; 161 ++it_new;
134 ++it_old; 162 ++it_old;
135 } 163 }
136 } 164 }
137 165
138 // Send updates for the remaining new namespaces, if any. 166 // Send updates for the remaining new namespaces, if any.
139 for (; it_new != end_new; ++it_new) 167 for (; it_new != end_new; ++it_new) {
140 NotifyNamespaceUpdated(it_new->first, kEmpty, *it_new->second); 168 changes.push_back(
169 new PolicyChangeInfo(it_new->first, kEmpty, *it_new->second));
170 }
141 171
142 // Sends updates for the remaining removed namespaces, if any. 172 // Sends updates for the remaining removed namespaces, if any.
143 for (; it_old != end_old; ++it_old) 173 for (; it_old != end_old; ++it_old) {
144 NotifyNamespaceUpdated(it_old->first, *it_old->second, kEmpty); 174 changes.push_back(
175 new PolicyChangeInfo(it_old->first, *it_new->second, kEmpty));
Joao da Silva 2012/12/22 21:42:00 The 2nd arg should be *it_old->second
Andrew T Wilson (Slow) 2013/01/04 15:54:48 Good catch :)
176 }
177
178 // Walk our pending list of changes and send updates.
179 for (ScopedVector<PolicyChangeInfo>::const_iterator iter = changes.begin();
180 iter != changes.end(); ++iter) {
181 NotifyNamespaceUpdated((*iter)->policy_namespace_, (*iter)->previous_,
182 (*iter)->current_);
183 }
145 184
146 CheckInitializationComplete(); 185 CheckInitializationComplete();
147 CheckRefreshComplete(); 186 CheckRefreshComplete();
148 } 187 }
149 188
150 void PolicyServiceImpl::CheckInitializationComplete() { 189 void PolicyServiceImpl::CheckInitializationComplete() {
151 // 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.
152 if (!initialization_complete_) { 191 if (!initialization_complete_) {
153 initialization_complete_ = true; 192 initialization_complete_ = true;
154 for (Iterator it = providers_.begin(); it != providers_.end(); ++it) { 193 for (Iterator it = providers_.begin(); it != providers_.end(); ++it) {
(...skipping 18 matching lines...) Expand all
173 if (refresh_pending_.empty() && !refresh_callbacks_.empty()) { 212 if (refresh_pending_.empty() && !refresh_callbacks_.empty()) {
174 std::vector<base::Closure> callbacks; 213 std::vector<base::Closure> callbacks;
175 callbacks.swap(refresh_callbacks_); 214 callbacks.swap(refresh_callbacks_);
176 std::vector<base::Closure>::iterator it; 215 std::vector<base::Closure>::iterator it;
177 for (it = callbacks.begin(); it != callbacks.end(); ++it) 216 for (it = callbacks.begin(); it != callbacks.end(); ++it)
178 it->Run(); 217 it->Run();
179 } 218 }
180 } 219 }
181 220
182 } // namespace policy 221 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698