15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/policy_service_impl.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/values.h" 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/policy/core/common/policy_bundle.h" 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/policy/core/common/policy_map.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "policy/policy_constants.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace policy { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef PolicyServiceImpl::Providers::const_iterator Iterator; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char* kProxyPolicies[] = { 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) key::kProxyMode, 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) key::kProxyServerMode, 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) key::kProxyServer, 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) key::kProxyPacUrl, 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) key::kProxyBypassList, 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FixDeprecatedPolicies(PolicyMap* policies) { 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Proxy settings have been configured by 5 policies that didn't mix well 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // together, and maps of policies had to take this into account when merging 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // policy sources. The proxy settings will eventually be configured by a 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // single Dictionary policy when all providers have support for that. For 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // now, the individual policies are mapped here to a single Dictionary policy 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // that the rest of the policy machinery uses. 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The highest (level, scope) pair for an existing proxy policy is determined 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // first, and then only policies with those exact attributes are merged. 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PolicyMap::Entry current_priority; // Defaults to the lowest priority. 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> proxy_settings(new base::DictionaryValue); 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < arraysize(kProxyPolicies); ++i) { 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PolicyMap::Entry* entry = policies->Get(kProxyPolicies[i]); 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (entry) { 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (entry->has_higher_priority_than(current_priority)) { 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) proxy_settings->Clear(); 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) current_priority = *entry; 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!entry->has_higher_priority_than(current_priority) && 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !current_priority.has_higher_priority_than(*entry)) { 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) proxy_settings->Set(kProxyPolicies[i], entry->value->DeepCopy()); 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) policies->Erase(kProxyPolicies[i]); 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Sets the new |proxy_settings| if kProxySettings isn't set yet, or if the 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // new priority is higher. 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PolicyMap::Entry* existing = policies->Get(key::kProxySettings); 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!proxy_settings->empty() && 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (!existing || current_priority.has_higher_priority_than(*existing))) { 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) policies->Set(key::kProxySettings, 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) current_priority.level, 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) current_priority.scope, 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) proxy_settings.release(), 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL); 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PolicyServiceImpl::PolicyServiceImpl(const Providers& providers) 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : update_task_ptr_factory_(this) { 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) initialization_complete_[domain] = true; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers_ = providers; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Iterator it = providers.begin(); it != providers.end(); ++it) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConfigurationPolicyProvider* provider = *it; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider->AddObserver(this); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain) { 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) initialization_complete_[domain] &= 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) provider->IsInitializationComplete(static_cast<PolicyDomain>(domain)); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There are no observers yet, but calls to GetPolicies() should already get 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the processed policy values. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MergeAndTriggerUpdates(); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PolicyServiceImpl::~PolicyServiceImpl() { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Iterator it = providers_.begin(); it != providers_.end(); ++it) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*it)->RemoveObserver(this); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteValues(&observers_); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyServiceImpl::AddObserver(PolicyDomain domain, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PolicyService::Observer* observer) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Observers*& list = observers_[domain]; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!list) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list = new Observers(); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list->AddObserver(observer); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyServiceImpl::RemoveObserver(PolicyDomain domain, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PolicyService::Observer* observer) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ObserverMap::iterator it = observers_.find(domain); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it == observers_.end()) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->second->RemoveObserver(observer); 112424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!it->second->might_have_observers()) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete it->second; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.erase(it); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const PolicyMap& PolicyServiceImpl::GetPolicies( 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const PolicyNamespace& ns) const { 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return policy_bundle_.Get(ns); 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool PolicyServiceImpl::IsInitializationComplete(PolicyDomain domain) const { 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(domain >= 0 && domain < POLICY_DOMAIN_SIZE); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return initialization_complete_[domain]; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyServiceImpl::RefreshPolicies(const base::Closure& callback) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!callback.is_null()) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) refresh_callbacks_.push_back(callback); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (providers_.empty()) { 133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Refresh is immediately complete if there are no providers. See the note 134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // on OnUpdatePolicy() about why this is a posted task. 135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) update_task_ptr_factory_.InvalidateWeakPtrs(); 136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::MessageLoop::current()->PostTask( 137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FROM_HERE, 138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&PolicyServiceImpl::MergeAndTriggerUpdates, 139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) update_task_ptr_factory_.GetWeakPtr())); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some providers might invoke OnUpdatePolicy synchronously while handling 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RefreshPolicies. Mark all as pending before refreshing. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Iterator it = providers_.begin(); it != providers_.end(); ++it) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) refresh_pending_.insert(*it); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Iterator it = providers_.begin(); it != providers_.end(); ++it) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*it)->RefreshPolicies(); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyServiceImpl::OnUpdatePolicy(ConfigurationPolicyProvider* provider) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(1, std::count(providers_.begin(), providers_.end(), provider)); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) refresh_pending_.erase(provider); 153a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 154a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Note: a policy change may trigger further policy changes in some providers. 155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // For example, disabling SigninAllowed would cause the CloudPolicyManager to 156a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // drop all its policies, which makes this method enter again for that 157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // provider. 158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // 159a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Therefore this update is posted asynchronously, to prevent reentrancy in 160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // MergeAndTriggerUpdates. Also, cancel a pending update if there is any, 161a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // since both will produce the same PolicyBundle. 162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) update_task_ptr_factory_.InvalidateWeakPtrs(); 163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::MessageLoop::current()->PostTask( 164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FROM_HERE, 165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&PolicyServiceImpl::MergeAndTriggerUpdates, 166a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) update_task_ptr_factory_.GetWeakPtr())); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyServiceImpl::NotifyNamespaceUpdated( 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const PolicyNamespace& ns, 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PolicyMap& previous, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PolicyMap& current) { 173a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ObserverMap::iterator iterator = observers_.find(ns.domain); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iterator != observers_.end()) { 175a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FOR_EACH_OBSERVER(PolicyService::Observer, 176a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) *iterator->second, 177a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) OnPolicyUpdated(ns, previous, current)); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyServiceImpl::MergeAndTriggerUpdates() { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Merge from each provider in their order of priority. 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PolicyNamespace chrome_namespace(POLICY_DOMAIN_CHROME, std::string()); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PolicyBundle bundle; 185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (Iterator it = providers_.begin(); it != providers_.end(); ++it) { 186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PolicyBundle provided_bundle; 187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) provided_bundle.CopyFrom((*it)->policies()); 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FixDeprecatedPolicies(&provided_bundle.Get(chrome_namespace)); 189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bundle.MergeFrom(provided_bundle); 190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Swap first, so that observers that call GetPolicies() see the current 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // values. 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) policy_bundle_.Swap(&bundle); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only notify observers of namespaces that have been modified. 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PolicyMap kEmpty; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PolicyBundle::const_iterator it_new = policy_bundle_.begin(); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PolicyBundle::const_iterator end_new = policy_bundle_.end(); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PolicyBundle::const_iterator it_old = bundle.begin(); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PolicyBundle::const_iterator end_old = bundle.end(); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (it_new != end_new && it_old != end_old) { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it_new->first < it_old->first) { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A new namespace is available. 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyNamespaceUpdated(it_new->first, kEmpty, *it_new->second); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it_new; 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (it_old->first < it_new->first) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A previously available namespace is now gone. 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyNamespaceUpdated(it_old->first, *it_old->second, kEmpty); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it_old; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!it_new->second->Equals(*it_old->second)) { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An existing namespace's policies have changed. 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyNamespaceUpdated(it_new->first, *it_old->second, *it_new->second); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it_new; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it_old; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send updates for the remaining new namespaces, if any. 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; it_new != end_new; ++it_new) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyNamespaceUpdated(it_new->first, kEmpty, *it_new->second); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sends updates for the remaining removed namespaces, if any. 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; it_old != end_old; ++it_old) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyNamespaceUpdated(it_old->first, *it_old->second, kEmpty); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckInitializationComplete(); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckRefreshComplete(); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyServiceImpl::CheckInitializationComplete() { 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check if all the providers just became initialized for each domain; if so, 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // notify that domain's observers. 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain) { 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (initialization_complete_[domain]) 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PolicyDomain policy_domain = static_cast<PolicyDomain>(domain); 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool all_complete = true; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Iterator it = providers_.begin(); it != providers_.end(); ++it) { 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!(*it)->IsInitializationComplete(policy_domain)) { 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) all_complete = false; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (all_complete) { 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) initialization_complete_[domain] = true; 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ObserverMap::iterator iter = observers_.find(policy_domain); 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (iter != observers_.end()) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(PolicyService::Observer, 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *iter->second, 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnPolicyServiceInitialized(policy_domain)); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyServiceImpl::CheckRefreshComplete() { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invoke all the callbacks if a refresh has just fully completed. 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (refresh_pending_.empty() && !refresh_callbacks_.empty()) { 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<base::Closure> callbacks; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callbacks.swap(refresh_callbacks_); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<base::Closure>::iterator it; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (it = callbacks.begin(); it != callbacks.end(); ++it) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->Run(); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace policy 273