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
22 namespace chromeos {
23
24 namespace {
25 const int kDeviceModeFetchRetryDelayMs = 500;
26 }
27
28 const int KioskModeSettings::kMaxIdleLogoutTimeout = 600000; // ms
29 const int KioskModeSettings::kMinIdleLogoutTimeout = 5000; // ms
30
31 const int KioskModeSettings::kMaxIdleLogoutWarningDuration = 60000; // ms
32 const int KioskModeSettings::kMinIdleLogoutWarningDuration = 1000; // ms
33
34 static base::LazyInstance<KioskModeSettings> g_kiosk_mode_settings =
35 LAZY_INSTANCE_INITIALIZER;
36
37 // static
Get()38 KioskModeSettings* KioskModeSettings::Get() {
39 return g_kiosk_mode_settings.Pointer();
40 }
41
IsKioskModeEnabled()42 bool KioskModeSettings::IsKioskModeEnabled() {
43 return is_kiosk_mode_;
44 }
45
Initialize(const base::Closure & notify_initialized)46 void 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
is_initialized() const98 bool KioskModeSettings::is_initialized() const {
99 return is_initialized_;
100 }
101
GetScreensaverPath(policy::AppPackUpdater::ScreenSaverUpdateCallback callback) const102 void 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
GetScreensaverTimeout() const129 base::TimeDelta KioskModeSettings::GetScreensaverTimeout() const {
130 if (!is_initialized_)
131 return base::TimeDelta::FromSeconds(-1);
132
133 return screensaver_timeout_;
134 }
135
GetIdleLogoutTimeout() const136 base::TimeDelta KioskModeSettings::GetIdleLogoutTimeout() const {
137 if (!is_initialized_)
138 return base::TimeDelta::FromSeconds(-1);
139
140 return idle_logout_timeout_;
141 }
142
GetIdleLogoutWarningDuration() const143 base::TimeDelta KioskModeSettings::GetIdleLogoutWarningDuration() const {
144 if (!is_initialized_)
145 return base::TimeDelta::FromSeconds(-1);
146
147 return idle_logout_warning_duration_;
148 }
149
KioskModeSettings()150 KioskModeSettings::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
~KioskModeSettings()175 KioskModeSettings::~KioskModeSettings() {
176 }
177
VerifyModeIsKnown(DeviceSettingsService::OwnershipStatus status)178 void 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