Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(109)

Side by Side Diff: chrome/browser/chromeos/login/new_user_view.cc

Issue 8436002: [cros] Remove Views implementation for login/OOBE. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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/new_user_view.h"
6
7 #include <signal.h>
8 #include <sys/types.h>
9
10 #include <algorithm>
11 #include <vector>
12
13 #include "base/bind.h"
14 #include "base/callback.h"
15 #include "base/command_line.h"
16 #include "base/message_loop.h"
17 #include "base/process_util.h"
18 #include "base/string_util.h"
19 #include "base/utf_string_conversions.h"
20 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/chromeos/cros/cros_library.h"
22 #include "chrome/browser/chromeos/login/rounded_rect_painter.h"
23 #include "chrome/browser/chromeos/login/textfield_with_margin.h"
24 #include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
25 #include "chrome/browser/chromeos/user_cros_settings_provider.h"
26 #include "chrome/browser/chromeos/views/copy_background.h"
27 #include "chrome/browser/prefs/pref_service.h"
28 #include "chrome/common/pref_names.h"
29 #include "grit/chromium_strings.h"
30 #include "grit/generated_resources.h"
31 #include "grit/ui_resources.h"
32 #include "ui/base/keycodes/keyboard_codes.h"
33 #include "ui/base/l10n/l10n_util.h"
34 #include "ui/base/resource/resource_bundle.h"
35 #include "ui/gfx/color_utils.h"
36 #include "ui/gfx/font.h"
37 #include "views/controls/button/menu_button.h"
38 #include "views/controls/button/text_button.h"
39 #include "views/controls/label.h"
40 #include "views/controls/link.h"
41 #include "views/controls/textfield/textfield.h"
42 #include "views/controls/throbber.h"
43
44 using views::View;
45
46 namespace {
47
48 const int kTextfieldWidth = 230;
49 const int kSplitterHeight = 1;
50 const int kTitlePad = 20;
51 const int kRowPad = 13;
52 const int kBottomPad = 33;
53 const int kLeftPad = 33;
54 const int kColumnPad = 7;
55 const int kLanguagesMenuHeight = 25;
56 const int kLanguagesMenuPad = 5;
57 const SkColor kLanguagesMenuTextColor = 0xFF999999;
58 const SkColor kErrorColor = 0xFF8F384F;
59 const SkColor kSplitterUp1Color = 0xFFD0D2D3;
60 const SkColor kSplitterUp2Color = 0xFFE1E3E4;
61 const SkColor kSplitterDown1Color = 0xFFE3E6E8;
62 const SkColor kSplitterDown2Color = 0xFFEAEDEE;
63 const char kDefaultDomain[] = "@gmail.com";
64
65 // Textfield that adds domain to the entered username if focus is lost and
66 // username doesn't have full domain.
67 class UsernameField : public chromeos::TextfieldWithMargin {
68 public:
69 explicit UsernameField(chromeos::NewUserView* controller)
70 : controller_(controller) {}
71
72 // views::Textfield overrides:
73 virtual void OnBlur() OVERRIDE {
74 string16 user_input;
75 bool was_trim = TrimWhitespace(text(), TRIM_ALL, &user_input) != TRIM_NONE;
76 if (!user_input.empty()) {
77 std::string username = UTF16ToUTF8(user_input);
78
79 if (username.find('@') == std::string::npos) {
80 username += kDefaultDomain;
81 SetText(UTF8ToUTF16(username));
82 was_trim = false;
83 }
84 }
85
86 if (was_trim)
87 SetText(user_input);
88 }
89
90 // Overridden from views::View:
91 virtual bool OnKeyPressed(const views::KeyEvent& e) OVERRIDE {
92 if (e.key_code() == ui::VKEY_LEFT) {
93 return controller_->NavigateAway();
94 }
95 return TextfieldWithMargin::OnKeyPressed(e);
96 }
97
98 private:
99 chromeos::NewUserView* controller_;
100 DISALLOW_COPY_AND_ASSIGN(UsernameField);
101 };
102
103 } // namespace
104
105 namespace chromeos {
106
107 NewUserView::NewUserView(Delegate* delegate, bool need_guest_link)
108 : username_field_(NULL),
109 password_field_(NULL),
110 title_label_(NULL),
111 title_hint_label_(NULL),
112 splitter_up1_(NULL),
113 splitter_up2_(NULL),
114 splitter_down1_(NULL),
115 splitter_down2_(NULL),
116 sign_in_button_(NULL),
117 guest_link_(NULL),
118 create_account_link_(NULL),
119 languages_menubutton_(NULL),
120 accel_focus_pass_(ui::VKEY_P, false, false, true),
121 accel_focus_user_(ui::VKEY_U, false, false, true),
122 accel_enterprise_enrollment_(ui::VKEY_E, false, true, true),
123 accel_login_off_the_record_(ui::VKEY_B, false, false, true),
124 accel_toggle_accessibility_(WizardAccessibilityHelper::GetAccelerator()),
125 delegate_(delegate),
126 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
127 login_in_process_(false),
128 need_guest_link_(false),
129 need_create_account_(false),
130 languages_menubutton_order_(-1),
131 sign_in_button_order_(-1) {
132 if (UserCrosSettingsProvider::cached_allow_guest()) {
133 need_create_account_ = true;
134 if (need_guest_link)
135 need_guest_link_ = true;
136 }
137 }
138
139 NewUserView::~NewUserView() {
140 }
141
142 void NewUserView::Init() {
143 // Use rounded rect background.
144 set_border(CreateWizardBorder(&BorderDefinition::kUserBorder));
145 views::Painter* painter = CreateWizardPainter(&BorderDefinition::kUserBorder);
146 set_background(views::Background::CreateBackgroundPainter(true, painter));
147 SkColor background_color = color_utils::AlphaBlend(
148 BorderDefinition::kUserBorder.top_color,
149 BorderDefinition::kUserBorder.bottom_color, 128);
150
151 title_label_ = new views::Label();
152 title_label_->SetBackgroundColor(background_color);
153 title_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
154 title_label_->SetMultiLine(true);
155 AddChildView(title_label_);
156
157 title_hint_label_ = new views::Label();
158 title_hint_label_->SetBackgroundColor(background_color);
159 title_hint_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
160 title_hint_label_->SetEnabledColor(SK_ColorGRAY);
161 title_hint_label_->SetMultiLine(true);
162 AddChildView(title_hint_label_);
163
164 splitter_up1_ = CreateSplitter(kSplitterUp1Color);
165 splitter_up2_ = CreateSplitter(kSplitterUp2Color);
166 splitter_down1_ = CreateSplitter(kSplitterDown1Color);
167 splitter_down2_ = CreateSplitter(kSplitterDown2Color);
168
169 username_field_ = new UsernameField(this);
170 username_field_->set_background(new CopyBackground(this));
171 username_field_->SetAccessibleName(
172 l10n_util::GetStringUTF16(IDS_CHROMEOS_ACC_USERNAME_LABEL));
173 AddChildView(username_field_);
174
175 password_field_ = new TextfieldWithMargin(views::Textfield::STYLE_PASSWORD);
176 password_field_->set_background(new CopyBackground(this));
177 AddChildView(password_field_);
178
179 language_switch_menu_.InitLanguageMenu();
180
181 RecreatePeculiarControls();
182
183 AddChildView(sign_in_button_);
184 if (need_guest_link_)
185 guest_link_ = InitLink(background_color);
186 if (need_create_account_)
187 create_account_link_ = InitLink(background_color);
188 AddChildView(languages_menubutton_);
189
190 // Set up accelerators.
191 AddAccelerator(accel_focus_user_);
192 AddAccelerator(accel_focus_pass_);
193 AddAccelerator(accel_enterprise_enrollment_);
194 AddAccelerator(accel_login_off_the_record_);
195 AddAccelerator(accel_toggle_accessibility_);
196
197 OnLocaleChanged();
198
199 // Controller to handle events from textfields
200 username_field_->SetController(this);
201 password_field_->SetController(this);
202 if (!CrosLibrary::Get()->EnsureLoaded()) {
203 EnableInputControls(false);
204 }
205
206 // The 'Sign in' button should be disabled when there is no text in the
207 // username and password fields.
208 sign_in_button_->SetEnabled(false);
209 }
210
211 bool NewUserView::AcceleratorPressed(const views::Accelerator& accelerator) {
212 if (accelerator == accel_focus_user_) {
213 username_field_->RequestFocus();
214 } else if (accelerator == accel_focus_pass_) {
215 password_field_->RequestFocus();
216 } else if (accelerator == accel_enterprise_enrollment_) {
217 delegate_->OnStartEnterpriseEnrollment();
218 } else if (accelerator == accel_login_off_the_record_) {
219 delegate_->OnLoginAsGuest();
220 } else if (accelerator == accel_toggle_accessibility_) {
221 WizardAccessibilityHelper::GetInstance()->ToggleAccessibility();
222 } else {
223 return false;
224 }
225 return true;
226 }
227
228 void NewUserView::RecreatePeculiarControls() {
229 // PreferredSize reported by MenuButton (and TextField) is not able
230 // to shrink, only grow; so recreate on text change.
231 delete languages_menubutton_;
232 languages_menubutton_ = new views::MenuButton(
233 NULL, string16(), &language_switch_menu_, true);
234 languages_menubutton_->set_menu_marker(
235 ResourceBundle::GetSharedInstance().GetBitmapNamed(
236 IDR_MENU_DROPARROW_SHARP));
237 languages_menubutton_->SetEnabledColor(kLanguagesMenuTextColor);
238 languages_menubutton_->set_focusable(true);
239 languages_menubutton_->SetEnabled(!g_browser_process->local_state()->
240 IsManagedPreference(prefs::kApplicationLocale));
241
242 // There is no way to get native button preferred size after the button was
243 // sized so delete and recreate the button on text update.
244 delete sign_in_button_;
245 sign_in_button_ = new login::WideButton(this, string16());
246 UpdateSignInButtonState();
247
248 if (!CrosLibrary::Get()->EnsureLoaded())
249 sign_in_button_->SetEnabled(false);
250 }
251
252 void NewUserView::UpdateSignInButtonState() {
253 bool enabled = !username_field_->text().empty() &&
254 !password_field_->text().empty();
255 sign_in_button_->SetEnabled(enabled);
256 }
257
258 views::View* NewUserView::CreateSplitter(SkColor color) {
259 views::View* splitter = new views::View();
260 splitter->set_background(views::Background::CreateSolidBackground(color));
261 AddChildView(splitter);
262 return splitter;
263 }
264
265 void NewUserView::AddChildView(View* view) {
266 // languages_menubutton_ and sign_in_button_ are recreated on text change,
267 // so we restore their original position in layout.
268 if (view == languages_menubutton_) {
269 if (languages_menubutton_order_ < 0) {
270 languages_menubutton_order_ = child_count();
271 }
272 views::View::AddChildViewAt(view, languages_menubutton_order_);
273 } else if (view == sign_in_button_) {
274 if (sign_in_button_order_ < 0) {
275 sign_in_button_order_ = child_count();
276 }
277 views::View::AddChildViewAt(view, sign_in_button_order_);
278 } else {
279 views::View::AddChildView(view);
280 }
281 }
282
283 void NewUserView::UpdateLocalizedStringsAndFonts() {
284 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
285 gfx::Font title_font = rb.GetFont(ResourceBundle::MediumBoldFont).DeriveFont(
286 kLoginTitleFontDelta);
287 const gfx::Font& title_hint_font = rb.GetFont(ResourceBundle::BoldFont);
288 const gfx::Font& base_font = rb.GetFont(ResourceBundle::BaseFont);
289
290 title_label_->SetFont(title_font);
291 title_label_->SetText(
292 l10n_util::GetStringUTF16(IDS_LOGIN_TITLE));
293 title_hint_label_->SetFont(title_hint_font);
294 title_hint_label_->SetText(l10n_util::GetStringUTF16(IDS_LOGIN_TITLE_HINT));
295 SetAndCorrectTextfieldFont(username_field_, base_font);
296 username_field_->set_text_to_display_when_empty(
297 l10n_util::GetStringUTF16(IDS_LOGIN_USERNAME));
298 SetAndCorrectTextfieldFont(password_field_, base_font);
299 password_field_->set_text_to_display_when_empty(
300 l10n_util::GetStringUTF16(IDS_LOGIN_PASSWORD));
301 sign_in_button_->SetText(l10n_util::GetStringUTF16(IDS_LOGIN_BUTTON));
302 if (need_guest_link_) {
303 guest_link_->SetFont(base_font);
304 guest_link_->SetText(
305 l10n_util::GetStringUTF16(IDS_BROWSE_WITHOUT_SIGNING_IN_BUTTON));
306 }
307 if (need_create_account_) {
308 create_account_link_->SetFont(base_font);
309 create_account_link_->SetText(
310 l10n_util::GetStringUTF16(IDS_CREATE_ACCOUNT_BUTTON));
311 }
312 delegate_->ClearErrors();
313 languages_menubutton_->SetText(language_switch_menu_.GetCurrentLocaleName());
314 }
315
316 void NewUserView::OnLocaleChanged() {
317 RecreatePeculiarControls();
318 UpdateLocalizedStringsAndFonts();
319 AddChildView(sign_in_button_);
320 AddChildView(languages_menubutton_);
321
322 Layout();
323 SchedulePaint();
324 RequestFocus();
325 }
326
327 void NewUserView::RequestFocus() {
328 if (username_field_->text().empty())
329 username_field_->RequestFocus();
330 else
331 password_field_->RequestFocus();
332 }
333
334 void NewUserView::ViewHierarchyChanged(bool is_add,
335 View *parent,
336 View *child) {
337 if (is_add && (child == username_field_ || child == password_field_)) {
338 MessageLoop::current()->PostTask(
339 FROM_HERE,
340 base::Bind(&NewUserView::Layout, weak_factory_.GetWeakPtr()));
341 }
342 }
343
344 // Sets the bounds of the view, using x and y as the origin.
345 // The width is determined by the min of width and the preferred size
346 // of the view, unless force_width is true in which case it is always used.
347 // The height is gotten from the preferred size and returned.
348 static int setViewBounds(
349 views::View* view, int x, int y, int width, bool force_width) {
350 gfx::Size pref_size = view->GetPreferredSize();
351 if (!force_width) {
352 if (pref_size.width() < width) {
353 width = pref_size.width();
354 }
355 }
356 int height = pref_size.height();
357 view->SetBounds(x, y, width, height);
358 return height;
359 }
360
361 void NewUserView::Layout() {
362 gfx::Insets insets = GetInsets();
363
364 // Place language selection in top right corner.
365 int x = std::max(0,
366 this->width() - insets.right() -
367 languages_menubutton_->GetPreferredSize().width() - kColumnPad);
368 int y = insets.top() + kLanguagesMenuPad;
369 int width = std::min(this->width() - insets.width() - 2 * kColumnPad,
370 languages_menubutton_->GetPreferredSize().width());
371 int height = kLanguagesMenuHeight;
372 languages_menubutton_->SetBounds(x, y, width, height);
373 y += height + kTitlePad;
374
375 width = std::min(this->width() - insets.width() - 2 * kColumnPad,
376 kTextfieldWidth);
377 x = insets.left() + kLeftPad;
378 int max_width = this->width() - x - std::max(insets.right(), x);
379 title_label_->SizeToFit(max_width);
380 title_hint_label_->SizeToFit(max_width);
381
382 // Top align title and title hint.
383 y += setViewBounds(title_label_, x, y, max_width, false);
384 y += setViewBounds(title_hint_label_, x, y, max_width, false);
385 int title_end = y + kTitlePad;
386
387 splitter_up1_->SetBounds(0, title_end, this->width(), kSplitterHeight);
388 splitter_up2_->SetBounds(0, title_end + 1, this->width(), kSplitterHeight);
389
390 // Bottom controls.
391 int links_height = 0;
392 if (need_create_account_)
393 links_height += create_account_link_->GetPreferredSize().height();
394 if (need_guest_link_)
395 links_height += guest_link_->GetPreferredSize().height();
396 if (need_create_account_ && need_guest_link_)
397 links_height += kRowPad;
398 y = this->height() - insets.bottom() - kBottomPad;
399 if (links_height)
400 y -= links_height + kBottomPad;
401 int bottom_start = y;
402
403 splitter_down1_->SetBounds(0, y, this->width(), kSplitterHeight);
404 splitter_down2_->SetBounds(0, y + 1, this->width(), kSplitterHeight);
405
406 y += kBottomPad;
407 if (need_guest_link_) {
408 y += setViewBounds(guest_link_,
409 x, y, max_width, false) + kRowPad;
410 }
411 if (need_create_account_) {
412 y += setViewBounds(create_account_link_, x, y, max_width, false);
413 }
414
415 // Center main controls.
416 height = username_field_->GetPreferredSize().height() +
417 password_field_->GetPreferredSize().height() +
418 sign_in_button_->GetPreferredSize().height() +
419 2 * kRowPad;
420 y = title_end + (bottom_start - title_end - height) / 2;
421
422 y += setViewBounds(username_field_, x, y, width, true) + kRowPad;
423 y += setViewBounds(password_field_, x, y, width, true) + kRowPad;
424
425 int sign_in_button_width = sign_in_button_->GetPreferredSize().width();
426 setViewBounds(sign_in_button_, x, y, sign_in_button_width, true);
427
428 SchedulePaint();
429 }
430
431 gfx::Size NewUserView::GetPreferredSize() {
432 return need_guest_link_ ?
433 gfx::Size(kNewUserPodFullWidth, kNewUserPodFullHeight) :
434 gfx::Size(kNewUserPodSmallWidth, kNewUserPodSmallHeight);
435 }
436
437 void NewUserView::SetUsername(const std::string& username) {
438 username_field_->SetText(UTF8ToUTF16(username));
439 }
440
441 void NewUserView::SetPassword(const std::string& password) {
442 password_field_->SetText(UTF8ToUTF16(password));
443 }
444
445 void NewUserView::Login() {
446 if (login_in_process_ ||
447 username_field_->text().empty() ||
448 password_field_->text().empty()) {
449 UpdateSignInButtonState();
450 return;
451 }
452
453 login_in_process_ = true;
454 std::string username = UTF16ToUTF8(username_field_->text());
455 // todo(cmasone) Need to sanitize memory used to store password.
456 std::string password = UTF16ToUTF8(password_field_->text());
457
458 if (username.find('@') == std::string::npos) {
459 username += kDefaultDomain;
460 username_field_->SetText(UTF8ToUTF16(username));
461 }
462
463 delegate_->OnLogin(username, password);
464 }
465
466 void NewUserView::LinkClicked(views::Link* source, int event_flags) {
467 if (source == create_account_link_) {
468 delegate_->OnCreateAccount();
469 } else if (source == guest_link_) {
470 delegate_->OnLoginAsGuest();
471 }
472 }
473
474 // Sign in button causes a login attempt.
475 void NewUserView::ButtonPressed(views::Button* sender,
476 const views::Event& event) {
477 DCHECK(sender == sign_in_button_);
478 Login();
479 }
480
481 void NewUserView::ClearAndFocusControls() {
482 login_in_process_ = false;
483 SetUsername(std::string());
484 SetPassword(std::string());
485 username_field_->RequestFocus();
486 UpdateSignInButtonState();
487 }
488
489 void NewUserView::ClearAndFocusPassword() {
490 login_in_process_ = false;
491 SetPassword(std::string());
492 password_field_->RequestFocus();
493 UpdateSignInButtonState();
494 }
495
496 gfx::Rect NewUserView::GetMainInputScreenBounds() const {
497 return GetUsernameBounds();
498 }
499
500 gfx::Rect NewUserView::CalculateThrobberBounds(views::Throbber* throbber) {
501 DCHECK(password_field_);
502 DCHECK(sign_in_button_);
503
504 gfx::Size throbber_size = throbber->GetPreferredSize();
505 int x = password_field_->x();
506 x += password_field_->width() - throbber_size.width();
507 int y = sign_in_button_->y();
508 y += (sign_in_button_->height() - throbber_size.height()) / 2;
509
510 return gfx::Rect(gfx::Point(x, y), throbber_size);
511 }
512
513 gfx::Rect NewUserView::GetPasswordBounds() const {
514 return password_field_->GetScreenBounds();
515 }
516
517 gfx::Rect NewUserView::GetUsernameBounds() const {
518 return username_field_->GetScreenBounds();
519 }
520
521 bool NewUserView::HandleKeyEvent(views::Textfield* sender,
522 const views::KeyEvent& key_event) {
523 if (!CrosLibrary::Get()->EnsureLoaded() || login_in_process_)
524 return false;
525
526 if (key_event.key_code() == ui::VKEY_RETURN) {
527 if (!username_field_->text().empty() && !password_field_->text().empty())
528 Login();
529 // Return true so that processing ends
530 return true;
531 }
532 delegate_->ClearErrors();
533 // Return false so that processing does not end
534 return false;
535 }
536
537 void NewUserView::ContentsChanged(views::Textfield* sender,
538 const string16& new_contents) {
539 UpdateSignInButtonState();
540 if (!new_contents.empty())
541 delegate_->ClearErrors();
542 }
543
544 void NewUserView::EnableInputControls(bool enabled) {
545 languages_menubutton_->SetEnabled(enabled &&
546 !g_browser_process->local_state()->IsManagedPreference(
547 prefs::kApplicationLocale));
548 username_field_->SetEnabled(enabled);
549 password_field_->SetEnabled(enabled);
550 if (need_guest_link_) {
551 guest_link_->SetEnabled(enabled);
552 }
553 if (need_create_account_) {
554 create_account_link_->SetEnabled(enabled);
555 }
556 UpdateSignInButtonState();
557 }
558
559 bool NewUserView::NavigateAway() {
560 if (!username_field_->text().empty() ||
561 !password_field_->text().empty())
562 return false;
563 delegate_->NavigateAway();
564 return true;
565 }
566
567 views::Link* NewUserView::InitLink(SkColor background_color) {
568 views::Link* link = new views::Link(string16());
569 link->set_listener(this);
570 link->SetBackgroundColor(background_color);
571 link->SetEnabledColor(login::kLinkColor);
572 link->SetPressedColor(login::kLinkColor);
573 AddChildView(link);
574 return link;
575 }
576
577 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/login/new_user_view.h ('k') | chrome/browser/chromeos/login/oobe_progress_bar.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698