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

Side by Side Diff: chrome/browser/ui/views/profile_chooser_view.cc

Issue 229293002: [Win] Move profile related UI from ui/views/ to ui/views/profiles (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 8 months 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
OLDNEW
(Empty)
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 #include "chrome/browser/ui/views/profile_chooser_view.h"
6
7 #include "base/prefs/pref_service.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/lifetime/application_lifetime.h"
11 #include "chrome/browser/profiles/profile_info_util.h"
12 #include "chrome/browser/profiles/profile_manager.h"
13 #include "chrome/browser/profiles/profile_window.h"
14 #include "chrome/browser/profiles/profiles_state.h"
15 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
16 #include "chrome/browser/signin/signin_manager_factory.h"
17 #include "chrome/browser/signin/signin_promo.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_dialogs.h"
20 #include "chrome/browser/ui/singleton_tabs.h"
21 #include "chrome/browser/ui/views/user_manager_view.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/common/profile_management_switches.h"
24 #include "chrome/common/url_constants.h"
25 #include "components/signin/core/browser/mutable_profile_oauth2_token_service.h"
26 #include "components/signin/core/browser/profile_oauth2_token_service.h"
27 #include "components/signin/core/browser/signin_manager.h"
28 #include "grit/chromium_strings.h"
29 #include "grit/generated_resources.h"
30 #include "grit/theme_resources.h"
31 #include "third_party/skia/include/core/SkColor.h"
32 #include "ui/base/l10n/l10n_util.h"
33 #include "ui/base/resource/resource_bundle.h"
34 #include "ui/gfx/canvas.h"
35 #include "ui/gfx/image/image.h"
36 #include "ui/gfx/image/image_skia.h"
37 #include "ui/gfx/text_elider.h"
38 #include "ui/native_theme/native_theme.h"
39 #include "ui/views/controls/button/blue_button.h"
40 #include "ui/views/controls/button/image_button.h"
41 #include "ui/views/controls/button/label_button.h"
42 #include "ui/views/controls/button/menu_button.h"
43 #include "ui/views/controls/label.h"
44 #include "ui/views/controls/link.h"
45 #include "ui/views/controls/separator.h"
46 #include "ui/views/controls/textfield/textfield.h"
47 #include "ui/views/controls/webview/webview.h"
48 #include "ui/views/layout/grid_layout.h"
49 #include "ui/views/layout/layout_constants.h"
50 #include "ui/views/widget/widget.h"
51
52 namespace {
53
54 // Helpers --------------------------------------------------------------------
55
56 const int kFixedMenuWidth = 250;
57 const int kButtonHeight = 29;
58 const int kProfileAvatarTutorialShowMax = 5;
59 const int kFixedGaiaViewHeight = 400;
60 const int kFixedGaiaViewWidth = 360;
61 const int kFixedAccountRemovalViewWidth = 280;
62
63 // Creates a GridLayout with a single column. This ensures that all the child
64 // views added get auto-expanded to fill the full width of the bubble.
65 views::GridLayout* CreateSingleColumnLayout(views::View* view, int width) {
66 views::GridLayout* layout = new views::GridLayout(view);
67 view->SetLayoutManager(layout);
68
69 views::ColumnSet* columns = layout->AddColumnSet(0);
70 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
71 views::GridLayout::FIXED, width, width);
72 return layout;
73 }
74
75 // Creates a GridLayout with two columns.
76 views::GridLayout* CreateDoubleColumnLayout(views::View* view) {
77 views::GridLayout* layout = new views::GridLayout(view);
78 view->SetLayoutManager(layout);
79
80 views::ColumnSet* columns = layout->AddColumnSet(0);
81 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
82 views::GridLayout::USE_PREF, 0, 0);
83 columns->AddPaddingColumn(0, views::kUnrelatedControlLargeHorizontalSpacing);
84 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
85 views::GridLayout::USE_PREF, 0, 0);
86 return layout;
87 }
88
89 views::Link* CreateLink(const base::string16& link_text,
90 views::LinkListener* listener) {
91 views::Link* link_button = new views::Link(link_text);
92 link_button->SetHorizontalAlignment(gfx::ALIGN_LEFT);
93 link_button->SetUnderline(false);
94 link_button->set_listener(listener);
95 return link_button;
96 }
97
98
99 // BackgroundColorHoverButton -------------------------------------------------
100
101 // A custom button that allows for setting a background color when hovered over.
102 class BackgroundColorHoverButton : public views::LabelButton {
103 public:
104 BackgroundColorHoverButton(views::ButtonListener* listener,
105 const base::string16& text,
106 const gfx::ImageSkia& normal_icon,
107 const gfx::ImageSkia& hover_icon);
108 virtual ~BackgroundColorHoverButton();
109
110 private:
111 // views::LabelButton:
112 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
113
114 DISALLOW_COPY_AND_ASSIGN(BackgroundColorHoverButton);
115 };
116
117 BackgroundColorHoverButton::BackgroundColorHoverButton(
118 views::ButtonListener* listener,
119 const base::string16& text,
120 const gfx::ImageSkia& normal_icon,
121 const gfx::ImageSkia& hover_icon)
122 : views::LabelButton(listener, text) {
123 SetBorder(views::Border::CreateEmptyBorder(0, views::kButtonHEdgeMarginNew,
124 0, views::kButtonHEdgeMarginNew));
125 set_min_size(gfx::Size(0, kButtonHeight));
126 SetImage(STATE_NORMAL, normal_icon);
127 SetImage(STATE_HOVERED, hover_icon);
128 SetImage(STATE_PRESSED, hover_icon);
129 }
130
131 BackgroundColorHoverButton::~BackgroundColorHoverButton() {}
132
133 void BackgroundColorHoverButton::OnPaint(gfx::Canvas* canvas) {
134 if ((state() == STATE_PRESSED) || (state() == STATE_HOVERED) || HasFocus()) {
135 canvas->DrawColor(GetNativeTheme()->GetSystemColor(
136 ui::NativeTheme::kColorId_MenuSeparatorColor));
137 }
138 LabelButton::OnPaint(canvas);
139 }
140
141 } // namespace
142
143
144 // EditableProfilePhoto -------------------------------------------------
145
146 // A custom Image control that shows a "change" button when moused over.
147 class EditableProfilePhoto : public views::ImageView {
148 public:
149 EditableProfilePhoto(views::ButtonListener* listener,
150 const gfx::Image& icon,
151 bool is_editing_allowed)
152 : views::ImageView(),
153 change_photo_button_(NULL) {
154 const int kLargeImageSide = 64;
155 gfx::Image image = profiles::GetSizedAvatarIconWithBorder(
156 icon, true,
157 kLargeImageSide + profiles::kAvatarIconPadding,
158 kLargeImageSide + profiles::kAvatarIconPadding);
159 SetImage(image.ToImageSkia());
160
161 if (!is_editing_allowed)
162 return;
163
164 set_notify_enter_exit_on_child(true);
165
166 // Button overlay that appears when hovering over the image.
167 change_photo_button_ = new views::LabelButton(listener,
168 l10n_util::GetStringUTF16(IDS_PROFILES_PROFILE_CHANGE_PHOTO_BUTTON));
169 change_photo_button_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
170 change_photo_button_->SetBorder(views::Border::NullBorder());
171 const SkColor color = SK_ColorWHITE;
172 change_photo_button_->SetTextColor(views::Button::STATE_NORMAL, color);
173 change_photo_button_->SetTextColor(views::Button::STATE_HOVERED, color);
174
175 const SkColor kBackgroundColor = SkColorSetARGB(125, 0, 0, 0);
176 change_photo_button_->set_background(
177 views::Background::CreateSolidBackground(kBackgroundColor));
178 // Need to take into account the border padding on the avatar.
179 const int kOverlayHeight = 20;
180 change_photo_button_->SetBounds(
181 profiles::kAvatarIconPadding,
182 kLargeImageSide - kOverlayHeight,
183 kLargeImageSide - profiles::kAvatarIconPadding,
184 kOverlayHeight);
185 change_photo_button_->SetVisible(false);
186 AddChildView(change_photo_button_);
187 }
188
189 views::LabelButton* change_photo_button() { return change_photo_button_; }
190
191 private:
192 // views::View:
193 virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE {
194 if (change_photo_button_)
195 change_photo_button_->SetVisible(true);
196 }
197
198 virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE {
199 if (change_photo_button_)
200 change_photo_button_->SetVisible(false);
201 }
202
203 // Button that is shown when hovering over the image view. Can be NULL if
204 // the photo isn't allowed to be edited (e.g. for guest profiles).
205 views::LabelButton* change_photo_button_;
206
207 DISALLOW_COPY_AND_ASSIGN(EditableProfilePhoto);
208 };
209
210
211 // EditableProfileName -------------------------------------------------
212
213 // A custom text control that turns into a textfield for editing when clicked.
214 class EditableProfileName : public views::LabelButton,
215 public views::ButtonListener {
216 public:
217 EditableProfileName(views::TextfieldController* controller,
218 const base::string16& text,
219 bool is_editing_allowed)
220 : views::LabelButton(this, text),
221 profile_name_textfield_(NULL) {
222 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
223 const gfx::FontList& medium_font_list =
224 rb->GetFontList(ui::ResourceBundle::MediumFont);
225 SetFontList(medium_font_list);
226 SetBorder(views::Border::NullBorder());
227
228 if (!is_editing_allowed)
229 return;
230
231 SetImage(STATE_HOVERED,
232 *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_EDIT_HOVER));
233 SetImage(STATE_PRESSED,
234 *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_EDIT_PRESSED));
235
236 // Textfield that overlaps the button.
237 profile_name_textfield_ = new views::Textfield();
238 profile_name_textfield_->set_controller(controller);
239 profile_name_textfield_->SetFontList(medium_font_list);
240 profile_name_textfield_->SetVisible(false);
241 AddChildView(profile_name_textfield_);
242 }
243
244 views::Textfield* profile_name_textfield() {
245 return profile_name_textfield_;
246 }
247
248 // Hide the editable textfield to show the profile name button instead.
249 void ShowReadOnlyView() {
250 if (profile_name_textfield_)
251 profile_name_textfield_->SetVisible(false);
252 }
253
254 private:
255 // views::ButtonListener:
256 virtual void ButtonPressed(views::Button* sender,
257 const ui::Event& event) OVERRIDE {
258 if (profile_name_textfield_) {
259 profile_name_textfield_->SetVisible(true);
260 profile_name_textfield_->SetText(GetText());
261 profile_name_textfield_->SelectAll(false);
262 profile_name_textfield_->RequestFocus();
263 }
264 }
265
266 // views::LabelButton:
267 virtual bool OnKeyReleased(const ui::KeyEvent& event) OVERRIDE {
268 // Override CustomButton's implementation, which presses the button when
269 // you press space and clicks it when you release space, as the space can be
270 // part of the new profile name typed in the textfield.
271 return false;
272 }
273
274 virtual void Layout() OVERRIDE {
275 if (profile_name_textfield_)
276 profile_name_textfield_->SetBounds(0, 0, width(), height());
277 // This layout trick keeps the text left-aligned and the icon right-aligned.
278 SetHorizontalAlignment(gfx::ALIGN_RIGHT);
279 views::LabelButton::Layout();
280 label()->SetHorizontalAlignment(gfx::ALIGN_LEFT);
281 }
282
283 // Button that is shown when hovering over the image view. Can be NULL if
284 // the profile name isn't allowed to be edited (e.g. for guest profiles).
285 views::Textfield* profile_name_textfield_;
286
287 DISALLOW_COPY_AND_ASSIGN(EditableProfileName);
288 };
289
290 // A title card with one back button right aligned and one label center aligned.
291 class TitleCard : public views::View {
292 public:
293 TitleCard(int message_id, views::ButtonListener* listener,
294 views::ImageButton** back_button) {
295 back_button_ = new views::ImageButton(listener);
296 back_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT,
297 views::ImageButton::ALIGN_MIDDLE);
298 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
299 back_button_->SetImage(views::ImageButton::STATE_NORMAL,
300 rb->GetImageSkiaNamed(IDR_BACK));
301 back_button_->SetImage(views::ImageButton::STATE_HOVERED,
302 rb->GetImageSkiaNamed(IDR_BACK_H));
303 back_button_->SetImage(views::ImageButton::STATE_PRESSED,
304 rb->GetImageSkiaNamed(IDR_BACK_P));
305 back_button_->SetImage(views::ImageButton::STATE_DISABLED,
306 rb->GetImageSkiaNamed(IDR_BACK_D));
307 *back_button = back_button_;
308
309 title_label_ = new views::Label(l10n_util::GetStringUTF16(message_id));
310 title_label_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
311 const gfx::FontList& medium_font_list =
312 rb->GetFontList(ui::ResourceBundle::MediumFont);
313 title_label_->SetFontList(medium_font_list);
314
315 AddChildView(back_button_);
316 AddChildView(title_label_);
317 }
318
319 private:
320 virtual void Layout() OVERRIDE{
321 back_button_->SetBounds(
322 0, 0, back_button_->GetPreferredSize().width(), height());
323 title_label_->SetBoundsRect(GetContentsBounds());
324 }
325
326 virtual gfx::Size GetPreferredSize() OVERRIDE{
327 int height = profiles::kAvatarIconPadding * 2 +
328 std::max(title_label_->GetPreferredSize().height(),
329 back_button_->GetPreferredSize().height());
330 return gfx::Size(width(), height);
331 }
332
333 views::ImageButton* back_button_;
334 views::Label* title_label_;
335
336 DISALLOW_COPY_AND_ASSIGN(TitleCard);
337 };
338
339 // ProfileChooserView ---------------------------------------------------------
340
341 // static
342 ProfileChooserView* ProfileChooserView::profile_bubble_ = NULL;
343 bool ProfileChooserView::close_on_deactivate_for_testing_ = true;
344
345 // static
346 void ProfileChooserView::ShowBubble(
347 BubbleViewMode view_mode,
348 views::View* anchor_view,
349 views::BubbleBorder::Arrow arrow,
350 views::BubbleBorder::BubbleAlignment border_alignment,
351 const gfx::Rect& anchor_rect,
352 Browser* browser) {
353 profile_bubble_ = new ProfileChooserView(
354 anchor_view, arrow, anchor_rect, browser);
355 views::BubbleDelegateView::CreateBubble(profile_bubble_);
356 profile_bubble_->set_close_on_deactivate(close_on_deactivate_for_testing_);
357 profile_bubble_->SetAlignment(border_alignment);
358 profile_bubble_->GetWidget()->Show();
359 profile_bubble_->SetArrowPaintType(views::BubbleBorder::PAINT_NONE);
360
361 if (view_mode != BUBBLE_VIEW_MODE_PROFILE_CHOOSER)
362 profile_bubble_->ShowView(view_mode, profile_bubble_->avatar_menu_.get());
363 }
364
365 // static
366 bool ProfileChooserView::IsShowing() {
367 return profile_bubble_ != NULL;
368 }
369
370 // static
371 void ProfileChooserView::Hide() {
372 if (IsShowing())
373 profile_bubble_->GetWidget()->Close();
374 }
375
376 ProfileChooserView::ProfileChooserView(views::View* anchor_view,
377 views::BubbleBorder::Arrow arrow,
378 const gfx::Rect& anchor_rect,
379 Browser* browser)
380 : BubbleDelegateView(anchor_view, arrow),
381 browser_(browser),
382 view_mode_(BUBBLE_VIEW_MODE_PROFILE_CHOOSER),
383 tutorial_showing_(false) {
384 // Reset the default margins inherited from the BubbleDelegateView.
385 set_margins(gfx::Insets());
386
387 ResetView();
388
389 set_background(views::Background::CreateSolidBackground(
390 GetNativeTheme()->GetSystemColor(
391 ui::NativeTheme::kColorId_DialogBackground)));
392
393 avatar_menu_.reset(new AvatarMenu(
394 &g_browser_process->profile_manager()->GetProfileInfoCache(),
395 this,
396 browser_));
397 avatar_menu_->RebuildMenu();
398
399 ProfileOAuth2TokenService* oauth2_token_service =
400 ProfileOAuth2TokenServiceFactory::GetForProfile(browser_->profile());
401 if (oauth2_token_service)
402 oauth2_token_service->AddObserver(this);
403 }
404
405 ProfileChooserView::~ProfileChooserView() {
406 ProfileOAuth2TokenService* oauth2_token_service =
407 ProfileOAuth2TokenServiceFactory::GetForProfile(browser_->profile());
408 if (oauth2_token_service)
409 oauth2_token_service->RemoveObserver(this);
410 }
411
412 void ProfileChooserView::ResetView() {
413 manage_accounts_link_ = NULL;
414 signin_current_profile_link_ = NULL;
415 users_button_ = NULL;
416 lock_button_ = NULL;
417 add_account_button_ = NULL;
418 current_profile_photo_ = NULL;
419 current_profile_name_ = NULL;
420 tutorial_ok_button_ = NULL;
421 tutorial_learn_more_link_ = NULL;
422 account_removal_cancel_button_ = NULL;
423 gaia_signin_cancel_button_ = NULL;
424 open_other_profile_indexes_map_.clear();
425 current_profile_accounts_map_.clear();
426 tutorial_showing_ = false;
427 }
428
429 void ProfileChooserView::Init() {
430 ShowView(BUBBLE_VIEW_MODE_PROFILE_CHOOSER, avatar_menu_.get());
431 }
432
433 void ProfileChooserView::OnAvatarMenuChanged(
434 AvatarMenu* avatar_menu) {
435 // Refresh the view with the new menu. We can't just update the local copy
436 // as this may have been triggered by a sign out action, in which case
437 // the view is being destroyed.
438 ShowView(BUBBLE_VIEW_MODE_PROFILE_CHOOSER, avatar_menu);
439 }
440
441 void ProfileChooserView::OnRefreshTokenAvailable(
442 const std::string& account_id) {
443 // Refresh the account management view when a new account is added to the
444 // profile.
445 if (view_mode_ == BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT ||
446 view_mode_ == BUBBLE_VIEW_MODE_GAIA_SIGNIN ||
447 view_mode_ == BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT) {
448 ShowView(BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT, avatar_menu_.get());
449 }
450 }
451
452 void ProfileChooserView::OnRefreshTokenRevoked(const std::string& account_id) {
453 // Refresh the account management view when an account is removed from the
454 // profile.
455 if (view_mode_ == BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT)
456 ShowView(BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT, avatar_menu_.get());
457 }
458
459 void ProfileChooserView::ShowView(BubbleViewMode view_to_display,
460 AvatarMenu* avatar_menu) {
461 // The account management view should only be displayed if the active profile
462 // is signed in.
463 if (view_to_display == BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT) {
464 const AvatarMenu::Item& active_item = avatar_menu->GetItemAt(
465 avatar_menu->GetActiveProfileIndex());
466 DCHECK(active_item.signed_in);
467 }
468
469 // Records if the tutorial card is currently shown before resetting the view.
470 bool tutorial_shown = tutorial_showing_;
471 ResetView();
472 RemoveAllChildViews(true);
473 view_mode_ = view_to_display;
474
475 if (view_mode_ == BUBBLE_VIEW_MODE_GAIA_SIGNIN ||
476 view_mode_ == BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT ||
477 view_mode_ == BUBBLE_VIEW_MODE_ACCOUNT_REMOVAL) {
478 bool is_removal_view = view_mode_ == BUBBLE_VIEW_MODE_ACCOUNT_REMOVAL;
479 views::GridLayout* layout = CreateSingleColumnLayout(this,
480 is_removal_view ? kFixedAccountRemovalViewWidth : kFixedGaiaViewWidth);
481 layout->StartRow(1, 0);
482 layout->AddView(is_removal_view ? CreateAccountRemovalView():
483 CreateGaiaSigninView(view_mode_ == BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT));
484 Layout();
485 if (GetBubbleFrameView())
486 SizeToContents();
487 return;
488 }
489
490 views::GridLayout* layout = CreateSingleColumnLayout(this, kFixedMenuWidth);
491 // Separate items into active and alternatives.
492 Indexes other_profiles;
493 views::View* tutorial_view = NULL;
494 views::View* current_profile_view = NULL;
495 views::View* current_profile_accounts = NULL;
496 views::View* option_buttons_view = NULL;
497 for (size_t i = 0; i < avatar_menu->GetNumberOfItems(); ++i) {
498 const AvatarMenu::Item& item = avatar_menu->GetItemAt(i);
499 if (item.active) {
500 option_buttons_view = CreateOptionsView(item.signed_in);
501 if (view_to_display == BUBBLE_VIEW_MODE_PROFILE_CHOOSER) {
502 tutorial_view = CreateTutorialView(item, tutorial_shown);
503 current_profile_view = CreateCurrentProfileView(item, false);
504 } else {
505 current_profile_view = CreateCurrentProfileEditableView(item);
506 current_profile_accounts = CreateCurrentProfileAccountsView(item);
507 }
508 } else {
509 other_profiles.push_back(i);
510 }
511 }
512
513 if (tutorial_view) {
514 layout->StartRow(1, 0);
515 layout->AddView(tutorial_view);
516 }
517
518 if (!current_profile_view) {
519 // Guest windows don't have an active profile.
520 current_profile_view = CreateGuestProfileView();
521 option_buttons_view = CreateOptionsView(false);
522 }
523
524 layout->StartRow(1, 0);
525 layout->AddView(current_profile_view);
526
527 if (view_to_display == BUBBLE_VIEW_MODE_PROFILE_CHOOSER) {
528 layout->StartRow(1, 0);
529 if (switches::IsFastUserSwitching())
530 layout->AddView(CreateOtherProfilesView(other_profiles));
531 } else {
532 DCHECK(current_profile_accounts);
533 layout->StartRow(0, 0);
534 layout->AddView(new views::Separator(views::Separator::HORIZONTAL));
535 layout->StartRow(1, 0);
536 layout->AddView(current_profile_accounts);
537 }
538
539 layout->StartRow(0, 0);
540 layout->AddView(new views::Separator(views::Separator::HORIZONTAL));
541
542 // Action buttons.
543 layout->StartRow(0, 0);
544 layout->AddView(option_buttons_view);
545
546 Layout();
547 if (GetBubbleFrameView())
548 SizeToContents();
549 }
550
551 void ProfileChooserView::WindowClosing() {
552 DCHECK_EQ(profile_bubble_, this);
553 profile_bubble_ = NULL;
554 }
555
556 void ProfileChooserView::ButtonPressed(views::Button* sender,
557 const ui::Event& event) {
558 // Disable button after clicking so that it doesn't get clicked twice and
559 // start a second action... which can crash Chrome. But don't disable if it
560 // has no parent (like in tests) because that will also crash.
561 if (sender->parent())
562 sender->SetEnabled(false);
563
564 if (sender == users_button_) {
565 chrome::ShowUserManager(base::FilePath());
566 } else if (sender == lock_button_) {
567 profiles::LockProfile(browser_->profile());
568 } else if (sender == add_account_button_) {
569 ShowView(BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT, avatar_menu_.get());
570 } else if (sender == tutorial_ok_button_) {
571 // If the user manually dismissed the tutorial, never show it again by
572 // setting the number of times shown to the maximum plus 1, so that later we
573 // could distinguish between the dismiss case and the case when the tutorial
574 // is indeed shown for the maximum number of times.
575 browser_->profile()->GetPrefs()->SetInteger(
576 prefs::kProfileAvatarTutorialShown, kProfileAvatarTutorialShowMax + 1);
577 ShowView(BUBBLE_VIEW_MODE_PROFILE_CHOOSER, avatar_menu_.get());
578 } else if (sender == remove_account_and_relaunch_button_) {
579 RemoveAccount();
580 } else if (sender == account_removal_cancel_button_) {
581 account_id_to_remove_.clear();
582 ShowView(BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT, avatar_menu_.get());
583 } else if (sender == gaia_signin_cancel_button_) {
584 std::string primary_account =
585 SigninManagerFactory::GetForProfile(browser_->profile())->
586 GetAuthenticatedUsername();
587 ShowView(primary_account.empty() ? BUBBLE_VIEW_MODE_PROFILE_CHOOSER :
588 BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT,
589 avatar_menu_.get());
590 } else if (current_profile_photo_ &&
591 sender == current_profile_photo_->change_photo_button()) {
592 avatar_menu_->EditProfile(avatar_menu_->GetActiveProfileIndex());
593 } else {
594 // One of the "other profiles" buttons was pressed.
595 ButtonIndexes::const_iterator match =
596 open_other_profile_indexes_map_.find(sender);
597 DCHECK(match != open_other_profile_indexes_map_.end());
598 avatar_menu_->SwitchToProfile(
599 match->second,
600 ui::DispositionFromEventFlags(event.flags()) == NEW_WINDOW,
601 ProfileMetrics::SWITCH_PROFILE_ICON);
602 }
603 }
604
605 void ProfileChooserView::OnMenuButtonClicked(views::View* source,
606 const gfx::Point& point) {
607 AccountButtonIndexes::const_iterator match =
608 current_profile_accounts_map_.find(source);
609 DCHECK(match != current_profile_accounts_map_.end());
610 account_id_to_remove_ = match->second;
611 ShowView(BUBBLE_VIEW_MODE_ACCOUNT_REMOVAL, avatar_menu_.get());
612 }
613
614 void ProfileChooserView::RemoveAccount() {
615 DCHECK(!account_id_to_remove_.empty());
616 MutableProfileOAuth2TokenService* oauth2_token_service =
617 ProfileOAuth2TokenServiceFactory::GetPlatformSpecificForProfile(
618 browser_->profile());
619 if (oauth2_token_service)
620 oauth2_token_service->RevokeCredentials(account_id_to_remove_);
621 account_id_to_remove_.clear();
622
623 chrome::AttemptRestart();
624 }
625
626 void ProfileChooserView::LinkClicked(views::Link* sender, int event_flags) {
627 if (sender == manage_accounts_link_) {
628 // ShowView() will DCHECK if this view is displayed for non signed-in users.
629 ShowView(BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT, avatar_menu_.get());
630 } else if (sender == tutorial_learn_more_link_) {
631 // TODO(guohui): update |learn_more_url| once it is decided.
632 const GURL lear_more_url("https://support.google.com/chrome/?hl=en#to");
633 chrome::NavigateParams params(
634 browser_->profile(),
635 lear_more_url,
636 content::PAGE_TRANSITION_LINK);
637 params.disposition = NEW_FOREGROUND_TAB;
638 chrome::Navigate(&params);
639 } else {
640 DCHECK(sender == signin_current_profile_link_);
641 ShowView(BUBBLE_VIEW_MODE_GAIA_SIGNIN, avatar_menu_.get());
642 }
643 }
644
645 bool ProfileChooserView::HandleKeyEvent(views::Textfield* sender,
646 const ui::KeyEvent& key_event) {
647 views::Textfield* name_textfield =
648 current_profile_name_->profile_name_textfield();
649 DCHECK(sender == name_textfield);
650
651 if (key_event.key_code() == ui::VKEY_RETURN ||
652 key_event.key_code() == ui::VKEY_TAB) {
653 // Pressing Tab/Enter commits the new profile name, unless it's empty.
654 base::string16 new_profile_name = name_textfield->text();
655 if (new_profile_name.empty())
656 return true;
657
658 const AvatarMenu::Item& active_item = avatar_menu_->GetItemAt(
659 avatar_menu_->GetActiveProfileIndex());
660 Profile* profile = g_browser_process->profile_manager()->GetProfile(
661 active_item.profile_path);
662 DCHECK(profile);
663
664 if (profile->IsManaged())
665 return true;
666
667 profiles::UpdateProfileName(profile, new_profile_name);
668 current_profile_name_->ShowReadOnlyView();
669 return true;
670 }
671 return false;
672 }
673
674 views::View* ProfileChooserView::CreateTutorialView(
675 const AvatarMenu::Item& current_avatar_item, bool tutorial_shown) {
676 if (!current_avatar_item.signed_in)
677 return NULL;
678
679 Profile* profile = browser_->profile();
680 const int show_count = profile->GetPrefs()->GetInteger(
681 prefs::kProfileAvatarTutorialShown);
682 // Do not show the tutorial if user has dismissed it.
683 if (show_count > kProfileAvatarTutorialShowMax)
684 return NULL;
685
686 if (!tutorial_shown) {
687 if (show_count == kProfileAvatarTutorialShowMax)
688 return NULL;
689 profile->GetPrefs()->SetInteger(
690 prefs::kProfileAvatarTutorialShown, show_count + 1);
691 }
692 tutorial_showing_ = true;
693
694 views::View* view = new views::View();
695 view->set_background(views::Background::CreateSolidBackground(
696 profiles::kAvatarTutorialBackgroundColor));
697 views::GridLayout* layout = CreateSingleColumnLayout(view,
698 kFixedMenuWidth - 2 * views::kButtonHEdgeMarginNew);
699 layout->SetInsets(views::kButtonVEdgeMarginNew,
700 views::kButtonHEdgeMarginNew,
701 views::kButtonVEdgeMarginNew,
702 views::kButtonHEdgeMarginNew);
703
704 // Adds title.
705 views::Label* title_label = new views::Label(
706 l10n_util::GetStringUTF16(IDS_PROFILES_SIGNIN_TUTORIAL_TITLE));
707 title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
708 title_label->SetAutoColorReadabilityEnabled(false);
709 title_label->SetEnabledColor(SK_ColorWHITE);
710 title_label ->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
711 ui::ResourceBundle::MediumFont));
712 layout->StartRow(1, 0);
713 layout->AddView(title_label);
714
715 // Adds body content.
716 views::Label* content_label = new views::Label(
717 l10n_util::GetStringUTF16(IDS_PROFILES_SIGNIN_TUTORIAL_CONTENT_TEXT));
718 content_label->SetMultiLine(true);
719 content_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
720 content_label->SetAutoColorReadabilityEnabled(false);
721 content_label->SetEnabledColor(profiles::kAvatarTutorialContentTextColor);
722 layout->StartRowWithPadding(1, 0, 0, views::kRelatedControlVerticalSpacing);
723 layout->AddView(content_label);
724
725 // Adds links and buttons.
726 views::View* button_row = new views::View();
727 views::GridLayout* button_layout = new views::GridLayout(button_row);
728 views::ColumnSet* button_columns = button_layout->AddColumnSet(0);
729 button_columns->AddColumn(views::GridLayout::LEADING,
730 views::GridLayout::CENTER, 0, views::GridLayout::USE_PREF, 0, 0);
731 button_columns->AddPaddingColumn(
732 1, views::kUnrelatedControlHorizontalSpacing);
733 button_columns->AddColumn(views::GridLayout::TRAILING,
734 views::GridLayout::CENTER, 0, views::GridLayout::USE_PREF, 0, 0);
735 button_row->SetLayoutManager(button_layout);
736
737 tutorial_learn_more_link_ = CreateLink(
738 l10n_util::GetStringUTF16(IDS_PROFILES_PROFILE_TUTORIAL_LEARN_MORE),
739 this);
740 tutorial_learn_more_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
741 tutorial_learn_more_link_->SetAutoColorReadabilityEnabled(false);
742 tutorial_learn_more_link_->SetEnabledColor(SK_ColorWHITE);
743 button_layout->StartRow(1, 0);
744 button_layout->AddView(tutorial_learn_more_link_);
745
746 tutorial_ok_button_ = new views::LabelButton(
747 this, l10n_util::GetStringUTF16(IDS_PROFILES_SIGNIN_TUTORIAL_OK_BUTTON));
748 tutorial_ok_button_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
749 tutorial_ok_button_->SetStyle(views::Button::STYLE_BUTTON);
750 button_layout->AddView(tutorial_ok_button_);
751
752 layout->StartRowWithPadding(1, 0, 0, views::kUnrelatedControlVerticalSpacing);
753 layout->AddView(button_row);
754
755 // Adds a padded caret image at the bottom.
756 views::View* padded_caret_view = new views::View();
757 views::GridLayout* padded_caret_layout =
758 new views::GridLayout(padded_caret_view);
759 views::ColumnSet* padded_columns = padded_caret_layout->AddColumnSet(0);
760 padded_columns->AddPaddingColumn(0, views::kButtonHEdgeMarginNew);
761 padded_columns->AddColumn(views::GridLayout::LEADING,
762 views::GridLayout::CENTER, 0, views::GridLayout::USE_PREF, 0, 0);
763 padded_caret_view->SetLayoutManager(padded_caret_layout);
764
765 views::ImageView* caret_image_view = new views::ImageView();
766 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
767 caret_image_view->SetImage(
768 *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_CARET));
769
770 padded_caret_layout->StartRow(1, 0);
771 padded_caret_layout->AddView(caret_image_view);
772
773 views::View* view_with_caret = new views::View();
774 views::GridLayout* layout_with_caret =
775 CreateSingleColumnLayout(view_with_caret, kFixedMenuWidth);
776 layout_with_caret->StartRow(1, 0);
777 layout_with_caret->AddView(view);
778 layout_with_caret->StartRow(1, 0);
779 layout_with_caret->AddView(padded_caret_view);
780 return view_with_caret;
781 }
782
783 views::View* ProfileChooserView::CreateCurrentProfileView(
784 const AvatarMenu::Item& avatar_item,
785 bool is_guest) {
786 views::View* view = new views::View();
787 views::GridLayout* layout = CreateDoubleColumnLayout(view);
788 layout->SetInsets(views::kButtonVEdgeMarginNew,
789 views::kButtonHEdgeMarginNew,
790 views::kButtonVEdgeMarginNew,
791 views::kButtonHEdgeMarginNew);
792
793 current_profile_photo_ =
794 new EditableProfilePhoto(this, avatar_item.icon, !is_guest);
795 view->SetBoundsRect(current_profile_photo_->bounds());
796 current_profile_name_ = new EditableProfileName(
797 this, profiles::GetAvatarNameForProfile(browser_->profile()), !is_guest);
798 layout->StartRow(1, 0);
799 layout->AddView(current_profile_photo_, 1, 3);
800 layout->AddView(current_profile_name_);
801
802 if (is_guest) {
803 layout->StartRow(1, 0);
804 layout->SkipColumns(1);
805 layout->StartRow(1, 0);
806 layout->SkipColumns(1);
807 } else if (avatar_item.signed_in) {
808 manage_accounts_link_ = CreateLink(
809 l10n_util::GetStringUTF16(IDS_PROFILES_PROFILE_MANAGE_ACCOUNTS_BUTTON),
810 this);
811 layout->StartRow(1, 0);
812 layout->SkipColumns(1);
813 layout->AddView(manage_accounts_link_);
814 layout->StartRow(1, 0);
815 layout->SkipColumns(1);
816 } else {
817 signin_current_profile_link_ = CreateLink(
818 l10n_util::GetStringFUTF16(
819 IDS_SYNC_START_SYNC_BUTTON_LABEL,
820 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)),
821 this);
822 layout->StartRow(1, 0);
823 layout->SkipColumns(1);
824 layout->AddView(signin_current_profile_link_);
825 layout->StartRow(1, 0);
826 layout->SkipColumns(1);
827 }
828
829 return view;
830 }
831
832 views::View* ProfileChooserView::CreateCurrentProfileEditableView(
833 const AvatarMenu::Item& avatar_item) {
834 DCHECK(avatar_item.signed_in);
835 views::View* view = new views::View();
836 views::GridLayout* layout = CreateDoubleColumnLayout(view);
837 layout->SetInsets(views::kButtonVEdgeMarginNew,
838 views::kButtonHEdgeMarginNew,
839 views::kButtonVEdgeMarginNew,
840 views::kButtonHEdgeMarginNew);
841
842 current_profile_photo_ =
843 new EditableProfilePhoto(this, avatar_item.icon, true);
844 view->SetBoundsRect(current_profile_photo_->bounds());
845 current_profile_name_ = new EditableProfileName(
846 this, profiles::GetAvatarNameForProfile(browser_->profile()), true);
847
848 layout->StartRow(1, 0);
849 layout->AddView(current_profile_photo_, 1, 3);
850 layout->AddView(current_profile_name_);
851
852 layout->StartRow(1, 0);
853 layout->SkipColumns(1);
854
855 layout->StartRow(1, 0);
856 layout->SkipColumns(1);
857 return view;
858 }
859
860 views::View* ProfileChooserView::CreateGuestProfileView() {
861 gfx::Image guest_icon =
862 ui::ResourceBundle::GetSharedInstance().GetImageNamed(IDR_LOGIN_GUEST);
863 AvatarMenu::Item guest_avatar_item(0, 0, guest_icon);
864 guest_avatar_item.active = true;
865 guest_avatar_item.name = l10n_util::GetStringUTF16(
866 IDS_PROFILES_GUEST_PROFILE_NAME);
867 guest_avatar_item.signed_in = false;
868
869 return CreateCurrentProfileView(guest_avatar_item, true);
870 }
871
872 views::View* ProfileChooserView::CreateOtherProfilesView(
873 const Indexes& avatars_to_show) {
874 views::View* view = new views::View();
875 views::GridLayout* layout = CreateSingleColumnLayout(
876 view, kFixedMenuWidth - 2 * views::kButtonHEdgeMarginNew);
877 layout->SetInsets(0, views::kButtonHEdgeMarginNew,
878 views::kButtonVEdgeMarginNew, views::kButtonHEdgeMarginNew);
879 int num_avatars_to_show = avatars_to_show.size();
880 for (int i = 0; i < num_avatars_to_show; ++i) {
881 const size_t index = avatars_to_show[i];
882 const AvatarMenu::Item& item = avatar_menu_->GetItemAt(index);
883 const int kSmallImageSide = 32;
884
885 gfx::Image image = profiles::GetSizedAvatarIconWithBorder(
886 item.icon, true,
887 kSmallImageSide + profiles::kAvatarIconPadding,
888 kSmallImageSide + profiles::kAvatarIconPadding);
889
890 views::LabelButton* button = new views::LabelButton(this, item.name);
891 open_other_profile_indexes_map_[button] = index;
892 button->SetImage(views::Button::STATE_NORMAL, *image.ToImageSkia());
893 button->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
894 ui::ResourceBundle::MediumFont));
895 button->SetBorder(views::Border::NullBorder());
896
897 layout->StartRow(1, 0);
898 layout->AddView(button);
899
900 // The last avatar in the list does not need any bottom padding.
901 if (i < num_avatars_to_show - 1)
902 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
903 }
904
905 return view;
906 }
907
908 views::View* ProfileChooserView::CreateOptionsView(bool enable_lock) {
909 views::View* view = new views::View();
910 views::GridLayout* layout;
911
912 // Only signed-in users have the ability to lock.
913 if (enable_lock) {
914 layout = new views::GridLayout(view);
915 views::ColumnSet* columns = layout->AddColumnSet(0);
916 int width_of_lock_button =
917 2 * views::kUnrelatedControlLargeHorizontalSpacing + 12;
918 int width_of_users_button = kFixedMenuWidth - width_of_lock_button;
919 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
920 views::GridLayout::FIXED, width_of_users_button,
921 width_of_users_button);
922 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
923 views::GridLayout::FIXED, width_of_lock_button,
924 width_of_lock_button);
925 view->SetLayoutManager(layout);
926 } else {
927 layout = CreateSingleColumnLayout(view, kFixedMenuWidth);
928 }
929
930 // The horizontal padding will be set by each button individually, so that
931 // in the hovered state the button spans the entire parent view.
932 layout->SetInsets(views::kRelatedControlVerticalSpacing, 0,
933 views::kRelatedControlVerticalSpacing, 0);
934
935 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
936 users_button_ = new BackgroundColorHoverButton(
937 this,
938 l10n_util::GetStringFUTF16(IDS_PROFILES_NOT_YOU_BUTTON,
939 profiles::GetAvatarNameForProfile(browser_->profile())),
940 *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_AVATAR),
941 *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_AVATAR));
942
943 layout->StartRow(1, 0);
944 layout->AddView(users_button_);
945
946 if (enable_lock) {
947 lock_button_ = new BackgroundColorHoverButton(
948 this,
949 base::string16(),
950 *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_LOCK),
951 *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_LOCK));
952 layout->AddView(lock_button_);
953 }
954 return view;
955 }
956
957 views::View* ProfileChooserView::CreateCurrentProfileAccountsView(
958 const AvatarMenu::Item& avatar_item) {
959 DCHECK(avatar_item.signed_in);
960 views::View* view = new views::View();
961 int column_width = kFixedMenuWidth - 2 * views::kButtonHEdgeMarginNew;
962 views::GridLayout* layout = CreateSingleColumnLayout(view, column_width);
963 layout->SetInsets(views::kButtonVEdgeMarginNew,
964 views::kButtonHEdgeMarginNew,
965 views::kButtonVEdgeMarginNew,
966 views::kButtonHEdgeMarginNew);
967
968 Profile* profile = browser_->profile();
969 std::string primary_account =
970 SigninManagerFactory::GetForProfile(profile)->GetAuthenticatedUsername();
971 DCHECK(!primary_account.empty());
972 std::vector<std::string>accounts =
973 profiles::GetSecondaryAccountsForProfile(profile, primary_account);
974
975 // The primary account should always be listed first.
976 // TODO(rogerta): we still need to further differentiate the primary account
977 // from the others in the UI, so more work is likely required here:
978 // crbug.com/311124.
979 CreateAccountButton(layout, primary_account, true, column_width);
980 for (size_t i = 0; i < accounts.size(); ++i)
981 CreateAccountButton(layout, accounts[i], false, column_width);
982 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
983
984 add_account_button_ = new views::BlueButton(
985 this,
986 l10n_util::GetStringFUTF16(IDS_PROFILES_PROFILE_ADD_ACCOUNT_BUTTON,
987 avatar_item.name));
988 layout->StartRow(1, 0);
989 layout->AddView(add_account_button_);
990 return view;
991 }
992
993 void ProfileChooserView::CreateAccountButton(views::GridLayout* layout,
994 const std::string& account,
995 bool is_primary_account,
996 int width) {
997 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
998 const gfx::ImageSkia* menu_marker =
999 rb->GetImageNamed(IDR_CLOSE_1).ToImageSkia();
1000 // Use a MenuButtonListener and not a regular ButtonListener to be
1001 // able to distinguish between the unnamed "other profile" buttons and the
1002 // unnamed "multiple accounts" buttons.
1003 views::MenuButton* email_button = new views::MenuButton(
1004 NULL,
1005 gfx::ElideEmail(base::UTF8ToUTF16(account),
1006 rb->GetFontList(ui::ResourceBundle::BaseFont),
1007 width - menu_marker->width()),
1008 this,
1009 true /* show_menu_marker */);
1010 email_button->SetBorder(views::Border::CreateEmptyBorder(0, 0, 0, 0));
1011 email_button->set_menu_marker(menu_marker);
1012 if (!is_primary_account)
1013 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
1014 layout->StartRow(1, 0);
1015 layout->AddView(email_button);
1016
1017 // Save the original email address, as the button text could be elided.
1018 current_profile_accounts_map_[email_button] = account;
1019 }
1020
1021 views::View* ProfileChooserView::CreateGaiaSigninView(
1022 bool add_secondary_account) {
1023 views::View* view = new views::View();
1024 views::GridLayout* layout =
1025 CreateSingleColumnLayout(view, kFixedGaiaViewWidth);
1026
1027 // Adds title.
1028 views::View* padded_title = new views::View();
1029 int available_width = kFixedGaiaViewWidth - 2 * views::kButtonHEdgeMarginNew;
1030 views::GridLayout* padded_layout = CreateSingleColumnLayout(
1031 padded_title, available_width);
1032 padded_layout->SetInsets(views::kButtonVEdgeMarginNew,
1033 views::kButtonHEdgeMarginNew,
1034 views::kButtonVEdgeMarginNew,
1035 views::kButtonHEdgeMarginNew);
1036 padded_layout->StartRow(1, 0);
1037 padded_layout->AddView(new TitleCard(
1038 add_secondary_account ? IDS_PROFILES_GAIA_ADD_ACCOUNT_TITLE :
1039 IDS_PROFILES_GAIA_SIGNIN_TITLE,
1040 this, &gaia_signin_cancel_button_));
1041
1042 layout->StartRow(1, 0);
1043 layout->AddView(padded_title);
1044 layout->StartRow(1, 0);
1045 layout->AddView(new views::Separator(views::Separator::HORIZONTAL));
1046
1047 // Adds Gaia signin webview
1048 Profile* profile = browser_->profile();
1049 views::WebView* web_view = new views::WebView(profile);
1050 signin::Source source = add_secondary_account ?
1051 signin::SOURCE_AVATAR_BUBBLE_ADD_ACCOUNT :
1052 signin::SOURCE_AVATAR_BUBBLE_SIGN_IN;
1053 GURL url(signin::GetPromoURL(
1054 source, false /* auto_close */, true /* is_constrained */));
1055 web_view->LoadInitialURL(url);
1056 web_view->SetPreferredSize(
1057 gfx::Size(kFixedGaiaViewWidth, kFixedGaiaViewHeight));
1058
1059 layout->StartRow(1, 0);
1060 layout->AddView(web_view);
1061
1062 return view;
1063 }
1064
1065 views::View* ProfileChooserView::CreateAccountRemovalView() {
1066 views::View* view = new views::View();
1067 views::GridLayout* layout = CreateSingleColumnLayout(
1068 view, kFixedAccountRemovalViewWidth - 2 * views::kButtonHEdgeMarginNew);
1069 layout->SetInsets(views::kButtonVEdgeMarginNew,
1070 views::kButtonHEdgeMarginNew,
1071 views::kButtonVEdgeMarginNew,
1072 views::kButtonHEdgeMarginNew);
1073
1074 // Adds title.
1075 layout->StartRow(1, 0);
1076 layout->AddView(new TitleCard(IDS_PROFILES_ACCOUNT_REMOVAL_TITLE, this,
1077 &account_removal_cancel_button_));
1078 layout->StartRowWithPadding(1, 0, 0, views::kRelatedControlVerticalSpacing);
1079 layout->AddView(new views::Separator(views::Separator::HORIZONTAL));
1080
1081 const std::string& primary_account = SigninManagerFactory::GetForProfile(
1082 browser_->profile())->GetAuthenticatedUsername();
1083 bool is_primary_account = primary_account == account_id_to_remove_;
1084
1085 // Adds main text.
1086 views::Label* content_label = new views::Label(is_primary_account ?
1087 l10n_util::GetStringFUTF16(IDS_PROFILES_PRIMARY_ACCOUNT_REMOVAL_TEXT,
1088 base::UTF8ToUTF16(account_id_to_remove_)) :
1089 l10n_util::GetStringUTF16(IDS_PROFILES_ACCOUNT_REMOVAL_TEXT));
1090
1091 content_label->SetMultiLine(true);
1092 content_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
1093 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
1094 const gfx::FontList& small_font_list =
1095 rb->GetFontList(ui::ResourceBundle::SmallFont);
1096 content_label->SetFontList(small_font_list);
1097 layout->StartRowWithPadding(1, 0, 0, views::kUnrelatedControlVerticalSpacing);
1098 layout->AddView(content_label);
1099
1100 // Adds button.
1101 if (!is_primary_account) {
1102 remove_account_and_relaunch_button_ = new views::BlueButton(
1103 this, l10n_util::GetStringUTF16(IDS_PROFILES_ACCOUNT_REMOVAL_BUTTON));
1104 remove_account_and_relaunch_button_->SetHorizontalAlignment(
1105 gfx::ALIGN_CENTER);
1106 layout->StartRowWithPadding(
1107 1, 0, 0, views::kUnrelatedControlVerticalSpacing);
1108 layout->AddView(remove_account_and_relaunch_button_);
1109 } else {
1110 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
1111 }
1112
1113 return view;
1114 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/profile_chooser_view.h ('k') | chrome/browser/ui/views/profile_reset_bubble_view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698