NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / ui / views / passwords / manage_passwords_bubble_view.cc
blob58f4d83e3fb16e72350ebba1bd6a84a8d998d7fb
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h"
7 #include "chrome/browser/chrome_notification_types.h"
8 #include "chrome/browser/ui/browser.h"
9 #include "chrome/browser/ui/browser_finder.h"
10 #include "chrome/browser/ui/browser_window.h"
11 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
12 #include "chrome/browser/ui/views/frame/browser_view.h"
13 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
14 #include "chrome/browser/ui/views/passwords/manage_password_item_view.h"
15 #include "chrome/browser/ui/views/passwords/manage_passwords_icon_view.h"
16 #include "content/public/browser/notification_source.h"
17 #include "content/public/browser/web_contents_view.h"
18 #include "grit/generated_resources.h"
19 #include "ui/base/l10n/l10n_util.h"
20 #include "ui/gfx/text_utils.h"
21 #include "ui/views/controls/button/blue_button.h"
22 #include "ui/views/controls/button/label_button.h"
23 #include "ui/views/layout/grid_layout.h"
24 #include "ui/views/layout/layout_constants.h"
27 // Helpers --------------------------------------------------------------------
29 namespace {
31 // Updates either the biggest possible width for the username field in the
32 // manage passwords bubble or the biggest possible width for the password field.
33 void UpdateBiggestWidth(const autofill::PasswordForm& password_form,
34 bool username,
35 int* biggest_width) {
36 const gfx::FontList font_list;
37 base::string16 display_string(username ?
38 password_form.username_value :
39 ManagePasswordItemView::GetPasswordDisplayString(
40 password_form.password_value));
41 *biggest_width = std::max(gfx::GetStringWidth(display_string, font_list),
42 *biggest_width);
45 } // namespace
48 // ManagePasswordsBubbleView --------------------------------------------------
50 // static
51 ManagePasswordsBubbleView* ManagePasswordsBubbleView::manage_passwords_bubble_ =
52 NULL;
54 // static
55 void ManagePasswordsBubbleView::ShowBubble(content::WebContents* web_contents,
56 ManagePasswordsIconView* icon_view) {
57 Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
58 DCHECK(browser);
59 DCHECK(browser->window());
60 DCHECK(browser->fullscreen_controller());
61 DCHECK(!IsShowing());
63 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
64 bool is_fullscreen = browser_view->IsFullscreen();
65 views::View* anchor_view = is_fullscreen ?
66 NULL : browser_view->GetLocationBarView()->manage_passwords_icon_view();
67 manage_passwords_bubble_ =
68 new ManagePasswordsBubbleView(web_contents, anchor_view, icon_view);
70 if (is_fullscreen) {
71 manage_passwords_bubble_->set_parent_window(
72 web_contents->GetView()->GetTopLevelNativeWindow());
75 views::BubbleDelegateView::CreateBubble(manage_passwords_bubble_);
77 // Adjust for fullscreen after creation as it relies on the content size.
78 if (is_fullscreen) {
79 manage_passwords_bubble_->AdjustForFullscreen(
80 browser_view->GetBoundsInScreen());
83 manage_passwords_bubble_->GetWidget()->Show();
86 // static
87 void ManagePasswordsBubbleView::CloseBubble() {
88 if (manage_passwords_bubble_)
89 manage_passwords_bubble_->Close();
92 // static
93 bool ManagePasswordsBubbleView::IsShowing() {
94 // The bubble may be in the process of closing.
95 return (manage_passwords_bubble_ != NULL) &&
96 manage_passwords_bubble_->GetWidget()->IsVisible();
99 ManagePasswordsBubbleView::ManagePasswordsBubbleView(
100 content::WebContents* web_contents,
101 views::View* anchor_view,
102 ManagePasswordsIconView* icon_view)
103 : BubbleDelegateView(
104 anchor_view,
105 anchor_view ?
106 views::BubbleBorder::TOP_RIGHT : views::BubbleBorder::NONE),
107 manage_passwords_bubble_model_(
108 new ManagePasswordsBubbleModel(web_contents)),
109 icon_view_(icon_view) {
110 // Compensate for built-in vertical padding in the anchor view's image.
111 set_anchor_view_insets(gfx::Insets(5, 0, 5, 0));
112 set_notify_enter_exit_on_child(true);
115 ManagePasswordsBubbleView::~ManagePasswordsBubbleView() {}
117 int ManagePasswordsBubbleView::GetMaximumUsernameOrPasswordWidth(
118 bool username) {
119 int biggest_width = 0;
120 if (manage_passwords_bubble_model_->manage_passwords_bubble_state() !=
121 ManagePasswordsBubbleModel::PASSWORD_TO_BE_SAVED) {
122 // If we are in the PASSWORD_TO_BE_SAVED state we only display the
123 // password that was just submitted and should not take these into account.
124 for (autofill::PasswordFormMap::const_iterator i(
125 manage_passwords_bubble_model_->best_matches().begin());
126 i != manage_passwords_bubble_model_->best_matches().end(); ++i) {
127 UpdateBiggestWidth((*i->second), username, &biggest_width);
130 if (manage_passwords_bubble_model_->password_submitted()) {
131 UpdateBiggestWidth(manage_passwords_bubble_model_->pending_credentials(),
132 username, &biggest_width);
134 return biggest_width;
137 void ManagePasswordsBubbleView::AdjustForFullscreen(
138 const gfx::Rect& screen_bounds) {
139 if (GetAnchorView())
140 return;
142 // The bubble's padding from the screen edge, used in fullscreen.
143 const int kFullscreenPaddingEnd = 20;
144 const size_t bubble_half_width = width() / 2;
145 const int x_pos = base::i18n::IsRTL() ?
146 screen_bounds.x() + bubble_half_width + kFullscreenPaddingEnd :
147 screen_bounds.right() - bubble_half_width - kFullscreenPaddingEnd;
148 SetAnchorRect(gfx::Rect(x_pos, screen_bounds.y(), 0, 0));
151 void ManagePasswordsBubbleView::Close() {
152 GetWidget()->Close();
155 void ManagePasswordsBubbleView::Init() {
156 using views::GridLayout;
158 GridLayout* layout = new GridLayout(this);
159 SetLayoutManager(layout);
161 // This calculates the necessary widths for the list of credentials in the
162 // bubble. We do not need to clamp the password field width because
163 // ManagePasswordItemView::GetPasswordFisplayString() does this.
165 const int predefined_username_field_max_width =
166 gfx::FontList().GetExpectedTextWidth(22);
167 const int max_username_or_password_width =
168 std::min(GetMaximumUsernameOrPasswordWidth(true),
169 predefined_username_field_max_width);
170 const int first_field_width = std::max(max_username_or_password_width,
171 views::Label(l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_DELETED)).
172 GetPreferredSize().width());
174 const int second_field_width = std::max(
175 GetMaximumUsernameOrPasswordWidth(false),
176 views::Label(l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_UNDO)).
177 GetPreferredSize().width());
179 const int kSingleColumnSetId = 0;
180 views::ColumnSet* column_set = layout->AddColumnSet(kSingleColumnSetId);
181 column_set->AddPaddingColumn(0, views::kPanelHorizMargin);
182 column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 0,
183 GridLayout::USE_PREF, 0, 0);
184 column_set->AddPaddingColumn(0, views::kPanelHorizMargin);
186 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
187 views::Label* title_label =
188 new views::Label(manage_passwords_bubble_model_->title());
189 title_label->SetMultiLine(true);
190 title_label->SetFontList(rb->GetFontList(ui::ResourceBundle::MediumFont));
192 layout->StartRowWithPadding(0, kSingleColumnSetId,
193 0, views::kRelatedControlSmallVerticalSpacing);
194 layout->AddView(title_label);
195 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
197 if (manage_passwords_bubble_model_->manage_passwords_bubble_state() ==
198 ManagePasswordsBubbleModel::PASSWORD_TO_BE_SAVED) {
199 const int kSingleColumnCredentialsId = 1;
200 views::ColumnSet* single_column =
201 layout->AddColumnSet(kSingleColumnCredentialsId);
202 single_column->AddPaddingColumn(0, views::kPanelHorizMargin);
203 single_column->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
204 GridLayout::USE_PREF, 0, 0);
205 single_column->AddPaddingColumn(0, views::kPanelHorizMargin);
207 layout->StartRow(0, kSingleColumnCredentialsId);
208 ManagePasswordItemView* item = new ManagePasswordItemView(
209 manage_passwords_bubble_model_,
210 manage_passwords_bubble_model_->pending_credentials(),
211 first_field_width, second_field_width);
212 item->SetBorder(views::Border::CreateSolidSidedBorder(
217 GetNativeTheme()->GetSystemColor(
218 ui::NativeTheme::kColorId_EnabledMenuButtonBorderColor)));
219 layout->AddView(item);
221 const int kDoubleColumnSetId = 2;
222 views::ColumnSet* double_column_set =
223 layout->AddColumnSet(kDoubleColumnSetId);
224 double_column_set->AddPaddingColumn(0, views::kPanelHorizMargin);
225 double_column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 1,
226 GridLayout::USE_PREF, 0, 0);
227 double_column_set->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
228 double_column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
229 GridLayout::USE_PREF, 0, 0);
230 double_column_set->AddPaddingColumn(0, views::kPanelHorizMargin);
232 cancel_button_ = new views::LabelButton(
233 this, l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_CANCEL_BUTTON));
234 cancel_button_->SetStyle(views::Button::STYLE_BUTTON);
235 save_button_ = new views::BlueButton(
236 this, l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_BUTTON));
238 layout->StartRowWithPadding(0, kDoubleColumnSetId,
239 0, views::kRelatedControlVerticalSpacing);
240 layout->AddView(save_button_);
241 layout->AddView(cancel_button_);
242 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
243 } else {
244 const int kSingleButtonSetId = 3;
245 views::ColumnSet* single_column_set =
246 layout->AddColumnSet(kSingleButtonSetId);
247 single_column_set->AddPaddingColumn(0, views::kPanelHorizMargin);
248 single_column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
249 GridLayout::USE_PREF, 0, 0);
250 single_column_set->AddPaddingColumn(0,
251 views::kUnrelatedControlHorizontalSpacing);
252 single_column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
253 GridLayout::USE_PREF, 0, 0);
254 single_column_set->AddPaddingColumn(0, views::kPanelHorizMargin);
256 const int kSingleColumnCredentialsId = 1;
257 views::ColumnSet* single_column =
258 layout->AddColumnSet(kSingleColumnCredentialsId);
259 single_column->AddPaddingColumn(0, views::kPanelHorizMargin);
260 single_column->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
261 GridLayout::USE_PREF, 0, 0);
262 single_column->AddPaddingColumn(0, views::kPanelHorizMargin);
264 if (!manage_passwords_bubble_model_->best_matches().empty()) {
265 for (autofill::PasswordFormMap::const_iterator i(
266 manage_passwords_bubble_model_->best_matches().begin());
267 i != manage_passwords_bubble_model_->best_matches().end(); ++i) {
268 layout->StartRow(0, kSingleColumnCredentialsId);
269 ManagePasswordItemView* item = new ManagePasswordItemView(
270 manage_passwords_bubble_model_, *i->second, first_field_width,
271 second_field_width);
272 if (i == manage_passwords_bubble_model_->best_matches().begin()) {
273 item->SetBorder(views::Border::CreateSolidSidedBorder(
278 GetNativeTheme()->GetSystemColor(
279 ui::NativeTheme::kColorId_EnabledMenuButtonBorderColor)));
280 } else {
281 item->SetBorder(views::Border::CreateSolidSidedBorder(
286 GetNativeTheme()->GetSystemColor(
287 ui::NativeTheme::kColorId_EnabledMenuButtonBorderColor)));
289 layout->AddView(item);
291 } else if (!manage_passwords_bubble_model_->password_submitted()) {
292 views::Label* empty_label = new views::Label(
293 l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_NO_PASSWORDS));
294 empty_label->SetMultiLine(true);
295 layout->StartRow(0, kSingleColumnSetId);
296 layout->AddView(empty_label);
299 if (manage_passwords_bubble_model_->password_submitted()) {
300 layout->StartRow(0, kSingleColumnCredentialsId);
301 ManagePasswordItemView* item = new ManagePasswordItemView(
302 manage_passwords_bubble_model_,
303 manage_passwords_bubble_model_->pending_credentials(),
304 first_field_width, second_field_width);
305 if (manage_passwords_bubble_model_->best_matches().empty()) {
306 item->SetBorder(views::Border::CreateSolidSidedBorder(
311 GetNativeTheme()->GetSystemColor(
312 ui::NativeTheme::kColorId_EnabledMenuButtonBorderColor)));
313 } else {
314 item->SetBorder(views::Border::CreateSolidSidedBorder(
319 GetNativeTheme()->GetSystemColor(
320 ui::NativeTheme::kColorId_EnabledMenuButtonBorderColor)));
322 layout->AddView(item);
325 manage_link_ =
326 new views::Link(manage_passwords_bubble_model_->manage_link());
327 manage_link_->set_listener(this);
328 layout->StartRowWithPadding(0, kSingleButtonSetId,
329 0, views::kRelatedControlVerticalSpacing);
330 layout->AddView(manage_link_);
332 done_button_ =
333 new views::LabelButton(this, l10n_util::GetStringUTF16(IDS_DONE));
334 done_button_->SetStyle(views::Button::STYLE_BUTTON);
335 layout->AddView(done_button_);
339 void ManagePasswordsBubbleView::WindowClosing() {
340 // Close() closes the window asynchronously, so by the time we reach here,
341 // |manage_passwords_bubble_| may have already been reset.
342 if (manage_passwords_bubble_ == this)
343 manage_passwords_bubble_ = NULL;
346 void ManagePasswordsBubbleView::ButtonPressed(views::Button* sender,
347 const ui::Event& event) {
348 if (sender == save_button_)
349 manage_passwords_bubble_model_->OnSaveClicked();
350 else if (sender == cancel_button_)
351 manage_passwords_bubble_model_->OnCancelClicked();
352 else
353 DCHECK_EQ(done_button_, sender);
354 icon_view_->SetTooltip(
355 manage_passwords_bubble_model_->manage_passwords_bubble_state() ==
356 ManagePasswordsBubbleModel::PASSWORD_TO_BE_SAVED);
357 Close();
360 void ManagePasswordsBubbleView::LinkClicked(views::Link* source,
361 int event_flags) {
362 DCHECK_EQ(source, manage_link_);
363 manage_passwords_bubble_model_->OnManageLinkClicked();