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"
8 #include "ash/cancel_mode.h"
10 #include "ash/shell_delegate.h"
11 #include "ash/shell_window_ids.h"
12 #include "ash/wm/session_state_animator.h"
13 #include "base/command_line.h"
14 #include "ui/aura/root_window.h"
15 #include "ui/views/corewm/compound_event_filter.h"
17 #if defined(OS_CHROMEOS)
18 #include "base/chromeos/chromeos_version.h"
23 SessionStateControllerImpl::TestApi::TestApi(
24 SessionStateControllerImpl
* controller
)
25 : controller_(controller
) {
28 SessionStateControllerImpl::TestApi::~TestApi() {
31 SessionStateControllerImpl::SessionStateControllerImpl()
32 : login_status_(user::LOGGED_IN_NONE
),
33 system_is_locked_(false),
34 shutting_down_(false),
35 shutdown_after_lock_(false) {
36 Shell::GetPrimaryRootWindow()->AddRootWindowObserver(this);
39 SessionStateControllerImpl::~SessionStateControllerImpl() {
40 Shell::GetPrimaryRootWindow()->RemoveRootWindowObserver(this);
43 void SessionStateControllerImpl::OnLoginStateChanged(user::LoginStatus status
) {
44 if (status
!= user::LOGGED_IN_LOCKED
)
45 login_status_
= status
;
46 system_is_locked_
= (status
== user::LOGGED_IN_LOCKED
);
49 void SessionStateControllerImpl::OnAppTerminating() {
50 // If we hear that Chrome is exiting but didn't request it ourselves, all we
51 // can really hope for is that we'll have time to clear the screen.
52 if (!shutting_down_
) {
53 shutting_down_
= true;
54 Shell
* shell
= ash::Shell::GetInstance();
55 shell
->env_filter()->set_cursor_hidden_by_filter(false);
56 shell
->cursor_manager()->HideCursor();
57 animator_
->StartAnimation(
58 internal::SessionStateAnimator::kAllContainersMask
,
59 internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY
,
60 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE
);
64 void SessionStateControllerImpl::OnLockStateChanged(bool locked
) {
65 if (shutting_down_
|| (system_is_locked_
== locked
))
68 system_is_locked_
= locked
;
71 animator_
->StartAnimation(
72 internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS
,
73 internal::SessionStateAnimator::ANIMATION_FADE_IN
,
74 internal::SessionStateAnimator::ANIMATION_SPEED_SHOW_LOCK_SCREEN
);
76 FOR_EACH_OBSERVER(LockStateObserver
, observers_
,
77 OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_STARTED
));
79 lock_fail_timer_
.Stop();
81 if (shutdown_after_lock_
) {
82 shutdown_after_lock_
= false;
83 StartLockToShutdownTimer();
86 animator_
->StartAnimation(
87 internal::SessionStateAnimator::DESKTOP_BACKGROUND
|
88 internal::SessionStateAnimator::LAUNCHER
|
89 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS
,
90 internal::SessionStateAnimator::ANIMATION_RESTORE
,
91 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE
);
95 void SessionStateControllerImpl::OnStartingLock() {
96 if (shutting_down_
|| system_is_locked_
)
99 animator_
->StartAnimation(
100 internal::SessionStateAnimator::LAUNCHER
,
101 internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY
,
102 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE
);
104 animator_
->StartAnimation(
105 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS
,
106 internal::SessionStateAnimator::ANIMATION_FULL_CLOSE
,
107 internal::SessionStateAnimator::ANIMATION_SPEED_FAST
);
109 DispatchCancelMode();
110 FOR_EACH_OBSERVER(LockStateObserver
, observers_
,
111 OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_STARTED
));
113 // Hide the screen locker containers so we can make them fade in later.
114 animator_
->StartAnimation(
115 internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS
,
116 internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY
,
117 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE
);
120 void SessionStateControllerImpl::StartLockAnimationAndLockImmediately() {
121 animator_
->StartAnimation(
122 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS
,
123 internal::SessionStateAnimator::ANIMATION_PARTIAL_CLOSE
,
124 internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE
);
125 DispatchCancelMode();
126 FOR_EACH_OBSERVER(LockStateObserver
, observers_
,
127 OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_STARTED
));
131 void SessionStateControllerImpl::StartLockAnimation(bool shutdown_after_lock
) {
132 shutdown_after_lock_
= shutdown_after_lock
;
134 animator_
->StartAnimation(
135 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS
,
136 internal::SessionStateAnimator::ANIMATION_PARTIAL_CLOSE
,
137 internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE
);
138 DispatchCancelMode();
139 FOR_EACH_OBSERVER(LockStateObserver
, observers_
,
140 OnLockStateEvent(LockStateObserver::EVENT_PRELOCK_ANIMATION_STARTED
));
144 void SessionStateControllerImpl::StartShutdownAnimation() {
145 animator_
->StartAnimation(
146 internal::SessionStateAnimator::kAllContainersMask
,
147 internal::SessionStateAnimator::ANIMATION_PARTIAL_CLOSE
,
148 internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE
);
150 StartPreShutdownAnimationTimer();
153 bool SessionStateControllerImpl::LockRequested() {
154 return lock_fail_timer_
.IsRunning();
157 bool SessionStateControllerImpl::ShutdownRequested() {
158 return shutting_down_
;
161 bool SessionStateControllerImpl::CanCancelLockAnimation() {
162 return lock_timer_
.IsRunning();
165 void SessionStateControllerImpl::CancelLockAnimation() {
166 if (!CanCancelLockAnimation())
168 shutdown_after_lock_
= false;
169 animator_
->StartAnimation(
170 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS
,
171 internal::SessionStateAnimator::ANIMATION_UNDO_PARTIAL_CLOSE
,
172 internal::SessionStateAnimator::ANIMATION_SPEED_REVERT
);
176 bool SessionStateControllerImpl::CanCancelShutdownAnimation() {
177 return pre_shutdown_timer_
.IsRunning() ||
178 shutdown_after_lock_
||
179 lock_to_shutdown_timer_
.IsRunning();
182 void SessionStateControllerImpl::CancelShutdownAnimation() {
183 if (!CanCancelShutdownAnimation())
185 if (lock_to_shutdown_timer_
.IsRunning()) {
186 lock_to_shutdown_timer_
.Stop();
189 if (shutdown_after_lock_
) {
190 shutdown_after_lock_
= false;
194 if (system_is_locked_
) {
195 // If we've already started shutdown transition at lock screen
196 // desktop background needs to be restored immediately.
197 animator_
->StartAnimation(
198 internal::SessionStateAnimator::DESKTOP_BACKGROUND
,
199 internal::SessionStateAnimator::ANIMATION_RESTORE
,
200 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE
);
201 animator_
->StartAnimation(
202 internal::SessionStateAnimator::kAllLockScreenContainersMask
,
203 internal::SessionStateAnimator::ANIMATION_UNDO_PARTIAL_CLOSE
,
204 internal::SessionStateAnimator::ANIMATION_SPEED_REVERT
);
206 animator_
->StartAnimation(
207 internal::SessionStateAnimator::kAllContainersMask
,
208 internal::SessionStateAnimator::ANIMATION_UNDO_PARTIAL_CLOSE
,
209 internal::SessionStateAnimator::ANIMATION_SPEED_REVERT
);
211 pre_shutdown_timer_
.Stop();
214 void SessionStateControllerImpl::RequestShutdown() {
216 RequestShutdownImpl();
219 void SessionStateControllerImpl::RequestShutdownImpl() {
220 DCHECK(!shutting_down_
);
221 shutting_down_
= true;
223 Shell
* shell
= ash::Shell::GetInstance();
224 shell
->env_filter()->set_cursor_hidden_by_filter(false);
225 shell
->cursor_manager()->HideCursor();
227 if (login_status_
!= user::LOGGED_IN_NONE
) {
228 // Hide the other containers before starting the animation.
229 // ANIMATION_FULL_CLOSE will make the screen locker windows partially
230 // transparent, and we don't want the other windows to show through.
231 animator_
->StartAnimation(
232 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS
|
233 internal::SessionStateAnimator::LAUNCHER
,
234 internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY
,
235 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE
);
236 animator_
->StartAnimation(
237 internal::SessionStateAnimator::kAllLockScreenContainersMask
,
238 internal::SessionStateAnimator::ANIMATION_FULL_CLOSE
,
239 internal::SessionStateAnimator::ANIMATION_SPEED_FAST
);
241 animator_
->StartAnimation(
242 internal::SessionStateAnimator::kAllContainersMask
,
243 internal::SessionStateAnimator::ANIMATION_FULL_CLOSE
,
244 internal::SessionStateAnimator::ANIMATION_SPEED_FAST
);
246 StartRealShutdownTimer();
249 void SessionStateControllerImpl::OnRootWindowHostCloseRequested(
250 const aura::RootWindow
*) {
251 Shell::GetInstance()->delegate()->Exit();
254 void SessionStateControllerImpl::StartLockTimer() {
258 animator_
->GetDuration(
259 internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE
),
260 this, &SessionStateControllerImpl::OnLockTimeout
);
263 void SessionStateControllerImpl::OnLockTimeout() {
264 delegate_
->RequestLockScreen();
265 lock_fail_timer_
.Start(
267 base::TimeDelta::FromMilliseconds(kLockFailTimeoutMs
),
268 this, &SessionStateControllerImpl::OnLockFailTimeout
);
271 void SessionStateControllerImpl::OnLockFailTimeout() {
272 DCHECK(!system_is_locked_
);
273 // Undo lock animation.
274 animator_
->StartAnimation(
275 internal::SessionStateAnimator::LAUNCHER
|
276 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS
,
277 internal::SessionStateAnimator::ANIMATION_RESTORE
,
278 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE
);
281 void SessionStateControllerImpl::StartLockToShutdownTimer() {
282 shutdown_after_lock_
= false;
283 lock_to_shutdown_timer_
.Stop();
284 lock_to_shutdown_timer_
.Start(
286 base::TimeDelta::FromMilliseconds(kLockToShutdownTimeoutMs
),
287 this, &SessionStateControllerImpl::OnLockToShutdownTimeout
);
291 void SessionStateControllerImpl::OnLockToShutdownTimeout() {
292 DCHECK(system_is_locked_
);
293 StartShutdownAnimation();
296 void SessionStateControllerImpl::StartPreShutdownAnimationTimer() {
297 pre_shutdown_timer_
.Stop();
298 pre_shutdown_timer_
.Start(
300 base::TimeDelta::FromMilliseconds(kShutdownTimeoutMs
),
301 this, &SessionStateControllerImpl::OnPreShutdownAnimationTimeout
);
304 void SessionStateControllerImpl::OnPreShutdownAnimationTimeout() {
306 RequestShutdownImpl();
309 void SessionStateControllerImpl::StartRealShutdownTimer() {
310 base::TimeDelta duration
=
311 base::TimeDelta::FromMilliseconds(kShutdownRequestDelayMs
);
312 duration
+= animator_
->GetDuration(
313 internal::SessionStateAnimator::ANIMATION_SPEED_FAST
);
315 real_shutdown_timer_
.Start(
318 this, &SessionStateControllerImpl::OnRealShutdownTimeout
);
321 void SessionStateControllerImpl::OnRealShutdownTimeout() {
322 DCHECK(shutting_down_
);
323 #if defined(OS_CHROMEOS)
324 if (!base::chromeos::IsRunningOnChromeOS()) {
325 ShellDelegate
* delegate
= Shell::GetInstance()->delegate();
332 delegate_
->RequestShutdown();
335 void SessionStateControllerImpl::OnLockScreenHide(base::Closure
& callback
) {
339 void SessionStateControllerImpl::SetLockScreenDisplayedCallback(
340 base::Closure
& callback
) {