This source file includes following definitions.
- FixDeprecatedPolicies
- AddObserver
- RemoveObserver
- GetPolicies
- IsInitializationComplete
- RefreshPolicies
- OnUpdatePolicy
- NotifyNamespaceUpdated
- MergeAndTriggerUpdates
- CheckInitializationComplete
- CheckRefreshComplete
#include "components/policy/core/common/policy_service_impl.h"
#include <algorithm>
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "components/policy/core/common/policy_bundle.h"
#include "components/policy/core/common/policy_map.h"
#include "policy/policy_constants.h"
namespace policy {
typedef PolicyServiceImpl::Providers::const_iterator Iterator;
namespace {
const char* kProxyPolicies[] = {
key::kProxyMode,
key::kProxyServerMode,
key::kProxyServer,
key::kProxyPacUrl,
key::kProxyBypassList,
};
void FixDeprecatedPolicies(PolicyMap* policies) {
PolicyMap::Entry current_priority;
scoped_ptr<base::DictionaryValue> proxy_settings(new base::DictionaryValue);
for (size_t i = 0; i < arraysize(kProxyPolicies); ++i) {
const PolicyMap::Entry* entry = policies->Get(kProxyPolicies[i]);
if (entry) {
if (entry->has_higher_priority_than(current_priority)) {
proxy_settings->Clear();
current_priority = *entry;
}
if (!entry->has_higher_priority_than(current_priority) &&
!current_priority.has_higher_priority_than(*entry)) {
proxy_settings->Set(kProxyPolicies[i], entry->value->DeepCopy());
}
policies->Erase(kProxyPolicies[i]);
}
}
const PolicyMap::Entry* existing = policies->Get(key::kProxySettings);
if (!proxy_settings->empty() &&
(!existing || current_priority.has_higher_priority_than(*existing))) {
policies->Set(key::kProxySettings,
current_priority.level,
current_priority.scope,
proxy_settings.release(),
NULL);
}
}
}
PolicyServiceImpl::PolicyServiceImpl(const Providers& providers)
: update_task_ptr_factory_(this) {
for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain)
initialization_complete_[domain] = true;
providers_ = providers;
for (Iterator it = providers.begin(); it != providers.end(); ++it) {
ConfigurationPolicyProvider* provider = *it;
provider->AddObserver(this);
for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain) {
initialization_complete_[domain] &=
provider->IsInitializationComplete(static_cast<PolicyDomain>(domain));
}
}
MergeAndTriggerUpdates();
}
PolicyServiceImpl::~PolicyServiceImpl() {
for (Iterator it = providers_.begin(); it != providers_.end(); ++it)
(*it)->RemoveObserver(this);
STLDeleteValues(&observers_);
}
void PolicyServiceImpl::AddObserver(PolicyDomain domain,
PolicyService::Observer* observer) {
Observers*& list = observers_[domain];
if (!list)
list = new Observers();
list->AddObserver(observer);
}
void PolicyServiceImpl::RemoveObserver(PolicyDomain domain,
PolicyService::Observer* observer) {
ObserverMap::iterator it = observers_.find(domain);
if (it == observers_.end()) {
NOTREACHED();
return;
}
it->second->RemoveObserver(observer);
if (!it->second->might_have_observers()) {
delete it->second;
observers_.erase(it);
}
}
const PolicyMap& PolicyServiceImpl::GetPolicies(
const PolicyNamespace& ns) const {
return policy_bundle_.Get(ns);
}
bool PolicyServiceImpl::IsInitializationComplete(PolicyDomain domain) const {
DCHECK(domain >= 0 && domain < POLICY_DOMAIN_SIZE);
return initialization_complete_[domain];
}
void PolicyServiceImpl::RefreshPolicies(const base::Closure& callback) {
if (!callback.is_null())
refresh_callbacks_.push_back(callback);
if (providers_.empty()) {
update_task_ptr_factory_.InvalidateWeakPtrs();
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&PolicyServiceImpl::MergeAndTriggerUpdates,
update_task_ptr_factory_.GetWeakPtr()));
} else {
for (Iterator it = providers_.begin(); it != providers_.end(); ++it)
refresh_pending_.insert(*it);
for (Iterator it = providers_.begin(); it != providers_.end(); ++it)
(*it)->RefreshPolicies();
}
}
void PolicyServiceImpl::OnUpdatePolicy(ConfigurationPolicyProvider* provider) {
DCHECK_EQ(1, std::count(providers_.begin(), providers_.end(), provider));
refresh_pending_.erase(provider);
update_task_ptr_factory_.InvalidateWeakPtrs();
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&PolicyServiceImpl::MergeAndTriggerUpdates,
update_task_ptr_factory_.GetWeakPtr()));
}
void PolicyServiceImpl::NotifyNamespaceUpdated(
const PolicyNamespace& ns,
const PolicyMap& previous,
const PolicyMap& current) {
ObserverMap::iterator iterator = observers_.find(ns.domain);
if (iterator != observers_.end()) {
FOR_EACH_OBSERVER(PolicyService::Observer,
*iterator->second,
OnPolicyUpdated(ns, previous, current));
}
}
void PolicyServiceImpl::MergeAndTriggerUpdates() {
const PolicyNamespace chrome_namespace(POLICY_DOMAIN_CHROME, std::string());
PolicyBundle bundle;
for (Iterator it = providers_.begin(); it != providers_.end(); ++it) {
PolicyBundle provided_bundle;
provided_bundle.CopyFrom((*it)->policies());
FixDeprecatedPolicies(&provided_bundle.Get(chrome_namespace));
bundle.MergeFrom(provided_bundle);
}
policy_bundle_.Swap(&bundle);
const PolicyMap kEmpty;
PolicyBundle::const_iterator it_new = policy_bundle_.begin();
PolicyBundle::const_iterator end_new = policy_bundle_.end();
PolicyBundle::const_iterator it_old = bundle.begin();
PolicyBundle::const_iterator end_old = bundle.end();
while (it_new != end_new && it_old != end_old) {
if (it_new->first < it_old->first) {
NotifyNamespaceUpdated(it_new->first, kEmpty, *it_new->second);
++it_new;
} else if (it_old->first < it_new->first) {
NotifyNamespaceUpdated(it_old->first, *it_old->second, kEmpty);
++it_old;
} else {
if (!it_new->second->Equals(*it_old->second)) {
NotifyNamespaceUpdated(it_new->first, *it_old->second, *it_new->second);
}
++it_new;
++it_old;
}
}
for (; it_new != end_new; ++it_new)
NotifyNamespaceUpdated(it_new->first, kEmpty, *it_new->second);
for (; it_old != end_old; ++it_old)
NotifyNamespaceUpdated(it_old->first, *it_old->second, kEmpty);
CheckInitializationComplete();
CheckRefreshComplete();
}
void PolicyServiceImpl::CheckInitializationComplete() {
for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain) {
if (initialization_complete_[domain])
continue;
PolicyDomain policy_domain = static_cast<PolicyDomain>(domain);
bool all_complete = true;
for (Iterator it = providers_.begin(); it != providers_.end(); ++it) {
if (!(*it)->IsInitializationComplete(policy_domain)) {
all_complete = false;
break;
}
}
if (all_complete) {
initialization_complete_[domain] = true;
ObserverMap::iterator iter = observers_.find(policy_domain);
if (iter != observers_.end()) {
FOR_EACH_OBSERVER(PolicyService::Observer,
*iter->second,
OnPolicyServiceInitialized(policy_domain));
}
}
}
}
void PolicyServiceImpl::CheckRefreshComplete() {
if (refresh_pending_.empty() && !refresh_callbacks_.empty()) {
std::vector<base::Closure> callbacks;
callbacks.swap(refresh_callbacks_);
std::vector<base::Closure>::iterator it;
for (it = callbacks.begin(); it != callbacks.end(); ++it)
it->Run();
}
}
}