// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef ASH_WM_LOCK_STATE_CONTROLLER_H_ #define ASH_WM_LOCK_STATE_CONTROLLER_H_ #include "ash/ash_export.h" #include "ash/shell_observer.h" #include "ash/wm/lock_state_observer.h" #include "ash/wm/session_state_animator.h" #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "ui/aura/window_tree_host_observer.h" namespace gfx { class Rect; class Size; } namespace ui { class Layer; } namespace ash { namespace test { class LockStateControllerTest; class PowerButtonControllerTest; } // Performs system-related functions on behalf of LockStateController. class ASH_EXPORT LockStateControllerDelegate { public: LockStateControllerDelegate() {} virtual ~LockStateControllerDelegate() {} virtual void RequestLockScreen() = 0; virtual void RequestShutdown() = 0; private: DISALLOW_COPY_AND_ASSIGN(LockStateControllerDelegate); }; // Displays onscreen animations and locks or suspends the system in response to // the power button being pressed or released. // Lock workflow: // Entry points: // * StartLockAnimation (bool shutdown after lock) - starts lock that can be // cancelled. // * StartLockAnimationAndLockImmediately - starts uninterruptible lock // animation. // This leads to call of either StartImmediatePreLockAnimation or // StartCancellablePreLockAnimation. Once they complete // PreLockAnimationFinished is called, and system lock is requested. // Once system locks and lock UI is created, OnLockStateChanged is called, and // StartPostLockAnimation is called. In PostLockAnimationFinished two // things happen : EVENT_LOCK_ANIMATION_FINISHED notification is sent (it // triggers third part of animation within lock UI), and check for continuing to // shutdown is made. // // Unlock workflow: // WebUI does first part of animation, and calls OnLockScreenHide(callback) that // triggers StartUnlockAnimationBeforeUIDestroyed(callback). Once callback is // called at the end of the animation, lock UI is deleted, system unlocks, and // OnLockStateChanged is called. It leads to // StartUnlockAnimationAfterUIDestroyed. class ASH_EXPORT LockStateController : public aura::WindowTreeHostObserver, public ShellObserver { public: // Amount of time that the power button needs to be held before we lock the // screen. static const int kLockTimeoutMs; // Amount of time that the power button needs to be held before we shut down. static const int kShutdownTimeoutMs; // Amount of time to wait for our lock requests to be honored before giving // up. static const int kLockFailTimeoutMs; // When the button has been held continuously from the unlocked state, amount // of time that we wait after the screen locker window is shown before // starting the pre-shutdown animation. static const int kLockToShutdownTimeoutMs; // Additional time (beyond kFastCloseAnimMs) to wait after starting the // fast-close shutdown animation before actually requesting shutdown, to give // the animation time to finish. static const int kShutdownRequestDelayMs; // Helper class used by tests to access internal state. class ASH_EXPORT TestApi { public: explicit TestApi(LockStateController* controller); virtual ~TestApi(); bool lock_fail_timer_is_running() const { return controller_->lock_fail_timer_.IsRunning(); } bool lock_to_shutdown_timer_is_running() const { return controller_->lock_to_shutdown_timer_.IsRunning(); } bool shutdown_timer_is_running() const { return controller_->pre_shutdown_timer_.IsRunning(); } bool real_shutdown_timer_is_running() const { return controller_->real_shutdown_timer_.IsRunning(); } bool is_animating_lock() const { return controller_->animating_lock_; } bool is_lock_cancellable() const { return controller_->CanCancelLockAnimation(); } void trigger_lock_fail_timeout() { controller_->OnLockFailTimeout(); controller_->lock_fail_timer_.Stop(); } void trigger_lock_to_shutdown_timeout() { controller_->OnLockToShutdownTimeout(); controller_->lock_to_shutdown_timer_.Stop(); } void trigger_shutdown_timeout() { controller_->OnPreShutdownAnimationTimeout(); controller_->pre_shutdown_timer_.Stop(); } void trigger_real_shutdown_timeout() { controller_->OnRealShutdownTimeout(); controller_->real_shutdown_timer_.Stop(); } private: LockStateController* controller_; // not owned DISALLOW_COPY_AND_ASSIGN(TestApi); }; LockStateController(); virtual ~LockStateController(); // Takes ownership of |delegate|. void SetDelegate(LockStateControllerDelegate* delegate); void AddObserver(LockStateObserver* observer); void RemoveObserver(LockStateObserver* observer); bool HasObserver(LockStateObserver* observer); // Starts locking (with slow animation) that can be cancelled. // After locking and |kLockToShutdownTimeoutMs| StartShutdownAnimation() // will be called unless CancelShutdownAnimation() is called, if // |shutdown_after_lock| is true. void StartLockAnimation(bool shutdown_after_lock); // Starts shutting down (with slow animation) that can be cancelled. void StartShutdownAnimation(); // Starts usual lock animation, but locks immediately. // Unlike StartLockAnimation it does no lead to StartShutdownAnimation. void StartLockAnimationAndLockImmediately(); // Returns true if we have requested system to lock, but haven't received // confirmation yet. bool LockRequested(); // Returns true if we are shutting down. bool ShutdownRequested(); // Returns true if we are within cancellable lock timeframe. bool CanCancelLockAnimation(); // Cancels locking and reverts lock animation. void CancelLockAnimation(); // Returns true if we are within cancellable shutdown timeframe. bool CanCancelShutdownAnimation(); // Cancels shutting down and reverts shutdown animation. void CancelShutdownAnimation(); // Called when Chrome gets a request to display the lock screen. void OnStartingLock(); // Displays the shutdown animation and requests shutdown when it's done. void RequestShutdown(); // Called when ScreenLocker is ready to close, but not yet destroyed. // Can be used to display "hiding" animations on unlock. // |callback| will be called when all animations are done. void OnLockScreenHide(base::Closure& callback); // Sets up the callback that should be called once lock animation is finished. // Callback is guaranteed to be called once and then discarded. void SetLockScreenDisplayedCallback(const base::Closure& callback); // aura::WindowTreeHostObserver override: virtual void OnHostCloseRequested(const aura::WindowTreeHost* host) OVERRIDE; // ShellObserver overrides: virtual void OnLoginStateChanged(user::LoginStatus status) OVERRIDE; virtual void OnAppTerminating() OVERRIDE; virtual void OnLockStateChanged(bool locked) OVERRIDE; private: friend class test::PowerButtonControllerTest; friend class test::LockStateControllerTest; struct UnlockedStateProperties { bool background_is_hidden; }; // Reverts the pre-lock animation, reports the error. void OnLockFailTimeout(); // Starts timer for gap between lock and shutdown. void StartLockToShutdownTimer(); // Calls StartShutdownAnimation(). void OnLockToShutdownTimeout(); // Starts timer for undoable shutdown animation. void StartPreShutdownAnimationTimer(); // Calls StartRealShutdownTimer(). void OnPreShutdownAnimationTimeout(); // Starts timer for final shutdown animation. // If |with_animation_time| is true, it will also include time of "fade to // white" shutdown animation. void StartRealShutdownTimer(bool with_animation_time); // Requests that the machine be shut down. void OnRealShutdownTimeout(); // Starts shutdown animation that can be cancelled and starts pre-shutdown // timer. void StartCancellableShutdownAnimation(); // If |request_lock_on_completion| is true, a lock request will be sent // after the pre-lock animation completes. (The pre-lock animation is // also displayed in response to already-in-progress lock requests; in // these cases an additional lock request is undesirable.) void StartImmediatePreLockAnimation(bool request_lock_on_completion); void StartCancellablePreLockAnimation(); void CancelPreLockAnimation(); void StartPostLockAnimation(); // This method calls |callback| when animation completes. void StartUnlockAnimationBeforeUIDestroyed(base::Closure &callback); void StartUnlockAnimationAfterUIDestroyed(); // These methods are called when corresponding animation completes. void LockAnimationCancelled(); void PreLockAnimationFinished(bool request_lock); void PostLockAnimationFinished(); void UnlockAnimationAfterUIDestroyedFinished(); // Stores properties of UI that have to be temporarily modified while locking. void StoreUnlockedProperties(); void RestoreUnlockedProperties(); // Fades in background layer with |speed| if it was hidden in unlocked state. void AnimateBackgroundAppearanceIfNecessary( ash::internal::SessionStateAnimator::AnimationSpeed speed, ui::LayerAnimationObserver* observer); // Fades out background layer with |speed| if it was hidden in unlocked state. void AnimateBackgroundHidingIfNecessary( ash::internal::SessionStateAnimator::AnimationSpeed speed, ui::LayerAnimationObserver* observer); scoped_ptr animator_; scoped_ptr delegate_; ObserverList observers_; // The current login status, or original login status from before we locked. user::LoginStatus login_status_; // Current lock status. bool system_is_locked_; // Are we in the process of shutting the machine down? bool shutting_down_; // Indicates whether controller should proceed to (cancellable) shutdown after // locking. bool shutdown_after_lock_; // Indicates that controller displays lock animation. bool animating_lock_; // Indicates that lock animation can be undone. bool can_cancel_lock_animation_; scoped_ptr unlocked_properties_; // Started when we request that the screen be locked. When it fires, we // assume that our request got dropped. base::OneShotTimer lock_fail_timer_; // Started when the screen is locked while the power button is held. Adds a // delay between the appearance of the lock screen and the beginning of the // pre-shutdown animation. base::OneShotTimer lock_to_shutdown_timer_; // Started when we begin displaying the pre-shutdown animation. When it // fires, we start the shutdown animation and get ready to request shutdown. base::OneShotTimer pre_shutdown_timer_; // Started when we display the shutdown animation. When it fires, we actually // request shutdown. Gives the animation time to complete before Chrome, X, // etc. are shut down. base::OneShotTimer real_shutdown_timer_; base::Closure lock_screen_displayed_callback_; base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(LockStateController); }; } // namespace ash #endif // ASH_WM_LOCK_STATE_CONTROLLER_H_