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

Side by Side Diff: components/autofill/content/renderer/password_form_conversion_utils.cc

Issue 1014683006: [Password manager] Recognise squashed login+sign-up forms (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix failing PasswordManagerTest Created 5 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/autofill/content/renderer/password_form_conversion_utils.h" 5 #include "components/autofill/content/renderer/password_form_conversion_utils.h"
6 6
7 #include "base/strings/string_util.h" 7 #include "base/strings/string_util.h"
8 #include "components/autofill/content/renderer/form_autofill_util.h" 8 #include "components/autofill/content/renderer/form_autofill_util.h"
9 #include "components/autofill/core/common/password_form.h" 9 #include "components/autofill/core/common/password_form.h"
10 #include "third_party/WebKit/public/platform/WebString.h" 10 #include "third_party/WebKit/public/platform/WebString.h"
11 #include "third_party/WebKit/public/web/WebDocument.h" 11 #include "third_party/WebKit/public/web/WebDocument.h"
12 #include "third_party/WebKit/public/web/WebFormControlElement.h" 12 #include "third_party/WebKit/public/web/WebFormControlElement.h"
13 #include "third_party/WebKit/public/web/WebInputElement.h" 13 #include "third_party/WebKit/public/web/WebInputElement.h"
14 #include "third_party/re2/re2/re2.h"
14 15
15 using blink::WebDocument; 16 using blink::WebDocument;
16 using blink::WebFormControlElement; 17 using blink::WebFormControlElement;
17 using blink::WebFormElement; 18 using blink::WebFormElement;
18 using blink::WebInputElement; 19 using blink::WebInputElement;
19 using blink::WebString; 20 using blink::WebString;
20 using blink::WebVector; 21 using blink::WebVector;
21 22
22 namespace autofill { 23 namespace autofill {
23 namespace { 24 namespace {
24 25
26 // Given the sequence of non-password and password text input fields of a form,
27 // represented as a string of Ns (non-password) and Ps (password), computes the
28 // layout type of that form.
29 PasswordForm::Layout SequenceToLayout(re2::StringPiece layout_sequence) {
30 if (RE2::FullMatch(layout_sequence, "NPN+PP"))
Garrett Casto 2015/03/17 22:49:37 As written this is over constrained and doesn't ca
vabr (Chromium) 2015/03/18 16:51:03 Ah, I forgot to get back from my distilled toy exa
31 return PasswordForm::Layout::LAYOUT_LOGIN_AND_SIGNUP;
32 return PasswordForm::Layout::LAYOUT_OTHER;
33 }
34
25 // Checks in a case-insensitive way if the autocomplete attribute for the given 35 // Checks in a case-insensitive way if the autocomplete attribute for the given
26 // |element| is present and has the specified |value_in_lowercase|. 36 // |element| is present and has the specified |value_in_lowercase|.
27 bool HasAutocompleteAttributeValue(const WebInputElement& element, 37 bool HasAutocompleteAttributeValue(const WebInputElement& element,
28 const char* value_in_lowercase) { 38 const char* value_in_lowercase) {
29 return LowerCaseEqualsASCII(element.getAttribute("autocomplete"), 39 return LowerCaseEqualsASCII(element.getAttribute("autocomplete"),
30 value_in_lowercase); 40 value_in_lowercase);
31 } 41 }
32 42
33 // Helper to determine which password is the main (current) one, and which is 43 // Helper to determine which password is the main (current) one, and which is
34 // the new password (e.g., on a sign-up or change password form), if any. 44 // the new password (e.g., on a sign-up or change password form), if any.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 nonscript_modified_values) { 128 nonscript_modified_values) {
119 WebInputElement latest_input_element; 129 WebInputElement latest_input_element;
120 WebInputElement username_element; 130 WebInputElement username_element;
121 password_form->username_marked_by_site = false; 131 password_form->username_marked_by_site = false;
122 std::vector<WebInputElement> passwords; 132 std::vector<WebInputElement> passwords;
123 std::vector<base::string16> other_possible_usernames; 133 std::vector<base::string16> other_possible_usernames;
124 134
125 WebVector<WebFormControlElement> control_elements; 135 WebVector<WebFormControlElement> control_elements;
126 form.getFormControlElements(control_elements); 136 form.getFormControlElements(control_elements);
127 137
138 std::string layout_sequence;
139 layout_sequence.reserve(control_elements.size());
128 for (size_t i = 0; i < control_elements.size(); ++i) { 140 for (size_t i = 0; i < control_elements.size(); ++i) {
129 WebFormControlElement control_element = control_elements[i]; 141 WebFormControlElement control_element = control_elements[i];
130 if (control_element.isActivatedSubmit()) 142 if (control_element.isActivatedSubmit())
131 password_form->submit_element = control_element.formControlName(); 143 password_form->submit_element = control_element.formControlName();
132 144
133 WebInputElement* input_element = toWebInputElement(&control_element); 145 WebInputElement* input_element = toWebInputElement(&control_element);
134 if (!input_element || !input_element->isEnabled()) 146 if (!input_element || !input_element->isEnabled())
135 continue; 147 continue;
136 148
149 if (input_element->isTextField()) {
150 if (input_element->isPasswordField())
151 layout_sequence.push_back('P');
152 else
153 layout_sequence.push_back('N');
154 }
155
137 if (input_element->isPasswordField()) { 156 if (input_element->isPasswordField()) {
138 passwords.push_back(*input_element); 157 passwords.push_back(*input_element);
139 // If we have not yet considered any element to be the username so far, 158 // If we have not yet considered any element to be the username so far,
140 // provisionally select the input element just before the first password 159 // provisionally select the input element just before the first password
141 // element to be the username. This choice will be overruled if we later 160 // element to be the username. This choice will be overruled if we later
142 // find an element with autocomplete='username'. 161 // find an element with autocomplete='username'.
143 if (username_element.isNull() && !latest_input_element.isNull()) { 162 if (username_element.isNull() && !latest_input_element.isNull()) {
144 username_element = latest_input_element; 163 username_element = latest_input_element;
145 // Remove the selected username from other_possible_usernames. 164 // Remove the selected username from other_possible_usernames.
146 if (!latest_input_element.value().isEmpty()) { 165 if (!latest_input_element.value().isEmpty()) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 // out to be a password. Save a non-empty username as a possible 206 // out to be a password. Save a non-empty username as a possible
188 // alternative, at least for now. 207 // alternative, at least for now.
189 if (username_element.isNull()) 208 if (username_element.isNull())
190 latest_input_element = *input_element; 209 latest_input_element = *input_element;
191 if (!input_element->value().isEmpty()) 210 if (!input_element->value().isEmpty())
192 other_possible_usernames.push_back(input_element->value()); 211 other_possible_usernames.push_back(input_element->value());
193 } 212 }
194 } 213 }
195 } 214 }
196 } 215 }
216 password_form->layout = SequenceToLayout(layout_sequence);
197 217
198 if (!username_element.isNull()) { 218 if (!username_element.isNull()) {
199 password_form->username_element = username_element.nameForAutofill(); 219 password_form->username_element = username_element.nameForAutofill();
200 base::string16 username_value = username_element.value(); 220 base::string16 username_value = username_element.value();
201 if (nonscript_modified_values != nullptr) { 221 if (nonscript_modified_values != nullptr) {
202 auto username_iterator = 222 auto username_iterator =
203 nonscript_modified_values->find(username_element); 223 nonscript_modified_values->find(username_element);
204 if (username_iterator != nonscript_modified_values->end()) { 224 if (username_iterator != nonscript_modified_values->end()) {
205 base::string16 typed_username_value = username_iterator->second; 225 base::string16 typed_username_value = username_iterator->second;
206 if (!StartsWith(username_value, typed_username_value, false)) { 226 if (!StartsWith(username_value, typed_username_value, false)) {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 blink::WebFormControlElement(), 307 blink::WebFormControlElement(),
288 REQUIRE_NONE, 308 REQUIRE_NONE,
289 EXTRACT_NONE, 309 EXTRACT_NONE,
290 &password_form->form_data, 310 &password_form->form_data,
291 NULL /* FormFieldData */); 311 NULL /* FormFieldData */);
292 312
293 return password_form.Pass(); 313 return password_form.Pass();
294 } 314 }
295 315
296 } // namespace autofill 316 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698