Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / browser / ui / autofill / password_generation_popup_controller_impl.cc
bloba2a2c7f924588f0fe188d36aa85dfb3200d71e0f
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.
5 #include "chrome/browser/ui/autofill/password_generation_popup_controller_impl.h"
7 #include <math.h>
9 #include "base/i18n/rtl.h"
10 #include "base/strings/string_split.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversion_utils.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/browser/ui/autofill/password_generation_popup_observer.h"
15 #include "chrome/browser/ui/autofill/password_generation_popup_view.h"
16 #include "chrome/browser/ui/autofill/popup_constants.h"
17 #include "chrome/browser/ui/browser_finder.h"
18 #include "chrome/browser/ui/chrome_pages.h"
19 #include "chrome/common/url_constants.h"
20 #include "chrome/grit/chromium_strings.h"
21 #include "chrome/grit/generated_resources.h"
22 #include "chrome/grit/google_chrome_strings.h"
23 #include "components/autofill/content/common/autofill_messages.h"
24 #include "components/autofill/core/browser/password_generator.h"
25 #include "components/password_manager/core/browser/password_manager.h"
26 #include "content/public/browser/native_web_keyboard_event.h"
27 #include "content/public/browser/render_view_host.h"
28 #include "content/public/browser/web_contents.h"
29 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/events/keycodes/keyboard_codes.h"
31 #include "ui/gfx/rect_conversions.h"
32 #include "ui/gfx/text_utils.h"
34 namespace autofill {
36 base::WeakPtr<PasswordGenerationPopupControllerImpl>
37 PasswordGenerationPopupControllerImpl::GetOrCreate(
38 base::WeakPtr<PasswordGenerationPopupControllerImpl> previous,
39 const gfx::RectF& bounds,
40 const PasswordForm& form,
41 int max_length,
42 password_manager::PasswordManager* password_manager,
43 PasswordGenerationPopupObserver* observer,
44 content::WebContents* web_contents,
45 gfx::NativeView container_view) {
46 if (previous.get() &&
47 previous->element_bounds() == bounds &&
48 previous->web_contents() == web_contents &&
49 previous->container_view() == container_view) {
50 return previous;
53 if (previous.get())
54 previous->Hide();
56 PasswordGenerationPopupControllerImpl* controller =
57 new PasswordGenerationPopupControllerImpl(
58 bounds,
59 form,
60 max_length,
61 password_manager,
62 observer,
63 web_contents,
64 container_view);
65 return controller->GetWeakPtr();
68 PasswordGenerationPopupControllerImpl::PasswordGenerationPopupControllerImpl(
69 const gfx::RectF& bounds,
70 const PasswordForm& form,
71 int max_length,
72 password_manager::PasswordManager* password_manager,
73 PasswordGenerationPopupObserver* observer,
74 content::WebContents* web_contents,
75 gfx::NativeView container_view)
76 : view_(NULL),
77 form_(form),
78 password_manager_(password_manager),
79 observer_(observer),
80 generator_(new PasswordGenerator(max_length)),
81 controller_common_(bounds, container_view, web_contents),
82 password_selected_(false),
83 display_password_(false),
84 weak_ptr_factory_(this) {
85 controller_common_.SetKeyPressCallback(
86 base::Bind(&PasswordGenerationPopupControllerImpl::HandleKeyPressEvent,
87 base::Unretained(this)));
89 std::vector<base::string16> pieces;
90 base::SplitStringDontTrim(
91 l10n_util::GetStringUTF16(IDS_PASSWORD_GENERATION_PROMPT),
92 '|', // separator
93 &pieces);
94 DCHECK_EQ(3u, pieces.size());
95 link_range_ = gfx::Range(pieces[0].size(),
96 pieces[0].size() + pieces[1].size());
97 help_text_ = JoinString(pieces, base::string16());
100 PasswordGenerationPopupControllerImpl::~PasswordGenerationPopupControllerImpl()
103 base::WeakPtr<PasswordGenerationPopupControllerImpl>
104 PasswordGenerationPopupControllerImpl::GetWeakPtr() {
105 return weak_ptr_factory_.GetWeakPtr();
108 bool PasswordGenerationPopupControllerImpl::HandleKeyPressEvent(
109 const content::NativeWebKeyboardEvent& event) {
110 switch (event.windowsKeyCode) {
111 case ui::VKEY_UP:
112 case ui::VKEY_DOWN:
113 PasswordSelected(true);
114 return true;
115 case ui::VKEY_ESCAPE:
116 Hide();
117 return true;
118 case ui::VKEY_RETURN:
119 case ui::VKEY_TAB:
120 // We suppress tab if the password is selected because we will
121 // automatically advance focus anyway.
122 return PossiblyAcceptPassword();
123 default:
124 return false;
128 bool PasswordGenerationPopupControllerImpl::PossiblyAcceptPassword() {
129 if (password_selected_) {
130 PasswordAccepted(); // This will delete |this|.
131 return true;
134 return false;
137 void PasswordGenerationPopupControllerImpl::PasswordSelected(bool selected) {
138 if (!display_password_ || selected == password_selected_)
139 return;
141 password_selected_ = selected;
142 view_->PasswordSelectionUpdated();
143 view_->UpdateBoundsAndRedrawPopup();
146 void PasswordGenerationPopupControllerImpl::PasswordAccepted() {
147 if (!display_password_)
148 return;
150 web_contents()->GetRenderViewHost()->Send(
151 new AutofillMsg_GeneratedPasswordAccepted(
152 web_contents()->GetRenderViewHost()->GetRoutingID(),
153 current_password_));
154 password_manager_->SetFormHasGeneratedPassword(form_);
155 Hide();
158 int PasswordGenerationPopupControllerImpl::GetMinimumWidth() {
159 // Minimum width in pixels.
160 const int minimum_width = 350;
162 // If the width of the field is longer than the minimum, use that instead.
163 return std::max(minimum_width,
164 controller_common_.RoundedElementBounds().width());
167 void PasswordGenerationPopupControllerImpl::CalculateBounds() {
168 gfx::Size bounds = view_->GetPreferredSizeOfPasswordView();
170 popup_bounds_ = controller_common_.GetPopupBounds(bounds.width(),
171 bounds.height());
174 void PasswordGenerationPopupControllerImpl::Show(bool display_password) {
175 display_password_ = display_password;
176 if (display_password_ && current_password_.empty())
177 current_password_ = base::ASCIIToUTF16(generator_->Generate());
179 if (!view_) {
180 view_ = PasswordGenerationPopupView::Create(this);
181 CalculateBounds();
182 view_->Show();
183 } else {
184 CalculateBounds();
185 view_->UpdateBoundsAndRedrawPopup();
188 controller_common_.RegisterKeyPressCallback();
190 if (observer_)
191 observer_->OnPopupShown(display_password_);
194 void PasswordGenerationPopupControllerImpl::HideAndDestroy() {
195 Hide();
198 void PasswordGenerationPopupControllerImpl::Hide() {
199 controller_common_.RemoveKeyPressCallback();
201 if (view_)
202 view_->Hide();
204 if (observer_)
205 observer_->OnPopupHidden();
207 delete this;
210 void PasswordGenerationPopupControllerImpl::ViewDestroyed() {
211 view_ = NULL;
213 Hide();
216 void PasswordGenerationPopupControllerImpl::OnSavedPasswordsLinkClicked() {
217 chrome::ShowSettingsSubPage(
218 chrome::FindBrowserWithWebContents(controller_common_.web_contents()),
219 chrome::kPasswordManagerSubPage);
222 void PasswordGenerationPopupControllerImpl::SetSelectionAtPoint(
223 const gfx::Point& point) {
224 PasswordSelected(view_->IsPointInPasswordBounds(point));
227 bool PasswordGenerationPopupControllerImpl::AcceptSelectedLine() {
228 if (!password_selected_)
229 return false;
231 PasswordAccepted();
232 return true;
235 void PasswordGenerationPopupControllerImpl::SelectionCleared() {
236 PasswordSelected(false);
239 gfx::NativeView PasswordGenerationPopupControllerImpl::container_view() {
240 return controller_common_.container_view();
243 const gfx::Rect& PasswordGenerationPopupControllerImpl::popup_bounds() const {
244 return popup_bounds_;
247 const gfx::RectF& PasswordGenerationPopupControllerImpl::element_bounds()
248 const {
249 return controller_common_.element_bounds();
252 bool PasswordGenerationPopupControllerImpl::IsRTL() const {
253 return base::i18n::IsRTL();
256 bool PasswordGenerationPopupControllerImpl::display_password() const {
257 return display_password_;
260 bool PasswordGenerationPopupControllerImpl::password_selected() const {
261 return password_selected_;
264 base::string16 PasswordGenerationPopupControllerImpl::password() const {
265 return current_password_;
268 base::string16 PasswordGenerationPopupControllerImpl::SuggestedText() {
269 return l10n_util::GetStringUTF16(IDS_PASSWORD_GENERATION_SUGGESTION);
272 const base::string16& PasswordGenerationPopupControllerImpl::HelpText() {
273 return help_text_;
276 const gfx::Range& PasswordGenerationPopupControllerImpl::HelpTextLinkRange() {
277 return link_range_;
280 } // namespace autofill