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 "components/autofill/content/common/autofill_messages.h"
23 #include "components/autofill/core/browser/password_generator.h"
24 #include "components/password_manager/core/browser/password_manager.h"
25 #include "content/public/browser/native_web_keyboard_event.h"
26 #include "content/public/browser/render_view_host.h"
27 #include "content/public/browser/web_contents.h"
28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/events/keycodes/keyboard_codes.h"
30 #include "ui/gfx/geometry/rect_conversions.h"
31 #include "ui/gfx/text_utils.h"
33 #if defined(OS_ANDROID)
34 #include "chrome/browser/android/chromium_application.h"
39 base::WeakPtr
<PasswordGenerationPopupControllerImpl
>
40 PasswordGenerationPopupControllerImpl::GetOrCreate(
41 base::WeakPtr
<PasswordGenerationPopupControllerImpl
> previous
,
42 const gfx::RectF
& bounds
,
43 const PasswordForm
& form
,
45 password_manager::PasswordManager
* password_manager
,
46 password_manager::PasswordManagerDriver
* driver
,
47 PasswordGenerationPopupObserver
* observer
,
48 content::WebContents
* web_contents
,
49 gfx::NativeView container_view
) {
51 previous
->element_bounds() == bounds
&&
52 previous
->web_contents() == web_contents
&&
53 previous
->container_view() == container_view
) {
60 PasswordGenerationPopupControllerImpl
* controller
=
61 new PasswordGenerationPopupControllerImpl(
62 bounds
, form
, max_length
, password_manager
, driver
, observer
,
63 web_contents
, container_view
);
64 return controller
->GetWeakPtr();
67 PasswordGenerationPopupControllerImpl::PasswordGenerationPopupControllerImpl(
68 const gfx::RectF
& bounds
,
69 const PasswordForm
& form
,
71 password_manager::PasswordManager
* password_manager
,
72 password_manager::PasswordManagerDriver
* driver
,
73 PasswordGenerationPopupObserver
* observer
,
74 content::WebContents
* web_contents
,
75 gfx::NativeView container_view
)
78 password_manager_(password_manager
),
81 generator_(new PasswordGenerator(max_length
)),
82 controller_common_(bounds
, container_view
, web_contents
),
83 password_selected_(false),
84 display_password_(false),
85 weak_ptr_factory_(this) {
86 controller_common_
.SetKeyPressCallback(
87 base::Bind(&PasswordGenerationPopupControllerImpl::HandleKeyPressEvent
,
88 base::Unretained(this)));
90 std::vector
<base::string16
> pieces
;
91 base::SplitStringDontTrim(
92 l10n_util::GetStringUTF16(IDS_PASSWORD_GENERATION_PROMPT
),
95 DCHECK_EQ(3u, pieces
.size());
96 link_range_
= gfx::Range(pieces
[0].size(),
97 pieces
[0].size() + pieces
[1].size());
98 help_text_
= JoinString(pieces
, base::string16());
101 PasswordGenerationPopupControllerImpl::~PasswordGenerationPopupControllerImpl()
104 base::WeakPtr
<PasswordGenerationPopupControllerImpl
>
105 PasswordGenerationPopupControllerImpl::GetWeakPtr() {
106 return weak_ptr_factory_
.GetWeakPtr();
109 bool PasswordGenerationPopupControllerImpl::HandleKeyPressEvent(
110 const content::NativeWebKeyboardEvent
& event
) {
111 switch (event
.windowsKeyCode
) {
114 PasswordSelected(true);
116 case ui::VKEY_ESCAPE
:
119 case ui::VKEY_RETURN
:
121 // We suppress tab if the password is selected because we will
122 // automatically advance focus anyway.
123 return PossiblyAcceptPassword();
129 bool PasswordGenerationPopupControllerImpl::PossiblyAcceptPassword() {
130 if (password_selected_
) {
131 PasswordAccepted(); // This will delete |this|.
138 void PasswordGenerationPopupControllerImpl::PasswordSelected(bool selected
) {
139 if (!display_password_
|| selected
== password_selected_
)
142 password_selected_
= selected
;
143 view_
->PasswordSelectionUpdated();
144 view_
->UpdateBoundsAndRedrawPopup();
147 void PasswordGenerationPopupControllerImpl::PasswordAccepted() {
148 if (!display_password_
)
151 driver_
->GeneratedPasswordAccepted(current_password_
);
152 password_manager_
->SetHasGeneratedPasswordForForm(driver_
, form_
, true);
156 int PasswordGenerationPopupControllerImpl::GetMinimumWidth() {
157 // Minimum width in pixels.
158 const int minimum_width
= 350;
160 // If the width of the field is longer than the minimum, use that instead.
161 return std::max(minimum_width
,
162 controller_common_
.RoundedElementBounds().width());
165 void PasswordGenerationPopupControllerImpl::CalculateBounds() {
166 gfx::Size bounds
= view_
->GetPreferredSizeOfPasswordView();
168 popup_bounds_
= controller_common_
.GetPopupBounds(bounds
.width(),
172 void PasswordGenerationPopupControllerImpl::Show(bool display_password
) {
173 display_password_
= display_password
;
174 if (display_password_
&& current_password_
.empty())
175 current_password_
= base::ASCIIToUTF16(generator_
->Generate());
178 view_
= PasswordGenerationPopupView::Create(this);
180 // Treat popup as being hidden if creation fails.
190 view_
->UpdateBoundsAndRedrawPopup();
193 controller_common_
.RegisterKeyPressCallback();
196 observer_
->OnPopupShown(display_password_
);
199 void PasswordGenerationPopupControllerImpl::HideAndDestroy() {
203 void PasswordGenerationPopupControllerImpl::Hide() {
204 controller_common_
.RemoveKeyPressCallback();
210 observer_
->OnPopupHidden();
215 void PasswordGenerationPopupControllerImpl::ViewDestroyed() {
221 void PasswordGenerationPopupControllerImpl::OnSavedPasswordsLinkClicked() {
222 #if defined(OS_ANDROID)
223 chrome::android::ChromiumApplication::ShowPasswordSettings();
225 chrome::ShowSettingsSubPage(
226 chrome::FindBrowserWithWebContents(controller_common_
.web_contents()),
227 chrome::kPasswordManagerSubPage
);
231 void PasswordGenerationPopupControllerImpl::SetSelectionAtPoint(
232 const gfx::Point
& point
) {
233 PasswordSelected(view_
->IsPointInPasswordBounds(point
));
236 bool PasswordGenerationPopupControllerImpl::AcceptSelectedLine() {
237 if (!password_selected_
)
244 void PasswordGenerationPopupControllerImpl::SelectionCleared() {
245 PasswordSelected(false);
248 gfx::NativeView
PasswordGenerationPopupControllerImpl::container_view() {
249 return controller_common_
.container_view();
252 const gfx::Rect
& PasswordGenerationPopupControllerImpl::popup_bounds() const {
253 return popup_bounds_
;
256 const gfx::RectF
& PasswordGenerationPopupControllerImpl::element_bounds()
258 return controller_common_
.element_bounds();
261 bool PasswordGenerationPopupControllerImpl::IsRTL() const {
262 return base::i18n::IsRTL();
265 bool PasswordGenerationPopupControllerImpl::display_password() const {
266 return display_password_
;
269 bool PasswordGenerationPopupControllerImpl::password_selected() const {
270 return password_selected_
;
273 base::string16
PasswordGenerationPopupControllerImpl::password() const {
274 return current_password_
;
277 base::string16
PasswordGenerationPopupControllerImpl::SuggestedText() {
278 return l10n_util::GetStringUTF16(IDS_PASSWORD_GENERATION_SUGGESTION
);
281 const base::string16
& PasswordGenerationPopupControllerImpl::HelpText() {
285 const gfx::Range
& PasswordGenerationPopupControllerImpl::HelpTextLinkRange() {
289 } // namespace autofill