blob: 09a46afa2a1436404485a642a920205f69a4cad8 [file] [log] [blame]
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001// 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 "ash/wm/lock_state_controller.h"
6
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +00007#include <algorithm>
8
9#include "ash/accessibility_delegate.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010#include "ash/ash_switches.h"
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010011#include "ash/cancel_mode.h"
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000012#include "ash/metrics/user_metrics_recorder.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010013#include "ash/shell.h"
14#include "ash/shell_delegate.h"
15#include "ash/shell_window_ids.h"
16#include "ash/wm/session_state_animator.h"
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010017#include "base/bind_helpers.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010018#include "base/command_line.h"
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010019#include "base/timer/timer.h"
Torne (Richard Coles)23730a62014-03-21 14:25:57 +000020#include "ui/aura/window_tree_host.h"
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010021#include "ui/compositor/layer_animation_sequence.h"
22#include "ui/compositor/scoped_layer_animation_settings.h"
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000023#include "ui/views/controls/menu/menu_controller.h"
24#include "ui/wm/core/compound_event_filter.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010025
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010026#if defined(OS_CHROMEOS)
27#include "base/sys_info.h"
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +000028#include "media/audio/sounds/sounds_manager.h"
29#endif
30
31#if defined(OS_CHROMEOS)
32using media::SoundsManager;
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010033#endif
34
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010035namespace ash {
36
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010037namespace {
38
Ben Murdochc5cede92014-04-10 11:22:14 +010039#if defined(OS_CHROMEOS)
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +000040const int kMaxShutdownSoundDurationMs = 1500;
Ben Murdochc5cede92014-04-10 11:22:14 +010041#endif
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +000042
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010043aura::Window* GetBackground() {
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000044 aura::Window* root_window = Shell::GetPrimaryRootWindow();
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010045 return Shell::GetContainer(root_window,
Ben Murdochc5cede92014-04-10 11:22:14 +010046 kShellWindowId_DesktopBackgroundContainer);
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010047}
48
49bool IsBackgroundHidden() {
50 return !GetBackground()->IsVisible();
51}
52
53void ShowBackground() {
54 ui::ScopedLayerAnimationSettings settings(
55 GetBackground()->layer()->GetAnimator());
56 settings.SetTransitionDuration(base::TimeDelta());
57 GetBackground()->Show();
58}
59
60void HideBackground() {
61 ui::ScopedLayerAnimationSettings settings(
62 GetBackground()->layer()->GetAnimator());
63 settings.SetTransitionDuration(base::TimeDelta());
64 GetBackground()->Hide();
65}
66
67// This observer is intended to use in cases when some action has to be taken
68// once some animation successfully completes (i.e. it was not aborted).
69// Observer will count a number of sequences it is attached to, and a number of
70// finished sequences (either Ended or Aborted). Once these two numbers are
71// equal, observer will delete itself, calling callback passed to constructor if
72// there were no aborted animations.
73// This way it can be either used to wait for some animation to be finished in
74// multiple layers, to wait once a sequence of animations is finished in one
75// layer or the mixture of both.
76class AnimationFinishedObserver : public ui::LayerAnimationObserver {
77 public:
78 explicit AnimationFinishedObserver(base::Closure &callback)
79 : callback_(callback),
80 sequences_attached_(0),
81 sequences_completed_(0),
82 paused_(false) {
83 }
84
85 // Pauses observer: no checks will be made while paused. It can be used when
86 // a sequence has some immediate animations in the beginning, and for
87 // animations that can be tested with flag that makes all animations
88 // immediate.
89 void Pause() {
90 paused_ = true;
91 }
92
93 // Unpauses observer. It does a check and calls callback if conditions are
94 // met.
95 void Unpause() {
96 if (!paused_)
97 return;
98 paused_ = false;
99 if (sequences_completed_ == sequences_attached_) {
100 callback_.Run();
101 delete this;
102 }
103 }
104
105 private:
106 virtual ~AnimationFinishedObserver() {
107 }
108
109 // LayerAnimationObserver implementation
110 virtual void OnLayerAnimationEnded(
111 ui::LayerAnimationSequence* sequence) OVERRIDE {
112 sequences_completed_++;
113 if ((sequences_completed_ == sequences_attached_) && !paused_) {
114 callback_.Run();
115 delete this;
116 }
117 }
118
119 virtual void OnLayerAnimationAborted(
120 ui::LayerAnimationSequence* sequence) OVERRIDE {
121 sequences_completed_++;
122 if ((sequences_completed_ == sequences_attached_) && !paused_)
123 delete this;
124 }
125
126 virtual void OnLayerAnimationScheduled(
127 ui::LayerAnimationSequence* sequence) OVERRIDE {
128 }
129
130 virtual void OnAttachedToSequence(
131 ui::LayerAnimationSequence* sequence) OVERRIDE {
132 LayerAnimationObserver::OnAttachedToSequence(sequence);
133 sequences_attached_++;
134 }
135
136 // Callback to be called.
137 base::Closure callback_;
138
139 // Number of sequences this observer was attached to.
140 int sequences_attached_;
141
142 // Number of sequences either ended or aborted.
143 int sequences_completed_;
144
145 bool paused_;
146
147 DISALLOW_COPY_AND_ASSIGN(AnimationFinishedObserver);
148};
149
150} // namespace
151
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100152const int LockStateController::kLockTimeoutMs = 400;
153const int LockStateController::kShutdownTimeoutMs = 400;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100154const int LockStateController::kLockFailTimeoutMs = 8000;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100155const int LockStateController::kLockToShutdownTimeoutMs = 150;
156const int LockStateController::kShutdownRequestDelayMs = 50;
157
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100158LockStateController::TestApi::TestApi(LockStateController* controller)
159 : controller_(controller) {
160}
161
162LockStateController::TestApi::~TestApi() {
163}
164
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100165LockStateController::LockStateController()
Ben Murdochc5cede92014-04-10 11:22:14 +0100166 : animator_(new SessionStateAnimator()),
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100167 login_status_(user::LOGGED_IN_NONE),
168 system_is_locked_(false),
169 shutting_down_(false),
170 shutdown_after_lock_(false),
171 animating_lock_(false),
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000172 can_cancel_lock_animation_(false),
173 weak_ptr_factory_(this) {
174 Shell::GetPrimaryRootWindow()->GetHost()->AddObserver(this);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100175}
176
177LockStateController::~LockStateController() {
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000178 Shell::GetPrimaryRootWindow()->GetHost()->RemoveObserver(this);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100179}
180
181void LockStateController::SetDelegate(LockStateControllerDelegate* delegate) {
182 delegate_.reset(delegate);
183}
184
185void LockStateController::AddObserver(LockStateObserver* observer) {
186 observers_.AddObserver(observer);
187}
188
189void LockStateController::RemoveObserver(LockStateObserver* observer) {
190 observers_.RemoveObserver(observer);
191}
192
193bool LockStateController::HasObserver(LockStateObserver* observer) {
194 return observers_.HasObserver(observer);
195}
196
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100197void LockStateController::StartLockAnimation(
198 bool shutdown_after_lock) {
199 if (animating_lock_)
200 return;
201 shutdown_after_lock_ = shutdown_after_lock;
202 can_cancel_lock_animation_ = true;
203
204 StartCancellablePreLockAnimation();
205}
206
207void LockStateController::StartShutdownAnimation() {
208 StartCancellableShutdownAnimation();
209}
210
211void LockStateController::StartLockAnimationAndLockImmediately() {
212 if (animating_lock_)
213 return;
214 StartImmediatePreLockAnimation(true /* request_lock_on_completion */);
215}
216
217bool LockStateController::LockRequested() {
218 return lock_fail_timer_.IsRunning();
219}
220
221bool LockStateController::ShutdownRequested() {
222 return shutting_down_;
223}
224
225bool LockStateController::CanCancelLockAnimation() {
226 return can_cancel_lock_animation_;
227}
228
229void LockStateController::CancelLockAnimation() {
230 if (!CanCancelLockAnimation())
231 return;
232 shutdown_after_lock_ = false;
233 animating_lock_ = false;
234 CancelPreLockAnimation();
235}
236
237bool LockStateController::CanCancelShutdownAnimation() {
238 return pre_shutdown_timer_.IsRunning() ||
239 shutdown_after_lock_ ||
240 lock_to_shutdown_timer_.IsRunning();
241}
242
243void LockStateController::CancelShutdownAnimation() {
244 if (!CanCancelShutdownAnimation())
245 return;
246 if (lock_to_shutdown_timer_.IsRunning()) {
247 lock_to_shutdown_timer_.Stop();
248 return;
249 }
250 if (shutdown_after_lock_) {
251 shutdown_after_lock_ = false;
252 return;
253 }
254
255 animator_->StartGlobalAnimation(
Ben Murdochc5cede92014-04-10 11:22:14 +0100256 SessionStateAnimator::ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS,
257 SessionStateAnimator::ANIMATION_SPEED_REVERT_SHUTDOWN);
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100258 pre_shutdown_timer_.Stop();
259}
260
261void LockStateController::OnStartingLock() {
262 if (shutting_down_ || system_is_locked_)
263 return;
264 if (animating_lock_)
265 return;
266 StartImmediatePreLockAnimation(false /* request_lock_on_completion */);
267}
268
269void LockStateController::RequestShutdown() {
270 if (shutting_down_)
271 return;
272
273 shutting_down_ = true;
274
275 Shell* shell = ash::Shell::GetInstance();
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100276 shell->cursor_manager()->HideCursor();
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000277 shell->cursor_manager()->LockCursor();
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100278
279 animator_->StartGlobalAnimation(
Ben Murdochc5cede92014-04-10 11:22:14 +0100280 SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS,
281 SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN);
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100282 StartRealShutdownTimer(true);
283}
284
285void LockStateController::OnLockScreenHide(
286 base::Callback<void(void)>& callback) {
287 StartUnlockAnimationBeforeUIDestroyed(callback);
288}
289
290void LockStateController::SetLockScreenDisplayedCallback(
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +0000291 const base::Closure& callback) {
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100292 lock_screen_displayed_callback_ = callback;
293}
294
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000295void LockStateController::OnHostCloseRequested(
296 const aura::WindowTreeHost* host) {
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100297 Shell::GetInstance()->delegate()->Exit();
298}
299
300void LockStateController::OnLoginStateChanged(
301 user::LoginStatus status) {
302 if (status != user::LOGGED_IN_LOCKED)
303 login_status_ = status;
304 system_is_locked_ = (status == user::LOGGED_IN_LOCKED);
305}
306
307void LockStateController::OnAppTerminating() {
308 // If we hear that Chrome is exiting but didn't request it ourselves, all we
309 // can really hope for is that we'll have time to clear the screen.
310 // This is also the case when the user signs off.
311 if (!shutting_down_) {
312 shutting_down_ = true;
313 Shell* shell = ash::Shell::GetInstance();
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100314 shell->cursor_manager()->HideCursor();
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000315 shell->cursor_manager()->LockCursor();
Ben Murdochc5cede92014-04-10 11:22:14 +0100316 animator_->StartAnimation(SessionStateAnimator::kAllContainersMask,
317 SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
318 SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100319 }
320}
321
322void LockStateController::OnLockStateChanged(bool locked) {
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000323 VLOG(1) << "OnLockStateChanged " << locked;
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100324 if (shutting_down_ || (system_is_locked_ == locked))
325 return;
326
327 system_is_locked_ = locked;
328
329 if (locked) {
330 StartPostLockAnimation();
331 lock_fail_timer_.Stop();
332 } else {
333 StartUnlockAnimationAfterUIDestroyed();
334 }
335}
336
337void LockStateController::OnLockFailTimeout() {
338 DCHECK(!system_is_locked_);
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000339 CHECK(false) << "We can not be sure about the lock state. Crash and let the "
340 << "SessionManager end the session";
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100341}
342
343void LockStateController::StartLockToShutdownTimer() {
344 shutdown_after_lock_ = false;
345 lock_to_shutdown_timer_.Stop();
346 lock_to_shutdown_timer_.Start(
347 FROM_HERE,
348 base::TimeDelta::FromMilliseconds(kLockToShutdownTimeoutMs),
349 this, &LockStateController::OnLockToShutdownTimeout);
350}
351
352void LockStateController::OnLockToShutdownTimeout() {
353 DCHECK(system_is_locked_);
354 StartCancellableShutdownAnimation();
355}
356
357void LockStateController::StartPreShutdownAnimationTimer() {
358 pre_shutdown_timer_.Stop();
359 pre_shutdown_timer_.Start(
360 FROM_HERE,
Ben Murdochc5cede92014-04-10 11:22:14 +0100361 animator_->GetDuration(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN),
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100362 this,
363 &LockStateController::OnPreShutdownAnimationTimeout);
364}
365
366void LockStateController::OnPreShutdownAnimationTimeout() {
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000367 VLOG(1) << "OnPreShutdownAnimationTimeout";
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100368 shutting_down_ = true;
369
370 Shell* shell = ash::Shell::GetInstance();
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100371 shell->cursor_manager()->HideCursor();
372
373 StartRealShutdownTimer(false);
374}
375
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000376void LockStateController::StartRealShutdownTimer(bool with_animation_time) {
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100377 base::TimeDelta duration =
378 base::TimeDelta::FromMilliseconds(kShutdownRequestDelayMs);
379 if (with_animation_time) {
Ben Murdochc5cede92014-04-10 11:22:14 +0100380 duration +=
381 animator_->GetDuration(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN);
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100382 }
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +0000383
384#if defined(OS_CHROMEOS)
385 const AccessibilityDelegate* const delegate =
386 Shell::GetInstance()->accessibility_delegate();
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000387 base::TimeDelta sound_duration = delegate->PlayShutdownSound();
388 sound_duration =
389 std::min(sound_duration,
390 base::TimeDelta::FromMilliseconds(kMaxShutdownSoundDurationMs));
391 duration = std::max(duration, sound_duration);
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +0000392#endif
393
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100394 real_shutdown_timer_.Start(
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000395 FROM_HERE, duration, this, &LockStateController::OnRealShutdownTimeout);
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100396}
397
398void LockStateController::OnRealShutdownTimeout() {
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000399 VLOG(1) << "OnRealShutdownTimeout";
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100400 DCHECK(shutting_down_);
401#if defined(OS_CHROMEOS)
402 if (!base::SysInfo::IsRunningOnChromeOS()) {
403 ShellDelegate* delegate = Shell::GetInstance()->delegate();
404 if (delegate) {
405 delegate->Exit();
406 return;
407 }
408 }
409#endif
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000410 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100411 UMA_ACCEL_SHUT_DOWN_POWER_BUTTON);
412 delegate_->RequestShutdown();
413}
414
415void LockStateController::StartCancellableShutdownAnimation() {
416 Shell* shell = ash::Shell::GetInstance();
417 // Hide cursor, but let it reappear if the mouse moves.
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100418 shell->cursor_manager()->HideCursor();
419
420 animator_->StartGlobalAnimation(
Ben Murdochc5cede92014-04-10 11:22:14 +0100421 SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS,
422 SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN);
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100423 StartPreShutdownAnimationTimer();
424}
425
426void LockStateController::StartImmediatePreLockAnimation(
427 bool request_lock_on_completion) {
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000428 VLOG(1) << "StartImmediatePreLockAnimation " << request_lock_on_completion;
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100429 animating_lock_ = true;
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100430 StoreUnlockedProperties();
431
432 base::Closure next_animation_starter =
433 base::Bind(&LockStateController::PreLockAnimationFinished,
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000434 weak_ptr_factory_.GetWeakPtr(),
435 request_lock_on_completion);
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100436 AnimationFinishedObserver* observer =
437 new AnimationFinishedObserver(next_animation_starter);
438
439 observer->Pause();
440
441 animator_->StartAnimationWithObserver(
Ben Murdochc5cede92014-04-10 11:22:14 +0100442 SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
443 SessionStateAnimator::ANIMATION_LIFT,
444 SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100445 observer);
446 animator_->StartAnimationWithObserver(
Ben Murdochc5cede92014-04-10 11:22:14 +0100447 SessionStateAnimator::LAUNCHER,
448 SessionStateAnimator::ANIMATION_FADE_OUT,
449 SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100450 observer);
451 // Hide the screen locker containers so we can raise them later.
Ben Murdochc5cede92014-04-10 11:22:14 +0100452 animator_->StartAnimation(SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
453 SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
454 SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100455 AnimateBackgroundAppearanceIfNecessary(
Ben Murdochc5cede92014-04-10 11:22:14 +0100456 SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, observer);
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100457
458 observer->Unpause();
459
460 DispatchCancelMode();
461 FOR_EACH_OBSERVER(LockStateObserver, observers_,
462 OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_STARTED));
463}
464
465void LockStateController::StartCancellablePreLockAnimation() {
466 animating_lock_ = true;
467 StoreUnlockedProperties();
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000468 VLOG(1) << "StartCancellablePreLockAnimation";
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100469 base::Closure next_animation_starter =
470 base::Bind(&LockStateController::PreLockAnimationFinished,
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000471 weak_ptr_factory_.GetWeakPtr(),
472 true /* request_lock */);
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100473 AnimationFinishedObserver* observer =
474 new AnimationFinishedObserver(next_animation_starter);
475
476 observer->Pause();
477
478 animator_->StartAnimationWithObserver(
Ben Murdochc5cede92014-04-10 11:22:14 +0100479 SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
480 SessionStateAnimator::ANIMATION_LIFT,
481 SessionStateAnimator::ANIMATION_SPEED_UNDOABLE,
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100482 observer);
483 animator_->StartAnimationWithObserver(
Ben Murdochc5cede92014-04-10 11:22:14 +0100484 SessionStateAnimator::LAUNCHER,
485 SessionStateAnimator::ANIMATION_FADE_OUT,
486 SessionStateAnimator::ANIMATION_SPEED_UNDOABLE,
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100487 observer);
488 // Hide the screen locker containers so we can raise them later.
Ben Murdochc5cede92014-04-10 11:22:14 +0100489 animator_->StartAnimation(SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
490 SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
491 SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100492 AnimateBackgroundAppearanceIfNecessary(
Ben Murdochc5cede92014-04-10 11:22:14 +0100493 SessionStateAnimator::ANIMATION_SPEED_UNDOABLE, observer);
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100494
495 DispatchCancelMode();
496 FOR_EACH_OBSERVER(LockStateObserver, observers_,
497 OnLockStateEvent(LockStateObserver::EVENT_PRELOCK_ANIMATION_STARTED));
498 observer->Unpause();
499}
500
501void LockStateController::CancelPreLockAnimation() {
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000502 VLOG(1) << "CancelPreLockAnimation";
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100503 base::Closure next_animation_starter =
504 base::Bind(&LockStateController::LockAnimationCancelled,
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000505 weak_ptr_factory_.GetWeakPtr());
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100506 AnimationFinishedObserver* observer =
507 new AnimationFinishedObserver(next_animation_starter);
508
509 observer->Pause();
510
511 animator_->StartAnimationWithObserver(
Ben Murdochc5cede92014-04-10 11:22:14 +0100512 SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
513 SessionStateAnimator::ANIMATION_UNDO_LIFT,
514 SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS,
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100515 observer);
516 animator_->StartAnimationWithObserver(
Ben Murdochc5cede92014-04-10 11:22:14 +0100517 SessionStateAnimator::LAUNCHER,
518 SessionStateAnimator::ANIMATION_FADE_IN,
519 SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS,
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100520 observer);
521 AnimateBackgroundHidingIfNecessary(
Ben Murdochc5cede92014-04-10 11:22:14 +0100522 SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS, observer);
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100523
524 observer->Unpause();
525}
526
527void LockStateController::StartPostLockAnimation() {
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000528 VLOG(1) << "StartPostLockAnimation";
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100529 base::Closure next_animation_starter =
530 base::Bind(&LockStateController::PostLockAnimationFinished,
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000531 weak_ptr_factory_.GetWeakPtr());
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100532
533 AnimationFinishedObserver* observer =
534 new AnimationFinishedObserver(next_animation_starter);
535
536 observer->Pause();
537 animator_->StartAnimationWithObserver(
Ben Murdochc5cede92014-04-10 11:22:14 +0100538 SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
539 SessionStateAnimator::ANIMATION_RAISE_TO_SCREEN,
540 SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100541 observer);
542 observer->Unpause();
543}
544
545void LockStateController::StartUnlockAnimationBeforeUIDestroyed(
546 base::Closure& callback) {
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000547 VLOG(1) << "StartUnlockAnimationBeforeUIDestroyed";
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100548 animator_->StartAnimationWithCallback(
Ben Murdochc5cede92014-04-10 11:22:14 +0100549 SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
550 SessionStateAnimator::ANIMATION_LIFT,
551 SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100552 callback);
553}
554
555void LockStateController::StartUnlockAnimationAfterUIDestroyed() {
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000556 VLOG(1) << "StartUnlockAnimationAfterUIDestroyed";
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100557 base::Closure next_animation_starter =
558 base::Bind(&LockStateController::UnlockAnimationAfterUIDestroyedFinished,
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000559 weak_ptr_factory_.GetWeakPtr());
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100560
561 AnimationFinishedObserver* observer =
562 new AnimationFinishedObserver(next_animation_starter);
563
564 observer->Pause();
565
566 animator_->StartAnimationWithObserver(
Ben Murdochc5cede92014-04-10 11:22:14 +0100567 SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
568 SessionStateAnimator::ANIMATION_DROP,
569 SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100570 observer);
571 animator_->StartAnimationWithObserver(
Ben Murdochc5cede92014-04-10 11:22:14 +0100572 SessionStateAnimator::LAUNCHER,
573 SessionStateAnimator::ANIMATION_FADE_IN,
574 SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100575 observer);
576 AnimateBackgroundHidingIfNecessary(
Ben Murdochc5cede92014-04-10 11:22:14 +0100577 SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, observer);
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100578 observer->Unpause();
579}
580
581void LockStateController::LockAnimationCancelled() {
582 can_cancel_lock_animation_ = false;
583 RestoreUnlockedProperties();
584}
585
586void LockStateController::PreLockAnimationFinished(bool request_lock) {
587 can_cancel_lock_animation_ = false;
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000588 VLOG(1) << "PreLockAnimationFinished";
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100589 if (request_lock) {
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000590 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100591 shutdown_after_lock_ ?
592 UMA_ACCEL_LOCK_SCREEN_POWER_BUTTON :
593 UMA_ACCEL_LOCK_SCREEN_LOCK_BUTTON);
594 delegate_->RequestLockScreen();
595 }
596
Torne (Richard Coles)23730a62014-03-21 14:25:57 +0000597 int lock_timeout = kLockFailTimeoutMs;
598
599#if defined(OS_CHROMEOS)
600 std::string board = base::SysInfo::GetLsbReleaseBoard();
601
602 // Increase lock timeout for slower hardware, see http://crbug.com/350628
603 if (board == "x86-mario" ||
604 board.substr(0, 8) == "x86-alex" ||
605 board.substr(0, 7) == "x86-zgb") {
606 lock_timeout *= 2;
607 }
608#endif
609
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100610 lock_fail_timer_.Start(
611 FROM_HERE,
Torne (Richard Coles)23730a62014-03-21 14:25:57 +0000612 base::TimeDelta::FromMilliseconds(lock_timeout),
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100613 this,
614 &LockStateController::OnLockFailTimeout);
615}
616
617void LockStateController::PostLockAnimationFinished() {
618 animating_lock_ = false;
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000619 VLOG(1) << "PostLockAnimationFinished";
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100620 FOR_EACH_OBSERVER(LockStateObserver, observers_,
621 OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_FINISHED));
622 if (!lock_screen_displayed_callback_.is_null()) {
623 lock_screen_displayed_callback_.Run();
624 lock_screen_displayed_callback_.Reset();
625 }
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000626 CHECK(!views::MenuController::GetActiveInstance());
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100627 if (shutdown_after_lock_) {
628 shutdown_after_lock_ = false;
629 StartLockToShutdownTimer();
630 }
631}
632
633void LockStateController::UnlockAnimationAfterUIDestroyedFinished() {
634 RestoreUnlockedProperties();
635}
636
637void LockStateController::StoreUnlockedProperties() {
638 if (!unlocked_properties_) {
639 unlocked_properties_.reset(new UnlockedStateProperties());
640 unlocked_properties_->background_is_hidden = IsBackgroundHidden();
641 }
642 if (unlocked_properties_->background_is_hidden) {
643 // Hide background so that it can be animated later.
Ben Murdochc5cede92014-04-10 11:22:14 +0100644 animator_->StartAnimation(SessionStateAnimator::DESKTOP_BACKGROUND,
645 SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
646 SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100647 ShowBackground();
648 }
649}
650
651void LockStateController::RestoreUnlockedProperties() {
652 if (!unlocked_properties_)
653 return;
654 if (unlocked_properties_->background_is_hidden) {
655 HideBackground();
656 // Restore background visibility.
Ben Murdochc5cede92014-04-10 11:22:14 +0100657 animator_->StartAnimation(SessionStateAnimator::DESKTOP_BACKGROUND,
658 SessionStateAnimator::ANIMATION_FADE_IN,
659 SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100660 }
661 unlocked_properties_.reset();
662}
663
664void LockStateController::AnimateBackgroundAppearanceIfNecessary(
Ben Murdochc5cede92014-04-10 11:22:14 +0100665 SessionStateAnimator::AnimationSpeed speed,
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100666 ui::LayerAnimationObserver* observer) {
667 if (unlocked_properties_.get() &&
668 unlocked_properties_->background_is_hidden) {
669 animator_->StartAnimationWithObserver(
Ben Murdochc5cede92014-04-10 11:22:14 +0100670 SessionStateAnimator::DESKTOP_BACKGROUND,
671 SessionStateAnimator::ANIMATION_FADE_IN,
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100672 speed,
673 observer);
674 }
675}
676
677void LockStateController::AnimateBackgroundHidingIfNecessary(
Ben Murdochc5cede92014-04-10 11:22:14 +0100678 SessionStateAnimator::AnimationSpeed speed,
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100679 ui::LayerAnimationObserver* observer) {
680 if (unlocked_properties_.get() &&
681 unlocked_properties_->background_is_hidden) {
682 animator_->StartAnimationWithObserver(
Ben Murdochc5cede92014-04-10 11:22:14 +0100683 SessionStateAnimator::DESKTOP_BACKGROUND,
684 SessionStateAnimator::ANIMATION_FADE_OUT,
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100685 speed,
686 observer);
687 }
688}
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100689
690} // namespace ash