Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: chrome/renderer/autofill/password_generation_manager.cc

Issue 12434004: Move remaining Autofill code to //components/autofill. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix long lines Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/renderer/autofill/password_generation_manager.h"
6
7 #include "base/logging.h"
8 #include "chrome/common/password_generation_util.h"
9 #include "components/autofill/common/autofill_messages.h"
10 #include "content/public/renderer/password_form_conversion_utils.h"
11 #include "content/public/renderer/render_view.h"
12 #include "google_apis/gaia/gaia_urls.h"
13 #include "third_party/WebKit/Source/Platform/chromium/public/WebCString.h"
14 #include "third_party/WebKit/Source/Platform/chromium/public/WebRect.h"
15 #include "third_party/WebKit/Source/Platform/chromium/public/WebVector.h"
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormElement.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
22 #include "ui/gfx/rect.h"
23
24 namespace autofill {
25
26 namespace {
27
28 // Returns true if we think that this form is for account creation. |passwords|
29 // is filled with the password field(s) in the form.
30 bool GetAccountCreationPasswordFields(
31 const WebKit::WebFormElement& form,
32 std::vector<WebKit::WebInputElement>* passwords) {
33 // Grab all of the passwords for the form.
34 WebKit::WebVector<WebKit::WebFormControlElement> control_elements;
35 form.getFormControlElements(control_elements);
36
37 size_t num_input_elements = 0;
38 for (size_t i = 0; i < control_elements.size(); i++) {
39 WebKit::WebInputElement* input_element =
40 toWebInputElement(&control_elements[i]);
41 // Only pay attention to visible password fields.
42 if (input_element &&
43 input_element->isTextField() &&
44 input_element->hasNonEmptyBoundingBox()) {
45 num_input_elements++;
46 if (input_element->isPasswordField())
47 passwords->push_back(*input_element);
48 }
49 }
50
51 // This may be too lenient, but we assume that any form with at least three
52 // input elements where at least one of them is a password is an account
53 // creation form.
54 if (!passwords->empty() && num_input_elements >= 3) {
55 // We trim |passwords| because occasionally there are forms where the
56 // security question answers are put in password fields and we don't want
57 // to fill those.
58 if (passwords->size() > 2)
59 passwords->resize(2);
60
61 return true;
62 }
63
64 return false;
65 }
66
67 } // namespace
68
69 PasswordGenerationManager::PasswordGenerationManager(
70 content::RenderView* render_view)
71 : content::RenderViewObserver(render_view),
72 render_view_(render_view),
73 enabled_(false) {
74 render_view_->GetWebView()->addTextFieldDecoratorClient(this);
75 }
76 PasswordGenerationManager::~PasswordGenerationManager() {}
77
78 void PasswordGenerationManager::DidFinishDocumentLoad(WebKit::WebFrame* frame) {
79 // In every navigation, the IPC message sent by the password autofill manager
80 // to query whether the current form is blacklisted or not happens when the
81 // document load finishes, so we need to clear previous states here before we
82 // hear back from the browser. We only clear this state on main frame load
83 // as we don't want subframe loads to clear state that we have recieved from
84 // the main frame. Note that we assume there is only one account creation
85 // form, but there could be multiple password forms in each frame.
86 if (!frame->parent()) {
87 not_blacklisted_password_form_origins_.clear();
88 // Initialize to an empty and invalid GURL.
89 account_creation_form_origin_ = GURL();
90 passwords_.clear();
91 }
92 }
93
94 void PasswordGenerationManager::DidFinishLoad(WebKit::WebFrame* frame) {
95 // We don't want to generate passwords if the browser won't store or sync
96 // them.
97 if (!enabled_)
98 return;
99
100 if (!ShouldAnalyzeDocument(frame->document()))
101 return;
102
103 WebKit::WebVector<WebKit::WebFormElement> forms;
104 frame->document().forms(forms);
105 for (size_t i = 0; i < forms.size(); ++i) {
106 if (forms[i].isNull())
107 continue;
108
109 // If we can't get a valid PasswordForm, we skip this form because the
110 // the password won't get saved even if we generate it.
111 scoped_ptr<content::PasswordForm> password_form(
112 content::CreatePasswordForm(forms[i]));
113 if (!password_form.get()) {
114 DVLOG(2) << "Skipping form as it would not be saved";
115 continue;
116 }
117
118 // Do not generate password for GAIA since it is used to retrieve the
119 // generated paswords.
120 GURL realm(password_form->signon_realm);
121 if (realm == GURL(GaiaUrls::GetInstance()->gaia_login_form_realm()))
122 continue;
123
124 std::vector<WebKit::WebInputElement> passwords;
125 if (GetAccountCreationPasswordFields(forms[i], &passwords)) {
126 DVLOG(2) << "Account creation form detected";
127 password_generation::LogPasswordGenerationEvent(
128 password_generation::SIGN_UP_DETECTED);
129 passwords_ = passwords;
130 account_creation_form_origin_ = password_form->origin;
131 MaybeShowIcon();
132 // We assume that there is only one account creation field per URL.
133 return;
134 }
135 }
136 password_generation::LogPasswordGenerationEvent(
137 password_generation::NO_SIGN_UP_DETECTED);
138 }
139
140 bool PasswordGenerationManager::ShouldAnalyzeDocument(
141 const WebKit::WebDocument& document) const {
142 // Make sure that this security origin is allowed to use password manager.
143 // Generating a password that can't be saved is a bad idea.
144 WebKit::WebSecurityOrigin origin = document.securityOrigin();
145 if (!origin.canAccessPasswordManager()) {
146 DVLOG(1) << "No PasswordManager access";
147 return false;
148 }
149
150 return true;
151 }
152
153 bool PasswordGenerationManager::shouldAddDecorationTo(
154 const WebKit::WebInputElement& element) {
155 return element.isPasswordField();
156 }
157
158 bool PasswordGenerationManager::visibleByDefault() {
159 return false;
160 }
161
162 WebKit::WebCString PasswordGenerationManager::imageNameForNormalState() {
163 return WebKit::WebCString("generatePassword");
164 }
165
166 WebKit::WebCString PasswordGenerationManager::imageNameForDisabledState() {
167 return imageNameForNormalState();
168 }
169
170 WebKit::WebCString PasswordGenerationManager::imageNameForReadOnlyState() {
171 return imageNameForNormalState();
172 }
173
174 WebKit::WebCString PasswordGenerationManager::imageNameForHoverState() {
175 return WebKit::WebCString("generatePasswordHover");
176 }
177
178 void PasswordGenerationManager::handleClick(WebKit::WebInputElement& element) {
179 gfx::Rect rect(element.decorationElementFor(this).boundsInViewportSpace());
180 scoped_ptr<content::PasswordForm> password_form(
181 content::CreatePasswordForm(element.form()));
182 // We should not have shown the icon we can't create a valid PasswordForm.
183 DCHECK(password_form.get());
184
185 Send(new AutofillHostMsg_ShowPasswordGenerationPopup(routing_id(),
186 rect,
187 element.maxLength(),
188 *password_form));
189 password_generation::LogPasswordGenerationEvent(
190 password_generation::BUBBLE_SHOWN);
191 }
192
193 void PasswordGenerationManager::willDetach(
194 const WebKit::WebInputElement& element) {
195 // No implementation
196 }
197
198 bool PasswordGenerationManager::OnMessageReceived(const IPC::Message& message) {
199 bool handled = true;
200 IPC_BEGIN_MESSAGE_MAP(PasswordGenerationManager, message)
201 IPC_MESSAGE_HANDLER(AutofillMsg_FormNotBlacklisted,
202 OnFormNotBlacklisted)
203 IPC_MESSAGE_HANDLER(AutofillMsg_GeneratedPasswordAccepted,
204 OnPasswordAccepted)
205 IPC_MESSAGE_HANDLER(AutofillMsg_PasswordGenerationEnabled,
206 OnPasswordGenerationEnabled)
207 IPC_MESSAGE_UNHANDLED(handled = false)
208 IPC_END_MESSAGE_MAP()
209 return handled;
210 }
211
212 void PasswordGenerationManager::OnFormNotBlacklisted(
213 const content::PasswordForm& form) {
214 not_blacklisted_password_form_origins_.push_back(form.origin);
215 MaybeShowIcon();
216 }
217
218 void PasswordGenerationManager::OnPasswordAccepted(const string16& password) {
219 for (std::vector<WebKit::WebInputElement>::iterator it = passwords_.begin();
220 it != passwords_.end(); ++it) {
221 it->setValue(password);
222 it->setAutofilled(true);
223 // Advance focus to the next input field. We assume password fields in
224 // an account creation form are always adjacent.
225 render_view_->GetWebView()->advanceFocus(false);
226 }
227 }
228
229 void PasswordGenerationManager::OnPasswordGenerationEnabled(bool enabled) {
230 enabled_ = enabled;
231 }
232
233 void PasswordGenerationManager::MaybeShowIcon() {
234 // We should show the password generation icon only when we have detected
235 // account creation form and we have confirmed from browser that this form
236 // is not blacklisted by the users.
237 if (!account_creation_form_origin_.is_valid() ||
238 passwords_.empty() ||
239 not_blacklisted_password_form_origins_.empty()) {
240 return;
241 }
242
243 for (std::vector<GURL>::iterator it =
244 not_blacklisted_password_form_origins_.begin();
245 it != not_blacklisted_password_form_origins_.end(); ++it) {
246 if (*it == account_creation_form_origin_) {
247 passwords_[0].decorationElementFor(this).setAttribute("style",
248 "display:block");
249 password_generation::LogPasswordGenerationEvent(
250 password_generation::ICON_SHOWN);
251 return;
252 }
253 }
254 }
255
256 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698