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.
5 #include "ash/wm/session_state_controller_impl.h"
7 #include "ash/ash_switches.h"
9 #include "ash/shell_delegate.h"
10 #include "ash/shell_window_ids.h"
11 #include "ash/wm/session_state_animator.h"
12 #include "base/command_line.h"
13 #include "ui/aura/root_window.h"
14 #include "ui/views/corewm/compound_event_filter.h"
16 #if defined(OS_CHROMEOS)
17 #include "base/chromeos/chromeos_version.h"
22 SessionStateControllerImpl::TestApi::TestApi(
23 SessionStateControllerImpl
* controller
)
24 : controller_(controller
) {
27 SessionStateControllerImpl::TestApi::~TestApi() {
30 SessionStateControllerImpl::SessionStateControllerImpl()
31 : login_status_(user::LOGGED_IN_NONE
),
32 system_is_locked_(false),
33 shutting_down_(false),
34 shutdown_after_lock_(false) {
35 Shell::GetPrimaryRootWindow()->AddRootWindowObserver(this);
38 SessionStateControllerImpl::~SessionStateControllerImpl() {
39 Shell::GetPrimaryRootWindow()->RemoveRootWindowObserver(this);
42 void SessionStateControllerImpl::OnLoginStateChanged(user::LoginStatus status
) {
43 if (status
!= user::LOGGED_IN_LOCKED
)
44 login_status_
= status
;
45 system_is_locked_
= (status
== user::LOGGED_IN_LOCKED
);
48 void SessionStateControllerImpl::OnAppTerminating() {
49 // If we hear that Chrome is exiting but didn't request it ourselves, all we
50 // can really hope for is that we'll have time to clear the screen.
51 if (!shutting_down_
) {
52 shutting_down_
= true;
53 Shell
* shell
= ash::Shell::GetInstance();
54 shell
->env_filter()->set_cursor_hidden_by_filter(false);
55 shell
->cursor_manager()->DisableMouseEvents();
56 animator_
->StartAnimation(
57 internal::SessionStateAnimator::kAllContainersMask
,
58 internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY
,
59 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE
);
63 void SessionStateControllerImpl::OnLockStateChanged(bool locked
) {
64 if (shutting_down_
|| (system_is_locked_
== locked
))
67 system_is_locked_
= locked
;
70 animator_
->StartAnimation(
71 internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS
,
72 internal::SessionStateAnimator::ANIMATION_FADE_IN
,
73 internal::SessionStateAnimator::ANIMATION_SPEED_SHOW_LOCK_SCREEN
);
74 FOR_EACH_OBSERVER(SessionStateObserver
, observers_
,
76 SessionStateObserver::EVENT_LOCK_ANIMATION_STARTED
));
78 lock_fail_timer_
.Stop();
80 if (shutdown_after_lock_
) {
81 shutdown_after_lock_
= false;
82 StartLockToShutdownTimer();
85 animator_
->StartAnimation(
86 internal::SessionStateAnimator::DESKTOP_BACKGROUND
|
87 internal::SessionStateAnimator::LAUNCHER
|
88 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS
,
89 internal::SessionStateAnimator::ANIMATION_RESTORE
,
90 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE
);
94 void SessionStateControllerImpl::OnStartingLock() {
95 if (shutting_down_
|| system_is_locked_
)
98 animator_
->StartAnimation(
99 internal::SessionStateAnimator::LAUNCHER
,
100 internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY
,
101 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE
);
103 animator_
->StartAnimation(
104 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS
,
105 internal::SessionStateAnimator::ANIMATION_FULL_CLOSE
,
106 internal::SessionStateAnimator::ANIMATION_SPEED_FAST
);
108 FOR_EACH_OBSERVER(SessionStateObserver
, observers_
,
109 OnSessionStateEvent(SessionStateObserver::EVENT_LOCK_ANIMATION_STARTED
));
111 // Hide the screen locker containers so we can make them fade in later.
112 animator_
->StartAnimation(
113 internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS
,
114 internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY
,
115 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE
);
118 void SessionStateControllerImpl::StartLockAnimationAndLockImmediately() {
119 animator_
->StartAnimation(
120 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS
,
121 internal::SessionStateAnimator::ANIMATION_PARTIAL_CLOSE
,
122 internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE
);
123 FOR_EACH_OBSERVER(SessionStateObserver
, observers_
,
124 OnSessionStateEvent(SessionStateObserver::EVENT_LOCK_ANIMATION_STARTED
));
128 void SessionStateControllerImpl::StartLockAnimation(bool shutdown_after_lock
) {
129 shutdown_after_lock_
= shutdown_after_lock
;
131 animator_
->StartAnimation(
132 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS
,
133 internal::SessionStateAnimator::ANIMATION_PARTIAL_CLOSE
,
134 internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE
);
135 FOR_EACH_OBSERVER(SessionStateObserver
, observers_
,
137 SessionStateObserver::EVENT_PRELOCK_ANIMATION_STARTED
));
141 void SessionStateControllerImpl::StartShutdownAnimation() {
142 animator_
->StartAnimation(
143 internal::SessionStateAnimator::kAllContainersMask
,
144 internal::SessionStateAnimator::ANIMATION_PARTIAL_CLOSE
,
145 internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE
);
147 StartPreShutdownAnimationTimer();
150 bool SessionStateControllerImpl::LockRequested() {
151 return lock_fail_timer_
.IsRunning();
154 bool SessionStateControllerImpl::ShutdownRequested() {
155 return shutting_down_
;
158 bool SessionStateControllerImpl::CanCancelLockAnimation() {
159 return lock_timer_
.IsRunning();
162 void SessionStateControllerImpl::CancelLockAnimation() {
163 if (!CanCancelLockAnimation())
165 shutdown_after_lock_
= false;
166 animator_
->StartAnimation(
167 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS
,
168 internal::SessionStateAnimator::ANIMATION_UNDO_PARTIAL_CLOSE
,
169 internal::SessionStateAnimator::ANIMATION_SPEED_REVERT
);
173 bool SessionStateControllerImpl::CanCancelShutdownAnimation() {
174 return pre_shutdown_timer_
.IsRunning() ||
175 shutdown_after_lock_
||
176 lock_to_shutdown_timer_
.IsRunning();
179 void SessionStateControllerImpl::CancelShutdownAnimation() {
180 if (!CanCancelShutdownAnimation())
182 if (lock_to_shutdown_timer_
.IsRunning()) {
183 lock_to_shutdown_timer_
.Stop();
186 if (shutdown_after_lock_
) {
187 shutdown_after_lock_
= false;
191 if (system_is_locked_
) {
192 // If we've already started shutdown transition at lock screen
193 // desktop background needs to be restored immediately.
194 animator_
->StartAnimation(
195 internal::SessionStateAnimator::DESKTOP_BACKGROUND
,
196 internal::SessionStateAnimator::ANIMATION_RESTORE
,
197 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE
);
198 animator_
->StartAnimation(
199 internal::SessionStateAnimator::kAllLockScreenContainersMask
,
200 internal::SessionStateAnimator::ANIMATION_UNDO_PARTIAL_CLOSE
,
201 internal::SessionStateAnimator::ANIMATION_SPEED_REVERT
);
203 animator_
->StartAnimation(
204 internal::SessionStateAnimator::kAllContainersMask
,
205 internal::SessionStateAnimator::ANIMATION_UNDO_PARTIAL_CLOSE
,
206 internal::SessionStateAnimator::ANIMATION_SPEED_REVERT
);
208 pre_shutdown_timer_
.Stop();
211 void SessionStateControllerImpl::RequestShutdown() {
213 RequestShutdownImpl();
216 void SessionStateControllerImpl::RequestShutdownImpl() {
217 DCHECK(!shutting_down_
);
218 shutting_down_
= true;
220 Shell
* shell
= ash::Shell::GetInstance();
221 shell
->env_filter()->set_cursor_hidden_by_filter(false);
222 shell
->cursor_manager()->DisableMouseEvents();
224 if (login_status_
!= user::LOGGED_IN_NONE
) {
225 // Hide the other containers before starting the animation.
226 // ANIMATION_FULL_CLOSE will make the screen locker windows partially
227 // transparent, and we don't want the other windows to show through.
228 animator_
->StartAnimation(
229 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS
|
230 internal::SessionStateAnimator::LAUNCHER
,
231 internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY
,
232 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE
);
233 animator_
->StartAnimation(
234 internal::SessionStateAnimator::kAllLockScreenContainersMask
,
235 internal::SessionStateAnimator::ANIMATION_FULL_CLOSE
,
236 internal::SessionStateAnimator::ANIMATION_SPEED_FAST
);
238 animator_
->StartAnimation(
239 internal::SessionStateAnimator::kAllContainersMask
,
240 internal::SessionStateAnimator::ANIMATION_FULL_CLOSE
,
241 internal::SessionStateAnimator::ANIMATION_SPEED_FAST
);
243 StartRealShutdownTimer();
246 void SessionStateControllerImpl::OnRootWindowHostCloseRequested(
247 const aura::RootWindow
*) {
248 Shell::GetInstance()->delegate()->Exit();
251 void SessionStateControllerImpl::StartLockTimer() {
255 animator_
->GetDuration(
256 internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE
),
257 this, &SessionStateControllerImpl::OnLockTimeout
);
260 void SessionStateControllerImpl::OnLockTimeout() {
261 delegate_
->RequestLockScreen();
262 lock_fail_timer_
.Start(
264 base::TimeDelta::FromMilliseconds(kLockFailTimeoutMs
),
265 this, &SessionStateControllerImpl::OnLockFailTimeout
);
268 void SessionStateControllerImpl::OnLockFailTimeout() {
269 DCHECK(!system_is_locked_
);
270 // Undo lock animation.
271 animator_
->StartAnimation(
272 internal::SessionStateAnimator::LAUNCHER
|
273 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS
,
274 internal::SessionStateAnimator::ANIMATION_RESTORE
,
275 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE
);
278 void SessionStateControllerImpl::StartLockToShutdownTimer() {
279 shutdown_after_lock_
= false;
280 lock_to_shutdown_timer_
.Stop();
281 lock_to_shutdown_timer_
.Start(
283 base::TimeDelta::FromMilliseconds(kLockToShutdownTimeoutMs
),
284 this, &SessionStateControllerImpl::OnLockToShutdownTimeout
);
288 void SessionStateControllerImpl::OnLockToShutdownTimeout() {
289 DCHECK(system_is_locked_
);
290 StartShutdownAnimation();
293 void SessionStateControllerImpl::StartPreShutdownAnimationTimer() {
294 pre_shutdown_timer_
.Stop();
295 pre_shutdown_timer_
.Start(
297 base::TimeDelta::FromMilliseconds(kShutdownTimeoutMs
),
298 this, &SessionStateControllerImpl::OnPreShutdownAnimationTimeout
);
301 void SessionStateControllerImpl::OnPreShutdownAnimationTimeout() {
303 RequestShutdownImpl();
306 void SessionStateControllerImpl::StartRealShutdownTimer() {
307 base::TimeDelta duration
=
308 base::TimeDelta::FromMilliseconds(kShutdownRequestDelayMs
);
309 duration
+= animator_
->GetDuration(
310 internal::SessionStateAnimator::ANIMATION_SPEED_FAST
);
312 real_shutdown_timer_
.Start(
315 this, &SessionStateControllerImpl::OnRealShutdownTimeout
);
318 void SessionStateControllerImpl::OnRealShutdownTimeout() {
319 DCHECK(shutting_down_
);
320 #if defined(OS_CHROMEOS)
321 if (!base::chromeos::IsRunningOnChromeOS()) {
322 ShellDelegate
* delegate
= Shell::GetInstance()->delegate();
329 delegate_
->RequestShutdown();
332 void SessionStateControllerImpl::OnLockScreenHide(base::Closure
& callback
) {
336 void SessionStateControllerImpl::SetLockScreenDisplayedCallback(
337 base::Closure
& callback
) {