Home | History | Annotate | Download | only in wm
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ash/wm/session_state_controller_impl.h"
      6 
      7 #include "ash/ash_switches.h"
      8 #include "ash/cancel_mode.h"
      9 #include "ash/shell.h"
     10 #include "ash/shell_delegate.h"
     11 #include "ash/shell_window_ids.h"
     12 #include "ash/wm/session_state_animator.h"
     13 #include "base/command_line.h"
     14 #include "ui/aura/root_window.h"
     15 #include "ui/views/corewm/compound_event_filter.h"
     16 
     17 #if defined(OS_CHROMEOS)
     18 #include "base/chromeos/chromeos_version.h"
     19 #endif
     20 
     21 namespace ash {
     22 
     23 SessionStateControllerImpl::TestApi::TestApi(
     24     SessionStateControllerImpl* controller)
     25     : controller_(controller) {
     26 }
     27 
     28 SessionStateControllerImpl::TestApi::~TestApi() {
     29 }
     30 
     31 SessionStateControllerImpl::SessionStateControllerImpl()
     32     : login_status_(user::LOGGED_IN_NONE),
     33       system_is_locked_(false),
     34       shutting_down_(false),
     35       shutdown_after_lock_(false) {
     36   Shell::GetPrimaryRootWindow()->AddRootWindowObserver(this);
     37 }
     38 
     39 SessionStateControllerImpl::~SessionStateControllerImpl() {
     40   Shell::GetPrimaryRootWindow()->RemoveRootWindowObserver(this);
     41 }
     42 
     43 void SessionStateControllerImpl::OnLoginStateChanged(user::LoginStatus status) {
     44   if (status != user::LOGGED_IN_LOCKED)
     45     login_status_ = status;
     46   system_is_locked_ = (status == user::LOGGED_IN_LOCKED);
     47 }
     48 
     49 void SessionStateControllerImpl::OnAppTerminating() {
     50   // If we hear that Chrome is exiting but didn't request it ourselves, all we
     51   // can really hope for is that we'll have time to clear the screen.
     52   if (!shutting_down_) {
     53     shutting_down_ = true;
     54     Shell* shell = ash::Shell::GetInstance();
     55     shell->env_filter()->set_cursor_hidden_by_filter(false);
     56     shell->cursor_manager()->HideCursor();
     57     animator_->StartAnimation(
     58         internal::SessionStateAnimator::kAllContainersMask,
     59         internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
     60         internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
     61   }
     62 }
     63 
     64 void SessionStateControllerImpl::OnLockStateChanged(bool locked) {
     65   if (shutting_down_ || (system_is_locked_ == locked))
     66     return;
     67 
     68   system_is_locked_ = locked;
     69 
     70   if (locked) {
     71     animator_->StartAnimation(
     72         internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
     73         internal::SessionStateAnimator::ANIMATION_FADE_IN,
     74         internal::SessionStateAnimator::ANIMATION_SPEED_SHOW_LOCK_SCREEN);
     75     DispatchCancelMode();
     76     FOR_EACH_OBSERVER(LockStateObserver, observers_,
     77         OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_STARTED));
     78     lock_timer_.Stop();
     79     lock_fail_timer_.Stop();
     80 
     81     if (shutdown_after_lock_) {
     82       shutdown_after_lock_ = false;
     83       StartLockToShutdownTimer();
     84     }
     85   } else {
     86     animator_->StartAnimation(
     87         internal::SessionStateAnimator::DESKTOP_BACKGROUND |
     88         internal::SessionStateAnimator::LAUNCHER |
     89         internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
     90         internal::SessionStateAnimator::ANIMATION_RESTORE,
     91         internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
     92   }
     93 }
     94 
     95 void SessionStateControllerImpl::OnStartingLock() {
     96   if (shutting_down_ || system_is_locked_)
     97     return;
     98 
     99   animator_->StartAnimation(
    100       internal::SessionStateAnimator::LAUNCHER,
    101       internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
    102       internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
    103 
    104   animator_->StartAnimation(
    105       internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
    106       internal::SessionStateAnimator::ANIMATION_FULL_CLOSE,
    107       internal::SessionStateAnimator::ANIMATION_SPEED_FAST);
    108 
    109   DispatchCancelMode();
    110   FOR_EACH_OBSERVER(LockStateObserver, observers_,
    111       OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_STARTED));
    112 
    113   // Hide the screen locker containers so we can make them fade in later.
    114   animator_->StartAnimation(
    115       internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
    116       internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
    117       internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
    118 }
    119 
    120 void SessionStateControllerImpl::StartLockAnimationAndLockImmediately() {
    121   animator_->StartAnimation(
    122       internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
    123       internal::SessionStateAnimator::ANIMATION_PARTIAL_CLOSE,
    124       internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE);
    125   DispatchCancelMode();
    126   FOR_EACH_OBSERVER(LockStateObserver, observers_,
    127       OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_STARTED));
    128   OnLockTimeout();
    129 }
    130 
    131 void SessionStateControllerImpl::StartLockAnimation(bool shutdown_after_lock) {
    132   shutdown_after_lock_ = shutdown_after_lock;
    133 
    134   animator_->StartAnimation(
    135       internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
    136       internal::SessionStateAnimator::ANIMATION_PARTIAL_CLOSE,
    137       internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE);
    138   DispatchCancelMode();
    139   FOR_EACH_OBSERVER(LockStateObserver, observers_,
    140       OnLockStateEvent(LockStateObserver::EVENT_PRELOCK_ANIMATION_STARTED));
    141   StartLockTimer();
    142 }
    143 
    144 void SessionStateControllerImpl::StartShutdownAnimation() {
    145   animator_->StartAnimation(
    146       internal::SessionStateAnimator::kAllContainersMask,
    147       internal::SessionStateAnimator::ANIMATION_PARTIAL_CLOSE,
    148       internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE);
    149 
    150   StartPreShutdownAnimationTimer();
    151 }
    152 
    153 bool SessionStateControllerImpl::LockRequested() {
    154   return lock_fail_timer_.IsRunning();
    155 }
    156 
    157 bool SessionStateControllerImpl::ShutdownRequested() {
    158   return shutting_down_;
    159 }
    160 
    161 bool SessionStateControllerImpl::CanCancelLockAnimation() {
    162   return lock_timer_.IsRunning();
    163 }
    164 
    165 void SessionStateControllerImpl::CancelLockAnimation() {
    166   if (!CanCancelLockAnimation())
    167     return;
    168   shutdown_after_lock_ = false;
    169   animator_->StartAnimation(
    170       internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
    171       internal::SessionStateAnimator::ANIMATION_UNDO_PARTIAL_CLOSE,
    172       internal::SessionStateAnimator::ANIMATION_SPEED_REVERT);
    173   lock_timer_.Stop();
    174 }
    175 
    176 bool SessionStateControllerImpl::CanCancelShutdownAnimation() {
    177   return pre_shutdown_timer_.IsRunning() ||
    178          shutdown_after_lock_ ||
    179          lock_to_shutdown_timer_.IsRunning();
    180 }
    181 
    182 void SessionStateControllerImpl::CancelShutdownAnimation() {
    183   if (!CanCancelShutdownAnimation())
    184     return;
    185   if (lock_to_shutdown_timer_.IsRunning()) {
    186     lock_to_shutdown_timer_.Stop();
    187     return;
    188   }
    189   if (shutdown_after_lock_) {
    190     shutdown_after_lock_ = false;
    191     return;
    192   }
    193 
    194   if (system_is_locked_) {
    195     // If we've already started shutdown transition at lock screen
    196     // desktop background needs to be restored immediately.
    197     animator_->StartAnimation(
    198         internal::SessionStateAnimator::DESKTOP_BACKGROUND,
    199         internal::SessionStateAnimator::ANIMATION_RESTORE,
    200         internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
    201     animator_->StartAnimation(
    202         internal::SessionStateAnimator::kAllLockScreenContainersMask,
    203         internal::SessionStateAnimator::ANIMATION_UNDO_PARTIAL_CLOSE,
    204         internal::SessionStateAnimator::ANIMATION_SPEED_REVERT);
    205   } else {
    206     animator_->StartAnimation(
    207         internal::SessionStateAnimator::kAllContainersMask,
    208         internal::SessionStateAnimator::ANIMATION_UNDO_PARTIAL_CLOSE,
    209         internal::SessionStateAnimator::ANIMATION_SPEED_REVERT);
    210   }
    211   pre_shutdown_timer_.Stop();
    212 }
    213 
    214 void SessionStateControllerImpl::RequestShutdown() {
    215   if (!shutting_down_)
    216     RequestShutdownImpl();
    217 }
    218 
    219 void SessionStateControllerImpl::RequestShutdownImpl() {
    220   DCHECK(!shutting_down_);
    221   shutting_down_ = true;
    222 
    223   Shell* shell = ash::Shell::GetInstance();
    224   shell->env_filter()->set_cursor_hidden_by_filter(false);
    225   shell->cursor_manager()->HideCursor();
    226 
    227   if (login_status_ != user::LOGGED_IN_NONE) {
    228     // Hide the other containers before starting the animation.
    229     // ANIMATION_FULL_CLOSE will make the screen locker windows partially
    230     // transparent, and we don't want the other windows to show through.
    231     animator_->StartAnimation(
    232         internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS |
    233         internal::SessionStateAnimator::LAUNCHER,
    234         internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
    235         internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
    236     animator_->StartAnimation(
    237         internal::SessionStateAnimator::kAllLockScreenContainersMask,
    238         internal::SessionStateAnimator::ANIMATION_FULL_CLOSE,
    239         internal::SessionStateAnimator::ANIMATION_SPEED_FAST);
    240   } else {
    241     animator_->StartAnimation(
    242         internal::SessionStateAnimator::kAllContainersMask,
    243         internal::SessionStateAnimator::ANIMATION_FULL_CLOSE,
    244         internal::SessionStateAnimator::ANIMATION_SPEED_FAST);
    245   }
    246   StartRealShutdownTimer();
    247 }
    248 
    249 void SessionStateControllerImpl::OnRootWindowHostCloseRequested(
    250                                                 const aura::RootWindow*) {
    251   Shell::GetInstance()->delegate()->Exit();
    252 }
    253 
    254 void SessionStateControllerImpl::StartLockTimer() {
    255   lock_timer_.Stop();
    256   lock_timer_.Start(
    257       FROM_HERE,
    258       animator_->GetDuration(
    259           internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE),
    260       this, &SessionStateControllerImpl::OnLockTimeout);
    261 }
    262 
    263 void SessionStateControllerImpl::OnLockTimeout() {
    264   delegate_->RequestLockScreen();
    265   lock_fail_timer_.Start(
    266       FROM_HERE,
    267       base::TimeDelta::FromMilliseconds(kLockFailTimeoutMs),
    268       this, &SessionStateControllerImpl::OnLockFailTimeout);
    269 }
    270 
    271 void SessionStateControllerImpl::OnLockFailTimeout() {
    272   DCHECK(!system_is_locked_);
    273   // Undo lock animation.
    274   animator_->StartAnimation(
    275       internal::SessionStateAnimator::LAUNCHER |
    276       internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
    277       internal::SessionStateAnimator::ANIMATION_RESTORE,
    278       internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
    279 }
    280 
    281 void SessionStateControllerImpl::StartLockToShutdownTimer() {
    282   shutdown_after_lock_ = false;
    283   lock_to_shutdown_timer_.Stop();
    284   lock_to_shutdown_timer_.Start(
    285       FROM_HERE,
    286       base::TimeDelta::FromMilliseconds(kLockToShutdownTimeoutMs),
    287       this, &SessionStateControllerImpl::OnLockToShutdownTimeout);
    288 }
    289 
    290 
    291 void SessionStateControllerImpl::OnLockToShutdownTimeout() {
    292   DCHECK(system_is_locked_);
    293   StartShutdownAnimation();
    294 }
    295 
    296 void SessionStateControllerImpl::StartPreShutdownAnimationTimer() {
    297   pre_shutdown_timer_.Stop();
    298   pre_shutdown_timer_.Start(
    299       FROM_HERE,
    300       base::TimeDelta::FromMilliseconds(kShutdownTimeoutMs),
    301       this, &SessionStateControllerImpl::OnPreShutdownAnimationTimeout);
    302 }
    303 
    304 void SessionStateControllerImpl::OnPreShutdownAnimationTimeout() {
    305   if (!shutting_down_)
    306     RequestShutdownImpl();
    307 }
    308 
    309 void SessionStateControllerImpl::StartRealShutdownTimer() {
    310   base::TimeDelta duration =
    311       base::TimeDelta::FromMilliseconds(kShutdownRequestDelayMs);
    312   duration += animator_->GetDuration(
    313       internal::SessionStateAnimator::ANIMATION_SPEED_FAST);
    314 
    315   real_shutdown_timer_.Start(
    316       FROM_HERE,
    317       duration,
    318       this, &SessionStateControllerImpl::OnRealShutdownTimeout);
    319 }
    320 
    321 void SessionStateControllerImpl::OnRealShutdownTimeout() {
    322   DCHECK(shutting_down_);
    323 #if defined(OS_CHROMEOS)
    324   if (!base::chromeos::IsRunningOnChromeOS()) {
    325     ShellDelegate* delegate = Shell::GetInstance()->delegate();
    326     if (delegate) {
    327       delegate->Exit();
    328       return;
    329     }
    330   }
    331 #endif
    332   delegate_->RequestShutdown();
    333 }
    334 
    335 void SessionStateControllerImpl::OnLockScreenHide(base::Closure& callback) {
    336   callback.Run();
    337 }
    338 
    339 void SessionStateControllerImpl::SetLockScreenDisplayedCallback(
    340     base::Closure& callback) {
    341   NOTIMPLEMENTED();
    342 }
    343 
    344 }  // namespace ash
    345