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 3// found in the LICENSE file. 4 5#include "components/policy/core/browser/configuration_policy_pref_store.h" 6 7#include <string> 8#include <vector> 9 10#include "base/bind.h" 11#include "base/logging.h" 12#include "base/message_loop/message_loop.h" 13#include "base/prefs/pref_value_map.h" 14#include "base/strings/string16.h" 15#include "base/strings/utf_string_conversions.h" 16#include "components/policy/core/browser/configuration_policy_handler_list.h" 17#include "components/policy/core/browser/policy_error_map.h" 18 19namespace policy { 20 21namespace { 22 23// Policies are loaded early on startup, before PolicyErrorMaps are ready to 24// be retrieved. This function is posted to UI to log any errors found on 25// Refresh below. 26void LogErrors(PolicyErrorMap* errors) { 27 PolicyErrorMap::const_iterator iter; 28 for (iter = errors->begin(); iter != errors->end(); ++iter) { 29 base::string16 policy = base::ASCIIToUTF16(iter->first); 30 DLOG(WARNING) << "Policy " << policy << ": " << iter->second; 31 } 32} 33 34} // namespace 35 36ConfigurationPolicyPrefStore::ConfigurationPolicyPrefStore( 37 PolicyService* service, 38 const ConfigurationPolicyHandlerList* handler_list, 39 PolicyLevel level) 40 : policy_service_(service), 41 handler_list_(handler_list), 42 level_(level) { 43 // Read initial policy. 44 prefs_.reset(CreatePreferencesFromPolicies()); 45 policy_service_->AddObserver(POLICY_DOMAIN_CHROME, this); 46} 47 48void ConfigurationPolicyPrefStore::AddObserver(PrefStore::Observer* observer) { 49 observers_.AddObserver(observer); 50} 51 52void ConfigurationPolicyPrefStore::RemoveObserver( 53 PrefStore::Observer* observer) { 54 observers_.RemoveObserver(observer); 55} 56 57bool ConfigurationPolicyPrefStore::HasObservers() const { 58 return observers_.might_have_observers(); 59} 60 61bool ConfigurationPolicyPrefStore::IsInitializationComplete() const { 62 return policy_service_->IsInitializationComplete(POLICY_DOMAIN_CHROME); 63} 64 65bool ConfigurationPolicyPrefStore::GetValue(const std::string& key, 66 const base::Value** value) const { 67 const base::Value* stored_value = NULL; 68 if (!prefs_.get() || !prefs_->GetValue(key, &stored_value)) 69 return false; 70 71 if (value) 72 *value = stored_value; 73 return true; 74} 75 76void ConfigurationPolicyPrefStore::OnPolicyUpdated( 77 const PolicyNamespace& ns, 78 const PolicyMap& previous, 79 const PolicyMap& current) { 80 DCHECK_EQ(POLICY_DOMAIN_CHROME, ns.domain); 81 DCHECK(ns.component_id.empty()); 82 Refresh(); 83} 84 85void ConfigurationPolicyPrefStore::OnPolicyServiceInitialized( 86 PolicyDomain domain) { 87 if (domain == POLICY_DOMAIN_CHROME) { 88 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, 89 OnInitializationCompleted(true)); 90 } 91} 92 93ConfigurationPolicyPrefStore::~ConfigurationPolicyPrefStore() { 94 policy_service_->RemoveObserver(POLICY_DOMAIN_CHROME, this); 95} 96 97void ConfigurationPolicyPrefStore::Refresh() { 98 scoped_ptr<PrefValueMap> new_prefs(CreatePreferencesFromPolicies()); 99 std::vector<std::string> changed_prefs; 100 new_prefs->GetDifferingKeys(prefs_.get(), &changed_prefs); 101 prefs_.swap(new_prefs); 102 103 // Send out change notifications. 104 for (std::vector<std::string>::const_iterator pref(changed_prefs.begin()); 105 pref != changed_prefs.end(); 106 ++pref) { 107 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, 108 OnPrefValueChanged(*pref)); 109 } 110} 111 112PrefValueMap* ConfigurationPolicyPrefStore::CreatePreferencesFromPolicies() { 113 scoped_ptr<PrefValueMap> prefs(new PrefValueMap); 114 PolicyMap filtered_policies; 115 filtered_policies.CopyFrom(policy_service_->GetPolicies( 116 PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))); 117 filtered_policies.FilterLevel(level_); 118 119 scoped_ptr<PolicyErrorMap> errors(new PolicyErrorMap); 120 121 handler_list_->ApplyPolicySettings(filtered_policies, 122 prefs.get(), 123 errors.get()); 124 125 // Retrieve and log the errors once the UI loop is ready. This is only an 126 // issue during startup. 127 base::MessageLoop::current()->PostTask( 128 FROM_HERE, base::Bind(&LogErrors, base::Owned(errors.release()))); 129 130 return prefs.release(); 131} 132 133} // namespace policy 134