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