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