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