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..4b9c335ea7c80a417faed0b46ac9a2f32185497b 100644 |
--- a/chrome/browser/policy/policy_service_impl.cc |
+++ b/chrome/browser/policy/policy_service_impl.cc |
@@ -6,6 +6,8 @@ |
#include <algorithm> |
+#include "base/bind.h" |
+#include "base/message_loop.h" |
#include "base/stl_util.h" |
#include "chrome/browser/policy/policy_map.h" |
@@ -13,7 +15,8 @@ namespace policy { |
typedef PolicyServiceImpl::Providers::const_iterator Iterator; |
-PolicyServiceImpl::PolicyServiceImpl(const Providers& providers) { |
+PolicyServiceImpl::PolicyServiceImpl(const Providers& providers) |
+ : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
initialization_complete_ = true; |
providers_ = providers; |
for (Iterator it = providers.begin(); it != providers.end(); ++it) { |
@@ -91,15 +94,53 @@ void PolicyServiceImpl::NotifyNamespaceUpdated( |
const PolicyBundle::PolicyNamespace& ns, |
const PolicyMap& previous, |
const PolicyMap& current) { |
- ObserverMap::iterator iterator = observers_.find(ns.first); |
+ // If running a unit test that hasn't setup a MessageLoop, don't send any |
+ // notifications. |
+ if (!MessageLoop::current()) |
+ return; |
+ |
+ // Don't queue up a task if we have no observers - that way Observers added |
+ // later don't get notified of changes that happened during construction time. |
+ if (observers_.find(ns.first) == observers_.end()) |
+ return; |
+ |
+ // Notify Observers via a queued task, so Observers can't trigger a re-entrant |
+ // call to MergeAndTriggerUpdates() by modifying policy. |
+ scoped_ptr<PolicyChangeInfo> changes( |
Joao da Silva
2013/01/07 09:23:52
#include "base/memory/scoped_ptr.h"
Andrew T Wilson (Slow)
2013/01/07 14:11:32
Done.
|
+ new PolicyChangeInfo(ns, previous, current)); |
+ MessageLoop::current()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&PolicyServiceImpl::NotifyNamespaceUpdatedTask, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ base::Passed(&changes))); |
+} |
+ |
+void PolicyServiceImpl::NotifyNamespaceUpdatedTask( |
+ scoped_ptr<PolicyChangeInfo> changes) { |
+ ObserverMap::iterator iterator = observers_.find( |
+ changes->policy_namespace_.first); |
if (iterator != observers_.end()) { |
FOR_EACH_OBSERVER( |
PolicyService::Observer, |
*iterator->second, |
- OnPolicyUpdated(ns.first, ns.second, previous, current)); |
+ OnPolicyUpdated(changes->policy_namespace_.first, |
+ changes->policy_namespace_.second, |
+ changes->previous_, |
+ changes->current_)); |
} |
} |
+PolicyServiceImpl::PolicyChangeInfo::PolicyChangeInfo( |
Joao da Silva
2013/01/07 09:23:52
Place the definitions for PolicyChangeInfo before
Andrew T Wilson (Slow)
2013/01/07 14:11:32
Done.
|
+ const PolicyBundle::PolicyNamespace& policy_namespace, |
+ const PolicyMap& previous, const PolicyMap& current) |
+ : policy_namespace_(policy_namespace) { |
+ previous_.CopyFrom(previous); |
+ current_.CopyFrom(current); |
+} |
+ |
+PolicyServiceImpl::PolicyChangeInfo::~PolicyChangeInfo() { |
+} |
+ |
void PolicyServiceImpl::MergeAndTriggerUpdates() { |
// Merge from each provider in their order of priority. |
PolicyBundle bundle; |