Home | History | Annotate | Download | only in wm
      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 
     41 aura::Window* GetBackground() {
     42   aura::Window* root_window = Shell::GetPrimaryRootWindow();
     43   return Shell::GetContainer(root_window,
     44       internal::kShellWindowId_DesktopBackgroundContainer);
     45 }
     46 
     47 bool IsBackgroundHidden() {
     48   return !GetBackground()->IsVisible();
     49 }
     50 
     51 void ShowBackground() {
     52   ui::ScopedLayerAnimationSettings settings(
     53       GetBackground()->layer()->GetAnimator());
     54   settings.SetTransitionDuration(base::TimeDelta());
     55   GetBackground()->Show();
     56 }
     57 
     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:
     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.
     87   void Pause() {
     88     paused_ = true;
     89   }
     90 
     91   // Unpauses observer. It does a check and calls callback if conditions are
     92   // met.
     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:
    104   virtual ~AnimationFinishedObserver() {
    105   }
    106 
    107   // LayerAnimationObserver implementation
    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 
    117   virtual void OnLayerAnimationAborted(
    118       ui::LayerAnimationSequence* sequence) OVERRIDE {
    119     sequences_completed_++;
    120     if ((sequences_completed_ == sequences_attached_) && !paused_)
    121       delete this;
    122   }
    123 
    124   virtual void OnLayerAnimationScheduled(
    125       ui::LayerAnimationSequence* sequence) OVERRIDE {
    126   }
    127 
    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 
    156 LockStateController::TestApi::TestApi(LockStateController* controller)
    157     : controller_(controller) {
    158 }
    159 
    160 LockStateController::TestApi::~TestApi() {
    161 }
    162 
    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 
    174 LockStateController::~LockStateController() {
    175   Shell::GetPrimaryRootWindow()->GetDispatcher()->RemoveRootWindowObserver(
    176       this);
    177 }
    178 
    179 void LockStateController::SetDelegate(LockStateControllerDelegate* delegate) {
    180   delegate_.reset(delegate);
    181 }
    182 
    183 void LockStateController::AddObserver(LockStateObserver* observer) {
    184   observers_.AddObserver(observer);
    185 }
    186 
    187 void LockStateController::RemoveObserver(LockStateObserver* observer) {
    188   observers_.RemoveObserver(observer);
    189 }
    190 
    191 bool LockStateController::HasObserver(LockStateObserver* observer) {
    192   return observers_.HasObserver(observer);
    193 }
    194 
    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 
    205 void LockStateController::StartShutdownAnimation() {
    206   StartCancellableShutdownAnimation();
    207 }
    208 
    209 void LockStateController::StartLockAnimationAndLockImmediately() {
    210   if (animating_lock_)
    211     return;
    212   StartImmediatePreLockAnimation(true /* request_lock_on_completion */);
    213 }
    214 
    215 bool LockStateController::LockRequested() {
    216   return lock_fail_timer_.IsRunning();
    217 }
    218 
    219 bool LockStateController::ShutdownRequested() {
    220   return shutting_down_;
    221 }
    222 
    223 bool LockStateController::CanCancelLockAnimation() {
    224   return can_cancel_lock_animation_;
    225 }
    226 
    227 void LockStateController::CancelLockAnimation() {
    228   if (!CanCancelLockAnimation())
    229     return;
    230   shutdown_after_lock_ = false;
    231   animating_lock_ = false;
    232   CancelPreLockAnimation();
    233 }
    234 
    235 bool LockStateController::CanCancelShutdownAnimation() {
    236   return pre_shutdown_timer_.IsRunning() ||
    237          shutdown_after_lock_ ||
    238          lock_to_shutdown_timer_.IsRunning();
    239 }
    240 
    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 
    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 
    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 
    282 void LockStateController::OnLockScreenHide(
    283   base::Callback<void(void)>& callback) {
    284   StartUnlockAnimationBeforeUIDestroyed(callback);
    285 }
    286 
    287 void LockStateController::SetLockScreenDisplayedCallback(
    288     const base::Closure& callback) {
    289   lock_screen_displayed_callback_ = callback;
    290 }
    291 
    292 void LockStateController::OnRootWindowHostCloseRequested(
    293                                                 const aura::RootWindow*) {
    294   Shell::GetInstance()->delegate()->Exit();
    295 }
    296 
    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 
    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 
    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 
    334 void LockStateController::OnLockFailTimeout() {
    335   DCHECK(!system_is_locked_);
    336   // Undo lock animation.
    337   StartUnlockAnimationAfterUIDestroyed();
    338 }
    339 
    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 
    349 void LockStateController::OnLockToShutdownTimeout() {
    350   DCHECK(system_is_locked_);
    351   StartCancellableShutdownAnimation();
    352 }
    353 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    577 void LockStateController::LockAnimationCancelled() {
    578   can_cancel_lock_animation_ = false;
    579   RestoreUnlockedProperties();
    580 }
    581 
    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 
    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 
    615 void LockStateController::UnlockAnimationAfterUIDestroyedFinished() {
    616   RestoreUnlockedProperties();
    617 }
    618 
    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 
    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 
    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 
    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