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/geometry/rect_conversions.h"
32 #include "ui/gfx/text_utils.h"
34 #if defined(OS_ANDROID)
35 #include "chrome/browser/android/chromium_application.h"
40 base::WeakPtr
<PasswordGenerationPopupControllerImpl
>
41 PasswordGenerationPopupControllerImpl::GetOrCreate(
42 base::WeakPtr
<PasswordGenerationPopupControllerImpl
> previous
,
43 const gfx::RectF
& bounds
,
44 const PasswordForm
& form
,
46 password_manager::PasswordManager
* password_manager
,
47 password_manager::PasswordManagerDriver
* driver
,
48 PasswordGenerationPopupObserver
* observer
,
49 content::WebContents
* web_contents
,
50 gfx::NativeView container_view
) {
52 previous
->element_bounds() == bounds
&&
53 previous
->web_contents() == web_contents
&&
54 previous
->container_view() == container_view
) {
61 PasswordGenerationPopupControllerImpl
* controller
=
62 new PasswordGenerationPopupControllerImpl(
63 bounds
, form
, max_length
, password_manager
, driver
, observer
,
64 web_contents
, container_view
);
65 return controller
->GetWeakPtr();
68 PasswordGenerationPopupControllerImpl::PasswordGenerationPopupControllerImpl(
69 const gfx::RectF
& bounds
,
70 const PasswordForm
& form
,
72 password_manager::PasswordManager
* password_manager
,
73 password_manager::PasswordManagerDriver
* driver
,
74 PasswordGenerationPopupObserver
* observer
,
75 content::WebContents
* web_contents
,
76 gfx::NativeView container_view
)
79 password_manager_(password_manager
),
82 generator_(new PasswordGenerator(max_length
)),
83 controller_common_(bounds
, container_view
, web_contents
),
84 password_selected_(false),
85 display_password_(false),
86 weak_ptr_factory_(this) {
87 controller_common_
.SetKeyPressCallback(
88 base::Bind(&PasswordGenerationPopupControllerImpl::HandleKeyPressEvent
,
89 base::Unretained(this)));
91 std::vector
<base::string16
> pieces
;
92 base::SplitStringDontTrim(
93 l10n_util::GetStringUTF16(IDS_PASSWORD_GENERATION_PROMPT
),
96 DCHECK_EQ(3u, pieces
.size());
97 link_range_
= gfx::Range(pieces
[0].size(),
98 pieces
[0].size() + pieces
[1].size());
99 help_text_
= JoinString(pieces
, base::string16());
102 PasswordGenerationPopupControllerImpl::~PasswordGenerationPopupControllerImpl()
105 base::WeakPtr
<PasswordGenerationPopupControllerImpl
>
106 PasswordGenerationPopupControllerImpl::GetWeakPtr() {
107 return weak_ptr_factory_
.GetWeakPtr();
110 bool PasswordGenerationPopupControllerImpl::HandleKeyPressEvent(
111 const content::NativeWebKeyboardEvent
& event
) {
112 switch (event
.windowsKeyCode
) {
115 PasswordSelected(true);
117 case ui::VKEY_ESCAPE
:
120 case ui::VKEY_RETURN
:
122 // We suppress tab if the password is selected because we will
123 // automatically advance focus anyway.
124 return PossiblyAcceptPassword();
130 bool PasswordGenerationPopupControllerImpl::PossiblyAcceptPassword() {
131 if (password_selected_
) {
132 PasswordAccepted(); // This will delete |this|.
139 void PasswordGenerationPopupControllerImpl::PasswordSelected(bool selected
) {
140 if (!display_password_
|| selected
== password_selected_
)
143 password_selected_
= selected
;
144 view_
->PasswordSelectionUpdated();
145 view_
->UpdateBoundsAndRedrawPopup();
148 void PasswordGenerationPopupControllerImpl::PasswordAccepted() {
149 if (!display_password_
)
152 driver_
->GeneratedPasswordAccepted(current_password_
);
153 password_manager_
->SetFormHasGeneratedPassword(driver_
, form_
);
157 int PasswordGenerationPopupControllerImpl::GetMinimumWidth() {
158 // Minimum width in pixels.
159 const int minimum_width
= 350;
161 // If the width of the field is longer than the minimum, use that instead.
162 return std::max(minimum_width
,
163 controller_common_
.RoundedElementBounds().width());
166 void PasswordGenerationPopupControllerImpl::CalculateBounds() {
167 gfx::Size bounds
= view_
->GetPreferredSizeOfPasswordView();
169 popup_bounds_
= controller_common_
.GetPopupBounds(bounds
.width(),
173 void PasswordGenerationPopupControllerImpl::Show(bool display_password
) {
174 display_password_
= display_password
;
175 if (display_password_
&& current_password_
.empty())
176 current_password_
= base::ASCIIToUTF16(generator_
->Generate());
179 view_
= PasswordGenerationPopupView::Create(this);
181 // Treat popup as being hidden if creation fails.
191 view_
->UpdateBoundsAndRedrawPopup();
194 controller_common_
.RegisterKeyPressCallback();
197 observer_
->OnPopupShown(display_password_
);
200 void PasswordGenerationPopupControllerImpl::HideAndDestroy() {
204 void PasswordGenerationPopupControllerImpl::Hide() {
205 controller_common_
.RemoveKeyPressCallback();
211 observer_
->OnPopupHidden();
216 void PasswordGenerationPopupControllerImpl::ViewDestroyed() {
222 void PasswordGenerationPopupControllerImpl::OnSavedPasswordsLinkClicked() {
223 #if defined(OS_ANDROID)
224 chrome::android::ChromiumApplication::ShowPasswordSettings();
226 chrome::ShowSettingsSubPage(
227 chrome::FindBrowserWithWebContents(controller_common_
.web_contents()),
228 chrome::kPasswordManagerSubPage
);
232 void PasswordGenerationPopupControllerImpl::SetSelectionAtPoint(
233 const gfx::Point
& point
) {
234 PasswordSelected(view_
->IsPointInPasswordBounds(point
));
237 bool PasswordGenerationPopupControllerImpl::AcceptSelectedLine() {
238 if (!password_selected_
)
245 void PasswordGenerationPopupControllerImpl::SelectionCleared() {
246 PasswordSelected(false);
249 gfx::NativeView
PasswordGenerationPopupControllerImpl::container_view() {
250 return controller_common_
.container_view();
253 const gfx::Rect
& PasswordGenerationPopupControllerImpl::popup_bounds() const {
254 return popup_bounds_
;
257 const gfx::RectF
& PasswordGenerationPopupControllerImpl::element_bounds()
259 return controller_common_
.element_bounds();
262 bool PasswordGenerationPopupControllerImpl::IsRTL() const {
263 return base::i18n::IsRTL();
266 bool PasswordGenerationPopupControllerImpl::display_password() const {
267 return display_password_
;
270 bool PasswordGenerationPopupControllerImpl::password_selected() const {
271 return password_selected_
;
274 base::string16
PasswordGenerationPopupControllerImpl::password() const {
275 return current_password_
;
278 base::string16
PasswordGenerationPopupControllerImpl::SuggestedText() {
279 return l10n_util::GetStringUTF16(IDS_PASSWORD_GENERATION_SUGGESTION
);
282 const base::string16
& PasswordGenerationPopupControllerImpl::HelpText() {
286 const gfx::Range
& PasswordGenerationPopupControllerImpl::HelpTextLinkRange() {
290 } // namespace autofill