1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
  248
  249
  250
  251
  252
  253
  254
  255
  256
  257
  258
  259
  260
  261
  262
  263
  264
  265
  266
  267
  268
  269
  270
  271
  272
  273
  274
  275
  276
  277
  278
  279
  280
  281
  282
  283
  284
  285
  286
  287
  288
  289
  290
  291
  292
  293
  294
  295
  296
  297
  298
  299
  300
  301
  302
  303
  304
  305
  306
  307
  308
  309
  310
  311
  312
  313
  314
  315
  316
  317
  318
  319
  320
  321
  322
  323
  324
  325
  326
  327
  328
  329
  330
  331
  332
  333
  334
  335
  336
  337
  338
  339
  340
  341
  342
  343
  344
  345
  346
  347
  348
  349
  350
  351
  352
  353
  354
  355
  356
  357
  358
  359
  360
  361
  362
  363
  364
  365
  366

ash / wm / lock_state_controller.h [blame]

// 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_