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_