Chromium Code Reviews| Index: chrome/browser/policy/policy_service_impl.cc |
| diff --git a/chrome/browser/policy/policy_service_impl.cc b/chrome/browser/policy/policy_service_impl.cc |
| index 2d0a2435e1f6354ba9841cb73b3ed4b58167813b..7589927be72a2cf1ada50294fd219c9c2c4c8cc8 100644 |
| --- a/chrome/browser/policy/policy_service_impl.cc |
| +++ b/chrome/browser/policy/policy_service_impl.cc |
| @@ -6,6 +6,7 @@ |
| #include <algorithm> |
| +#include "base/memory/scoped_vector.h" |
| #include "base/stl_util.h" |
| #include "chrome/browser/policy/policy_map.h" |
| @@ -100,6 +101,26 @@ void PolicyServiceImpl::NotifyNamespaceUpdated( |
| } |
| } |
| +namespace { |
| + |
| +// Information we batch up for pending policy changes before sending updates to |
| +// observers. |
| +class PolicyChangeInfo { |
| + public: |
| + PolicyChangeInfo(const PolicyBundle::PolicyNamespace& policy_namespace, |
| + const PolicyMap& previous, const PolicyMap& current) |
| + : policy_namespace_(policy_namespace) { |
| + previous_.CopyFrom(previous); |
| + current_.CopyFrom(current); |
| + } |
| + |
| + PolicyBundle::PolicyNamespace policy_namespace_; |
| + PolicyMap previous_; |
| + PolicyMap current_; |
| +}; |
| + |
| +} // namespace |
| + |
| void PolicyServiceImpl::MergeAndTriggerUpdates() { |
| // Merge from each provider in their order of priority. |
| PolicyBundle bundle; |
| @@ -110,8 +131,11 @@ void PolicyServiceImpl::MergeAndTriggerUpdates() { |
| // values. |
| policy_bundle_.Swap(&bundle); |
| - // Only notify observers of namespaces that have been modified. |
| + // Walk the changes and create a list of updates - otherwise, activities |
| + // taken by observers that modify the underlying policy store (like signing |
| + // out and deleting policy) can cause crashes. |
| const PolicyMap kEmpty; |
| + ScopedVector<PolicyChangeInfo> changes; |
| PolicyBundle::const_iterator it_new = policy_bundle_.begin(); |
| PolicyBundle::const_iterator end_new = policy_bundle_.end(); |
| PolicyBundle::const_iterator it_old = bundle.begin(); |
| @@ -119,16 +143,20 @@ void PolicyServiceImpl::MergeAndTriggerUpdates() { |
| while (it_new != end_new && it_old != end_old) { |
| if (it_new->first < it_old->first) { |
| // A new namespace is available. |
| - NotifyNamespaceUpdated(it_new->first, kEmpty, *it_new->second); |
| + changes.push_back( |
| + new PolicyChangeInfo(it_new->first, kEmpty, *it_new->second)); |
| ++it_new; |
| } else if (it_new->first > it_old->first) { |
| // A previously available namespace is now gone. |
| - NotifyNamespaceUpdated(it_old->first, *it_old->second, kEmpty); |
| + changes.push_back( |
| + new PolicyChangeInfo(it_old->first, *it_old->second, kEmpty)); |
| ++it_old; |
| } else { |
| if (!it_new->second->Equals(*it_old->second)) { |
| // An existing namespace's policies have changed. |
| - NotifyNamespaceUpdated(it_new->first, *it_old->second, *it_new->second); |
| + changes.push_back( |
| + new PolicyChangeInfo(it_new->first, *it_old->second, |
| + *it_new->second)); |
| } |
| ++it_new; |
| ++it_old; |
| @@ -136,12 +164,23 @@ void PolicyServiceImpl::MergeAndTriggerUpdates() { |
| } |
| // Send updates for the remaining new namespaces, if any. |
| - for (; it_new != end_new; ++it_new) |
| - NotifyNamespaceUpdated(it_new->first, kEmpty, *it_new->second); |
| + for (; it_new != end_new; ++it_new) { |
| + changes.push_back( |
| + new PolicyChangeInfo(it_new->first, kEmpty, *it_new->second)); |
| + } |
| // Sends updates for the remaining removed namespaces, if any. |
| - for (; it_old != end_old; ++it_old) |
| - NotifyNamespaceUpdated(it_old->first, *it_old->second, kEmpty); |
| + for (; it_old != end_old; ++it_old) { |
| + changes.push_back( |
| + 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 :)
|
| + } |
| + |
| + // Walk our pending list of changes and send updates. |
| + for (ScopedVector<PolicyChangeInfo>::const_iterator iter = changes.begin(); |
| + iter != changes.end(); ++iter) { |
| + NotifyNamespaceUpdated((*iter)->policy_namespace_, (*iter)->previous_, |
| + (*iter)->current_); |
| + } |
| CheckInitializationComplete(); |
| CheckRefreshComplete(); |