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