kiosk_mode_settings.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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 "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
6
7#include <algorithm>
8
9#include "base/bind.h"
10#include "base/command_line.h"
11#include "base/lazy_instance.h"
12#include "chrome/browser/browser_process.h"
13#include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_screensaver.h"
14#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
15#include "chrome/browser/chromeos/settings/cros_settings.h"
16#include "chrome/browser/lifetime/application_lifetime.h"
17#include "chromeos/chromeos_switches.h"
18#include "chromeos/settings/cros_settings_names.h"
19#include "components/policy/core/common/cloud/cloud_policy_constants.h"
20#include "content/public/browser/browser_thread.h"
21
22namespace chromeos {
23
24namespace {
25const int kDeviceModeFetchRetryDelayMs = 500;
26}
27
28const int KioskModeSettings::kMaxIdleLogoutTimeout = 600000;  // ms
29const int KioskModeSettings::kMinIdleLogoutTimeout = 5000;  // ms
30
31const int KioskModeSettings::kMaxIdleLogoutWarningDuration = 60000;  // ms
32const int KioskModeSettings::kMinIdleLogoutWarningDuration = 1000;  // ms
33
34static base::LazyInstance<KioskModeSettings> g_kiosk_mode_settings =
35    LAZY_INSTANCE_INITIALIZER;
36
37// static
38KioskModeSettings* KioskModeSettings::Get() {
39  return g_kiosk_mode_settings.Pointer();
40}
41
42bool KioskModeSettings::IsKioskModeEnabled() {
43  return is_kiosk_mode_;
44}
45
46void KioskModeSettings::Initialize(const base::Closure& notify_initialized) {
47  // No need to call more than once.
48  if (is_initialized_) {
49    notify_initialized.Run();
50    return;
51  }
52
53  CrosSettings* cros_settings = CrosSettings::Get();
54  if (CrosSettingsProvider::TRUSTED != cros_settings->PrepareTrustedValues(
55      base::Bind(&KioskModeSettings::Initialize,
56                 base::Unretained(this),
57                 notify_initialized))) {
58    return;
59  }
60
61  // Ignored till we land the code to pull the screensaver path from the app
62  // packs with the screensaver id.
63  cros_settings->GetString(kScreenSaverExtensionId, &screensaver_id_);
64
65  int screensaver_timeout = 0;
66  int idle_logout_timeout = 0;
67  int idle_logout_warning_duration = 0;
68  cros_settings->GetInteger(kScreenSaverTimeout, &screensaver_timeout);
69  cros_settings->GetInteger(kIdleLogoutTimeout, &idle_logout_timeout);
70  cros_settings->GetInteger(kIdleLogoutWarningDuration,
71                            &idle_logout_warning_duration);
72
73  // Restrict idle timeouts to safe values to prevent them from being turned off
74  // or otherwise misused.
75  idle_logout_timeout = std::min(idle_logout_timeout,
76                                 KioskModeSettings::kMaxIdleLogoutTimeout);
77  idle_logout_timeout = std::max(idle_logout_timeout,
78                                 KioskModeSettings::kMinIdleLogoutTimeout);
79
80  idle_logout_warning_duration =
81      std::min(idle_logout_warning_duration,
82               KioskModeSettings::kMaxIdleLogoutWarningDuration);
83  idle_logout_warning_duration =
84      std::max(idle_logout_warning_duration,
85               KioskModeSettings::kMinIdleLogoutWarningDuration);
86
87  screensaver_timeout_ = base::TimeDelta::FromMilliseconds(
88      screensaver_timeout);
89  idle_logout_timeout_ =
90      base::TimeDelta::FromMilliseconds(idle_logout_timeout);
91  idle_logout_warning_duration_ =
92      base::TimeDelta::FromMilliseconds(idle_logout_warning_duration);
93
94  is_initialized_ = true;
95  notify_initialized.Run();
96}
97
98bool KioskModeSettings::is_initialized() const {
99  return is_initialized_;
100}
101
102void KioskModeSettings::GetScreensaverPath(
103    policy::AppPackUpdater::ScreenSaverUpdateCallback callback) const {
104  if (!is_initialized_) {
105    callback.Run(base::FilePath());
106    return;
107  }
108
109  // Command line flag overrides policy since it can be used
110  // for testing and dev workflows.
111  if (CommandLine::ForCurrentProcess()->HasSwitch(
112          switches::kKioskModeScreensaverPath)) {
113    callback.Run(base::FilePath(
114        CommandLine::ForCurrentProcess()->
115            GetSwitchValueASCII(switches::kKioskModeScreensaverPath)));
116    return;
117  }
118
119  if (g_browser_process) {
120    policy::BrowserPolicyConnectorChromeOS* connector =
121        g_browser_process->platform_part()->browser_policy_connector_chromeos();
122    if (connector && connector->GetAppPackUpdater()) {
123      connector->GetAppPackUpdater()->SetScreenSaverUpdateCallback(callback);
124      return;
125    }
126  }
127}
128
129base::TimeDelta KioskModeSettings::GetScreensaverTimeout() const {
130  if (!is_initialized_)
131    return base::TimeDelta::FromSeconds(-1);
132
133  return screensaver_timeout_;
134}
135
136base::TimeDelta KioskModeSettings::GetIdleLogoutTimeout() const {
137  if (!is_initialized_)
138    return base::TimeDelta::FromSeconds(-1);
139
140  return idle_logout_timeout_;
141}
142
143base::TimeDelta KioskModeSettings::GetIdleLogoutWarningDuration() const {
144  if (!is_initialized_)
145    return base::TimeDelta::FromSeconds(-1);
146
147  return idle_logout_warning_duration_;
148}
149
150KioskModeSettings::KioskModeSettings() : is_initialized_(false) {
151  // In case we've force-enabled kiosk mode.
152  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableKioskMode)) {
153    is_kiosk_mode_ = true;
154    return;
155  }
156
157  // Precache the value as we know it at construction time to avoid serving
158  // different values to different users.
159  if (g_browser_process) {
160    policy::BrowserPolicyConnectorChromeOS* connector =
161        g_browser_process->platform_part()->browser_policy_connector_chromeos();
162    policy::DeviceMode device_mode = connector->GetDeviceMode();
163    if (device_mode == policy::DEVICE_MODE_RETAIL_KIOSK) {
164      is_kiosk_mode_ = true;
165      return;
166    } else if (device_mode == policy::DEVICE_MODE_PENDING){
167      DeviceSettingsService::Get()->GetOwnershipStatusAsync(
168          base::Bind(&KioskModeSettings::VerifyModeIsKnown,
169                     base::Unretained(this)));
170    }
171  }
172  is_kiosk_mode_ = false;
173}
174
175KioskModeSettings::~KioskModeSettings() {
176}
177
178void KioskModeSettings::VerifyModeIsKnown(
179    DeviceSettingsService::OwnershipStatus status) {
180  if (status != DeviceSettingsService::OWNERSHIP_TAKEN)
181    return;
182
183  if (g_browser_process) {
184    policy::BrowserPolicyConnectorChromeOS* connector =
185        g_browser_process->platform_part()->browser_policy_connector_chromeos();
186    policy::DeviceMode device_mode = connector->GetDeviceMode();
187    // We retry asking for the mode until it becomes known.
188    switch (device_mode) {
189      case policy::DEVICE_MODE_PENDING:
190        content::BrowserThread::PostDelayedTask(
191            content::BrowserThread::UI, FROM_HERE,
192            base::Bind(&KioskModeSettings::VerifyModeIsKnown,
193                       base::Unretained(this), status),
194            base::TimeDelta::FromMilliseconds(kDeviceModeFetchRetryDelayMs));
195        break;
196      case policy::DEVICE_MODE_RETAIL_KIOSK:
197        chrome::AttemptRestart();
198        break;
199      default:
200        break;
201    }
202  }
203}
204
205
206}  // namespace chromeos
207