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"
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"
36 base::WeakPtr
<PasswordGenerationPopupControllerImpl
>
37 PasswordGenerationPopupControllerImpl::GetOrCreate(
38 base::WeakPtr
<PasswordGenerationPopupControllerImpl
> previous
,
39 const gfx::RectF
& bounds
,
40 const PasswordForm
& form
,
42 password_manager::PasswordManager
* password_manager
,
43 PasswordGenerationPopupObserver
* observer
,
44 content::WebContents
* web_contents
,
45 gfx::NativeView container_view
) {
47 previous
->element_bounds() == bounds
&&
48 previous
->web_contents() == web_contents
&&
49 previous
->container_view() == container_view
) {
56 PasswordGenerationPopupControllerImpl
* controller
=
57 new PasswordGenerationPopupControllerImpl(
65 return controller
->GetWeakPtr();
68 PasswordGenerationPopupControllerImpl::PasswordGenerationPopupControllerImpl(
69 const gfx::RectF
& bounds
,
70 const PasswordForm
& form
,
72 password_manager::PasswordManager
* password_manager
,
73 PasswordGenerationPopupObserver
* observer
,
74 content::WebContents
* web_contents
,
75 gfx::NativeView container_view
)
78 password_manager_(password_manager
),
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
),
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
) {
113 PasswordSelected(true);
115 case ui::VKEY_ESCAPE
:
118 case ui::VKEY_RETURN
:
120 // We suppress tab if the password is selected because we will
121 // automatically advance focus anyway.
122 return PossiblyAcceptPassword();
128 bool PasswordGenerationPopupControllerImpl::PossiblyAcceptPassword() {
129 if (password_selected_
) {
130 PasswordAccepted(); // This will delete |this|.
137 void PasswordGenerationPopupControllerImpl::PasswordSelected(bool selected
) {
138 if (!display_password_
|| selected
== password_selected_
)
141 password_selected_
= selected
;
142 view_
->PasswordSelectionUpdated();
143 view_
->UpdateBoundsAndRedrawPopup();
146 void PasswordGenerationPopupControllerImpl::PasswordAccepted() {
147 if (!display_password_
)
150 web_contents()->GetRenderViewHost()->Send(
151 new AutofillMsg_GeneratedPasswordAccepted(
152 web_contents()->GetRenderViewHost()->GetRoutingID(),
154 password_manager_
->SetFormHasGeneratedPassword(form_
);
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(),
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());
180 view_
= PasswordGenerationPopupView::Create(this);
185 view_
->UpdateBoundsAndRedrawPopup();
188 controller_common_
.RegisterKeyPressCallback();
191 observer_
->OnPopupShown(display_password_
);
194 void PasswordGenerationPopupControllerImpl::HideAndDestroy() {
198 void PasswordGenerationPopupControllerImpl::Hide() {
199 controller_common_
.RemoveKeyPressCallback();
205 observer_
->OnPopupHidden();
210 void PasswordGenerationPopupControllerImpl::ViewDestroyed() {
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_
)
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()
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() {
276 const gfx::Range
& PasswordGenerationPopupControllerImpl::HelpTextLinkRange() {
280 } // namespace autofill