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/strings/string_split.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversion_utils.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/ui/autofill/password_generation_popup_observer.h"
14 #include "chrome/browser/ui/autofill/password_generation_popup_view.h"
15 #include "chrome/browser/ui/autofill/popup_constants.h"
16 #include "chrome/browser/ui/browser_finder.h"
17 #include "chrome/browser/ui/chrome_pages.h"
18 #include "chrome/common/url_constants.h"
19 #include "chrome/grit/chromium_strings.h"
20 #include "chrome/grit/generated_resources.h"
21 #include "chrome/grit/google_chrome_strings.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/rect_conversions.h"
31 #include "ui/gfx/text_utils.h"
35 base::WeakPtr<PasswordGenerationPopupControllerImpl>
36 PasswordGenerationPopupControllerImpl::GetOrCreate(
37 base::WeakPtr<PasswordGenerationPopupControllerImpl> previous,
38 const gfx::RectF& bounds,
39 const PasswordForm& form,
41 password_manager::PasswordManager* password_manager,
42 PasswordGenerationPopupObserver* observer,
43 content::WebContents* web_contents,
44 gfx::NativeView container_view) {
46 previous->element_bounds() == bounds &&
47 previous->web_contents() == web_contents &&
48 previous->container_view() == container_view) {
55 PasswordGenerationPopupControllerImpl* controller =
56 new PasswordGenerationPopupControllerImpl(
64 return controller->GetWeakPtr();
67 PasswordGenerationPopupControllerImpl::PasswordGenerationPopupControllerImpl(
68 const gfx::RectF& bounds,
69 const PasswordForm& form,
71 password_manager::PasswordManager* password_manager,
72 PasswordGenerationPopupObserver* observer,
73 content::WebContents* web_contents,
74 gfx::NativeView container_view)
77 password_manager_(password_manager),
79 generator_(new PasswordGenerator(max_length)),
80 controller_common_(bounds, container_view, web_contents),
81 password_selected_(false),
82 display_password_(false),
83 weak_ptr_factory_(this) {
84 controller_common_.SetKeyPressCallback(
85 base::Bind(&PasswordGenerationPopupControllerImpl::HandleKeyPressEvent,
86 base::Unretained(this)));
88 std::vector<base::string16> pieces;
89 base::SplitStringDontTrim(
90 l10n_util::GetStringUTF16(IDS_PASSWORD_GENERATION_PROMPT),
93 DCHECK_EQ(3u, pieces.size());
94 link_range_ = gfx::Range(pieces[0].size(),
95 pieces[0].size() + pieces[1].size());
96 help_text_ = JoinString(pieces, base::string16());
99 PasswordGenerationPopupControllerImpl::~PasswordGenerationPopupControllerImpl()
102 base::WeakPtr<PasswordGenerationPopupControllerImpl>
103 PasswordGenerationPopupControllerImpl::GetWeakPtr() {
104 return weak_ptr_factory_.GetWeakPtr();
107 bool PasswordGenerationPopupControllerImpl::HandleKeyPressEvent(
108 const content::NativeWebKeyboardEvent& event) {
109 switch (event.windowsKeyCode) {
112 PasswordSelected(true);
114 case ui::VKEY_ESCAPE:
117 case ui::VKEY_RETURN:
119 // We suppress tab if the password is selected because we will
120 // automatically advance focus anyway.
121 return PossiblyAcceptPassword();
127 bool PasswordGenerationPopupControllerImpl::PossiblyAcceptPassword() {
128 if (password_selected_) {
129 PasswordAccepted(); // This will delete |this|.
136 void PasswordGenerationPopupControllerImpl::PasswordSelected(bool selected) {
137 if (!display_password_ || selected == password_selected_)
140 password_selected_ = selected;
141 view_->PasswordSelectionUpdated();
142 view_->UpdateBoundsAndRedrawPopup();
145 void PasswordGenerationPopupControllerImpl::PasswordAccepted() {
146 if (!display_password_)
149 web_contents()->GetRenderViewHost()->Send(
150 new AutofillMsg_GeneratedPasswordAccepted(
151 web_contents()->GetRenderViewHost()->GetRoutingID(),
153 password_manager_->SetFormHasGeneratedPassword(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);
184 view_->UpdateBoundsAndRedrawPopup();
187 controller_common_.RegisterKeyPressCallback();
190 observer_->OnPopupShown(display_password_);
193 void PasswordGenerationPopupControllerImpl::HideAndDestroy() {
197 void PasswordGenerationPopupControllerImpl::Hide() {
198 controller_common_.RemoveKeyPressCallback();
204 observer_->OnPopupHidden();
209 void PasswordGenerationPopupControllerImpl::ViewDestroyed() {
215 void PasswordGenerationPopupControllerImpl::OnSavedPasswordsLinkClicked() {
216 chrome::ShowSettingsSubPage(
217 chrome::FindBrowserWithWebContents(controller_common_.web_contents()),
218 chrome::kPasswordManagerSubPage);
221 void PasswordGenerationPopupControllerImpl::SetSelectionAtPoint(
222 const gfx::Point& point) {
223 PasswordSelected(view_->IsPointInPasswordBounds(point));
226 bool PasswordGenerationPopupControllerImpl::AcceptSelectedLine() {
227 if (!password_selected_)
234 void PasswordGenerationPopupControllerImpl::SelectionCleared() {
235 PasswordSelected(false);
238 gfx::NativeView PasswordGenerationPopupControllerImpl::container_view() {
239 return controller_common_.container_view();
242 const gfx::Rect& PasswordGenerationPopupControllerImpl::popup_bounds() const {
243 return popup_bounds_;
246 bool PasswordGenerationPopupControllerImpl::display_password() const {
247 return display_password_;
250 bool PasswordGenerationPopupControllerImpl::password_selected() const {
251 return password_selected_;
254 base::string16 PasswordGenerationPopupControllerImpl::password() const {
255 return current_password_;
258 base::string16 PasswordGenerationPopupControllerImpl::SuggestedText() {
259 return l10n_util::GetStringUTF16(IDS_PASSWORD_GENERATION_SUGGESTION);
262 const base::string16& PasswordGenerationPopupControllerImpl::HelpText() {
266 const gfx::Range& PasswordGenerationPopupControllerImpl::HelpTextLinkRange() {
270 } // namespace autofill