• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 
7 #include <algorithm>
8 
9 #include "ash/accessibility_delegate.h"
10 #include "ash/ash_switches.h"
11 #include "ash/cancel_mode.h"
12 #include "ash/metrics/user_metrics_recorder.h"
13 #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"
17 #include "base/bind_helpers.h"
18 #include "base/command_line.h"
19 #include "base/timer/timer.h"
20 #include "content/public/browser/user_metrics.h"
21 #include "ui/aura/root_window.h"
22 #include "ui/compositor/layer_animation_sequence.h"
23 #include "ui/compositor/scoped_layer_animation_settings.h"
24 #include "ui/views/corewm/compound_event_filter.h"
25 
26 #if defined(OS_CHROMEOS)
27 #include "base/sys_info.h"
28 #include "media/audio/sounds/sounds_manager.h"
29 #endif
30 
31 #if defined(OS_CHROMEOS)
32 using media::SoundsManager;
33 #endif
34 
35 namespace ash {
36 
37 namespace {
38 
39 const int kMaxShutdownSoundDurationMs = 1500;
40 
GetBackground()41 aura::Window* GetBackground() {
42   aura::Window* root_window = Shell::GetPrimaryRootWindow();
43   return Shell::GetContainer(root_window,
44       internal::kShellWindowId_DesktopBackgroundContainer);
45 }
46 
IsBackgroundHidden()47 bool IsBackgroundHidden() {
48   return !GetBackground()->IsVisible();
49 }
50 
ShowBackground()51 void ShowBackground() {
52   ui::ScopedLayerAnimationSettings settings(
53       GetBackground()->layer()->GetAnimator());
54   settings.SetTransitionDuration(base::TimeDelta());
55   GetBackground()->Show();
56 }
57 
HideBackground()58 void HideBackground() {
59   ui::ScopedLayerAnimationSettings settings(
60       GetBackground()->layer()->GetAnimator());
61   settings.SetTransitionDuration(base::TimeDelta());
62   GetBackground()->Hide();
63 }
64 
65 // This observer is intended to use in cases when some action has to be taken
66 // once some animation successfully completes (i.e. it was not aborted).
67 // Observer will count a number of sequences it is attached to, and a number of
68 // finished sequences (either Ended or Aborted). Once these two numbers are
69 // equal, observer will delete itself, calling callback passed to constructor if
70 // there were no aborted animations.
71 // This way it can be either used to wait for some animation to be finished in
72 // multiple layers, to wait once a sequence of animations is finished in one
73 // layer or the mixture of both.
74 class AnimationFinishedObserver : public ui::LayerAnimationObserver {
75  public:
AnimationFinishedObserver(base::Closure & callback)76   explicit AnimationFinishedObserver(base::Closure &callback)
77       : callback_(callback),
78         sequences_attached_(0),
79         sequences_completed_(0),
80         paused_(false) {
81   }
82 
83   // Pauses observer: no checks will be made while paused. It can be used when
84   // a sequence has some immediate animations in the beginning, and for
85   // animations that can be tested with flag that makes all animations
86   // immediate.
Pause()87   void Pause() {
88     paused_ = true;
89   }
90 
91   // Unpauses observer. It does a check and calls callback if conditions are
92   // met.
Unpause()93   void Unpause() {
94     if (!paused_)
95       return;
96     paused_ = false;
97     if (sequences_completed_ == sequences_attached_) {
98       callback_.Run();
99       delete this;
100     }
101   }
102 
103  private:
~AnimationFinishedObserver()104   virtual ~AnimationFinishedObserver() {
105   }
106 
107   // LayerAnimationObserver implementation
OnLayerAnimationEnded(ui::LayerAnimationSequence * sequence)108   virtual void OnLayerAnimationEnded(
109       ui::LayerAnimationSequence* sequence) OVERRIDE {
110     sequences_completed_++;
111     if ((sequences_completed_ == sequences_attached_) && !paused_) {
112       callback_.Run();
113       delete this;
114     }
115   }
116 
OnLayerAnimationAborted(ui::LayerAnimationSequence * sequence)117   virtual void OnLayerAnimationAborted(
118       ui::LayerAnimationSequence* sequence) OVERRIDE {
119     sequences_completed_++;
120     if ((sequences_completed_ == sequences_attached_) && !paused_)
121       delete this;
122   }
123 
OnLayerAnimationScheduled(ui::LayerAnimationSequence * sequence)124   virtual void OnLayerAnimationScheduled(
125       ui::LayerAnimationSequence* sequence) OVERRIDE {
126   }
127 
OnAttachedToSequence(ui::LayerAnimationSequence * sequence)128   virtual void OnAttachedToSequence(
129       ui::LayerAnimationSequence* sequence) OVERRIDE {
130     LayerAnimationObserver::OnAttachedToSequence(sequence);
131     sequences_attached_++;
132   }
133 
134   // Callback to be called.
135   base::Closure callback_;
136 
137   // Number of sequences this observer was attached to.
138   int sequences_attached_;
139 
140   // Number of sequences either ended or aborted.
141   int sequences_completed_;
142 
143   bool paused_;
144 
145   DISALLOW_COPY_AND_ASSIGN(AnimationFinishedObserver);
146 };
147 
148 }  // namespace
149 
150 const int LockStateController::kLockTimeoutMs = 400;
151 const int LockStateController::kShutdownTimeoutMs = 400;
152 const int LockStateController::kLockFailTimeoutMs = 8000;
153 const int LockStateController::kLockToShutdownTimeoutMs = 150;
154 const int LockStateController::kShutdownRequestDelayMs = 50;
155 
TestApi(LockStateController * controller)156 LockStateController::TestApi::TestApi(LockStateController* controller)
157     : controller_(controller) {
158 }
159 
~TestApi()160 LockStateController::TestApi::~TestApi() {
161 }
162 
LockStateController()163 LockStateController::LockStateController()
164     : animator_(new internal::SessionStateAnimator()),
165       login_status_(user::LOGGED_IN_NONE),
166       system_is_locked_(false),
167       shutting_down_(false),
168       shutdown_after_lock_(false),
169       animating_lock_(false),
170       can_cancel_lock_animation_(false) {
171   Shell::GetPrimaryRootWindow()->GetDispatcher()->AddRootWindowObserver(this);
172 }
173 
~LockStateController()174 LockStateController::~LockStateController() {
175   Shell::GetPrimaryRootWindow()->GetDispatcher()->RemoveRootWindowObserver(
176       this);
177 }
178 
SetDelegate(LockStateControllerDelegate * delegate)179 void LockStateController::SetDelegate(LockStateControllerDelegate* delegate) {
180   delegate_.reset(delegate);
181 }
182 
AddObserver(LockStateObserver * observer)183 void LockStateController::AddObserver(LockStateObserver* observer) {
184   observers_.AddObserver(observer);
185 }
186 
RemoveObserver(LockStateObserver * observer)187 void LockStateController::RemoveObserver(LockStateObserver* observer) {
188   observers_.RemoveObserver(observer);
189 }
190 
HasObserver(LockStateObserver * observer)191 bool LockStateController::HasObserver(LockStateObserver* observer) {
192   return observers_.HasObserver(observer);
193 }
194 
StartLockAnimation(bool shutdown_after_lock)195 void LockStateController::StartLockAnimation(
196     bool shutdown_after_lock) {
197   if (animating_lock_)
198     return;
199   shutdown_after_lock_ = shutdown_after_lock;
200   can_cancel_lock_animation_ = true;
201 
202   StartCancellablePreLockAnimation();
203 }
204 
StartShutdownAnimation()205 void LockStateController::StartShutdownAnimation() {
206   StartCancellableShutdownAnimation();
207 }
208 
StartLockAnimationAndLockImmediately()209 void LockStateController::StartLockAnimationAndLockImmediately() {
210   if (animating_lock_)
211     return;
212   StartImmediatePreLockAnimation(true /* request_lock_on_completion */);
213 }
214 
LockRequested()215 bool LockStateController::LockRequested() {
216   return lock_fail_timer_.IsRunning();
217 }
218 
ShutdownRequested()219 bool LockStateController::ShutdownRequested() {
220   return shutting_down_;
221 }
222 
CanCancelLockAnimation()223 bool LockStateController::CanCancelLockAnimation() {
224   return can_cancel_lock_animation_;
225 }
226 
CancelLockAnimation()227 void LockStateController::CancelLockAnimation() {
228   if (!CanCancelLockAnimation())
229     return;
230   shutdown_after_lock_ = false;
231   animating_lock_ = false;
232   CancelPreLockAnimation();
233 }
234 
CanCancelShutdownAnimation()235 bool LockStateController::CanCancelShutdownAnimation() {
236   return pre_shutdown_timer_.IsRunning() ||
237          shutdown_after_lock_ ||
238          lock_to_shutdown_timer_.IsRunning();
239 }
240 
CancelShutdownAnimation()241 void LockStateController::CancelShutdownAnimation() {
242   if (!CanCancelShutdownAnimation())
243     return;
244   if (lock_to_shutdown_timer_.IsRunning()) {
245     lock_to_shutdown_timer_.Stop();
246     return;
247   }
248   if (shutdown_after_lock_) {
249     shutdown_after_lock_ = false;
250     return;
251   }
252 
253   animator_->StartGlobalAnimation(
254       internal::SessionStateAnimator::ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS,
255       internal::SessionStateAnimator::ANIMATION_SPEED_REVERT_SHUTDOWN);
256   pre_shutdown_timer_.Stop();
257 }
258 
OnStartingLock()259 void LockStateController::OnStartingLock() {
260   if (shutting_down_ || system_is_locked_)
261     return;
262   if (animating_lock_)
263     return;
264   StartImmediatePreLockAnimation(false /* request_lock_on_completion */);
265 }
266 
RequestShutdown()267 void LockStateController::RequestShutdown() {
268   if (shutting_down_)
269     return;
270 
271   shutting_down_ = true;
272 
273   Shell* shell = ash::Shell::GetInstance();
274   shell->cursor_manager()->HideCursor();
275 
276   animator_->StartGlobalAnimation(
277       internal::SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS,
278       internal::SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN);
279   StartRealShutdownTimer(true);
280 }
281 
OnLockScreenHide(base::Callback<void (void)> & callback)282 void LockStateController::OnLockScreenHide(
283   base::Callback<void(void)>& callback) {
284   StartUnlockAnimationBeforeUIDestroyed(callback);
285 }
286 
SetLockScreenDisplayedCallback(const base::Closure & callback)287 void LockStateController::SetLockScreenDisplayedCallback(
288     const base::Closure& callback) {
289   lock_screen_displayed_callback_ = callback;
290 }
291 
OnRootWindowHostCloseRequested(const aura::RootWindow *)292 void LockStateController::OnRootWindowHostCloseRequested(
293                                                 const aura::RootWindow*) {
294   Shell::GetInstance()->delegate()->Exit();
295 }
296 
OnLoginStateChanged(user::LoginStatus status)297 void LockStateController::OnLoginStateChanged(
298     user::LoginStatus status) {
299   if (status != user::LOGGED_IN_LOCKED)
300     login_status_ = status;
301   system_is_locked_ = (status == user::LOGGED_IN_LOCKED);
302 }
303 
OnAppTerminating()304 void LockStateController::OnAppTerminating() {
305   // If we hear that Chrome is exiting but didn't request it ourselves, all we
306   // can really hope for is that we'll have time to clear the screen.
307   // This is also the case when the user signs off.
308   if (!shutting_down_) {
309     shutting_down_ = true;
310     Shell* shell = ash::Shell::GetInstance();
311     shell->cursor_manager()->HideCursor();
312     shell->cursor_manager()->LockCursor();
313     animator_->StartAnimation(
314         internal::SessionStateAnimator::kAllContainersMask,
315         internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
316         internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
317   }
318 }
319 
OnLockStateChanged(bool locked)320 void LockStateController::OnLockStateChanged(bool locked) {
321   if (shutting_down_ || (system_is_locked_ == locked))
322     return;
323 
324   system_is_locked_ = locked;
325 
326   if (locked) {
327     StartPostLockAnimation();
328     lock_fail_timer_.Stop();
329   } else {
330     StartUnlockAnimationAfterUIDestroyed();
331   }
332 }
333 
OnLockFailTimeout()334 void LockStateController::OnLockFailTimeout() {
335   DCHECK(!system_is_locked_);
336   // Undo lock animation.
337   StartUnlockAnimationAfterUIDestroyed();
338 }
339 
StartLockToShutdownTimer()340 void LockStateController::StartLockToShutdownTimer() {
341   shutdown_after_lock_ = false;
342   lock_to_shutdown_timer_.Stop();
343   lock_to_shutdown_timer_.Start(
344       FROM_HERE,
345       base::TimeDelta::FromMilliseconds(kLockToShutdownTimeoutMs),
346       this, &LockStateController::OnLockToShutdownTimeout);
347 }
348 
OnLockToShutdownTimeout()349 void LockStateController::OnLockToShutdownTimeout() {
350   DCHECK(system_is_locked_);
351   StartCancellableShutdownAnimation();
352 }
353 
StartPreShutdownAnimationTimer()354 void LockStateController::StartPreShutdownAnimationTimer() {
355   pre_shutdown_timer_.Stop();
356   pre_shutdown_timer_.Start(
357       FROM_HERE,
358       animator_->
359           GetDuration(internal::SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN),
360       this,
361       &LockStateController::OnPreShutdownAnimationTimeout);
362 }
363 
OnPreShutdownAnimationTimeout()364 void LockStateController::OnPreShutdownAnimationTimeout() {
365   shutting_down_ = true;
366 
367   Shell* shell = ash::Shell::GetInstance();
368   shell->cursor_manager()->HideCursor();
369 
370   StartRealShutdownTimer(false);
371 }
372 
StartRealShutdownTimer(bool with_animation_time)373 void LockStateController::StartRealShutdownTimer(bool with_animation_time) {
374   base::TimeDelta duration =
375       base::TimeDelta::FromMilliseconds(kShutdownRequestDelayMs);
376   if (with_animation_time) {
377     duration += animator_->GetDuration(
378         internal::SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN);
379   }
380 
381 #if defined(OS_CHROMEOS)
382   const AccessibilityDelegate* const delegate =
383       Shell::GetInstance()->accessibility_delegate();
384   base::TimeDelta sound_duration = delegate->PlayShutdownSound();
385   sound_duration =
386       std::min(sound_duration,
387                base::TimeDelta::FromMilliseconds(kMaxShutdownSoundDurationMs));
388   duration = std::max(duration, sound_duration);
389 #endif
390 
391   real_shutdown_timer_.Start(
392       FROM_HERE, duration, this, &LockStateController::OnRealShutdownTimeout);
393 }
394 
OnRealShutdownTimeout()395 void LockStateController::OnRealShutdownTimeout() {
396   DCHECK(shutting_down_);
397 #if defined(OS_CHROMEOS)
398   if (!base::SysInfo::IsRunningOnChromeOS()) {
399     ShellDelegate* delegate = Shell::GetInstance()->delegate();
400     if (delegate) {
401       delegate->Exit();
402       return;
403     }
404   }
405 #endif
406   Shell::GetInstance()->metrics()->RecordUserMetricsAction(
407       UMA_ACCEL_SHUT_DOWN_POWER_BUTTON);
408   delegate_->RequestShutdown();
409 }
410 
StartCancellableShutdownAnimation()411 void LockStateController::StartCancellableShutdownAnimation() {
412   Shell* shell = ash::Shell::GetInstance();
413   // Hide cursor, but let it reappear if the mouse moves.
414   shell->cursor_manager()->HideCursor();
415 
416   animator_->StartGlobalAnimation(
417       internal::SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS,
418       internal::SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN);
419   StartPreShutdownAnimationTimer();
420 }
421 
StartImmediatePreLockAnimation(bool request_lock_on_completion)422 void LockStateController::StartImmediatePreLockAnimation(
423     bool request_lock_on_completion) {
424   animating_lock_ = true;
425 
426   StoreUnlockedProperties();
427 
428   base::Closure next_animation_starter =
429       base::Bind(&LockStateController::PreLockAnimationFinished,
430       base::Unretained(this), request_lock_on_completion);
431   AnimationFinishedObserver* observer =
432       new AnimationFinishedObserver(next_animation_starter);
433 
434   observer->Pause();
435 
436   animator_->StartAnimationWithObserver(
437       internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
438       internal::SessionStateAnimator::ANIMATION_LIFT,
439       internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
440       observer);
441   animator_->StartAnimationWithObserver(
442       internal::SessionStateAnimator::LAUNCHER,
443       internal::SessionStateAnimator::ANIMATION_FADE_OUT,
444       internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
445       observer);
446   // Hide the screen locker containers so we can raise them later.
447   animator_->StartAnimation(
448       internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
449       internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
450       internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
451   AnimateBackgroundAppearanceIfNecessary(
452       internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
453       observer);
454 
455   observer->Unpause();
456 
457   DispatchCancelMode();
458   FOR_EACH_OBSERVER(LockStateObserver, observers_,
459       OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_STARTED));
460 }
461 
StartCancellablePreLockAnimation()462 void LockStateController::StartCancellablePreLockAnimation() {
463   animating_lock_ = true;
464   StoreUnlockedProperties();
465 
466   base::Closure next_animation_starter =
467       base::Bind(&LockStateController::PreLockAnimationFinished,
468       base::Unretained(this), true /* request_lock */);
469   AnimationFinishedObserver* observer =
470       new AnimationFinishedObserver(next_animation_starter);
471 
472   observer->Pause();
473 
474   animator_->StartAnimationWithObserver(
475       internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
476       internal::SessionStateAnimator::ANIMATION_LIFT,
477       internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE,
478       observer);
479   animator_->StartAnimationWithObserver(
480       internal::SessionStateAnimator::LAUNCHER,
481       internal::SessionStateAnimator::ANIMATION_FADE_OUT,
482       internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE,
483       observer);
484   // Hide the screen locker containers so we can raise them later.
485   animator_->StartAnimation(
486       internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
487       internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
488       internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
489   AnimateBackgroundAppearanceIfNecessary(
490       internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE,
491       observer);
492 
493   DispatchCancelMode();
494   FOR_EACH_OBSERVER(LockStateObserver, observers_,
495       OnLockStateEvent(LockStateObserver::EVENT_PRELOCK_ANIMATION_STARTED));
496   observer->Unpause();
497 }
498 
CancelPreLockAnimation()499 void LockStateController::CancelPreLockAnimation() {
500   base::Closure next_animation_starter =
501       base::Bind(&LockStateController::LockAnimationCancelled,
502       base::Unretained(this));
503   AnimationFinishedObserver* observer =
504       new AnimationFinishedObserver(next_animation_starter);
505 
506   observer->Pause();
507 
508   animator_->StartAnimationWithObserver(
509       internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
510       internal::SessionStateAnimator::ANIMATION_UNDO_LIFT,
511       internal::SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS,
512       observer);
513   animator_->StartAnimationWithObserver(
514       internal::SessionStateAnimator::LAUNCHER,
515       internal::SessionStateAnimator::ANIMATION_FADE_IN,
516       internal::SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS,
517       observer);
518   AnimateBackgroundHidingIfNecessary(
519       internal::SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS,
520       observer);
521 
522   observer->Unpause();
523 }
524 
StartPostLockAnimation()525 void LockStateController::StartPostLockAnimation() {
526   base::Closure next_animation_starter =
527       base::Bind(&LockStateController::PostLockAnimationFinished,
528       base::Unretained(this));
529 
530   AnimationFinishedObserver* observer =
531       new AnimationFinishedObserver(next_animation_starter);
532 
533   observer->Pause();
534   animator_->StartAnimationWithObserver(
535       internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
536       internal::SessionStateAnimator::ANIMATION_RAISE_TO_SCREEN,
537       internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
538       observer);
539   observer->Unpause();
540 }
541 
StartUnlockAnimationBeforeUIDestroyed(base::Closure & callback)542 void LockStateController::StartUnlockAnimationBeforeUIDestroyed(
543     base::Closure& callback) {
544   animator_->StartAnimationWithCallback(
545       internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
546       internal::SessionStateAnimator::ANIMATION_LIFT,
547       internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
548       callback);
549 }
550 
StartUnlockAnimationAfterUIDestroyed()551 void LockStateController::StartUnlockAnimationAfterUIDestroyed() {
552   base::Closure next_animation_starter =
553       base::Bind(&LockStateController::UnlockAnimationAfterUIDestroyedFinished,
554                  base::Unretained(this));
555 
556   AnimationFinishedObserver* observer =
557       new AnimationFinishedObserver(next_animation_starter);
558 
559   observer->Pause();
560 
561   animator_->StartAnimationWithObserver(
562       internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
563       internal::SessionStateAnimator::ANIMATION_DROP,
564       internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
565       observer);
566   animator_->StartAnimationWithObserver(
567       internal::SessionStateAnimator::LAUNCHER,
568       internal::SessionStateAnimator::ANIMATION_FADE_IN,
569       internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
570       observer);
571   AnimateBackgroundHidingIfNecessary(
572       internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
573       observer);
574   observer->Unpause();
575 }
576 
LockAnimationCancelled()577 void LockStateController::LockAnimationCancelled() {
578   can_cancel_lock_animation_ = false;
579   RestoreUnlockedProperties();
580 }
581 
PreLockAnimationFinished(bool request_lock)582 void LockStateController::PreLockAnimationFinished(bool request_lock) {
583   can_cancel_lock_animation_ = false;
584 
585   if (request_lock) {
586     Shell::GetInstance()->metrics()->RecordUserMetricsAction(
587         shutdown_after_lock_ ?
588         UMA_ACCEL_LOCK_SCREEN_POWER_BUTTON :
589         UMA_ACCEL_LOCK_SCREEN_LOCK_BUTTON);
590     delegate_->RequestLockScreen();
591   }
592 
593   lock_fail_timer_.Start(
594       FROM_HERE,
595       base::TimeDelta::FromMilliseconds(kLockFailTimeoutMs),
596       this,
597       &LockStateController::OnLockFailTimeout);
598 }
599 
PostLockAnimationFinished()600 void LockStateController::PostLockAnimationFinished() {
601   animating_lock_ = false;
602 
603   FOR_EACH_OBSERVER(LockStateObserver, observers_,
604       OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_FINISHED));
605   if (!lock_screen_displayed_callback_.is_null()) {
606     lock_screen_displayed_callback_.Run();
607     lock_screen_displayed_callback_.Reset();
608   }
609   if (shutdown_after_lock_) {
610     shutdown_after_lock_ = false;
611     StartLockToShutdownTimer();
612   }
613 }
614 
UnlockAnimationAfterUIDestroyedFinished()615 void LockStateController::UnlockAnimationAfterUIDestroyedFinished() {
616   RestoreUnlockedProperties();
617 }
618 
StoreUnlockedProperties()619 void LockStateController::StoreUnlockedProperties() {
620   if (!unlocked_properties_) {
621     unlocked_properties_.reset(new UnlockedStateProperties());
622     unlocked_properties_->background_is_hidden = IsBackgroundHidden();
623   }
624   if (unlocked_properties_->background_is_hidden) {
625     // Hide background so that it can be animated later.
626     animator_->StartAnimation(
627         internal::SessionStateAnimator::DESKTOP_BACKGROUND,
628         internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
629         internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
630     ShowBackground();
631   }
632 }
633 
RestoreUnlockedProperties()634 void LockStateController::RestoreUnlockedProperties() {
635   if (!unlocked_properties_)
636     return;
637   if (unlocked_properties_->background_is_hidden) {
638     HideBackground();
639     // Restore background visibility.
640     animator_->StartAnimation(
641         internal::SessionStateAnimator::DESKTOP_BACKGROUND,
642         internal::SessionStateAnimator::ANIMATION_FADE_IN,
643         internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
644   }
645   unlocked_properties_.reset();
646 }
647 
AnimateBackgroundAppearanceIfNecessary(internal::SessionStateAnimator::AnimationSpeed speed,ui::LayerAnimationObserver * observer)648 void LockStateController::AnimateBackgroundAppearanceIfNecessary(
649     internal::SessionStateAnimator::AnimationSpeed speed,
650     ui::LayerAnimationObserver* observer) {
651   if (unlocked_properties_.get() &&
652       unlocked_properties_->background_is_hidden) {
653     animator_->StartAnimationWithObserver(
654         internal::SessionStateAnimator::DESKTOP_BACKGROUND,
655         internal::SessionStateAnimator::ANIMATION_FADE_IN,
656         speed,
657         observer);
658   }
659 }
660 
AnimateBackgroundHidingIfNecessary(internal::SessionStateAnimator::AnimationSpeed speed,ui::LayerAnimationObserver * observer)661 void LockStateController::AnimateBackgroundHidingIfNecessary(
662     internal::SessionStateAnimator::AnimationSpeed speed,
663     ui::LayerAnimationObserver* observer) {
664   if (unlocked_properties_.get() &&
665       unlocked_properties_->background_is_hidden) {
666     animator_->StartAnimationWithObserver(
667         internal::SessionStateAnimator::DESKTOP_BACKGROUND,
668         internal::SessionStateAnimator::ANIMATION_FADE_OUT,
669         speed,
670         observer);
671   }
672 }
673 
674 }  // namespace ash
675