Home | History | Annotate | Download | only in profiles
      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/browser_process.h"
     10 #include "chrome/browser/lifetime/application_lifetime.h"
     11 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
     12 #include "chrome/browser/profiles/profile_info_cache.h"
     13 #include "chrome/browser/profiles/profile_manager.h"
     14 #include "chrome/browser/profiles/profile_metrics.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_header_helper.h"
     19 #include "chrome/browser/signin/signin_manager_factory.h"
     20 #include "chrome/browser/signin/signin_promo.h"
     21 #include "chrome/browser/ui/browser.h"
     22 #include "chrome/browser/ui/browser_commands.h"
     23 #include "chrome/browser/ui/browser_dialogs.h"
     24 #include "chrome/browser/ui/chrome_pages.h"
     25 #include "chrome/browser/ui/singleton_tabs.h"
     26 #include "chrome/browser/ui/views/profiles/user_manager_view.h"
     27 #include "chrome/common/pref_names.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_error_controller.h"
     32 #include "components/signin/core/browser/signin_manager.h"
     33 #include "components/signin/core/common/profile_management_switches.h"
     34 #include "grit/chromium_strings.h"
     35 #include "grit/generated_resources.h"
     36 #include "grit/theme_resources.h"
     37 #include "third_party/skia/include/core/SkColor.h"
     38 #include "ui/base/l10n/l10n_util.h"
     39 #include "ui/base/resource/resource_bundle.h"
     40 #include "ui/gfx/canvas.h"
     41 #include "ui/gfx/image/image.h"
     42 #include "ui/gfx/image/image_skia.h"
     43 #include "ui/gfx/path.h"
     44 #include "ui/gfx/skia_util.h"
     45 #include "ui/gfx/text_elider.h"
     46 #include "ui/native_theme/native_theme.h"
     47 #include "ui/views/controls/button/blue_button.h"
     48 #include "ui/views/controls/button/image_button.h"
     49 #include "ui/views/controls/button/label_button.h"
     50 #include "ui/views/controls/button/menu_button.h"
     51 #include "ui/views/controls/label.h"
     52 #include "ui/views/controls/link.h"
     53 #include "ui/views/controls/separator.h"
     54 #include "ui/views/controls/styled_label.h"
     55 #include "ui/views/controls/textfield/textfield.h"
     56 #include "ui/views/controls/webview/webview.h"
     57 #include "ui/views/layout/grid_layout.h"
     58 #include "ui/views/layout/layout_constants.h"
     59 #include "ui/views/widget/widget.h"
     60 
     61 namespace {
     62 
     63 // Helpers --------------------------------------------------------------------
     64 
     65 const int kFixedMenuWidth = 250;
     66 const int kButtonHeight = 29;
     67 const int kProfileAvatarTutorialShowMax = 1;
     68 const int kFixedGaiaViewHeight = 400;
     69 const int kFixedGaiaViewWidth = 360;
     70 const int kFixedAccountRemovalViewWidth = 280;
     71 const int kFixedEndPreviewViewWidth = 280;
     72 const int kLargeImageSide = 88;
     73 
     74 // Creates a GridLayout with a single column. This ensures that all the child
     75 // views added get auto-expanded to fill the full width of the bubble.
     76 views::GridLayout* CreateSingleColumnLayout(views::View* view, int width) {
     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::FIXED, width, width);
     83   return layout;
     84 }
     85 
     86 views::Link* CreateLink(const base::string16& link_text,
     87                         views::LinkListener* listener) {
     88   views::Link* link_button = new views::Link(link_text);
     89   link_button->SetHorizontalAlignment(gfx::ALIGN_LEFT);
     90   link_button->SetUnderline(false);
     91   link_button->set_listener(listener);
     92   return link_button;
     93 }
     94 
     95 gfx::ImageSkia CreateSquarePlaceholderImage(int size) {
     96   SkBitmap bitmap;
     97   bitmap.setConfig(SkBitmap::kA8_Config, size, size);
     98   bitmap.allocPixels();
     99   bitmap.eraseARGB(0, 0, 0, 0);
    100   return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
    101 }
    102 
    103 bool HasAuthError(Profile* profile) {
    104   const SigninErrorController* error =
    105       profiles::GetSigninErrorController(profile);
    106   return error && error->HasError();
    107 }
    108 
    109 std::string GetAuthErrorAccountId(Profile* profile) {
    110   const SigninErrorController* error =
    111       profiles::GetSigninErrorController(profile);
    112   if (!error)
    113     return std::string();
    114 
    115   return error->error_account_id();
    116 }
    117 
    118 std::string GetAuthErrorUsername(Profile* profile) {
    119   const SigninErrorController* error =
    120       profiles::GetSigninErrorController(profile);
    121   if (!error)
    122     return std::string();
    123 
    124   return error->error_username();
    125 }
    126 
    127 // BackgroundColorHoverButton -------------------------------------------------
    128 
    129 // A custom button that allows for setting a background color when hovered over.
    130 class BackgroundColorHoverButton : public views::LabelButton {
    131  public:
    132   BackgroundColorHoverButton(views::ButtonListener* listener,
    133                              const base::string16& text,
    134                              const gfx::ImageSkia& normal_icon,
    135                              const gfx::ImageSkia& hover_icon);
    136   virtual ~BackgroundColorHoverButton();
    137 
    138  private:
    139   // views::LabelButton:
    140   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
    141 
    142   DISALLOW_COPY_AND_ASSIGN(BackgroundColorHoverButton);
    143 };
    144 
    145 BackgroundColorHoverButton::BackgroundColorHoverButton(
    146     views::ButtonListener* listener,
    147     const base::string16& text,
    148     const gfx::ImageSkia& normal_icon,
    149     const gfx::ImageSkia& hover_icon)
    150     : views::LabelButton(listener, text) {
    151   SetBorder(views::Border::CreateEmptyBorder(0, views::kButtonHEdgeMarginNew,
    152                                              0, views::kButtonHEdgeMarginNew));
    153   set_min_size(gfx::Size(0, kButtonHeight));
    154   SetImage(STATE_NORMAL, normal_icon);
    155   SetImage(STATE_HOVERED, hover_icon);
    156   SetImage(STATE_PRESSED, hover_icon);
    157 }
    158 
    159 BackgroundColorHoverButton::~BackgroundColorHoverButton() {}
    160 
    161 void BackgroundColorHoverButton::OnPaint(gfx::Canvas* canvas) {
    162   if ((state() == STATE_PRESSED) || (state() == STATE_HOVERED) || HasFocus()) {
    163     canvas->DrawColor(GetNativeTheme()->GetSystemColor(
    164         ui::NativeTheme::kColorId_ButtonHoverBackgroundColor));
    165   }
    166   LabelButton::OnPaint(canvas);
    167 }
    168 
    169 // SizedContainer -------------------------------------------------
    170 
    171 // A simple container view that takes an explicit preferred size.
    172 class SizedContainer : public views::View {
    173  public:
    174   explicit SizedContainer(const gfx::Size& preferred_size)
    175       : preferred_size_(preferred_size) {}
    176 
    177   virtual gfx::Size GetPreferredSize() const OVERRIDE {
    178     return preferred_size_;
    179   }
    180 
    181  private:
    182   gfx::Size preferred_size_;
    183 };
    184 
    185 }  // namespace
    186 
    187 
    188 // EditableProfilePhoto -------------------------------------------------
    189 
    190 // A custom Image control that shows a "change" button when moused over.
    191 class EditableProfilePhoto : public views::ImageView {
    192  public:
    193   EditableProfilePhoto(views::ButtonListener* listener,
    194                        const gfx::Image& icon,
    195                        bool is_editing_allowed,
    196                        const gfx::Rect& bounds)
    197       : views::ImageView(),
    198         change_photo_button_(NULL) {
    199     gfx::Image image = profiles::GetSizedAvatarIcon(
    200         icon, true, kLargeImageSide, kLargeImageSide);
    201     SetImage(image.ToImageSkia());
    202     SetBoundsRect(bounds);
    203 
    204     // Calculate the circular mask that will be used to display the photo.
    205     circular_mask_.addCircle(SkIntToScalar(bounds.width() / 2),
    206                              SkIntToScalar(bounds.height() / 2),
    207                              SkIntToScalar(bounds.width() / 2));
    208 
    209     if (!is_editing_allowed)
    210       return;
    211 
    212     set_notify_enter_exit_on_child(true);
    213 
    214     // Button overlay that appears when hovering over the image.
    215     change_photo_button_ = new views::LabelButton(listener, base::string16());
    216     change_photo_button_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
    217     change_photo_button_->SetBorder(views::Border::NullBorder());
    218 
    219     const SkColor kBackgroundColor = SkColorSetARGB(65, 255, 255, 255);
    220     change_photo_button_->set_background(
    221         views::Background::CreateSolidBackground(kBackgroundColor));
    222     change_photo_button_->SetImage(views::LabelButton::STATE_NORMAL,
    223         *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
    224             IDR_ICON_PROFILES_EDIT_CAMERA));
    225 
    226     change_photo_button_->SetSize(bounds.size());
    227     change_photo_button_->SetVisible(false);
    228     AddChildView(change_photo_button_);
    229   }
    230 
    231   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
    232     // Display the profile picture as a circle.
    233     canvas->ClipPath(circular_mask_, true);
    234     views::ImageView::OnPaint(canvas);
    235   }
    236 
    237   virtual void PaintChildren(gfx::Canvas* canvas,
    238                              const views::CullSet& cull_set) OVERRIDE {
    239     // Display any children (the "change photo" overlay) as a circle.
    240     canvas->ClipPath(circular_mask_, true);
    241     View::PaintChildren(canvas, cull_set);
    242   }
    243 
    244   views::LabelButton* change_photo_button() { return change_photo_button_; }
    245 
    246  private:
    247   // views::View:
    248   virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE {
    249     if (change_photo_button_)
    250       change_photo_button_->SetVisible(true);
    251   }
    252 
    253   virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE {
    254     if (change_photo_button_)
    255       change_photo_button_->SetVisible(false);
    256   }
    257 
    258   gfx::Path circular_mask_;
    259 
    260   // Button that is shown when hovering over the image view. Can be NULL if
    261   // the photo isn't allowed to be edited (e.g. for guest profiles).
    262   views::LabelButton* change_photo_button_;
    263 
    264   DISALLOW_COPY_AND_ASSIGN(EditableProfilePhoto);
    265 };
    266 
    267 
    268 // EditableProfileName -------------------------------------------------
    269 
    270 // A custom text control that turns into a textfield for editing when clicked.
    271 class EditableProfileName : public views::LabelButton,
    272                             public views::ButtonListener {
    273  public:
    274   EditableProfileName(views::TextfieldController* controller,
    275                       const base::string16& text,
    276                       bool is_editing_allowed)
    277       : views::LabelButton(this, text),
    278         profile_name_textfield_(NULL) {
    279     ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
    280     const gfx::FontList& medium_font_list =
    281         rb->GetFontList(ui::ResourceBundle::MediumFont);
    282     SetFontList(medium_font_list);
    283     SetHorizontalAlignment(gfx::ALIGN_CENTER);
    284 
    285     if (!is_editing_allowed) {
    286       SetBorder(views::Border::CreateEmptyBorder(2, 0, 2, 0));
    287       return;
    288     }
    289 
    290     // Show an "edit" pencil icon when hovering over. In the default state,
    291     // we need to create an empty placeholder of the correct size, so that
    292     // the text doesn't jump around when the hovered icon appears.
    293     gfx::ImageSkia hover_image =
    294         *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_EDIT_HOVER);
    295     SetImage(STATE_NORMAL, CreateSquarePlaceholderImage(hover_image.width()));
    296     SetImage(STATE_HOVERED, hover_image);
    297     SetImage(STATE_PRESSED,
    298              *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_EDIT_PRESSED));
    299     // To center the text, we need to offest it by the width of the icon we
    300     // are adding. We need to also add a small top/bottom padding to account
    301     // for the textfield's border.
    302     SetBorder(views::Border::CreateEmptyBorder(2, hover_image.width(), 2, 0));
    303 
    304     // Textfield that overlaps the button.
    305     profile_name_textfield_ = new views::Textfield();
    306     profile_name_textfield_->set_controller(controller);
    307     profile_name_textfield_->SetFontList(medium_font_list);
    308     profile_name_textfield_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
    309 
    310     profile_name_textfield_->SetVisible(false);
    311     AddChildView(profile_name_textfield_);
    312   }
    313 
    314   views::Textfield* profile_name_textfield() {
    315     return profile_name_textfield_;
    316   }
    317 
    318   // Hide the editable textfield to show the profile name button instead.
    319   void ShowReadOnlyView() {
    320     if (profile_name_textfield_)
    321       profile_name_textfield_->SetVisible(false);
    322   }
    323 
    324  private:
    325   // views::ButtonListener:
    326   virtual void ButtonPressed(views::Button* sender,
    327                             const ui::Event& event) OVERRIDE {
    328     if (profile_name_textfield_) {
    329       profile_name_textfield_->SetVisible(true);
    330       profile_name_textfield_->SetText(GetText());
    331       profile_name_textfield_->SelectAll(false);
    332       profile_name_textfield_->RequestFocus();
    333     }
    334   }
    335 
    336   // views::LabelButton:
    337   virtual bool OnKeyReleased(const ui::KeyEvent& event) OVERRIDE {
    338     // Override CustomButton's implementation, which presses the button when
    339     // you press space and clicks it when you release space, as the space can be
    340     // part of the new profile name typed in the textfield.
    341     return false;
    342   }
    343 
    344   virtual void Layout() OVERRIDE {
    345     if (profile_name_textfield_)
    346       profile_name_textfield_->SetBounds(0, 0, width(), height());
    347     // This layout trick keeps the text left-aligned and the icon right-aligned.
    348     SetHorizontalAlignment(gfx::ALIGN_RIGHT);
    349     views::LabelButton::Layout();
    350     label()->SetHorizontalAlignment(gfx::ALIGN_CENTER);
    351   }
    352 
    353   // Textfield that is shown when editing the profile name. Can be NULL if
    354   // the profile name isn't allowed to be edited (e.g. for guest profiles).
    355   views::Textfield* profile_name_textfield_;
    356 
    357   DISALLOW_COPY_AND_ASSIGN(EditableProfileName);
    358 };
    359 
    360 // A title card with one back button right aligned and one label center aligned.
    361 class TitleCard : public views::View {
    362  public:
    363   TitleCard(int message_id, views::ButtonListener* listener,
    364              views::ImageButton** back_button) {
    365     back_button_ = new views::ImageButton(listener);
    366     back_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT,
    367                                     views::ImageButton::ALIGN_MIDDLE);
    368     ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
    369     back_button_->SetImage(views::ImageButton::STATE_NORMAL,
    370                            rb->GetImageSkiaNamed(IDR_BACK));
    371     back_button_->SetImage(views::ImageButton::STATE_HOVERED,
    372                            rb->GetImageSkiaNamed(IDR_BACK_H));
    373     back_button_->SetImage(views::ImageButton::STATE_PRESSED,
    374                            rb->GetImageSkiaNamed(IDR_BACK_P));
    375     back_button_->SetImage(views::ImageButton::STATE_DISABLED,
    376                            rb->GetImageSkiaNamed(IDR_BACK_D));
    377     *back_button = back_button_;
    378 
    379     title_label_ = new views::Label(l10n_util::GetStringUTF16(message_id));
    380     title_label_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
    381     const gfx::FontList& medium_font_list =
    382         rb->GetFontList(ui::ResourceBundle::MediumFont);
    383     title_label_->SetFontList(medium_font_list);
    384 
    385     AddChildView(back_button_);
    386     AddChildView(title_label_);
    387   }
    388 
    389   // Creates a new view that has the |title_card| with padding at the top, an
    390   // edge-to-edge separator below, and the specified |view| at the bottom.
    391   static views::View* AddPaddedTitleCard(views::View* view,
    392                                          TitleCard* title_card,
    393                                          int width) {
    394     views::View* titled_view = new views::View();
    395     views::GridLayout* layout = new views::GridLayout(titled_view);
    396     titled_view->SetLayoutManager(layout);
    397 
    398     // Column set 0 is a single column layout with horizontal padding at left
    399     // and right, and column set 1 is a single column layout with no padding.
    400     views::ColumnSet* columns = layout->AddColumnSet(0);
    401     columns->AddPaddingColumn(1, views::kButtonHEdgeMarginNew);
    402     int available_width = width - 2 * views::kButtonHEdgeMarginNew;
    403     columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
    404         views::GridLayout::FIXED, available_width, available_width);
    405     columns->AddPaddingColumn(1, views::kButtonHEdgeMarginNew);
    406     layout->AddColumnSet(1)->AddColumn(views::GridLayout::FILL,
    407         views::GridLayout::FILL, 0,views::GridLayout::FIXED, width, width);
    408 
    409     layout->StartRowWithPadding(1, 0, 0, views::kButtonVEdgeMarginNew);
    410     layout->AddView(title_card);
    411     layout->StartRowWithPadding(1, 1, 0, views::kRelatedControlVerticalSpacing);
    412     layout->AddView(new views::Separator(views::Separator::HORIZONTAL));
    413 
    414     layout->StartRow(1, 1);
    415     layout->AddView(view);
    416 
    417     return titled_view;
    418   }
    419 
    420  private:
    421   virtual void Layout() OVERRIDE{
    422     back_button_->SetBounds(
    423         0, 0, back_button_->GetPreferredSize().width(), height());
    424     title_label_->SetBoundsRect(GetContentsBounds());
    425   }
    426 
    427   virtual gfx::Size GetPreferredSize() const OVERRIDE{
    428     int height = std::max(title_label_->GetPreferredSize().height(),
    429         back_button_->GetPreferredSize().height());
    430     return gfx::Size(width(), height);
    431   }
    432 
    433   views::ImageButton* back_button_;
    434   views::Label* title_label_;
    435 
    436   DISALLOW_COPY_AND_ASSIGN(TitleCard);
    437 };
    438 
    439 // ProfileChooserView ---------------------------------------------------------
    440 
    441 // static
    442 ProfileChooserView* ProfileChooserView::profile_bubble_ = NULL;
    443 bool ProfileChooserView::close_on_deactivate_for_testing_ = true;
    444 
    445 // static
    446 void ProfileChooserView::ShowBubble(
    447     profiles::BubbleViewMode view_mode,
    448     const signin::ManageAccountsParams& manage_accounts_params,
    449     views::View* anchor_view,
    450     views::BubbleBorder::Arrow arrow,
    451     views::BubbleBorder::BubbleAlignment border_alignment,
    452     Browser* browser) {
    453   if (IsShowing())
    454     return;
    455 
    456   profile_bubble_ = new ProfileChooserView(anchor_view, arrow, browser,
    457       view_mode, manage_accounts_params.service_type);
    458   views::BubbleDelegateView::CreateBubble(profile_bubble_);
    459   profile_bubble_->set_close_on_deactivate(close_on_deactivate_for_testing_);
    460   profile_bubble_->SetAlignment(border_alignment);
    461   profile_bubble_->GetWidget()->Show();
    462   profile_bubble_->SetArrowPaintType(views::BubbleBorder::PAINT_NONE);
    463 }
    464 
    465 // static
    466 bool ProfileChooserView::IsShowing() {
    467   return profile_bubble_ != NULL;
    468 }
    469 
    470 // static
    471 void ProfileChooserView::Hide() {
    472   if (IsShowing())
    473     profile_bubble_->GetWidget()->Close();
    474 }
    475 
    476 ProfileChooserView::ProfileChooserView(views::View* anchor_view,
    477                                        views::BubbleBorder::Arrow arrow,
    478                                        Browser* browser,
    479                                        profiles::BubbleViewMode view_mode,
    480                                        signin::GAIAServiceType service_type)
    481     : BubbleDelegateView(anchor_view, arrow),
    482       browser_(browser),
    483       view_mode_(view_mode),
    484       tutorial_mode_(profiles::TUTORIAL_MODE_NONE),
    485       gaia_service_type_(service_type) {
    486   // Reset the default margins inherited from the BubbleDelegateView.
    487   set_margins(gfx::Insets());
    488 
    489   ResetView();
    490 
    491   avatar_menu_.reset(new AvatarMenu(
    492       &g_browser_process->profile_manager()->GetProfileInfoCache(),
    493       this,
    494       browser_));
    495   avatar_menu_->RebuildMenu();
    496 
    497   ProfileOAuth2TokenService* oauth2_token_service =
    498       ProfileOAuth2TokenServiceFactory::GetForProfile(browser_->profile());
    499   if (oauth2_token_service)
    500     oauth2_token_service->AddObserver(this);
    501 }
    502 
    503 ProfileChooserView::~ProfileChooserView() {
    504   ProfileOAuth2TokenService* oauth2_token_service =
    505       ProfileOAuth2TokenServiceFactory::GetForProfile(browser_->profile());
    506   if (oauth2_token_service)
    507     oauth2_token_service->RemoveObserver(this);
    508 }
    509 
    510 void ProfileChooserView::ResetView() {
    511   question_mark_button_ = NULL;
    512   manage_accounts_link_ = NULL;
    513   signin_current_profile_link_ = NULL;
    514   users_button_ = NULL;
    515   lock_button_ = NULL;
    516   add_account_link_ = NULL;
    517   current_profile_photo_ = NULL;
    518   current_profile_name_ = NULL;
    519   tutorial_ok_button_ = NULL;
    520   tutorial_learn_more_link_ = NULL;
    521   tutorial_enable_new_profile_management_button_ = NULL;
    522   tutorial_end_preview_link_ = NULL;
    523   tutorial_send_feedback_button_ = NULL;
    524   end_preview_and_relaunch_button_ = NULL;
    525   end_preview_cancel_button_ = NULL;
    526   remove_account_button_ = NULL;
    527   account_removal_cancel_button_ = NULL;
    528   gaia_signin_cancel_button_ = NULL;
    529   open_other_profile_indexes_map_.clear();
    530   delete_account_button_map_.clear();
    531   reauth_account_button_map_.clear();
    532   tutorial_mode_ = profiles::TUTORIAL_MODE_NONE;
    533 }
    534 
    535 void ProfileChooserView::Init() {
    536   // If view mode is PROFILE_CHOOSER but there is an auth error, force
    537   // ACCOUNT_MANAGEMENT mode.
    538   if (view_mode_ == profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER &&
    539       HasAuthError(browser_->profile())) {
    540     view_mode_ = profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT;
    541   }
    542 
    543   ShowView(view_mode_, avatar_menu_.get());
    544 }
    545 
    546 void ProfileChooserView::OnAvatarMenuChanged(
    547     AvatarMenu* avatar_menu) {
    548   // Refresh the view with the new menu. We can't just update the local copy
    549   // as this may have been triggered by a sign out action, in which case
    550   // the view is being destroyed.
    551   ShowView(profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER, avatar_menu);
    552 }
    553 
    554 void ProfileChooserView::OnRefreshTokenAvailable(
    555     const std::string& account_id) {
    556   // Refresh the account management view when a new account is added to the
    557   // profile.
    558   if (view_mode_ == profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT ||
    559       view_mode_ == profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN ||
    560       view_mode_ == profiles::BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT ||
    561       view_mode_ == profiles::BUBBLE_VIEW_MODE_GAIA_REAUTH) {
    562     ShowView(profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT, avatar_menu_.get());
    563   }
    564 }
    565 
    566 void ProfileChooserView::OnRefreshTokenRevoked(const std::string& account_id) {
    567   // Refresh the account management view when an account is removed from the
    568   // profile.
    569   if (view_mode_ == profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT)
    570     ShowView(profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT, avatar_menu_.get());
    571 }
    572 
    573 void ProfileChooserView::ShowView(profiles::BubbleViewMode view_to_display,
    574                                   AvatarMenu* avatar_menu) {
    575   // The account management view should only be displayed if the active profile
    576   // is signed in.
    577   if (view_to_display == profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT) {
    578     const AvatarMenu::Item& active_item = avatar_menu->GetItemAt(
    579         avatar_menu->GetActiveProfileIndex());
    580     DCHECK(active_item.signed_in);
    581   }
    582 
    583   // Records the last tutorial mode.
    584   profiles::TutorialMode last_tutorial_mode = tutorial_mode_;
    585   ResetView();
    586   RemoveAllChildViews(true);
    587   view_mode_ = view_to_display;
    588 
    589   views::GridLayout* layout;
    590   views::View* sub_view;
    591   switch (view_mode_) {
    592     case profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN:
    593     case profiles::BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT:
    594     case profiles::BUBBLE_VIEW_MODE_GAIA_REAUTH:
    595       layout = CreateSingleColumnLayout(this, kFixedGaiaViewWidth);
    596       sub_view = CreateGaiaSigninView();
    597       break;
    598     case profiles::BUBBLE_VIEW_MODE_ACCOUNT_REMOVAL:
    599       layout = CreateSingleColumnLayout(this, kFixedAccountRemovalViewWidth);
    600       sub_view = CreateAccountRemovalView();
    601       break;
    602     case profiles::BUBBLE_VIEW_MODE_END_PREVIEW:
    603       layout = CreateSingleColumnLayout(this, kFixedEndPreviewViewWidth);
    604       sub_view = CreateEndPreviewView();
    605       break;
    606     default:
    607       layout = CreateSingleColumnLayout(this, kFixedMenuWidth);
    608       sub_view = CreateProfileChooserView(avatar_menu, last_tutorial_mode);
    609   }
    610   sub_view->set_background(views::Background::CreateSolidBackground(
    611       GetNativeTheme()->GetSystemColor(
    612           ui::NativeTheme::kColorId_DialogBackground)));
    613 
    614   layout->StartRow(1, 0);
    615   layout->AddView(sub_view);
    616   Layout();
    617   if (GetBubbleFrameView())
    618     SizeToContents();
    619 }
    620 
    621 void ProfileChooserView::WindowClosing() {
    622   DCHECK_EQ(profile_bubble_, this);
    623   profile_bubble_ = NULL;
    624 }
    625 
    626 void ProfileChooserView::ButtonPressed(views::Button* sender,
    627                                        const ui::Event& event) {
    628   // Disable button after clicking so that it doesn't get clicked twice and
    629   // start a second action... which can crash Chrome.  But don't disable if it
    630   // has no parent (like in tests) because that will also crash.
    631   if (sender->parent())
    632     sender->SetEnabled(false);
    633 
    634   if (sender == users_button_) {
    635     profiles::ShowUserManagerMaybeWithTutorial(browser_->profile());
    636     // If this is a guest session, also close all the guest browser windows.
    637     if (browser_->profile()->IsGuestSession())
    638       profiles::CloseGuestProfileWindows();
    639   } else if (sender == lock_button_) {
    640     profiles::LockProfile(browser_->profile());
    641     PostActionPerformed(ProfileMetrics::PROFILE_DESKTOP_MENU_LOCK);
    642   } else if (sender == tutorial_ok_button_) {
    643     // If the user manually dismissed the tutorial, never show it again by
    644     // setting the number of times shown to the maximum plus 1, so that later we
    645     // could distinguish between the dismiss case and the case when the tutorial
    646     // is indeed shown for the maximum number of times.
    647     browser_->profile()->GetPrefs()->SetInteger(
    648         prefs::kProfileAvatarTutorialShown, kProfileAvatarTutorialShowMax + 1);
    649 
    650     ProfileMetrics::LogProfileUpgradeEnrollment(
    651         ProfileMetrics::PROFILE_ENROLLMENT_CLOSE_WELCOME_CARD);
    652     ShowView(profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER, avatar_menu_.get());
    653   } else if (sender == tutorial_enable_new_profile_management_button_) {
    654     ProfileMetrics::LogProfileUpgradeEnrollment(
    655         ProfileMetrics::PROFILE_ENROLLMENT_ACCEPT_NEW_PROFILE_MGMT);
    656     profiles::EnableNewProfileManagementPreview(browser_->profile());
    657   } else if (sender == remove_account_button_) {
    658     RemoveAccount();
    659   } else if (sender == account_removal_cancel_button_) {
    660     account_id_to_remove_.clear();
    661     ShowView(profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT, avatar_menu_.get());
    662   } else if (sender == gaia_signin_cancel_button_) {
    663     std::string primary_account =
    664         SigninManagerFactory::GetForProfile(browser_->profile())->
    665         GetAuthenticatedUsername();
    666     ShowView(primary_account.empty() ?
    667                  profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER :
    668                  profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT,
    669              avatar_menu_.get());
    670   } else if (sender == question_mark_button_) {
    671     tutorial_mode_ = profiles::TUTORIAL_MODE_SEND_FEEDBACK;
    672     ShowView(profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER, avatar_menu_.get());
    673   } else if (sender == tutorial_send_feedback_button_) {
    674     ProfileMetrics::LogProfileUpgradeEnrollment(
    675         ProfileMetrics::PROFILE_ENROLLMENT_SEND_FEEDBACK);
    676     chrome::OpenFeedbackDialog(browser_);
    677   } else if (sender == end_preview_and_relaunch_button_) {
    678     ProfileMetrics::LogProfileUpgradeEnrollment(
    679         ProfileMetrics::PROFILE_ENROLLMENT_DISABLE_NEW_PROFILE_MGMT);
    680     profiles::DisableNewProfileManagementPreview(browser_->profile());
    681   } else if (sender == end_preview_cancel_button_) {
    682     tutorial_mode_ = profiles::TUTORIAL_MODE_SEND_FEEDBACK;
    683     ShowView(profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER, avatar_menu_.get());
    684   } else if (current_profile_photo_ &&
    685              sender == current_profile_photo_->change_photo_button()) {
    686     avatar_menu_->EditProfile(avatar_menu_->GetActiveProfileIndex());
    687     PostActionPerformed(ProfileMetrics::PROFILE_DESKTOP_MENU_EDIT_IMAGE);
    688   } else if (sender == signin_current_profile_link_) {
    689     // Only show the inline signin if the new UI flag is flipped. Otherwise,
    690     // use the tab signin page.
    691     if (switches::IsNewProfileManagement())
    692       ShowView(profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN, avatar_menu_.get());
    693     else
    694       chrome::ShowBrowserSignin(browser_, signin::SOURCE_MENU);
    695   } else {
    696     // Either one of the "other profiles", or one of the profile accounts
    697     // buttons was pressed.
    698     ButtonIndexes::const_iterator profile_match =
    699         open_other_profile_indexes_map_.find(sender);
    700     if (profile_match != open_other_profile_indexes_map_.end()) {
    701       avatar_menu_->SwitchToProfile(
    702           profile_match->second,
    703           ui::DispositionFromEventFlags(event.flags()) == NEW_WINDOW,
    704           ProfileMetrics::SWITCH_PROFILE_ICON);
    705     } else {
    706       // This was a profile accounts button.
    707       AccountButtonIndexes::const_iterator account_match =
    708           delete_account_button_map_.find(sender);
    709       if (account_match != delete_account_button_map_.end()) {
    710         account_id_to_remove_ = account_match->second;
    711         ShowView(profiles::BUBBLE_VIEW_MODE_ACCOUNT_REMOVAL,
    712             avatar_menu_.get());
    713       } else {
    714         account_match = reauth_account_button_map_.find(sender);
    715         DCHECK(account_match != reauth_account_button_map_.end());
    716         ShowView(profiles::BUBBLE_VIEW_MODE_GAIA_REAUTH, avatar_menu_.get());
    717       }
    718     }
    719   }
    720 }
    721 
    722 void ProfileChooserView::RemoveAccount() {
    723   DCHECK(!account_id_to_remove_.empty());
    724   MutableProfileOAuth2TokenService* oauth2_token_service =
    725       ProfileOAuth2TokenServiceFactory::GetPlatformSpecificForProfile(
    726       browser_->profile());
    727   if (oauth2_token_service) {
    728     oauth2_token_service->RevokeCredentials(account_id_to_remove_);
    729     PostActionPerformed(ProfileMetrics::PROFILE_DESKTOP_MENU_REMOVE_ACCT);
    730   }
    731   account_id_to_remove_.clear();
    732 
    733   ShowView(profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT, avatar_menu_.get());
    734 }
    735 
    736 void ProfileChooserView::LinkClicked(views::Link* sender, int event_flags) {
    737   if (sender == manage_accounts_link_) {
    738     // This link can either mean show/hide the account management view,
    739     // depending on which view it is displayed. ShowView() will DCHECK if
    740     // the account management view is displayed for non signed-in users.
    741     ShowView(
    742         view_mode_ == profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT ?
    743             profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER :
    744             profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT,
    745         avatar_menu_.get());
    746   } else if (sender == add_account_link_) {
    747     ShowView(profiles::BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT, avatar_menu_.get());
    748     PostActionPerformed(ProfileMetrics::PROFILE_DESKTOP_MENU_ADD_ACCT);
    749   } else if (sender == tutorial_learn_more_link_) {
    750     ProfileMetrics::LogProfileUpgradeEnrollment(
    751         ProfileMetrics::PROFILE_ENROLLMENT_LAUNCH_LEARN_MORE);
    752     // TODO(guohui): update |learn_more_url| once it is decided.
    753     const GURL lear_more_url("https://support.google.com/chrome/?hl=en#to");
    754     chrome::NavigateParams params(
    755         browser_->profile(),
    756         lear_more_url,
    757         content::PAGE_TRANSITION_LINK);
    758     params.disposition = NEW_FOREGROUND_TAB;
    759     chrome::Navigate(&params);
    760   } else {
    761     DCHECK(sender == tutorial_end_preview_link_);
    762     ShowView(profiles::BUBBLE_VIEW_MODE_END_PREVIEW, avatar_menu_.get());
    763   }
    764 }
    765 
    766 void ProfileChooserView::StyledLabelLinkClicked(
    767     const gfx::Range& range, int event_flags) {
    768   chrome::ShowSettings(browser_);
    769 }
    770 
    771 bool ProfileChooserView::HandleKeyEvent(views::Textfield* sender,
    772                                         const ui::KeyEvent& key_event) {
    773   views::Textfield* name_textfield =
    774       current_profile_name_->profile_name_textfield();
    775   DCHECK(sender == name_textfield);
    776 
    777   if (key_event.key_code() == ui::VKEY_RETURN ||
    778       key_event.key_code() == ui::VKEY_TAB) {
    779     // Pressing Tab/Enter commits the new profile name, unless it's empty.
    780     base::string16 new_profile_name = name_textfield->text();
    781     if (new_profile_name.empty())
    782       return true;
    783 
    784     const AvatarMenu::Item& active_item = avatar_menu_->GetItemAt(
    785         avatar_menu_->GetActiveProfileIndex());
    786     Profile* profile = g_browser_process->profile_manager()->GetProfile(
    787         active_item.profile_path);
    788     DCHECK(profile);
    789 
    790     if (profile->IsSupervised())
    791       return true;
    792 
    793     profiles::UpdateProfileName(profile, new_profile_name);
    794     PostActionPerformed(ProfileMetrics::PROFILE_DESKTOP_MENU_EDIT_NAME);
    795     current_profile_name_->ShowReadOnlyView();
    796     return true;
    797   }
    798   return false;
    799 }
    800 
    801 void ProfileChooserView::PostActionPerformed(
    802     ProfileMetrics::ProfileDesktopMenu action_performed) {
    803   ProfileMetrics::LogProfileDesktopMenu(action_performed, gaia_service_type_);
    804   gaia_service_type_ = signin::GAIA_SERVICE_TYPE_NONE;
    805 }
    806 
    807 views::View* ProfileChooserView::CreateProfileChooserView(
    808     AvatarMenu* avatar_menu,
    809     profiles::TutorialMode last_tutorial_mode) {
    810   // TODO(guohui, noms): the view should be customized based on whether new
    811   // profile management preview is enabled or not.
    812 
    813   views::View* view = new views::View();
    814   views::GridLayout* layout = CreateSingleColumnLayout(view, kFixedMenuWidth);
    815   // Separate items into active and alternatives.
    816   Indexes other_profiles;
    817   views::View* tutorial_view = NULL;
    818   views::View* current_profile_view = NULL;
    819   views::View* current_profile_accounts = NULL;
    820   views::View* option_buttons_view = NULL;
    821   bool is_new_profile_management = switches::IsNewProfileManagement();
    822   for (size_t i = 0; i < avatar_menu->GetNumberOfItems(); ++i) {
    823     const AvatarMenu::Item& item = avatar_menu->GetItemAt(i);
    824     if (item.active) {
    825       option_buttons_view = CreateOptionsView(item.signed_in);
    826       current_profile_view = CreateCurrentProfileView(item, false);
    827       if (view_mode_ == profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER) {
    828         if (is_new_profile_management) {
    829           tutorial_view =
    830               last_tutorial_mode == profiles::TUTORIAL_MODE_SEND_FEEDBACK ?
    831               CreateSendPreviewFeedbackView() :
    832               CreatePreviewEnabledTutorialView(
    833                   item, last_tutorial_mode == profiles::TUTORIAL_MODE_WELCOME);
    834         } else {
    835           tutorial_view = CreateNewProfileManagementPreviewView();
    836         }
    837       } else {
    838         current_profile_accounts = CreateCurrentProfileAccountsView(item);
    839       }
    840     } else {
    841       other_profiles.push_back(i);
    842     }
    843   }
    844 
    845   if (tutorial_view) {
    846     // Be sure not to track the tutorial display on View refresh, and only count
    847     // the preview-promo view, shown when New Profile Management is off.
    848     if (tutorial_mode_ != last_tutorial_mode && !is_new_profile_management) {
    849       ProfileMetrics::LogProfileUpgradeEnrollment(
    850           ProfileMetrics::PROFILE_ENROLLMENT_SHOW_PREVIEW_PROMO);
    851     }
    852     layout->StartRow(1, 0);
    853     layout->AddView(tutorial_view);
    854   }
    855 
    856   if (!current_profile_view) {
    857     // Guest windows don't have an active profile.
    858     current_profile_view = CreateGuestProfileView();
    859     option_buttons_view = CreateOptionsView(false);
    860   }
    861 
    862   layout->StartRow(1, 0);
    863   layout->AddView(current_profile_view);
    864 
    865   if (view_mode_ != profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER) {
    866     DCHECK(current_profile_accounts);
    867     layout->StartRow(0, 0);
    868     layout->AddView(new views::Separator(views::Separator::HORIZONTAL));
    869     layout->StartRow(1, 0);
    870     layout->AddView(current_profile_accounts);
    871   }
    872 
    873   if (browser_->profile()->IsSupervised()) {
    874     layout->StartRow(0, 0);
    875     layout->AddView(new views::Separator(views::Separator::HORIZONTAL));
    876     layout->StartRow(1, 0);
    877     layout->AddView(CreateSupervisedUserDisclaimerView());
    878   }
    879 
    880   if (view_mode_ == profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER) {
    881     layout->StartRow(1, 0);
    882     if (switches::IsFastUserSwitching())
    883       layout->AddView(CreateOtherProfilesView(other_profiles));
    884   }
    885 
    886   layout->StartRow(0, 0);
    887   layout->AddView(new views::Separator(views::Separator::HORIZONTAL));
    888 
    889   // Option buttons. Only available with the new profile management flag.
    890   if (option_buttons_view) {
    891     layout->StartRow(0, 0);
    892     layout->AddView(option_buttons_view);
    893   }
    894 
    895   return view;
    896 }
    897 
    898 views::View* ProfileChooserView::CreatePreviewEnabledTutorialView(
    899     const AvatarMenu::Item& current_avatar_item,
    900     bool tutorial_shown) {
    901   if (!switches::IsNewProfileManagementPreviewEnabled())
    902     return NULL;
    903 
    904   Profile* profile = browser_->profile();
    905   const int show_count = profile->GetPrefs()->GetInteger(
    906       prefs::kProfileAvatarTutorialShown);
    907   // Do not show the tutorial if user has dismissed it.
    908   if (show_count > kProfileAvatarTutorialShowMax)
    909     return NULL;
    910 
    911   if (!tutorial_shown) {
    912     if (show_count == kProfileAvatarTutorialShowMax)
    913       return NULL;
    914     profile->GetPrefs()->SetInteger(
    915         prefs::kProfileAvatarTutorialShown, show_count + 1);
    916   }
    917 
    918   return CreateTutorialView(
    919       profiles::TUTORIAL_MODE_WELCOME,
    920       l10n_util::GetStringUTF16(IDS_PROFILES_PREVIEW_ENABLED_TUTORIAL_TITLE),
    921       l10n_util::GetStringUTF16(
    922           IDS_PROFILES_PREVIEW_ENABLED_TUTORIAL_CONTENT_TEXT),
    923       l10n_util::GetStringUTF16(IDS_PROFILES_PROFILE_TUTORIAL_LEARN_MORE),
    924       l10n_util::GetStringUTF16(IDS_PROFILES_TUTORIAL_OK_BUTTON),
    925       &tutorial_learn_more_link_,
    926       &tutorial_ok_button_);
    927 }
    928 
    929 views::View* ProfileChooserView::CreateSendPreviewFeedbackView() {
    930   return CreateTutorialView(
    931       profiles::TUTORIAL_MODE_SEND_FEEDBACK,
    932       l10n_util::GetStringUTF16(IDS_PROFILES_FEEDBACK_TUTORIAL_TITLE),
    933       l10n_util::GetStringUTF16(
    934           IDS_PROFILES_FEEDBACK_TUTORIAL_CONTENT_TEXT),
    935       l10n_util::GetStringUTF16(IDS_PROFILES_END_PREVIEW),
    936       l10n_util::GetStringUTF16(IDS_PROFILES_SEND_FEEDBACK_BUTTON),
    937       &tutorial_end_preview_link_,
    938       &tutorial_send_feedback_button_);
    939 }
    940 
    941 views::View* ProfileChooserView::CreateTutorialView(
    942     profiles::TutorialMode tutorial_mode,
    943     const base::string16& title_text,
    944     const base::string16& content_text,
    945     const base::string16& link_text,
    946     const base::string16& button_text,
    947     views::Link** link,
    948     views::LabelButton** button) {
    949   tutorial_mode_ = tutorial_mode;
    950 
    951   views::View* view = new views::View();
    952   view->set_background(views::Background::CreateSolidBackground(
    953       profiles::kAvatarTutorialBackgroundColor));
    954   views::GridLayout* layout = CreateSingleColumnLayout(view,
    955       kFixedMenuWidth - 2 * views::kButtonHEdgeMarginNew);
    956   layout->SetInsets(views::kButtonVEdgeMarginNew,
    957                     views::kButtonHEdgeMarginNew,
    958                     views::kButtonVEdgeMarginNew,
    959                     views::kButtonHEdgeMarginNew);
    960 
    961   // Adds title.
    962   views::Label* title_label = new views::Label(title_text);
    963   title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
    964   title_label->SetAutoColorReadabilityEnabled(false);
    965   title_label->SetEnabledColor(SK_ColorWHITE);
    966   title_label->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
    967       ui::ResourceBundle::MediumFont));
    968   layout->StartRow(1, 0);
    969   layout->AddView(title_label);
    970 
    971   // Adds body content.
    972   views::Label* content_label = new views::Label(content_text);
    973   content_label->SetMultiLine(true);
    974   content_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
    975   content_label->SetAutoColorReadabilityEnabled(false);
    976   content_label->SetEnabledColor(profiles::kAvatarTutorialContentTextColor);
    977   layout->StartRowWithPadding(1, 0, 0, views::kRelatedControlVerticalSpacing);
    978   layout->AddView(content_label);
    979 
    980   // Adds links and buttons.
    981   views::View* button_row = new views::View();
    982   views::GridLayout* button_layout = new views::GridLayout(button_row);
    983   views::ColumnSet* button_columns = button_layout->AddColumnSet(0);
    984   button_columns->AddColumn(views::GridLayout::LEADING,
    985       views::GridLayout::CENTER, 0, views::GridLayout::USE_PREF, 0, 0);
    986   button_columns->AddPaddingColumn(
    987       1, views::kUnrelatedControlHorizontalSpacing);
    988   button_columns->AddColumn(views::GridLayout::TRAILING,
    989       views::GridLayout::CENTER, 0, views::GridLayout::USE_PREF, 0, 0);
    990   button_row->SetLayoutManager(button_layout);
    991 
    992   *link = CreateLink(link_text, this);
    993   (*link)->SetHorizontalAlignment(gfx::ALIGN_LEFT);
    994   (*link)->SetAutoColorReadabilityEnabled(false);
    995   (*link)->SetEnabledColor(SK_ColorWHITE);
    996   button_layout->StartRow(1, 0);
    997   button_layout->AddView(*link);
    998 
    999   *button = new views::LabelButton(this, button_text);
   1000   (*button)->SetHorizontalAlignment(gfx::ALIGN_CENTER);
   1001   (*button)->SetStyle(views::Button::STYLE_BUTTON);
   1002   button_layout->AddView(*button);
   1003 
   1004   layout->StartRowWithPadding(1, 0, 0, views::kUnrelatedControlVerticalSpacing);
   1005   layout->AddView(button_row);
   1006 
   1007   // Adds a padded caret image at the bottom.
   1008   views::View* padded_caret_view = new views::View();
   1009   views::GridLayout* padded_caret_layout =
   1010       new views::GridLayout(padded_caret_view);
   1011   views::ColumnSet* padded_columns = padded_caret_layout->AddColumnSet(0);
   1012   padded_columns->AddPaddingColumn(0, views::kButtonHEdgeMarginNew);
   1013   padded_columns->AddColumn(views::GridLayout::LEADING,
   1014       views::GridLayout::CENTER, 0, views::GridLayout::USE_PREF, 0, 0);
   1015   padded_caret_view->SetLayoutManager(padded_caret_layout);
   1016 
   1017   views::ImageView* caret_image_view = new views::ImageView();
   1018   ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
   1019   caret_image_view->SetImage(
   1020       *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_CARET));
   1021 
   1022   padded_caret_layout->StartRow(1, 0);
   1023   padded_caret_layout->AddView(caret_image_view);
   1024 
   1025   views::View* view_with_caret = new views::View();
   1026   views::GridLayout* layout_with_caret =
   1027       CreateSingleColumnLayout(view_with_caret, kFixedMenuWidth);
   1028   layout_with_caret->StartRow(1, 0);
   1029   layout_with_caret->AddView(view);
   1030   layout_with_caret->StartRow(1, 0);
   1031   layout_with_caret->AddView(padded_caret_view);
   1032   return view_with_caret;
   1033 }
   1034 
   1035 views::View* ProfileChooserView::CreateCurrentProfileView(
   1036     const AvatarMenu::Item& avatar_item,
   1037     bool is_guest) {
   1038   views::View* view = new views::View();
   1039   int column_width = kFixedMenuWidth - 2 * views::kButtonHEdgeMarginNew;
   1040   views::GridLayout* layout = CreateSingleColumnLayout(view, column_width);
   1041   layout->SetInsets(views::kButtonVEdgeMarginNew,
   1042                     views::kButtonHEdgeMarginNew,
   1043                     views::kUnrelatedControlVerticalSpacing,
   1044                     views::kButtonHEdgeMarginNew);
   1045 
   1046   // Profile icon, centered.
   1047   int x_offset = (column_width - kLargeImageSide) / 2;
   1048   current_profile_photo_ = new EditableProfilePhoto(
   1049       this, avatar_item.icon, !is_guest,
   1050       gfx::Rect(x_offset, 0, kLargeImageSide, kLargeImageSide));
   1051   SizedContainer* profile_icon_container =
   1052       new SizedContainer(gfx::Size(column_width, kLargeImageSide));
   1053   profile_icon_container->AddChildView(current_profile_photo_);
   1054 
   1055   if (switches::IsNewProfileManagementPreviewEnabled()) {
   1056     question_mark_button_ = new views::ImageButton(this);
   1057     question_mark_button_->SetImageAlignment(
   1058         views::ImageButton::ALIGN_LEFT, views::ImageButton::ALIGN_MIDDLE);
   1059     ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
   1060     question_mark_button_->SetImage(views::ImageButton::STATE_NORMAL,
   1061         rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_QUESTION_STABLE));
   1062     question_mark_button_->SetImage(views::ImageButton::STATE_HOVERED,
   1063         rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_QUESTION_HOVER));
   1064     question_mark_button_->SetImage(views::ImageButton::STATE_PRESSED,
   1065         rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_QUESTION_SELECT));
   1066     gfx::Size preferred_size = question_mark_button_->GetPreferredSize();
   1067     question_mark_button_->SetBounds(
   1068         0, 0, preferred_size.width(), preferred_size.height());
   1069     profile_icon_container->AddChildView(question_mark_button_);
   1070   }
   1071 
   1072   if (browser_->profile()->IsSupervised()) {
   1073     views::ImageView* supervised_icon = new views::ImageView();
   1074     ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
   1075     supervised_icon->SetImage(
   1076         rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_SUPERVISED));
   1077     gfx::Size preferred_size = supervised_icon->GetPreferredSize();
   1078     gfx::Rect parent_bounds = current_profile_photo_->bounds();
   1079     supervised_icon->SetBounds(
   1080         parent_bounds.right() - preferred_size.width(),
   1081         parent_bounds.bottom() - preferred_size.height(),
   1082         preferred_size.width(),
   1083         preferred_size.height());
   1084     profile_icon_container->AddChildView(supervised_icon);
   1085   }
   1086 
   1087   layout->StartRow(1, 0);
   1088   layout->AddView(profile_icon_container);
   1089 
   1090   // Profile name, centered.
   1091   bool editing_allowed = !is_guest && !browser_->profile()->IsSupervised();
   1092   current_profile_name_ = new EditableProfileName(
   1093       this, profiles::GetAvatarNameForProfile(browser_->profile()),
   1094                                               editing_allowed);
   1095   layout->StartRow(1, 0);
   1096   layout->AddView(current_profile_name_);
   1097 
   1098   if (is_guest)
   1099     return view;
   1100 
   1101   // The available links depend on the type of profile that is active.
   1102   if (avatar_item.signed_in) {
   1103     layout->StartRow(1, 0);
   1104     if (switches::IsNewProfileManagement()) {
   1105       base::string16 link_title = l10n_util::GetStringUTF16(
   1106           view_mode_ == profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER ?
   1107               IDS_PROFILES_PROFILE_MANAGE_ACCOUNTS_BUTTON :
   1108               IDS_PROFILES_PROFILE_HIDE_MANAGE_ACCOUNTS_BUTTON);
   1109       manage_accounts_link_ = CreateLink(link_title, this);
   1110       manage_accounts_link_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
   1111       layout->AddView(manage_accounts_link_);
   1112     } else {
   1113       views::Label* email_label = new views::Label(avatar_item.sync_state);
   1114       email_label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
   1115       layout->AddView(email_label);
   1116     }
   1117   } else {
   1118     SigninManagerBase* signin_manager =
   1119         SigninManagerFactory::GetForProfile(
   1120             browser_->profile()->GetOriginalProfile());
   1121     if (signin_manager->IsSigninAllowed()) {
   1122       signin_current_profile_link_ = new views::BlueButton(
   1123         this, l10n_util::GetStringFUTF16(IDS_SYNC_START_SYNC_BUTTON_LABEL,
   1124             l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)));
   1125       layout->StartRow(1, 0);
   1126       layout->AddView(signin_current_profile_link_);
   1127     }
   1128   }
   1129 
   1130   return view;
   1131 }
   1132 
   1133 views::View* ProfileChooserView::CreateGuestProfileView() {
   1134   gfx::Image guest_icon =
   1135       ui::ResourceBundle::GetSharedInstance().GetImageNamed(
   1136           profiles::GetPlaceholderAvatarIconResourceID());
   1137   AvatarMenu::Item guest_avatar_item(0, 0, guest_icon);
   1138   guest_avatar_item.active = true;
   1139   guest_avatar_item.name = l10n_util::GetStringUTF16(
   1140       IDS_PROFILES_GUEST_PROFILE_NAME);
   1141   guest_avatar_item.signed_in = false;
   1142 
   1143   return CreateCurrentProfileView(guest_avatar_item, true);
   1144 }
   1145 
   1146 views::View* ProfileChooserView::CreateOtherProfilesView(
   1147     const Indexes& avatars_to_show) {
   1148   views::View* view = new views::View();
   1149   views::GridLayout* layout = CreateSingleColumnLayout(view, kFixedMenuWidth);
   1150 
   1151   int num_avatars_to_show = avatars_to_show.size();
   1152   for (int i = 0; i < num_avatars_to_show; ++i) {
   1153     const size_t index = avatars_to_show[i];
   1154     const AvatarMenu::Item& item = avatar_menu_->GetItemAt(index);
   1155     const int kSmallImageSide = 32;
   1156 
   1157     gfx::Image image = profiles::GetSizedAvatarIcon(
   1158         item.icon, true, kSmallImageSide, kSmallImageSide);
   1159 
   1160     views::LabelButton* button = new BackgroundColorHoverButton(
   1161         this,
   1162         item.name,
   1163         *image.ToImageSkia(),
   1164         *image.ToImageSkia());
   1165     button->set_min_size(gfx::Size(
   1166         0, kButtonHeight + views::kRelatedControlVerticalSpacing));
   1167 
   1168     open_other_profile_indexes_map_[button] = index;
   1169 
   1170     layout->StartRow(1, 0);
   1171     layout->AddView(new views::Separator(views::Separator::HORIZONTAL));
   1172     layout->StartRow(1, 0);
   1173     layout->AddView(button);
   1174   }
   1175 
   1176   return view;
   1177 }
   1178 
   1179 views::View* ProfileChooserView::CreateOptionsView(bool enable_lock) {
   1180   if (!switches::IsNewProfileManagement())
   1181     return NULL;
   1182 
   1183   views::View* view = new views::View();
   1184   views::GridLayout* layout;
   1185 
   1186   // Only signed-in users have the ability to lock.
   1187   if (enable_lock) {
   1188     layout = new views::GridLayout(view);
   1189     views::ColumnSet* columns = layout->AddColumnSet(0);
   1190     int width_of_lock_button =
   1191         2 * views::kUnrelatedControlLargeHorizontalSpacing + 12;
   1192     int width_of_users_button = kFixedMenuWidth - width_of_lock_button;
   1193     columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
   1194                        views::GridLayout::FIXED, width_of_users_button,
   1195                        width_of_users_button);
   1196     columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
   1197                        views::GridLayout::FIXED, width_of_lock_button,
   1198                        width_of_lock_button);
   1199     view->SetLayoutManager(layout);
   1200   } else {
   1201     layout = CreateSingleColumnLayout(view, kFixedMenuWidth);
   1202   }
   1203 
   1204   base::string16 text = browser_->profile()->IsGuestSession() ?
   1205       l10n_util::GetStringUTF16(IDS_PROFILES_EXIT_GUEST) :
   1206       l10n_util::GetStringFUTF16(IDS_PROFILES_NOT_YOU_BUTTON,
   1207           profiles::GetAvatarNameForProfile(browser_->profile()));
   1208   ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
   1209   users_button_ = new BackgroundColorHoverButton(
   1210       this,
   1211       text,
   1212       *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_AVATAR),
   1213       *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_AVATAR));
   1214   users_button_->set_min_size(gfx::Size(
   1215       0, kButtonHeight + views::kRelatedControlVerticalSpacing));
   1216 
   1217   layout->StartRow(1, 0);
   1218   layout->AddView(users_button_);
   1219 
   1220   if (enable_lock) {
   1221     lock_button_ = new BackgroundColorHoverButton(
   1222         this,
   1223         base::string16(),
   1224         *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_LOCK),
   1225         *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_LOCK));
   1226     lock_button_->set_min_size(gfx::Size(
   1227       0, kButtonHeight + views::kRelatedControlVerticalSpacing));
   1228     layout->AddView(lock_button_);
   1229   }
   1230   return view;
   1231 }
   1232 
   1233 views::View* ProfileChooserView::CreateSupervisedUserDisclaimerView() {
   1234   views::View* view = new views::View();
   1235   views::GridLayout* layout = CreateSingleColumnLayout(
   1236       view, kFixedMenuWidth - 2 * views::kButtonHEdgeMarginNew);
   1237   layout->SetInsets(views::kRelatedControlVerticalSpacing,
   1238                     views::kButtonHEdgeMarginNew,
   1239                     views::kRelatedControlVerticalSpacing,
   1240                     views::kButtonHEdgeMarginNew);
   1241   views::Label* disclaimer = new views::Label(
   1242       avatar_menu_->GetSupervisedUserInformation());
   1243   disclaimer->SetMultiLine(true);
   1244   disclaimer->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   1245   ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
   1246   disclaimer->SetFontList(rb->GetFontList(ui::ResourceBundle::SmallFont));
   1247   layout->StartRow(1, 0);
   1248   layout->AddView(disclaimer);
   1249 
   1250   return view;
   1251 }
   1252 
   1253 views::View* ProfileChooserView::CreateCurrentProfileAccountsView(
   1254     const AvatarMenu::Item& avatar_item) {
   1255   DCHECK(avatar_item.signed_in);
   1256   views::View* view = new views::View();
   1257   view->set_background(views::Background::CreateSolidBackground(
   1258       profiles::kAvatarBubbleAccountsBackgroundColor));
   1259   views::GridLayout* layout = CreateSingleColumnLayout(view, kFixedMenuWidth);
   1260 
   1261   Profile* profile = browser_->profile();
   1262   std::string primary_account =
   1263       SigninManagerFactory::GetForProfile(profile)->GetAuthenticatedUsername();
   1264   DCHECK(!primary_account.empty());
   1265   std::vector<std::string>accounts =
   1266       profiles::GetSecondaryAccountsForProfile(profile, primary_account);
   1267 
   1268   // Get state of authentication error, if any.
   1269   std::string error_account_id = GetAuthErrorAccountId(profile);
   1270 
   1271   // The primary account should always be listed first.
   1272   // TODO(rogerta): we still need to further differentiate the primary account
   1273   // from the others in the UI, so more work is likely required here:
   1274   // crbug.com/311124.
   1275   CreateAccountButton(layout, primary_account, true,
   1276                       error_account_id == primary_account, kFixedMenuWidth);
   1277   for (size_t i = 0; i < accounts.size(); ++i)
   1278     CreateAccountButton(layout, accounts[i], false,
   1279                         error_account_id == accounts[i], kFixedMenuWidth);
   1280   layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   1281 
   1282   add_account_link_ = CreateLink(l10n_util::GetStringFUTF16(
   1283       IDS_PROFILES_PROFILE_ADD_ACCOUNT_BUTTON, avatar_item.name), this);
   1284   add_account_link_->SetBorder(views::Border::CreateEmptyBorder(
   1285       0, views::kButtonVEdgeMarginNew,
   1286       views::kRelatedControlVerticalSpacing, 0));
   1287   layout->StartRow(1, 0);
   1288   layout->AddView(add_account_link_);
   1289   return view;
   1290 }
   1291 
   1292 void ProfileChooserView::CreateAccountButton(views::GridLayout* layout,
   1293                                              const std::string& account,
   1294                                              bool is_primary_account,
   1295                                              bool reauth_required,
   1296                                              int width) {
   1297   ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
   1298   const gfx::ImageSkia* delete_default_image =
   1299       rb->GetImageNamed(IDR_CLOSE_1).ToImageSkia();
   1300   const int kDeleteButtonWidth = delete_default_image->width();
   1301   const gfx::ImageSkia warning_default_image = reauth_required ?
   1302       *rb->GetImageNamed(IDR_ICON_PROFILES_ACCOUNT_BUTTON_ERROR).ToImageSkia() :
   1303       gfx::ImageSkia();
   1304   const int kWarningButtonWidth = reauth_required ?
   1305       warning_default_image.width() + views::kRelatedButtonHSpacing : 0;
   1306   int available_width = width - 2 * views::kButtonHEdgeMarginNew
   1307       - kDeleteButtonWidth - kWarningButtonWidth;
   1308   views::LabelButton* email_button = new BackgroundColorHoverButton(
   1309       reauth_required ? this : NULL,
   1310       gfx::ElideText(base::UTF8ToUTF16(account), gfx::FontList(),
   1311                      available_width, gfx::ELIDE_EMAIL),
   1312       warning_default_image,
   1313       warning_default_image);
   1314   layout->StartRow(1, 0);
   1315   layout->AddView(email_button);
   1316 
   1317   // Delete button.
   1318   views::ImageButton* delete_button = new views::ImageButton(this);
   1319   delete_button->SetImageAlignment(views::ImageButton::ALIGN_RIGHT,
   1320                                    views::ImageButton::ALIGN_MIDDLE);
   1321   delete_button->SetImage(views::ImageButton::STATE_NORMAL,
   1322                           delete_default_image);
   1323   delete_button->SetImage(views::ImageButton::STATE_HOVERED,
   1324                           rb->GetImageSkiaNamed(IDR_CLOSE_1_H));
   1325   delete_button->SetImage(views::ImageButton::STATE_PRESSED,
   1326                           rb->GetImageSkiaNamed(IDR_CLOSE_1_P));
   1327   delete_button->SetBounds(
   1328       width - views::kButtonHEdgeMarginNew - kDeleteButtonWidth,
   1329       0, kDeleteButtonWidth, kButtonHeight);
   1330 
   1331   email_button->set_notify_enter_exit_on_child(true);
   1332   email_button->AddChildView(delete_button);
   1333 
   1334   // Save the original email address, as the button text could be elided.
   1335   delete_account_button_map_[delete_button] = account;
   1336   if (reauth_required)
   1337     reauth_account_button_map_[email_button] = account;
   1338 }
   1339 
   1340 views::View* ProfileChooserView::CreateGaiaSigninView() {
   1341   GURL url;
   1342   int message_id;
   1343 
   1344   switch (view_mode_) {
   1345     case profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN:
   1346       url = signin::GetPromoURL(signin::SOURCE_AVATAR_BUBBLE_SIGN_IN,
   1347                                 false /* auto_close */,
   1348                                 true /* is_constrained */);
   1349       message_id = IDS_PROFILES_GAIA_SIGNIN_TITLE;
   1350       break;
   1351     case profiles::BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT:
   1352       url = signin::GetPromoURL(signin::SOURCE_AVATAR_BUBBLE_ADD_ACCOUNT,
   1353                                 false /* auto_close */,
   1354                                 true /* is_constrained */);
   1355       message_id = IDS_PROFILES_GAIA_ADD_ACCOUNT_TITLE;
   1356       break;
   1357     case profiles::BUBBLE_VIEW_MODE_GAIA_REAUTH: {
   1358       DCHECK(HasAuthError(browser_->profile()));
   1359       url = signin::GetReauthURL(browser_->profile(),
   1360                                  GetAuthErrorUsername(browser_->profile()));
   1361       message_id = IDS_PROFILES_GAIA_REAUTH_TITLE;
   1362       break;
   1363     }
   1364     default:
   1365       NOTREACHED() << "Called with invalid mode=" << view_mode_;
   1366       return NULL;
   1367   }
   1368 
   1369   // Adds Gaia signin webview
   1370   Profile* profile = browser_->profile();
   1371   views::WebView* web_view = new views::WebView(profile);
   1372   web_view->LoadInitialURL(url);
   1373   web_view->SetPreferredSize(
   1374       gfx::Size(kFixedGaiaViewWidth, kFixedGaiaViewHeight));
   1375 
   1376   TitleCard* title_card = new TitleCard(message_id, this,
   1377                                         &gaia_signin_cancel_button_);
   1378   return TitleCard::AddPaddedTitleCard(
   1379       web_view, title_card, kFixedGaiaViewWidth);
   1380 }
   1381 
   1382 views::View* ProfileChooserView::CreateAccountRemovalView() {
   1383   views::View* view = new views::View();
   1384   views::GridLayout* layout = CreateSingleColumnLayout(
   1385       view, kFixedAccountRemovalViewWidth - 2 * views::kButtonHEdgeMarginNew);
   1386   layout->SetInsets(0,
   1387                     views::kButtonHEdgeMarginNew,
   1388                     views::kButtonVEdgeMarginNew,
   1389                     views::kButtonHEdgeMarginNew);
   1390 
   1391   const std::string& primary_account = SigninManagerFactory::GetForProfile(
   1392       browser_->profile())->GetAuthenticatedUsername();
   1393   bool is_primary_account = primary_account == account_id_to_remove_;
   1394 
   1395   // Adds main text.
   1396   layout->StartRowWithPadding(1, 0, 0, views::kUnrelatedControlVerticalSpacing);
   1397   ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
   1398   const gfx::FontList& small_font_list =
   1399       rb->GetFontList(ui::ResourceBundle::SmallFont);
   1400 
   1401   if (is_primary_account) {
   1402     std::vector<size_t> offsets;
   1403     const base::string16 settings_text =
   1404         l10n_util::GetStringUTF16(IDS_PROFILES_SETTINGS_LINK);
   1405     const base::string16 primary_account_removal_text =
   1406         l10n_util::GetStringFUTF16(IDS_PROFILES_PRIMARY_ACCOUNT_REMOVAL_TEXT,
   1407             base::UTF8ToUTF16(account_id_to_remove_), settings_text, &offsets);
   1408     views::StyledLabel* primary_account_removal_label =
   1409         new views::StyledLabel(primary_account_removal_text, this);
   1410     primary_account_removal_label->AddStyleRange(
   1411         gfx::Range(offsets[1], offsets[1] + settings_text.size()),
   1412         views::StyledLabel::RangeStyleInfo::CreateForLink());
   1413     primary_account_removal_label->SetBaseFontList(small_font_list);
   1414     layout->AddView(primary_account_removal_label);
   1415   } else {
   1416     views::Label* content_label = new views::Label(
   1417         l10n_util::GetStringUTF16(IDS_PROFILES_ACCOUNT_REMOVAL_TEXT));
   1418     content_label->SetMultiLine(true);
   1419     content_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   1420     content_label->SetFontList(small_font_list);
   1421     layout->AddView(content_label);
   1422   }
   1423 
   1424   // Adds button.
   1425   if (!is_primary_account) {
   1426     remove_account_button_ = new views::BlueButton(
   1427         this, l10n_util::GetStringUTF16(IDS_PROFILES_ACCOUNT_REMOVAL_BUTTON));
   1428     remove_account_button_->SetHorizontalAlignment(
   1429         gfx::ALIGN_CENTER);
   1430     layout->StartRowWithPadding(
   1431         1, 0, 0, views::kUnrelatedControlVerticalSpacing);
   1432     layout->AddView(remove_account_button_);
   1433   } else {
   1434     layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
   1435   }
   1436 
   1437   TitleCard* title_card = new TitleCard(IDS_PROFILES_ACCOUNT_REMOVAL_TITLE,
   1438       this, &account_removal_cancel_button_);
   1439   return TitleCard::AddPaddedTitleCard(view, title_card,
   1440       kFixedAccountRemovalViewWidth);
   1441 }
   1442 
   1443 views::View* ProfileChooserView::CreateNewProfileManagementPreviewView() {
   1444   return CreateTutorialView(
   1445       profiles::TUTORIAL_MODE_ENABLE_PREVIEW,
   1446       l10n_util::GetStringUTF16(IDS_PROFILES_PREVIEW_TUTORIAL_TITLE),
   1447       l10n_util::GetStringUTF16(IDS_PROFILES_PREVIEW_TUTORIAL_CONTENT_TEXT),
   1448       l10n_util::GetStringUTF16(IDS_PROFILES_PROFILE_TUTORIAL_LEARN_MORE),
   1449       l10n_util::GetStringUTF16(IDS_PROFILES_TUTORIAL_TRY_BUTTON),
   1450       &tutorial_learn_more_link_,
   1451       &tutorial_enable_new_profile_management_button_);
   1452 }
   1453 
   1454 views::View* ProfileChooserView::CreateEndPreviewView() {
   1455   views::View* view = new views::View();
   1456   views::GridLayout* layout = CreateSingleColumnLayout(
   1457       view, kFixedAccountRemovalViewWidth - 2 * views::kButtonHEdgeMarginNew);
   1458   layout->SetInsets(0,
   1459                     views::kButtonHEdgeMarginNew,
   1460                     views::kButtonVEdgeMarginNew,
   1461                     views::kButtonHEdgeMarginNew);
   1462 
   1463   // Adds main text.
   1464   views::Label* content_label = new views::Label(
   1465       l10n_util::GetStringUTF16(IDS_PROFILES_END_PREVIEW_TEXT));
   1466   content_label->SetMultiLine(true);
   1467   content_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   1468   ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
   1469   const gfx::FontList& small_font_list =
   1470       rb->GetFontList(ui::ResourceBundle::SmallFont);
   1471   content_label->SetFontList(small_font_list);
   1472   layout->StartRowWithPadding(1, 0, 0, views::kUnrelatedControlVerticalSpacing);
   1473   layout->AddView(content_label);
   1474 
   1475   // Adds button.
   1476   end_preview_and_relaunch_button_ = new views::BlueButton(
   1477       this, l10n_util::GetStringUTF16(IDS_PROFILES_END_PREVIEW_AND_RELAUNCH));
   1478   end_preview_and_relaunch_button_->SetHorizontalAlignment(
   1479       gfx::ALIGN_CENTER);
   1480   layout->StartRowWithPadding(
   1481       1, 0, 0, views::kUnrelatedControlVerticalSpacing);
   1482   layout->AddView(end_preview_and_relaunch_button_);
   1483 
   1484   TitleCard* title_card = new TitleCard(
   1485       IDS_PROFILES_END_PREVIEW, this, &end_preview_cancel_button_);
   1486   return TitleCard::AddPaddedTitleCard(
   1487       view, title_card, kFixedAccountRemovalViewWidth);
   1488 }
   1489 
   1490