1// Copyright (c) 2011 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 CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_LOCKER_H_
6#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_LOCKER_H_
7#pragma once
8
9#include <string>
10
11#include "base/memory/scoped_ptr.h"
12#include "base/task.h"
13#include "base/time.h"
14#include "chrome/browser/chromeos/login/captcha_view.h"
15#include "chrome/browser/chromeos/login/login_status_consumer.h"
16#include "chrome/browser/chromeos/login/message_bubble.h"
17#include "chrome/browser/chromeos/login/user_manager.h"
18#include "views/accelerator.h"
19
20namespace gfx {
21class Rect;
22}  // namespace gfx
23
24namespace views {
25class View;
26class WidgetGtk;
27}  // namespace views
28
29namespace chromeos {
30
31class Authenticator;
32class BackgroundView;
33class InputEventObserver;
34class LockerInputEventObserver;
35class MessageBubble;
36class MouseEventRelay;
37class ScreenLockView;
38class LoginFailure;
39
40namespace test {
41class ScreenLockerTester;
42}  // namespace test
43
44// ScreenLocker creates a background view as well as ScreenLockView to
45// authenticate the user. ScreenLocker manages its life cycle and will
46// delete itself when it's unlocked.
47class ScreenLocker : public LoginStatusConsumer,
48                     public MessageBubbleDelegate,
49                     public CaptchaView::Delegate,
50                     public views::AcceleratorTarget {
51 public:
52  // Interface that helps switching from ScreenLockView to CaptchaView.
53  class ScreenLockViewContainer {
54   public:
55    virtual void SetScreenLockView(views::View* screen_lock_view) = 0;
56
57   protected:
58    virtual ~ScreenLockViewContainer() {}
59  };
60
61  explicit ScreenLocker(const UserManager::User& user);
62
63  // Returns the default instance if it has been created.
64  static ScreenLocker* default_screen_locker() {
65    return screen_locker_;
66  }
67
68  // Initialize and show the screen locker.
69  void Init();
70
71  // LoginStatusConsumer implements:
72  virtual void OnLoginFailure(const chromeos::LoginFailure& error);
73  virtual void OnLoginSuccess(const std::string& username,
74                              const std::string& password,
75                              const GaiaAuthConsumer::ClientLoginResult& result,
76                              bool pending_requests);
77
78  // Overridden from views::BubbleDelegate.
79  virtual void BubbleClosing(Bubble* bubble, bool closed_by_escape);
80  virtual bool CloseOnEscape() { return true; }
81  virtual bool FadeInOnShow() { return false; }
82  virtual void OnHelpLinkActivated() {}
83
84  // CaptchaView::Delegate implementation:
85  virtual void OnCaptchaEntered(const std::string& captcha);
86
87  // Authenticates the user with given |password| and authenticator.
88  void Authenticate(const string16& password);
89
90  // Close message bubble to clear error messages.
91  void ClearErrors();
92
93  // (Re)enable input field.
94  void EnableInput();
95
96  // Exit the chrome, which will sign out the current session.
97  void Signout();
98
99  // Present user a CAPTCHA challenge with image from |captcha_url|,
100  // After that shows error bubble with |message|.
101  void ShowCaptchaAndErrorMessage(const GURL& captcha_url,
102                                  const std::wstring& message);
103
104  // Disables all UI needed and shows error bubble with |message|.
105  // If |sign_out_only| is true then all other input except "Sign Out"
106  // button is blocked.
107  void ShowErrorMessage(const std::wstring& message, bool sign_out_only);
108
109  // Called when the all inputs are grabbed.
110  void OnGrabInputs();
111
112  // Returns the user to authenticate.
113  const UserManager::User& user() const {
114    return user_;
115  }
116
117  // Returns a view that has given view |id|, or null if it doesn't exist.
118  views::View* GetViewByID(int id);
119
120  // Initialize ScreenLocker class. It will listen to
121  // LOGIN_USER_CHANGED notification so that the screen locker accepts
122  // lock event only after a user is logged in.
123  static void InitClass();
124
125  // Show the screen locker.
126  static void Show();
127
128  // Hide the screen locker.
129  static void Hide();
130
131  // Notifies that PowerManager rejected UnlockScreen request.
132  static void UnlockScreenFailed();
133
134  // Returns the tester
135  static test::ScreenLockerTester* GetTester();
136
137 private:
138  friend class DeleteTask<ScreenLocker>;
139  friend class test::ScreenLockerTester;
140  friend class LockerInputEventObserver;
141
142  virtual ~ScreenLocker();
143
144  // Sets the authenticator.
145  void SetAuthenticator(Authenticator* authenticator);
146
147  // Called when the screen lock is ready.
148  void ScreenLockReady();
149
150  // Called when the window manager is ready to handle locked state.
151  void OnWindowManagerReady();
152
153  // Shows error_info_ bubble with the |message| and |arrow_location| specified.
154  // Assumes that UI controls were locked before that.
155  void ShowErrorBubble(const std::wstring& message,
156                       BubbleBorder::ArrowLocation arrow_location);
157
158  // Stops screen saver.
159  void StopScreenSaver();
160
161  // Starts screen saver.
162  void StartScreenSaver();
163
164  // Overridden from AcceleratorTarget:
165  virtual bool AcceleratorPressed(const views::Accelerator& accelerator);
166
167  // Event handler for client-event.
168  CHROMEGTK_CALLBACK_1(ScreenLocker, void, OnClientEvent, GdkEventClient*);
169
170  // The screen locker window.
171  views::WidgetGtk* lock_window_;
172
173  // TYPE_CHILD widget to grab the keyboard/mouse input.
174  views::WidgetGtk* lock_widget_;
175
176  // A view that accepts password.
177  ScreenLockView* screen_lock_view_;
178
179  // A view that can display html page as background.
180  BackgroundView* background_view_;
181
182  // View used to present CAPTCHA challenge input.
183  CaptchaView* captcha_view_;
184
185  // Containers that hold currently visible view.
186  // Initially it's ScreenLockView instance.
187  // When CAPTCHA input dialog is presented it's swapped to CaptchaView
188  // instance, then back after CAPTCHA input is done.
189  ScreenLockViewContainer* grab_container_;
190  ScreenLockViewContainer* background_container_;
191
192  // View that's not owned by grab_container_ - either ScreenLockView or
193  // CaptchaView instance. Keep that under scoped_ptr so that it's deleted.
194  scoped_ptr<views::View> secondary_view_;
195
196  // Postponed error message to be shown after CAPTCHA input is done.
197  std::wstring postponed_error_message_;
198
199  // Logged in user.
200  UserManager::User user_;
201
202  // Used to authenticate the user to unlock.
203  scoped_refptr<Authenticator> authenticator_;
204
205  // ScreenLocker grabs all keyboard and mouse events on its
206  // gdk window and never let other gdk_window to handle inputs.
207  // This MouseEventRelay object is used to forward events to
208  // the message bubble's gdk_window so that close button works.
209  scoped_ptr<MouseEventRelay> mouse_event_relay_;
210
211  // A message loop observer to detect user's keyboard/mouse event.
212  // Used when |unlock_on_input_| is true.
213  scoped_ptr<InputEventObserver> input_event_observer_;
214
215  // A message loop observer to detect user's keyboard/mouse event.
216  // Used when to show the screen locker upon such an event.
217  scoped_ptr<LockerInputEventObserver> locker_input_event_observer_;
218
219  // An info bubble to display login failure message.
220  MessageBubble* error_info_;
221
222  // True if the screen locker's window has been drawn.
223  bool drawn_;
224
225  // True if both mouse input and keyboard input are grabbed.
226  bool input_grabbed_;
227
228  // Unlock the screen when it detects key/mouse event without asking
229  // password. True when chrome is in BWSI or auto login mode.
230  bool unlock_on_input_;
231
232  // True if the screen is locked, or false otherwise.  This changes
233  // from false to true, but will never change from true to
234  // false. Instead, ScreenLocker object gets deleted when unlocked.
235  bool locked_;
236
237  // Reference to the single instance of the screen locker object.
238  // This is used to make sure there is only one screen locker instance.
239  static ScreenLocker* screen_locker_;
240
241  // The time when the screen locker object is created.
242  base::Time start_time_;
243  // The time when the authentication is started.
244  base::Time authentication_start_time_;
245
246  DISALLOW_COPY_AND_ASSIGN(ScreenLocker);
247};
248
249}  // namespace chromeos
250
251#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_LOCKER_H_
252