1// Copyright 2013 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 "chrome/browser/chromeos/policy/login_profile_policy_provider.h"
6
7#include <string>
8
9#include "base/bind.h"
10#include "base/callback.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/values.h"
13#include "chromeos/dbus/power_policy_controller.h"
14#include "components/policy/core/browser/policy_error_map.h"
15#include "components/policy/core/common/external_data_fetcher.h"
16#include "components/policy/core/common/policy_bundle.h"
17#include "components/policy/core/common/policy_map.h"
18#include "components/policy/core/common/policy_types.h"
19#include "policy/policy_constants.h"
20
21namespace policy {
22
23namespace {
24
25const char kLidCloseAction[] = "LidCloseAction";
26const char kUserActivityScreenDimDelayScale[] =
27    "UserActivityScreenDimDelayScale";
28
29const char kActionSuspend[] = "Suspend";
30const char kActionLogout[] = "Logout";
31const char kActionShutdown[]  = "Shutdown";
32const char kActionDoNothing[] = "DoNothing";
33
34scoped_ptr<base::Value> GetAction(const std::string &action) {
35  if (action == kActionSuspend) {
36    return scoped_ptr<base::Value>(new base::FundamentalValue(
37        chromeos::PowerPolicyController::ACTION_SUSPEND));
38  }
39  if (action == kActionLogout) {
40    return scoped_ptr<base::Value>(new base::FundamentalValue(
41        chromeos::PowerPolicyController::ACTION_STOP_SESSION));
42  }
43  if (action == kActionShutdown) {
44    return scoped_ptr<base::Value>(new base::FundamentalValue(
45        chromeos::PowerPolicyController::ACTION_SHUT_DOWN));
46  }
47  if (action == kActionDoNothing) {
48    return scoped_ptr<base::Value>(new base::FundamentalValue(
49        chromeos::PowerPolicyController::ACTION_DO_NOTHING));
50  }
51  return scoped_ptr<base::Value>();
52}
53
54
55// Applies the value of |device_policy| in |device_policy_map| as the
56// recommended value of |user_policy| in |user_policy_map|. If the value of
57// |device_policy| is unset, does nothing.
58void ApplyDevicePolicyAsRecommendedPolicy(const std::string& device_policy,
59                                          const std::string& user_policy,
60                                          const PolicyMap& device_policy_map,
61                                          PolicyMap* user_policy_map) {
62  const base::Value* value = device_policy_map.GetValue(device_policy);
63  if (value) {
64    user_policy_map->Set(user_policy,
65                         POLICY_LEVEL_RECOMMENDED,
66                         POLICY_SCOPE_USER,
67                         value->DeepCopy(),
68                         NULL);
69  }
70}
71
72// Applies |value| as the mandatory value of |user_policy| in |user_policy_map|.
73// If |value| is NULL, does nothing.
74void ApplyValueAsMandatoryPolicy(const base::Value* value,
75                                 const std::string& user_policy,
76                                 PolicyMap* user_policy_map) {
77  if (value) {
78    user_policy_map->Set(user_policy,
79                         POLICY_LEVEL_MANDATORY,
80                         POLICY_SCOPE_USER,
81                         value->DeepCopy(),
82                         NULL);
83  }
84}
85
86}  // namespace
87
88LoginProfilePolicyProvider::LoginProfilePolicyProvider(
89    PolicyService* device_policy_service)
90    : device_policy_service_(device_policy_service),
91      waiting_for_device_policy_refresh_(false),
92      weak_factory_(this) {
93}
94
95LoginProfilePolicyProvider::~LoginProfilePolicyProvider() {
96}
97
98void LoginProfilePolicyProvider::Init(SchemaRegistry* registry) {
99  ConfigurationPolicyProvider::Init(registry);
100  device_policy_service_->AddObserver(POLICY_DOMAIN_CHROME, this);
101  if (device_policy_service_->IsInitializationComplete(POLICY_DOMAIN_CHROME))
102    UpdateFromDevicePolicy();
103}
104
105void LoginProfilePolicyProvider::Shutdown() {
106  device_policy_service_->RemoveObserver(POLICY_DOMAIN_CHROME, this);
107  weak_factory_.InvalidateWeakPtrs();
108  ConfigurationPolicyProvider::Shutdown();
109}
110
111void LoginProfilePolicyProvider::RefreshPolicies() {
112  waiting_for_device_policy_refresh_ = true;
113  weak_factory_.InvalidateWeakPtrs();
114  device_policy_service_->RefreshPolicies(base::Bind(
115      &LoginProfilePolicyProvider::OnDevicePolicyRefreshDone,
116      weak_factory_.GetWeakPtr()));
117}
118
119void LoginProfilePolicyProvider::OnPolicyUpdated(const PolicyNamespace& ns,
120                                                 const PolicyMap& previous,
121                                                 const PolicyMap& current) {
122  if (ns == PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
123    UpdateFromDevicePolicy();
124}
125
126void LoginProfilePolicyProvider::OnPolicyServiceInitialized(
127    PolicyDomain domain) {
128  if (domain == POLICY_DOMAIN_CHROME)
129    UpdateFromDevicePolicy();
130}
131
132void LoginProfilePolicyProvider::OnDevicePolicyRefreshDone() {
133  waiting_for_device_policy_refresh_ = false;
134  UpdateFromDevicePolicy();
135}
136
137void LoginProfilePolicyProvider::UpdateFromDevicePolicy() {
138  // If a policy refresh is in progress, wait for it to finish.
139  if (waiting_for_device_policy_refresh_)
140    return;
141
142  const PolicyNamespace chrome_namespaces(POLICY_DOMAIN_CHROME, std::string());
143  const PolicyMap& device_policy_map =
144      device_policy_service_->GetPolicies(chrome_namespaces);
145  scoped_ptr<PolicyBundle> bundle(new PolicyBundle);
146  PolicyMap& user_policy_map = bundle->Get(chrome_namespaces);
147
148  ApplyDevicePolicyAsRecommendedPolicy(
149      key::kDeviceLoginScreenDefaultLargeCursorEnabled,
150      key::kLargeCursorEnabled,
151      device_policy_map, &user_policy_map);
152  ApplyDevicePolicyAsRecommendedPolicy(
153      key::kDeviceLoginScreenDefaultSpokenFeedbackEnabled,
154      key::kSpokenFeedbackEnabled,
155      device_policy_map, &user_policy_map);
156  ApplyDevicePolicyAsRecommendedPolicy(
157      key::kDeviceLoginScreenDefaultHighContrastEnabled,
158      key::kHighContrastEnabled,
159      device_policy_map, &user_policy_map);
160  ApplyDevicePolicyAsRecommendedPolicy(
161      key::kDeviceLoginScreenDefaultScreenMagnifierType,
162      key::kScreenMagnifierType,
163      device_policy_map, &user_policy_map);
164  ApplyDevicePolicyAsRecommendedPolicy(
165      key::kDeviceLoginScreenDefaultVirtualKeyboardEnabled,
166      key::kVirtualKeyboardEnabled,
167      device_policy_map, &user_policy_map);
168
169  const base::Value* value =
170      device_policy_map.GetValue(key::kDeviceLoginScreenPowerManagement);
171  const base::DictionaryValue* dict = NULL;
172  if (value && value->GetAsDictionary(&dict)) {
173    scoped_ptr<base::DictionaryValue> policy_value(dict->DeepCopy());
174    std::string lid_close_action;
175    base::Value* screen_dim_delay_scale = NULL;
176
177    if (policy_value->GetString(kLidCloseAction, &lid_close_action)) {
178      scoped_ptr<base::Value> action = GetAction(lid_close_action);
179      if (action) {
180        ApplyValueAsMandatoryPolicy(
181            action.get(), key::kLidCloseAction, &user_policy_map);
182      }
183      policy_value->Remove(kLidCloseAction, NULL);
184    }
185
186    if (policy_value->Get(kUserActivityScreenDimDelayScale,
187                          &screen_dim_delay_scale)) {
188      ApplyValueAsMandatoryPolicy(screen_dim_delay_scale,
189                                  key::kUserActivityScreenDimDelayScale,
190                                  &user_policy_map);
191      policy_value->Remove(kUserActivityScreenDimDelayScale, NULL);
192    }
193
194    // |policy_value| is expected to be a valid value for the
195    // PowerManagementIdleSettings policy now.
196    if (!policy_value->empty()) {
197      ApplyValueAsMandatoryPolicy(policy_value.get(),
198                                  key::kPowerManagementIdleSettings,
199                                  &user_policy_map);
200    }
201  }
202
203  UpdatePolicy(bundle.Pass());
204}
205
206}  // namespace policy
207