| // Copyright 2013 The Chromium Authors |
| // 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 <memory> |
| #include <optional> |
| |
| #include "ash/ash_export.h" |
| #include "ash/public/cpp/session/session_observer.h" |
| #include "ash/shutdown_reason.h" |
| #include "ash/wallpaper/wallpaper_constants.h" |
| #include "ash/wm/lock_state_observer.h" |
| #include "ash/wm/session_state_animator.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/observer_list.h" |
| #include "base/timer/elapsed_timer.h" |
| #include "base/timer/timer.h" |
| #include "components/prefs/pref_registry_simple.h" |
| #include "components/prefs/pref_service.h" |
| #include "third_party/cros_system_api/dbus/power_manager/dbus-constants.h" |
| #include "ui/aura/window_tree_host_observer.h" |
| #include "ui/gfx/image/image.h" |
| |
| namespace ash { |
| |
| class ShutdownController; |
| enum class ShutdownReason; |
| |
| // Displays onscreen animations and locks or suspends the system in response to |
| // the power button being pressed or released. |
| // Lock workflow: |
| // Entry point: |
| // * StartLockAnimation (bool shutdown after lock) - starts lock that can be |
| // cancelled. |
| // Once it completes, 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 |
| // StartUnlockAnimationAfterLockUIDestroyed. |
| class ASH_EXPORT LockStateController : public aura::WindowTreeHostObserver, |
| public SessionObserver { |
| public: |
| // A bitfield mask including NON_LOCK_SCREEN_CONTAINERS and LAUNCHER, used for |
| // pre-lock hiding animation. |
| static const int kPreLockContainersMask; |
| |
| LockStateController(ShutdownController* shutdown_controller, |
| PrefService* local_state); |
| |
| LockStateController(const LockStateController&) = delete; |
| LockStateController& operator=(const LockStateController&) = delete; |
| |
| ~LockStateController() override; |
| |
| static void RegisterPrefs(PrefRegistrySimple* registry); |
| |
| void AddObserver(LockStateObserver* observer); |
| void RemoveObserver(LockStateObserver* observer); |
| |
| // Starts locking (with slow pre-lock animation) that can be cancelled. |
| void StartLockAnimation(); |
| |
| // Starts locking without slow animation. |
| void LockWithoutAnimation(); |
| |
| // Returns true if we have requested system to lock, but haven't received |
| // confirmation yet. |
| bool LockRequested(); |
| |
| // Cancels locking and reverts lock animation. |
| void CancelLockAnimation(); |
| |
| // 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(SessionStateAnimator::AnimationCallback 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(base::OnceClosure callback); |
| |
| // Displays the shutdown animation and requests a system shutdown or system |
| // restart depending on the the state of the |RebootOnShutdown| device policy. |
| void RequestShutdown(ShutdownReason reason); |
| |
| // The difference between this and `RequestShutdown` is that this one starts |
| // the shutdown that can be canceled. Note, please use only when necessary and |
| // together with `MaybeCancelShutdownAnimation`. E.g., requesting through the |
| // physical power button, while pressing the power button with different |
| // duration can lead to different shutdown states. |
| void RequestCancelableShutdown(ShutdownReason reason); |
| |
| // True if the real non-cancelable shutting down started. |
| bool ShutdownRequested() const; |
| |
| // Reverts the shutdown animation and updates the shutdown state to canceled. |
| // Then the shutdown process will not move forward. Returns true if the |
| // shutdown is canceled, otherwise false. |
| bool MaybeCancelShutdownAnimation(); |
| |
| // Requests restart with the same animation as `RequestShutdown` and take the |
| // informed restore image if forest feature is enabled, restart directly |
| // otherwise. `description` is a human-readable string describing the source |
| // of request the restart. |
| void RequestRestart(power_manager::RequestRestartReason reason, |
| const std::string& description); |
| |
| // Requests sign out with the same animation as `RequestShutdown` and take the |
| // informed restore image if forest feature is enabled, sign out directly |
| // otherwise. |
| void RequestSignOut(); |
| |
| // aura::WindowTreeHostObserver override: |
| void OnHostCloseRequested(aura::WindowTreeHost* host) override; |
| |
| // SessionObserver overrides: |
| void OnChromeTerminating() override; |
| void OnLockStateChanged(bool locked) override; |
| |
| void set_animator_for_test(SessionStateAnimator* animator) { |
| animator_.reset(animator); |
| } |
| bool animating_lock_for_test() const { return animating_lock_; } |
| |
| private: |
| friend class LockStateControllerTestApi; |
| |
| struct UnlockedStateProperties { |
| bool wallpaper_is_hidden; |
| }; |
| |
| // Specifies the requested session state. |
| enum class RequestedSessionState { |
| kShutdown = 0, |
| kCancelableShutdown, |
| kRestart, |
| kSignOut, |
| }; |
| |
| // Cancels unlock animation. |
| void CancelUnlockAnimation(); |
| |
| // Reverts the pre-lock animation, reports the error. |
| void OnLockFailTimeout(); |
| |
| void PreLockAnimation(SessionStateAnimator::AnimationSpeed speed, |
| bool request_lock_on_completion); |
| void StartPostLockAnimation(); |
| void OnPostLockFailTimeout(); |
| // This method calls |callback| when animation completes. |
| void StartUnlockAnimationBeforeLockUIDestroyed(base::OnceClosure callback); |
| void StartUnlockAnimationAfterLockUIDestroyed(); |
| |
| // These methods are called when corresponding animation completes. |
| void LockAnimationCancelled(bool aborted); |
| void PreLockAnimationFinished(bool request_lock, bool aborted); |
| void PostLockAnimationFinished(bool aborted); |
| void UnlockAnimationAfterLockUIDestroyedFinished(bool aborted); |
| |
| // Stores properties of UI that have to be temporarily modified while locking. |
| void StoreUnlockedProperties(); |
| void RestoreUnlockedProperties(); |
| |
| // Fades in wallpaper layer with |speed| if it was hidden in unlocked state. |
| void AnimateWallpaperAppearanceIfNecessary( |
| SessionStateAnimator::AnimationSpeed speed, |
| SessionStateAnimator::AnimationSequence* animation_sequence); |
| |
| // Fades out wallpaper layer with |speed| if it was hidden in unlocked state. |
| void AnimateWallpaperHidingIfNecessary( |
| SessionStateAnimator::AnimationSpeed speed, |
| SessionStateAnimator::AnimationSequence* animation_sequence); |
| |
| // Passed as a callback to the animation sequence that runs as part of |
| // StartUnlockAnimationBeforeLockUIDestroyed. The callback will be invoked |
| // after the animations complete, it will then check if the power button was |
| // pressed at all during the unlock animation, and if so, immediately revert |
| // the animations and notify ScreenLocker that the unlock process is to be |
| // aborted. |
| void OnUnlockAnimationBeforeLockUIDestroyedFinished(); |
| |
| // Notifies observers. |
| void OnLockStateEvent(LockStateObserver::EventType event); |
| |
| // Starts timer for undoable shutdown animation. |
| void StartPreShutdownAnimationTimer(); |
| |
| // Calls `StartSessionStateChangeTimer()` with |
| // `RequestedSessionState::kCancelableShutdown` when |
| // `cancelable_shutdown_timer_` expires. |
| void OnPreShutdownAnimationTimeout(); |
| |
| // Starts timer for final session state change animation. If |
| // `with_animation_time` is true, it will also include time of "fade to white" |
| // shutdown animation (NOTE: we are using the same animation for restart and |
| // signout as well). If `requested_session_state` is shutdown related, |
| // shutdown sound duration will be included in the duration calculation as |
| // well. |
| void StartSessionStateChangeTimer( |
| bool with_animation_time, |
| RequestedSessionState requested_session_state); |
| |
| // Called by `session_state_change_timer_` to start the |
| // `requested_session_state` change. |
| void OnSessionStateChangeTimeout( |
| RequestedSessionState requested_session_state); |
| |
| // Takes a screenshot for the informed restore dialog first and then starts |
| // the session state change process. `requested_session_state` indicates the |
| // requested session state. |
| void SessionStateChangeWithInformedRestore( |
| RequestedSessionState requested_session_state); |
| |
| // Binds to a callback that will be called by the DLP manager to let us know |
| // whether capturing the screenshot should `proceed` or abort due to some |
| // restricted contents on the screen. `requested_session_state` indicates the |
| // requested session state change. |
| void OnDlpRestrictionCheckedAtScreenCapture( |
| RequestedSessionState requested_session_state, |
| const base::FilePath& file_path, |
| bool proceed); |
| |
| // Starts the session state change process with the given |
| // `requested_session_state`. |
| void StartSessionStateChange(RequestedSessionState requested_session_state); |
| |
| // Triggers the session state change process when the |
| // `take_screenshot_fail_timer_` times out. `requested_session_state` |
| // indicates the requested session state change. |
| void OnTakeScreenshotFailTimeout( |
| RequestedSessionState requested_session_state); |
| |
| // Callback invoked once the image is taken. `requested_session_state` |
| // indicates the requested session state after the image had been taken. |
| // `file_path` indicates the path to save the informed restore image. Note: |
| // `gfx::Image` is cheap to pass by value. |
| void OnInformedRestoreImageTaken( |
| RequestedSessionState requested_session_state, |
| const base::FilePath& file_path, |
| base::TimeTicks start_time, |
| gfx::Image informed_restore_image); |
| |
| // Callback invoked when the informed restore image was encoded and saved. |
| // `file_path` is the file path to save the informed restore image. |
| void OnInformedRestoreImageSaved(base::TimeTicks start_time, |
| const base::FilePath& file_path); |
| |
| // Called when `session_state_change_timer_` times out with `kRestart` |
| // requested. |
| void DoRestart(power_manager::RequestRestartReason reason, |
| const std::string& description); |
| |
| std::unique_ptr<SessionStateAnimator> animator_; |
| |
| // Current lock status. |
| bool system_is_locked_ = false; |
| |
| // True if the real non-cancelable shutting down process started. |
| bool shutting_down_ = false; |
| |
| // True if the requested cancelable shutdown gets canceled. |
| bool shutdown_canceled_ = false; |
| |
| // The reason (e.g. user action) for a pending shutdown. |
| std::optional<ShutdownReason> shutdown_reason_; |
| |
| // Callback bound on restart requested and run when |
| // `session_state_change_timer_` times out. |
| base::OnceClosure restart_callback_; |
| |
| // Indicates whether controller should proceed to (cancellable) shutdown after |
| // locking. |
| bool shutdown_after_lock_ = false; |
| |
| // Indicates that controller displays lock animation. |
| bool animating_lock_ = false; |
| |
| // Indicates that controller displays unlock animation. |
| bool animating_unlock_ = false; |
| |
| // Indicates that the power button has been pressed during the unlock |
| // animation |
| bool pb_pressed_during_unlock_ = false; |
| |
| // Indicates whether post lock animation should be immediate. |
| bool post_lock_immediate_animation_ = false; |
| |
| std::unique_ptr<UnlockedStateProperties> unlocked_properties_; |
| |
| // How long has it been since the request to lock the screen? |
| std::unique_ptr<base::ElapsedTimer> lock_duration_timer_; |
| |
| // Controller used to trigger the actual shutdown. |
| raw_ptr<ShutdownController, DanglingUntriaged> shutdown_controller_; |
| |
| // 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 we call StartPostLockAnimation. When it fires, we assume |
| // that our request got dropped. |
| base::OneShotTimer post_lock_fail_timer_; |
| |
| // Started when a cancelable shutdown requested and the shutdown animation |
| // triggered. When it fires, the real non-cancelable shutdown will start. |
| base::OneShotTimer cancelable_shutdown_timer_; |
| |
| // Started when we display the session state change animation (NOTE, shutdown, |
| // restart and signout have the same animation). When it fires, we actually |
| // request the session state change. Gives the animation time to complete |
| // before Chrome etc are shut down. |
| base::OneShotTimer session_state_change_timer_; |
| |
| base::OnceClosure lock_screen_displayed_callback_; |
| |
| base::OnceCallback<void(bool)> start_unlock_callback_; |
| |
| // A new layer that mirrors the wallpaper layer, which will be added to the |
| // layer hierarchy and help include the wallpaper into the informed restore |
| // screenshot. |
| std::unique_ptr<ui::Layer> mirror_wallpaper_layer_; |
| |
| // A timer tracks the time duration it takes to take the informed restore |
| // image. If this timer timeouts before taking the screenshot completes, the |
| // shutdown process will be triggered immediately without the informed restore |
| // image. This is done to avoid the shutdown process being blocked too long to |
| // be noticed by the users. |
| base::OneShotTimer take_screenshot_fail_timer_; |
| |
| ScopedSessionObserver scoped_session_observer_; |
| |
| // The wallpaper blur before entering lock state. Used to restore the |
| // wallpaper blur after exiting lock state. |
| float saved_blur_; |
| |
| base::ObserverList<LockStateObserver>::Unchecked observers_; |
| |
| // To access the pref kLoginShutdownTimestampPrefName |
| raw_ptr<PrefService> local_state_; |
| |
| // If set, it will be called once the operation on the informed restore image |
| // is completed, either it was deleted or saved to the disk. |
| base::OnceClosure informed_restore_image_callback_for_test_; |
| |
| // Disables the `take_screenshot_fail_timer_` for test, which means the timer |
| // will never start if this is set to true. |
| bool disable_screenshot_timeout_for_test_ = false; |
| |
| base::WeakPtrFactory<LockStateController> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace ash |
| |
| #endif // ASH_WM_LOCK_STATE_CONTROLLER_H_ |