• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "chrome/browser/chromeos/login/screen_lock_view.h"
6 
7 #include "base/utf_string_conversions.h"
8 #include "chrome/browser/chromeos/login/rounded_rect_painter.h"
9 #include "chrome/browser/chromeos/login/screen_locker.h"
10 #include "chrome/browser/chromeos/login/textfield_with_margin.h"
11 #include "chrome/browser/chromeos/login/user_manager.h"
12 #include "chrome/browser/chromeos/login/user_view.h"
13 #include "chrome/browser/chromeos/login/username_view.h"
14 #include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
15 #include "chrome/browser/chromeos/views/copy_background.h"
16 #include "chrome/browser/profiles/profile_manager.h"
17 #include "content/common/notification_service.h"
18 #include "grit/generated_resources.h"
19 #include "grit/theme_resources.h"
20 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/base/resource/resource_bundle.h"
22 #include "views/background.h"
23 #include "views/border.h"
24 #include "views/controls/image_view.h"
25 #include "views/controls/label.h"
26 #include "views/controls/textfield/native_textfield_wrapper.h"
27 #include "views/controls/textfield/textfield.h"
28 #include "views/layout/grid_layout.h"
29 
30 namespace chromeos {
31 
32 namespace {
33 
34 const int kCornerRadius = 5;
35 
36 // A Textfield for password, which also sets focus to itself
37 // when a mouse is clicked on it. This is necessary in screen locker
38 // as mouse events are grabbed in the screen locker.
39 class PasswordField : public TextfieldWithMargin {
40  public:
PasswordField()41   PasswordField()
42       : TextfieldWithMargin(views::Textfield::STYLE_PASSWORD),
43         context_menu_disabled_(false) {
44     set_text_to_display_when_empty(
45         l10n_util::GetStringUTF16(IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT));
46   }
47 
48   // views::View overrides.
OnMousePressed(const views::MouseEvent & e)49   virtual bool OnMousePressed(const views::MouseEvent& e) {
50     RequestFocus();
51     return false;
52   }
53 
ViewHierarchyChanged(bool is_add,views::View * parent,views::View * child)54   virtual void ViewHierarchyChanged(bool is_add,
55                                     views::View* parent,
56                                     views::View* child) OVERRIDE {
57     Textfield::ViewHierarchyChanged(is_add, parent, child);
58     // Wiat until native widget is created.
59     if (!context_menu_disabled_ && native_wrapper_) {
60       gfx::NativeView widget = native_wrapper_->GetTestingHandle();
61       if (widget) {
62         context_menu_disabled_ = true;
63         g_signal_connect(widget, "button-press-event",
64                          G_CALLBACK(OnButtonPressEventThunk), this);
65       }
66     }
67   }
68 
69   CHROMEGTK_CALLBACK_1(PasswordField, gboolean, OnButtonPressEvent,
70                        GdkEventButton*);
71 
72  private:
73   bool context_menu_disabled_;
74 
75   DISALLOW_COPY_AND_ASSIGN(PasswordField);
76 };
77 
OnButtonPressEvent(GtkWidget * widget,GdkEventButton * event)78 gboolean PasswordField::OnButtonPressEvent(GtkWidget* widget,
79                                            GdkEventButton* event) {
80   // Eat button 2/3 and alt + any button to disable context menu.
81   return event->state & GDK_MOD1_MASK ||
82       event->button == 2 ||
83       event->button == 3;
84 }
85 
86 }  // namespace
87 
88 using views::GridLayout;
89 using login::kBorderSize;
90 
ScreenLockView(ScreenLocker * screen_locker)91 ScreenLockView::ScreenLockView(ScreenLocker* screen_locker)
92     : user_view_(NULL),
93       password_field_(NULL),
94       screen_locker_(screen_locker),
95       main_(NULL),
96       username_(NULL) {
97   DCHECK(screen_locker_);
98 }
99 
~ScreenLockView()100 ScreenLockView::~ScreenLockView() {
101 }
102 
GetPreferredSize()103 gfx::Size ScreenLockView::GetPreferredSize() {
104   return main_->GetPreferredSize();
105 }
106 
Layout()107 void ScreenLockView::Layout() {
108   int username_height = login::kSelectedLabelHeight;
109   main_->SetBounds(0, 0, width(), height());
110   username_->SetBounds(
111       kBorderSize,
112       login::kUserImageSize - username_height + kBorderSize,
113       login::kUserImageSize,
114       username_height);
115 }
116 
Init()117 void ScreenLockView::Init() {
118   registrar_.Add(this,
119                  NotificationType::LOGIN_USER_IMAGE_CHANGED,
120                  NotificationService::AllSources());
121 
122   user_view_ = new UserView(this,
123                             false,  // is_login
124                             true);  // need_background
125   main_ = new views::View();
126   // Use rounded rect background.
127   views::Painter* painter =
128       CreateWizardPainter(&BorderDefinition::kUserBorder);
129 
130   main_->set_background(
131       views::Background::CreateBackgroundPainter(true, painter));
132   main_->set_border(CreateWizardBorder(&BorderDefinition::kUserBorder));
133 
134   // Password field.
135   password_field_ = new PasswordField();
136 
137   password_field_->SetController(this);
138   password_field_->set_background(new CopyBackground(main_));
139 
140   // Setup ThrobberView's host view.
141   set_host_view(password_field_);
142 
143   // User icon.
144   UserManager::User user = screen_locker_->user();
145   user_view_->SetImage(user.image(), user.image());
146 
147   // User name.
148   std::wstring text = UTF8ToWide(user.GetDisplayName());
149 
150   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
151   const gfx::Font& font = rb.GetFont(ResourceBundle::MediumBoldFont).DeriveFont(
152       kSelectedUsernameFontDelta);
153 
154   // Layouts image, textfield and button components.
155   GridLayout* layout = new GridLayout(main_);
156   main_->SetLayoutManager(layout);
157   views::ColumnSet* column_set = layout->AddColumnSet(0);
158   column_set->AddPaddingColumn(0, kBorderSize);
159   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
160                         GridLayout::USE_PREF, 0, 0);
161   column_set->AddPaddingColumn(0, kBorderSize);
162 
163   column_set = layout->AddColumnSet(1);
164   column_set->AddPaddingColumn(0, kBorderSize);
165   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
166                         GridLayout::USE_PREF, 0, 0);
167   column_set->AddPaddingColumn(0, kBorderSize);
168 
169   layout->AddPaddingRow(0, kBorderSize);
170   layout->StartRow(0, 0);
171   layout->AddView(user_view_);
172   layout->AddPaddingRow(0, kBorderSize);
173   layout->StartRow(0, 1);
174   layout->AddView(password_field_);
175   layout->AddPaddingRow(0, kBorderSize);
176 
177   AddChildView(main_);
178 
179   UsernameView* username = UsernameView::CreateShapedUsernameView(text, false);
180   username_ = username;
181   username->SetColor(login::kTextColor);
182   username->SetFont(font);
183   AddChildView(username);
184 }
185 
ClearAndSetFocusToPassword()186 void ScreenLockView::ClearAndSetFocusToPassword() {
187   password_field_->RequestFocus();
188   password_field_->SetText(string16());
189 }
190 
SetSignoutEnabled(bool enabled)191 void ScreenLockView::SetSignoutEnabled(bool enabled) {
192   user_view_->SetSignoutEnabled(enabled);
193 }
194 
GetPasswordBoundsRelativeTo(const views::View * view)195 gfx::Rect ScreenLockView::GetPasswordBoundsRelativeTo(const views::View* view) {
196   gfx::Point p;
197   views::View::ConvertPointToView(password_field_, view, &p);
198   return gfx::Rect(p, size());
199 }
200 
201 
SetEnabled(bool enabled)202 void ScreenLockView::SetEnabled(bool enabled) {
203   views::View::SetEnabled(enabled);
204 
205   if (!enabled) {
206     // TODO(oshima): Re-enabling does not move the focus to the view
207     // that had a focus (issue http://crbug.com/43131).
208     // Clear focus on the textfield so that re-enabling can set focus
209     // back to the text field.
210     // FocusManager may be null if the view does not have
211     // associated Widget yet.
212     if (password_field_->GetFocusManager())
213       password_field_->GetFocusManager()->ClearFocus();
214   }
215   password_field_->SetEnabled(enabled);
216 }
217 
OnSignout()218 void ScreenLockView::OnSignout() {
219   screen_locker_->Signout();
220 }
221 
ContentsChanged(views::Textfield * sender,const string16 & new_contents)222 void ScreenLockView::ContentsChanged(views::Textfield* sender,
223                                      const string16& new_contents) {
224   if (!new_contents.empty())
225     screen_locker_->ClearErrors();
226 }
227 
HandleKeyEvent(views::Textfield * sender,const views::KeyEvent & key_event)228 bool ScreenLockView::HandleKeyEvent(
229     views::Textfield* sender,
230     const views::KeyEvent& key_event) {
231   screen_locker_->ClearErrors();
232   if (key_event.key_code() == ui::VKEY_RETURN) {
233     screen_locker_->Authenticate(password_field_->text());
234     return true;
235   }
236   return false;
237 }
238 
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)239 void ScreenLockView::Observe(
240     NotificationType type,
241     const NotificationSource& source,
242     const NotificationDetails& details) {
243   if (type != NotificationType::LOGIN_USER_IMAGE_CHANGED || !user_view_)
244     return;
245 
246   UserManager::User* user = Details<UserManager::User>(details).ptr();
247   if (screen_locker_->user().email() != user->email())
248     return;
249   user_view_->SetImage(user->image(), user->image());
250 }
251 
252 }  // namespace chromeos
253