1// Copyright 2013 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#ifndef ASH_WM_LOCK_STATE_CONTROLLER_H_
6#define ASH_WM_LOCK_STATE_CONTROLLER_H_
7
8#include "ash/ash_export.h"
9#include "ash/shell_observer.h"
10#include "ash/wm/lock_state_observer.h"
11#include "ash/wm/session_state_animator.h"
12#include "base/basictypes.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/memory/weak_ptr.h"
15#include "base/observer_list.h"
16#include "base/time/time.h"
17#include "base/timer/timer.h"
18#include "ui/aura/window_tree_host_observer.h"
19
20namespace gfx {
21class Rect;
22class Size;
23}
24
25namespace ui {
26class Layer;
27}
28
29namespace ash {
30
31namespace test {
32class LockStateControllerTest;
33class PowerButtonControllerTest;
34}
35
36// Performs system-related functions on behalf of LockStateController.
37class ASH_EXPORT LockStateControllerDelegate {
38 public:
39  LockStateControllerDelegate() {}
40  virtual ~LockStateControllerDelegate() {}
41
42  virtual void RequestLockScreen() = 0;
43  virtual void RequestShutdown() = 0;
44
45 private:
46  DISALLOW_COPY_AND_ASSIGN(LockStateControllerDelegate);
47};
48
49// Displays onscreen animations and locks or suspends the system in response to
50// the power button being pressed or released.
51// Lock workflow:
52// Entry points:
53//  * StartLockAnimation (bool shutdown after lock) - starts lock that can be
54//    cancelled.
55//  * StartLockAnimationAndLockImmediately (bool shutdown after lock) - starts
56//    uninterruptible lock animation.
57// This leads to call of either StartImmediatePreLockAnimation or
58// StartCancellablePreLockAnimation. Once they complete
59// PreLockAnimationFinished is called, and system lock is requested.
60// Once system locks and lock UI is created, OnLockStateChanged is called, and
61// StartPostLockAnimation is called. In PostLockAnimationFinished two
62// things happen : EVENT_LOCK_ANIMATION_FINISHED notification is sent (it
63// triggers third part of animation within lock UI), and check for continuing to
64// shutdown is made.
65//
66// Unlock workflow:
67// WebUI does first part of animation, and calls OnLockScreenHide(callback) that
68// triggers StartUnlockAnimationBeforeUIDestroyed(callback). Once callback is
69// called at the end of the animation, lock UI is deleted, system unlocks, and
70// OnLockStateChanged is called. It leads to
71// StartUnlockAnimationAfterUIDestroyed.
72class ASH_EXPORT LockStateController : public aura::WindowTreeHostObserver,
73                                       public ShellObserver {
74 public:
75  // Amount of time that the power button needs to be held before we lock the
76  // screen.
77  static const int kLockTimeoutMs;
78
79  // Amount of time that the power button needs to be held before we shut down.
80  static const int kShutdownTimeoutMs;
81
82  // Amount of time to wait for our lock requests to be honored before giving
83  // up.
84  static const int kLockFailTimeoutMs;
85
86  // When the button has been held continuously from the unlocked state, amount
87  // of time that we wait after the screen locker window is shown before
88  // starting the pre-shutdown animation.
89  static const int kLockToShutdownTimeoutMs;
90
91  // Additional time (beyond kFastCloseAnimMs) to wait after starting the
92  // fast-close shutdown animation before actually requesting shutdown, to give
93  // the animation time to finish.
94  static const int kShutdownRequestDelayMs;
95
96  // Helper class used by tests to access internal state.
97  class ASH_EXPORT TestApi {
98   public:
99    explicit TestApi(LockStateController* controller);
100
101    virtual ~TestApi();
102
103    bool lock_fail_timer_is_running() const {
104      return controller_->lock_fail_timer_.IsRunning();
105    }
106    bool lock_to_shutdown_timer_is_running() const {
107      return controller_->lock_to_shutdown_timer_.IsRunning();
108    }
109    bool shutdown_timer_is_running() const {
110      return controller_->pre_shutdown_timer_.IsRunning();
111    }
112    bool real_shutdown_timer_is_running() const {
113      return controller_->real_shutdown_timer_.IsRunning();
114    }
115    bool is_animating_lock() const {
116      return controller_->animating_lock_;
117    }
118    bool is_lock_cancellable() const {
119      return controller_->CanCancelLockAnimation();
120    }
121
122    void trigger_lock_fail_timeout() {
123      controller_->OnLockFailTimeout();
124      controller_->lock_fail_timer_.Stop();
125    }
126    void trigger_lock_to_shutdown_timeout() {
127      controller_->OnLockToShutdownTimeout();
128      controller_->lock_to_shutdown_timer_.Stop();
129    }
130    void trigger_shutdown_timeout() {
131      controller_->OnPreShutdownAnimationTimeout();
132      controller_->pre_shutdown_timer_.Stop();
133    }
134    void trigger_real_shutdown_timeout() {
135      controller_->OnRealShutdownTimeout();
136      controller_->real_shutdown_timer_.Stop();
137    }
138
139   private:
140    LockStateController* controller_;  // not owned
141
142    DISALLOW_COPY_AND_ASSIGN(TestApi);
143  };
144
145  LockStateController();
146  virtual ~LockStateController();
147
148  void SetDelegate(scoped_ptr<LockStateControllerDelegate> delegate);
149
150  void AddObserver(LockStateObserver* observer);
151  void RemoveObserver(LockStateObserver* observer);
152  bool HasObserver(LockStateObserver* observer);
153
154  // Starts locking (with slow animation) that can be cancelled.
155  // After locking and |kLockToShutdownTimeoutMs| StartShutdownAnimation()
156  // will be called unless CancelShutdownAnimation() is called, if
157  // |shutdown_after_lock| is true.
158  void StartLockAnimation(bool shutdown_after_lock);
159
160  // Starts shutting down (with slow animation) that can be cancelled.
161  void StartShutdownAnimation();
162
163  // Starts usual lock animation, but locks immediately.  After locking and
164  // |kLockToShutdownTimeoutMs| StartShutdownAnimation() will be called unless
165  // CancelShutdownAnimation() is called, if  |shutdown_after_lock| is true.
166  void StartLockAnimationAndLockImmediately(bool shutdown_after_lock);
167
168  // Returns true if we have requested system to lock, but haven't received
169  // confirmation yet.
170  bool LockRequested();
171
172  // Returns true if we are shutting down.
173  bool ShutdownRequested();
174
175  // Returns true if we are within cancellable lock timeframe.
176  bool CanCancelLockAnimation();
177
178  // Cancels locking and reverts lock animation.
179  void CancelLockAnimation();
180
181  // Returns true if we are within cancellable shutdown timeframe.
182  bool CanCancelShutdownAnimation();
183
184  // Cancels shutting down and reverts shutdown animation.
185  void CancelShutdownAnimation();
186
187  // Called when Chrome gets a request to display the lock screen.
188  void OnStartingLock();
189
190  // Displays the shutdown animation and requests shutdown when it's done.
191  void RequestShutdown();
192
193  // Called when ScreenLocker is ready to close, but not yet destroyed.
194  // Can be used to display "hiding" animations on unlock.
195  // |callback| will be called when all animations are done.
196  void OnLockScreenHide(base::Closure& callback);
197
198  // Sets up the callback that should be called once lock animation is finished.
199  // Callback is guaranteed to be called once and then discarded.
200  void SetLockScreenDisplayedCallback(const base::Closure& callback);
201
202  // aura::WindowTreeHostObserver override:
203  virtual void OnHostCloseRequested(const aura::WindowTreeHost* host) OVERRIDE;
204
205  // ShellObserver overrides:
206  virtual void OnLoginStateChanged(user::LoginStatus status) OVERRIDE;
207  virtual void OnAppTerminating() OVERRIDE;
208  virtual void OnLockStateChanged(bool locked) OVERRIDE;
209
210  void set_animator_for_test(SessionStateAnimator* animator) {
211    animator_.reset(animator);
212  }
213
214 private:
215  friend class test::PowerButtonControllerTest;
216  friend class test::LockStateControllerTest;
217
218  struct UnlockedStateProperties {
219    bool background_is_hidden;
220  };
221
222  // Reverts the pre-lock animation, reports the error.
223  void OnLockFailTimeout();
224
225  // Starts timer for gap between lock and shutdown.
226  void StartLockToShutdownTimer();
227
228  // Calls StartShutdownAnimation().
229  void OnLockToShutdownTimeout();
230
231  // Starts timer for undoable shutdown animation.
232  void StartPreShutdownAnimationTimer();
233
234  // Calls StartRealShutdownTimer().
235  void OnPreShutdownAnimationTimeout();
236
237  // Starts timer for final shutdown animation.
238  // If |with_animation_time| is true, it will also include time of "fade to
239  // white" shutdown animation.
240  void StartRealShutdownTimer(bool with_animation_time);
241
242  // Requests that the machine be shut down.
243  void OnRealShutdownTimeout();
244
245  // Starts shutdown animation that can be cancelled and starts pre-shutdown
246  // timer.
247  void StartCancellableShutdownAnimation();
248
249  // If |request_lock_on_completion| is true, a lock request will be sent
250  // after the pre-lock animation completes.  (The pre-lock animation is
251  // also displayed in response to already-in-progress lock requests; in
252  // these cases an additional lock request is undesirable.)
253  void StartImmediatePreLockAnimation(bool request_lock_on_completion);
254  void StartCancellablePreLockAnimation();
255  void CancelPreLockAnimation();
256  void StartPostLockAnimation();
257  // This method calls |callback| when animation completes.
258  void StartUnlockAnimationBeforeUIDestroyed(base::Closure &callback);
259  void StartUnlockAnimationAfterUIDestroyed();
260
261  // These methods are called when corresponding animation completes.
262  void LockAnimationCancelled();
263  void PreLockAnimationFinished(bool request_lock);
264  void PostLockAnimationFinished();
265  void UnlockAnimationAfterUIDestroyedFinished();
266
267  // Stores properties of UI that have to be temporarily modified while locking.
268  void StoreUnlockedProperties();
269  void RestoreUnlockedProperties();
270
271  // Fades in background layer with |speed| if it was hidden in unlocked state.
272  void AnimateBackgroundAppearanceIfNecessary(
273      ash::SessionStateAnimator::AnimationSpeed speed,
274      SessionStateAnimator::AnimationSequence* animation_sequence);
275
276  // Fades out background layer with |speed| if it was hidden in unlocked state.
277  void AnimateBackgroundHidingIfNecessary(
278      ash::SessionStateAnimator::AnimationSpeed speed,
279      SessionStateAnimator::AnimationSequence* animation_sequence);
280
281  scoped_ptr<SessionStateAnimator> animator_;
282
283  scoped_ptr<LockStateControllerDelegate> delegate_;
284
285  ObserverList<LockStateObserver> observers_;
286
287  // The current login status, or original login status from before we locked.
288  user::LoginStatus login_status_;
289
290  // Current lock status.
291  bool system_is_locked_;
292
293  // Are we in the process of shutting the machine down?
294  bool shutting_down_;
295
296  // Indicates whether controller should proceed to (cancellable) shutdown after
297  // locking.
298  bool shutdown_after_lock_;
299
300  // Indicates that controller displays lock animation.
301  bool animating_lock_;
302
303  // Indicates that lock animation can be undone.
304  bool can_cancel_lock_animation_;
305
306  scoped_ptr<UnlockedStateProperties> unlocked_properties_;
307
308  // Started when we request that the screen be locked.  When it fires, we
309  // assume that our request got dropped.
310  base::OneShotTimer<LockStateController> lock_fail_timer_;
311
312  // Started when the screen is locked while the power button is held.  Adds a
313  // delay between the appearance of the lock screen and the beginning of the
314  // pre-shutdown animation.
315  base::OneShotTimer<LockStateController> lock_to_shutdown_timer_;
316
317  // Started when we begin displaying the pre-shutdown animation.  When it
318  // fires, we start the shutdown animation and get ready to request shutdown.
319  base::OneShotTimer<LockStateController> pre_shutdown_timer_;
320
321  // Started when we display the shutdown animation.  When it fires, we actually
322  // request shutdown.  Gives the animation time to complete before Chrome, X,
323  // etc. are shut down.
324  base::OneShotTimer<LockStateController> real_shutdown_timer_;
325
326  base::Closure lock_screen_displayed_callback_;
327
328  base::WeakPtrFactory<LockStateController> weak_ptr_factory_;
329
330  DISALLOW_COPY_AND_ASSIGN(LockStateController);
331};
332
333}  // namespace ash
334
335#endif  // ASH_WM_LOCK_STATE_CONTROLLER_H_
336