Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / autofill / password_generation_popup_controller_impl.cc
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.
4
5 #include "chrome/browser/ui/autofill/password_generation_popup_controller_impl.h"
6
7 #include <math.h>
8
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.h"
17 #include "chrome/browser/ui/browser_finder.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"
32
33 namespace autofill {
34
35 base::WeakPtr<PasswordGenerationPopupControllerImpl>
36 PasswordGenerationPopupControllerImpl::GetOrCreate(
37     base::WeakPtr<PasswordGenerationPopupControllerImpl> previous,
38     const gfx::RectF& bounds,
39     const PasswordForm& form,
40     int max_length,
41     password_manager::PasswordManager* password_manager,
42     PasswordGenerationPopupObserver* observer,
43     content::WebContents* web_contents,
44     gfx::NativeView container_view) {
45   if (previous.get() &&
46       previous->element_bounds() == bounds &&
47       previous->web_contents() == web_contents &&
48       previous->container_view() == container_view) {
49     return previous;
50   }
51
52   if (previous.get())
53     previous->Hide();
54
55   PasswordGenerationPopupControllerImpl* controller =
56       new PasswordGenerationPopupControllerImpl(
57           bounds,
58           form,
59           max_length,
60           password_manager,
61           observer,
62           web_contents,
63           container_view);
64   return controller->GetWeakPtr();
65 }
66
67 PasswordGenerationPopupControllerImpl::PasswordGenerationPopupControllerImpl(
68     const gfx::RectF& bounds,
69     const PasswordForm& form,
70     int max_length,
71     password_manager::PasswordManager* password_manager,
72     PasswordGenerationPopupObserver* observer,
73     content::WebContents* web_contents,
74     gfx::NativeView container_view)
75     : view_(NULL),
76       form_(form),
77       password_manager_(password_manager),
78       observer_(observer),
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)));
87
88   std::vector<base::string16> pieces;
89   base::SplitStringDontTrim(
90       l10n_util::GetStringUTF16(IDS_PASSWORD_GENERATION_PROMPT),
91       '|',  // separator
92       &pieces);
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());
97 }
98
99 PasswordGenerationPopupControllerImpl::~PasswordGenerationPopupControllerImpl()
100   {}
101
102 base::WeakPtr<PasswordGenerationPopupControllerImpl>
103 PasswordGenerationPopupControllerImpl::GetWeakPtr() {
104   return weak_ptr_factory_.GetWeakPtr();
105 }
106
107 bool PasswordGenerationPopupControllerImpl::HandleKeyPressEvent(
108     const content::NativeWebKeyboardEvent& event) {
109   switch (event.windowsKeyCode) {
110     case ui::VKEY_UP:
111     case ui::VKEY_DOWN:
112       PasswordSelected(true);
113       return true;
114     case ui::VKEY_ESCAPE:
115       Hide();
116       return true;
117     case ui::VKEY_RETURN:
118     case ui::VKEY_TAB:
119       // We suppress tab if the password is selected because we will
120       // automatically advance focus anyway.
121       return PossiblyAcceptPassword();
122     default:
123       return false;
124   }
125 }
126
127 bool PasswordGenerationPopupControllerImpl::PossiblyAcceptPassword() {
128   if (password_selected_) {
129     PasswordAccepted();  // This will delete |this|.
130     return true;
131   }
132
133   return false;
134 }
135
136 void PasswordGenerationPopupControllerImpl::PasswordSelected(bool selected) {
137   if (!display_password_ || selected == password_selected_)
138     return;
139
140   password_selected_ = selected;
141   view_->PasswordSelectionUpdated();
142   view_->UpdateBoundsAndRedrawPopup();
143 }
144
145 void PasswordGenerationPopupControllerImpl::PasswordAccepted() {
146   if (!display_password_)
147     return;
148
149   web_contents()->GetRenderViewHost()->Send(
150       new AutofillMsg_GeneratedPasswordAccepted(
151           web_contents()->GetRenderViewHost()->GetRoutingID(),
152           current_password_));
153   password_manager_->SetFormHasGeneratedPassword(form_);
154   Hide();
155 }
156
157 int PasswordGenerationPopupControllerImpl::GetMinimumWidth() {
158   // Minimum width in pixels.
159   const int minimum_width = 350;
160
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());
164 }
165
166 void PasswordGenerationPopupControllerImpl::CalculateBounds() {
167   gfx::Size bounds = view_->GetPreferredSizeOfPasswordView();
168
169   popup_bounds_ = controller_common_.GetPopupBounds(bounds.width(),
170                                                     bounds.height());
171 }
172
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());
177
178   if (!view_) {
179     view_ = PasswordGenerationPopupView::Create(this);
180     CalculateBounds();
181     view_->Show();
182   } else {
183     CalculateBounds();
184     view_->UpdateBoundsAndRedrawPopup();
185   }
186
187   controller_common_.RegisterKeyPressCallback();
188
189   if (observer_)
190     observer_->OnPopupShown(display_password_);
191 }
192
193 void PasswordGenerationPopupControllerImpl::HideAndDestroy() {
194   Hide();
195 }
196
197 void PasswordGenerationPopupControllerImpl::Hide() {
198   controller_common_.RemoveKeyPressCallback();
199
200   if (view_)
201     view_->Hide();
202
203   if (observer_)
204     observer_->OnPopupHidden();
205
206   delete this;
207 }
208
209 void PasswordGenerationPopupControllerImpl::ViewDestroyed() {
210   view_ = NULL;
211
212   Hide();
213 }
214
215 void PasswordGenerationPopupControllerImpl::OnSavedPasswordsLinkClicked() {
216   Browser* browser =
217       chrome::FindBrowserWithWebContents(controller_common_.web_contents());
218   content::OpenURLParams params(
219       GURL(chrome::kPasswordManagerAccountDashboardURL), content::Referrer(),
220       NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK, false);
221   browser->OpenURL(params);
222 }
223
224 void PasswordGenerationPopupControllerImpl::SetSelectionAtPoint(
225     const gfx::Point& point) {
226   PasswordSelected(view_->IsPointInPasswordBounds(point));
227 }
228
229 bool PasswordGenerationPopupControllerImpl::AcceptSelectedLine() {
230   if (!password_selected_)
231     return false;
232
233   PasswordAccepted();
234   return true;
235 }
236
237 void PasswordGenerationPopupControllerImpl::SelectionCleared() {
238   PasswordSelected(false);
239 }
240
241 gfx::NativeView PasswordGenerationPopupControllerImpl::container_view() {
242   return controller_common_.container_view();
243 }
244
245 const gfx::Rect& PasswordGenerationPopupControllerImpl::popup_bounds() const {
246   return popup_bounds_;
247 }
248
249 bool PasswordGenerationPopupControllerImpl::display_password() const {
250   return display_password_;
251 }
252
253 bool PasswordGenerationPopupControllerImpl::password_selected() const {
254   return password_selected_;
255 }
256
257 base::string16 PasswordGenerationPopupControllerImpl::password() const {
258   return current_password_;
259 }
260
261 base::string16 PasswordGenerationPopupControllerImpl::SuggestedText() {
262   return l10n_util::GetStringUTF16(IDS_PASSWORD_GENERATION_SUGGESTION);
263 }
264
265 const base::string16& PasswordGenerationPopupControllerImpl::HelpText() {
266   return help_text_;
267 }
268
269 const gfx::Range& PasswordGenerationPopupControllerImpl::HelpTextLinkRange() {
270   return link_range_;
271 }
272
273 }  // namespace autofill