screen_lock_view.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2010 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#include "chrome/browser/chromeos/login/screen_lock_view.h"
6
7#include "app/l10n_util.h"
8#include "app/resource_bundle.h"
9#include "base/utf_string_conversions.h"
10#include "chrome/browser/chromeos/login/helper.h"
11#include "chrome/browser/chromeos/login/screen_locker.h"
12#include "chrome/browser/chromeos/login/user_manager.h"
13#include "chrome/browser/chromeos/login/user_view.h"
14#include "chrome/common/notification_service.h"
15#include "grit/generated_resources.h"
16#include "grit/theme_resources.h"
17#include "views/background.h"
18#include "views/border.h"
19#include "views/controls/button/text_button.h"
20#include "views/controls/image_view.h"
21#include "views/controls/label.h"
22#include "views/grid_layout.h"
23
24namespace chromeos {
25
26namespace {
27
28// A Textfield for password, which also sets focus to itself
29// when a mouse is clicked on it. This is necessary in screen locker
30// as mouse events are grabbed in the screen locker.
31class PasswordField : public views::Textfield {
32 public:
33  PasswordField()
34      : views::Textfield(views::Textfield::STYLE_PASSWORD) {
35    set_text_to_display_when_empty(
36        l10n_util::GetStringUTF16(IDS_LOGIN_EMPTY_PASSWORD_TEXT));
37  }
38
39  // views::View overrides.
40  virtual bool OnMousePressed(const views::MouseEvent& e) {
41    RequestFocus();
42    return false;
43  }
44
45 private:
46  DISALLOW_COPY_AND_ASSIGN(PasswordField);
47};
48
49}  // namespace
50
51using views::GridLayout;
52using login::kBorderSize;
53
54ScreenLockView::ScreenLockView(ScreenLocker* screen_locker)
55    : user_view_(NULL),
56      password_field_(NULL),
57      unlock_button_(NULL),
58      screen_locker_(screen_locker) {
59  DCHECK(screen_locker_);
60}
61
62void ScreenLockView::Init() {
63  registrar_.Add(this,
64                 NotificationType::LOGIN_USER_IMAGE_CHANGED,
65                 NotificationService::AllSources());
66
67  user_view_ = new UserView(this, false);
68  views::View* main = new views::View();
69  main->set_background(
70      views::Background::CreateSolidBackground(login::kBackgroundColor));
71
72  // Password field.
73  password_field_ = new PasswordField();
74  password_field_->SetController(this);
75
76  // Unlock button.
77  unlock_button_ = new views::TextButton(
78      this, l10n_util::GetString(IDS_UNLOCK_BUTTON));
79  unlock_button_->set_tag(login::UNLOCK);
80
81  // User icon.
82  UserManager::User user = screen_locker_->user();
83  user_view_->SetImage(user.image());
84
85  // User name.
86  std::wstring text = UTF8ToWide(user.GetDisplayName());
87  views::Label* label = new views::Label(text);
88  label->SetColor(login::kTextColor);
89  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
90  const gfx::Font& font =
91      rb.GetFont(ResourceBundle::LargeFont).DeriveFont(0, gfx::Font::BOLD);
92  label->SetFont(font);
93
94  // Layouts image, textfield and button components.
95  GridLayout* layout = new GridLayout(main);
96  main->SetLayoutManager(layout);
97  views::ColumnSet* column_set = layout->AddColumnSet(0);
98  column_set->AddPaddingColumn(0, kBorderSize);
99  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
100                        GridLayout::USE_PREF, 0, 0);
101  column_set->AddPaddingColumn(0, kBorderSize);
102
103  column_set = layout->AddColumnSet(1);
104  column_set->AddPaddingColumn(0, 5);
105  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
106                        GridLayout::USE_PREF, 0, 0);
107  column_set->AddPaddingColumn(0, 5);
108  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
109                        GridLayout::USE_PREF, 0, 0);
110  column_set->AddPaddingColumn(0, 5);
111
112  layout->AddPaddingRow(0, kBorderSize);
113  layout->StartRow(0, 0);
114  layout->AddView(user_view_);
115  layout->AddPaddingRow(0, kBorderSize);
116  layout->StartRow(0, 1);
117  layout->AddView(password_field_);
118  layout->AddView(unlock_button_);
119  layout->AddPaddingRow(0, 5);
120
121  unlock_button_->SetFocusable(true);
122
123  // Layouts the main view and the account label.
124  layout = new GridLayout(this);
125  SetLayoutManager(layout);
126  column_set = layout->AddColumnSet(0);
127  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
128                        GridLayout::USE_PREF, 0, 0);
129
130  column_set = layout->AddColumnSet(1);
131  column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
132                        GridLayout::USE_PREF, 0, 0);
133
134  layout->StartRow(0, 0);
135  layout->AddView(main);
136  layout->StartRow(0, 1);
137  layout->AddView(label);
138}
139
140void ScreenLockView::ClearAndSetFocusToPassword() {
141  password_field_->RequestFocus();
142  password_field_->SetText(string16());
143}
144
145void ScreenLockView::SetSignoutEnabled(bool enabled) {
146  user_view_->SetSignoutEnabled(enabled);
147}
148
149gfx::Rect ScreenLockView::GetPasswordBoundsRelativeTo(const views::View* view) {
150  gfx::Point p;
151  views::View::ConvertPointToView(password_field_, view, &p);
152  return gfx::Rect(p, size());
153}
154
155void ScreenLockView::SetEnabled(bool enabled) {
156  views::View::SetEnabled(enabled);
157
158  if (!enabled) {
159    user_view_->StartThrobber();
160    // TODO(oshima): Re-enabling does not move the focus to the view
161    // that had a focus (issue http://crbug.com/43131).
162    // Move the focus to other field as a workaround.
163    unlock_button_->RequestFocus();
164  } else {
165    user_view_->StopThrobber();
166  }
167  unlock_button_->SetEnabled(enabled);
168  password_field_->SetEnabled(enabled);
169}
170
171void ScreenLockView::ButtonPressed(views::Button* sender,
172                                   const views::Event& event) {
173  if (sender->tag() == login::UNLOCK)
174    screen_locker_->Authenticate(password_field_->text());
175  else
176    NOTREACHED();
177}
178
179void ScreenLockView::OnSignout() {
180  screen_locker_->Signout();
181}
182
183bool ScreenLockView::HandleKeystroke(
184    views::Textfield* sender,
185    const views::Textfield::Keystroke& keystroke) {
186  screen_locker_->ClearErrors();
187  if (keystroke.GetKeyboardCode() == base::VKEY_RETURN) {
188    screen_locker_->Authenticate(password_field_->text());
189    return true;
190  }
191  return false;
192}
193
194void ScreenLockView::Observe(
195    NotificationType type,
196    const NotificationSource& source,
197    const NotificationDetails& details) {
198  if (type != NotificationType::LOGIN_USER_IMAGE_CHANGED || !user_view_)
199    return;
200
201  UserManager::User* user = Details<UserManager::User>(details).ptr();
202  if (screen_locker_->user().email() != user->email())
203    return;
204
205  user_view_->SetImage(user->image());
206}
207
208}  // namespace chromeos
209