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

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

Issue 1292693004: [Password Manager] Autofill forms with field name and id attributes missing. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Incorporated Vaclav's Inputs. Created 5 years, 3 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
« no previous file with comments | « chrome/test/data/password/ambiguous_password_form.html ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_autofill_agent.h" 5 #include "components/autofill/content/renderer/password_autofill_agent.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/i18n/case_conversion.h" 9 #include "base/i18n/case_conversion.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 47
48 // The size above which we stop triggering autocomplete. 48 // The size above which we stop triggering autocomplete.
49 static const size_t kMaximumTextSizeForAutocomplete = 1000; 49 static const size_t kMaximumTextSizeForAutocomplete = 1000;
50 50
51 // Experiment information 51 // Experiment information
52 const char kFillOnAccountSelectFieldTrialName[] = "FillOnAccountSelect"; 52 const char kFillOnAccountSelectFieldTrialName[] = "FillOnAccountSelect";
53 const char kFillOnAccountSelectFieldTrialEnabledWithHighlightGroup[] = 53 const char kFillOnAccountSelectFieldTrialEnabledWithHighlightGroup[] =
54 "EnableWithHighlight"; 54 "EnableWithHighlight";
55 const char kFillOnAccountSelectFieldTrialEnabledWithNoHighlightGroup[] = 55 const char kFillOnAccountSelectFieldTrialEnabledWithNoHighlightGroup[] =
56 "EnableWithNoHighlight"; 56 "EnableWithNoHighlight";
57 const char kDummyUsernameField[] = "anonymous_username";
58 const char kDummyPasswordField[] = "anonymous_password";
57 59
58 // Maps element names to the actual elements to simplify form filling. 60 // Maps element names to the actual elements to simplify form filling.
59 typedef std::map<base::string16, blink::WebInputElement> FormInputElementMap; 61 typedef std::map<base::string16, blink::WebInputElement> FormInputElementMap;
60 62
61 // Use the shorter name when referencing SavePasswordProgressLogger::StringID 63 // Use the shorter name when referencing SavePasswordProgressLogger::StringID
62 // values to spare line breaks. The code provides enough context for that 64 // values to spare line breaks. The code provides enough context for that
63 // already. 65 // already.
64 typedef SavePasswordProgressLogger Logger; 66 typedef SavePasswordProgressLogger Logger;
65 67
66 typedef std::vector<FormInputElementMap> FormElementsList; 68 typedef std::vector<FormInputElementMap> FormElementsList;
67 69
68 bool FillDataContainsFillableUsername(const PasswordFormFillData& fill_data) { 70 bool FillDataContainsFillableUsername(const PasswordFormFillData& fill_data) {
69 return !fill_data.username_field.name.empty() && 71 return !fill_data.username_field.name.empty() &&
70 (!fill_data.additional_logins.empty() || 72 (!fill_data.additional_logins.empty() ||
71 !fill_data.username_field.value.empty()); 73 !fill_data.username_field.value.empty());
72 } 74 }
73 75
74 // Returns true if |control_elements| contains an element named |name| and is 76 // Returns true if |control_elements| contains an element named |name| and is
75 // visible. 77 // visible.
76 bool IsNamedElementVisible( 78 bool IsNamedElementVisible(
77 const std::vector<blink::WebFormControlElement>& control_elements, 79 const std::vector<blink::WebFormControlElement>& control_elements,
78 const base::string16& name) { 80 const base::string16& name) {
79 for (size_t i = 0; i < control_elements.size(); ++i) { 81 for (const blink::WebFormControlElement& control_element : control_elements) {
80 if (control_elements[i].nameForAutofill() == name) { 82 if (control_element.nameForAutofill() == name) {
81 return IsWebNodeVisible(control_elements[i]); 83 return IsWebNodeVisible(control_element);
82 } 84 }
83 } 85 }
84 return false; 86 return false;
85 } 87 }
86 88
89 // Returns true if password form has username and password fields with either
90 // same or no name and id attributes supplied.
91 bool DoesFormContainAmbiguousOrEmptyNames(
92 const PasswordFormFillData& fill_data) {
93 return (fill_data.username_field.name == fill_data.password_field.name) ||
94 (fill_data.password_field.name ==
95 base::ASCIIToUTF16(kDummyPasswordField) &&
96 (!FillDataContainsFillableUsername(fill_data) ||
97 fill_data.username_field.name ==
98 base::ASCIIToUTF16(kDummyUsernameField)));
99 }
100
101 bool IsPasswordField(const FormFieldData& field) {
102 return (field.form_control_type == "password");
103 }
104
105 // Returns true if |password_element| is having
106 // |autocomplete='current-password'| attribute set.
107 bool HasAutocompleteCurrentPasswordAttribute(
dvadym 2015/09/24 15:43:17 Please use function HasAutocompleteAttributeValue
Pritam Nikam 2015/09/25 07:39:11 Done.
108 const blink::WebInputElement& password_element) {
109 return password_element.getAttribute("autocomplete") == "current-password";
110 }
111
112 // Returns true if |password_element| is having |autocomplete='new-password'|
113 // attribute set.
114 bool HasAutocompleteNewPasswordAttribute(
dvadym 2015/09/24 15:43:17 Please use function HasAutocompleteAttributeValue
Pritam Nikam 2015/09/25 07:39:11 Done.
115 const blink::WebInputElement& password_element) {
116 return password_element.getAttribute("autocomplete") == "new-password";
117 }
118
119 // Returns true if any password field within |control_elements| is supplied with
120 // either |autocomplete='current-password'| or |autocomplete='new-password'|
121 // attribute.
122 bool HasPasswordWithAutocompleteAttribute(
123 const std::vector<blink::WebFormControlElement>& control_elements) {
124 for (const blink::WebFormControlElement& control_element : control_elements) {
125 if (!control_element.hasHTMLTagName("input"))
126 continue;
127
128 const blink::WebInputElement input_element =
129 control_element.toConst<blink::WebInputElement>();
130 if (input_element.isPasswordField() &&
131 (HasAutocompleteCurrentPasswordAttribute(input_element) ||
132 HasAutocompleteNewPasswordAttribute(input_element)))
133 return true;
134 }
135
136 return false;
137 }
138
139 // Returns the |field|'s autofillable name. If |ambiguous_or_empty_names| is set
140 // to true returns a dummy name instead.
141 base::string16 FieldName(const FormFieldData& field,
142 bool ambiguous_or_empty_names) {
143 return ambiguous_or_empty_names
144 ? IsPasswordField(field) ? base::ASCIIToUTF16(kDummyPasswordField)
145 : base::ASCIIToUTF16(kDummyUsernameField)
146 : field.name;
147 }
148
87 // Utility function to find the unique entry of |control_elements| for the 149 // Utility function to find the unique entry of |control_elements| for the
88 // specified input |field|. On successful find, adds it to |result| and returns 150 // specified input |field|. On successful find, adds it to |result| and returns
89 // |true|. Otherwise clears the references from each |HTMLInputElement| from 151 // |true|. Otherwise clears the references from each |HTMLInputElement| from
90 // |result| and returns |false|. 152 // |result| and returns |false|.
91 bool FindFormInputElement( 153 bool FindFormInputElement(
92 const std::vector<blink::WebFormControlElement>& control_elements, 154 const std::vector<blink::WebFormControlElement>& control_elements,
93 const FormFieldData& field, 155 const FormFieldData& field,
156 bool ambiguous_or_empty_names,
94 FormInputElementMap* result) { 157 FormInputElementMap* result) {
95 // Match the first input element, if any. 158 // Match the first input element, if any.
96 // If more than one match is made, then we have ambiguity (due to misuse
97 // of "name" attribute) so is it considered not found.
98 bool found_input = false; 159 bool found_input = false;
99 for (size_t i = 0; i < control_elements.size(); ++i) { 160 bool form_has_password_field_with_autocomplete =
100 if (control_elements[i].nameForAutofill() != field.name) 161 HasPasswordWithAutocompleteAttribute(control_elements);
dvadym 2015/09/24 15:43:17 Here I'm concerned about perfomance a little bit.
Pritam Nikam 2015/09/25 07:39:11 Done.
162 base::string16 field_name = FieldName(field, ambiguous_or_empty_names);
163 for (const blink::WebFormControlElement& control_element : control_elements) {
164 if (!ambiguous_or_empty_names &&
165 control_element.nameForAutofill() != field_name) {
166 continue;
167 }
168
169 if (!control_element.hasHTMLTagName("input"))
101 continue; 170 continue;
102 171
103 if (!control_elements[i].hasHTMLTagName("input")) 172 // Only fill saved passwords into password fields and usernames into text
173 // fields.
174 const blink::WebInputElement input_element =
175 control_element.toConst<blink::WebInputElement>();
176 bool is_password_field = IsPasswordField(field);
177 if (input_element.isPasswordField() != is_password_field)
104 continue; 178 continue;
105 179
180 // For change password form with ambiguous or empty names keep only the
181 // first password field having |autocomplete='current-password'| attribute
182 // set. Also make sure we avoid keeping password fields having
183 // |autocomplete='new-password'| attribute set.
184 if (ambiguous_or_empty_names && is_password_field &&
185 form_has_password_field_with_autocomplete &&
186 !HasAutocompleteCurrentPasswordAttribute(input_element)) {
187 continue;
188 }
189
106 // Check for a non-unique match. 190 // Check for a non-unique match.
107 if (found_input) { 191 if (found_input) {
192 // For change password form keep only the first password field entry.
193 if (ambiguous_or_empty_names && is_password_field)
194 continue;
195
108 found_input = false; 196 found_input = false;
109 break; 197 break;
110 } 198 }
111 199
112 // Only fill saved passwords into password fields and usernames into 200 (*result)[field_name] = input_element;
113 // text fields.
114 const blink::WebInputElement input_element =
115 control_elements[i].toConst<blink::WebInputElement>();
116 if (input_element.isPasswordField() !=
117 (field.form_control_type == "password"))
118 continue;
119
120 (*result)[field.name] = input_element;
121 found_input = true; 201 found_input = true;
122 } 202 }
123 203
124 // A required element was not found. This is not the right form. 204 // A required element was not found. This is not the right form.
125 // Make sure no input elements from a partially matched form in this 205 // Make sure no input elements from a partially matched form in this
126 // iteration remain in the result set. 206 // iteration remain in the result set.
127 // Note: clear will remove a reference from each InputElement. 207 // Note: clear will remove a reference from each InputElement.
128 if (!found_input) { 208 if (!found_input) {
129 result->clear(); 209 result->clear();
130 return false; 210 return false;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 252
173 return group_name != 253 return group_name !=
174 kFillOnAccountSelectFieldTrialEnabledWithNoHighlightGroup; 254 kFillOnAccountSelectFieldTrialEnabledWithNoHighlightGroup;
175 } 255 }
176 256
177 // Helper to search through |control_elements| for the specified input elements 257 // Helper to search through |control_elements| for the specified input elements
178 // in |data|, and add results to |result|. 258 // in |data|, and add results to |result|.
179 bool FindFormInputElements( 259 bool FindFormInputElements(
180 const std::vector<blink::WebFormControlElement>& control_elements, 260 const std::vector<blink::WebFormControlElement>& control_elements,
181 const PasswordFormFillData& data, 261 const PasswordFormFillData& data,
262 bool ambiguous_or_empty_names,
182 FormInputElementMap* result) { 263 FormInputElementMap* result) {
183 return FindFormInputElement(control_elements, data.password_field, result) && 264 return FindFormInputElement(control_elements, data.password_field,
265 ambiguous_or_empty_names, result) &&
184 (!FillDataContainsFillableUsername(data) || 266 (!FillDataContainsFillableUsername(data) ||
185 FindFormInputElement(control_elements, data.username_field, result)); 267 FindFormInputElement(control_elements, data.username_field,
268 ambiguous_or_empty_names, result));
186 } 269 }
187 270
188 // Helper to locate form elements identified by |data|. 271 // Helper to locate form elements identified by |data|.
189 void FindFormElements(content::RenderFrame* render_frame, 272 void FindFormElements(content::RenderFrame* render_frame,
190 const PasswordFormFillData& data, 273 const PasswordFormFillData& data,
274 bool ambiguous_or_empty_names,
191 FormElementsList* results) { 275 FormElementsList* results) {
192 DCHECK(results); 276 DCHECK(results);
193 277
194 blink::WebDocument doc = render_frame->GetWebFrame()->document(); 278 blink::WebDocument doc = render_frame->GetWebFrame()->document();
195 if (!doc.isHTMLDocument()) 279 if (!doc.isHTMLDocument())
196 return; 280 return;
197 281
198 if (data.origin != GetCanonicalOriginForDocument(doc)) 282 if (data.origin != GetCanonicalOriginForDocument(doc))
199 return; 283 return;
200 284
201 blink::WebVector<blink::WebFormElement> forms; 285 blink::WebVector<blink::WebFormElement> forms;
202 doc.forms(forms); 286 doc.forms(forms);
203 287
204 for (size_t i = 0; i < forms.size(); ++i) { 288 for (size_t i = 0; i < forms.size(); ++i) {
205 blink::WebFormElement fe = forms[i]; 289 blink::WebFormElement fe = forms[i];
206 290
207 // Action URL must match. 291 // Action URL must match.
208 if (data.action != GetCanonicalActionForForm(fe)) 292 if (data.action != GetCanonicalActionForForm(fe))
209 continue; 293 continue;
210 294
211 std::vector<blink::WebFormControlElement> control_elements = 295 std::vector<blink::WebFormControlElement> control_elements =
212 ExtractAutofillableElementsInForm(fe); 296 ExtractAutofillableElementsInForm(fe);
213 FormInputElementMap cur_map; 297 FormInputElementMap cur_map;
214 if (FindFormInputElements(control_elements, data, &cur_map)) 298 if (FindFormInputElements(control_elements, data, ambiguous_or_empty_names,
299 &cur_map))
215 results->push_back(cur_map); 300 results->push_back(cur_map);
216 } 301 }
217 // If the element to be filled are not in a <form> element, the "action" and 302 // If the element to be filled are not in a <form> element, the "action" and
218 // origin should be the same. 303 // origin should be the same.
219 if (data.action != data.origin) 304 if (data.action != data.origin)
220 return; 305 return;
221 306
222 std::vector<blink::WebFormControlElement> control_elements = 307 std::vector<blink::WebFormControlElement> control_elements =
223 GetUnownedAutofillableFormFieldElements(doc.all(), nullptr); 308 GetUnownedAutofillableFormFieldElements(doc.all(), nullptr);
224 FormInputElementMap unowned_elements_map; 309 FormInputElementMap unowned_elements_map;
225 if (FindFormInputElements(control_elements, data, &unowned_elements_map)) 310 if (FindFormInputElements(control_elements, data, ambiguous_or_empty_names,
311 &unowned_elements_map))
226 results->push_back(unowned_elements_map); 312 results->push_back(unowned_elements_map);
227 } 313 }
228 314
229 bool IsElementEditable(const blink::WebInputElement& element) { 315 bool IsElementEditable(const blink::WebInputElement& element) {
230 return element.isEnabled() && !element.isReadOnly(); 316 return element.isEnabled() && !element.isReadOnly();
231 } 317 }
232 318
233 bool DoUsernamesMatch(const base::string16& username1, 319 bool DoUsernamesMatch(const base::string16& username1,
234 const base::string16& username2, 320 const base::string16& username2,
235 bool exact_match) { 321 bool exact_match) {
236 if (exact_match) 322 if (exact_match)
237 return username1 == username2; 323 return username1 == username2;
238 return FieldIsSuggestionSubstringStartingOnTokenBoundary(username1, username2, 324 return FieldIsSuggestionSubstringStartingOnTokenBoundary(username1, username2,
239 true); 325 true);
240 } 326 }
241 327
242 // Returns |true| if the given element is editable. Otherwise, returns |false|. 328 // Returns |true| if the given element is editable. Otherwise, returns |false|.
243 bool IsElementAutocompletable(const blink::WebInputElement& element) { 329 bool IsElementAutocompletable(const blink::WebInputElement& element) {
244 return IsElementEditable(element); 330 return IsElementEditable(element);
245 } 331 }
246 332
247 // Return true if either password_value or new_password_value is not empty and 333 // Return true if either password_value or new_password_value is not empty and
248 // not default.i 334 // not default.
249 bool FormContainsNonDefaultPasswordValue(const PasswordForm& password_form) { 335 bool FormContainsNonDefaultPasswordValue(const PasswordForm& password_form) {
250 return (!password_form.password_value.empty() && 336 return (!password_form.password_value.empty() &&
251 !password_form.password_value_is_default) || 337 !password_form.password_value_is_default) ||
252 (!password_form.new_password_value.empty() && 338 (!password_form.new_password_value.empty() &&
253 !password_form.new_password_value_is_default); 339 !password_form.new_password_value_is_default);
254 } 340 }
255 341
256 // Log a message including the name, method and action of |form|. 342 // Log a message including the name, method and action of |form|.
257 void LogHTMLForm(SavePasswordProgressLogger* logger, 343 void LogHTMLForm(SavePasswordProgressLogger* logger,
258 SavePasswordProgressLogger::StringID message_id, 344 SavePasswordProgressLogger::StringID message_id,
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 if (!bottom_frame_origin.equals(cur_frame->securityOrigin().toString())) 532 if (!bottom_frame_origin.equals(cur_frame->securityOrigin().toString()))
447 return false; 533 return false;
448 } 534 }
449 535
450 // If we can't modify the password, don't try to set the username 536 // If we can't modify the password, don't try to set the username
451 if (!IsElementAutocompletable(password_element)) 537 if (!IsElementAutocompletable(password_element))
452 return false; 538 return false;
453 539
454 bool form_contains_fillable_username_field = 540 bool form_contains_fillable_username_field =
455 FillDataContainsFillableUsername(fill_data); 541 FillDataContainsFillableUsername(fill_data);
542 bool ambiguous_or_empty_names =
543 DoesFormContainAmbiguousOrEmptyNames(fill_data);
544 base::string16 username_field_name;
545 if (form_contains_fillable_username_field)
546 username_field_name =
547 FieldName(fill_data.username_field, ambiguous_or_empty_names);
548
456 // If the form contains an autocompletable username field, try to set the 549 // If the form contains an autocompletable username field, try to set the
457 // username to the preferred name, but only if: 550 // username to the preferred name, but only if:
458 // (a) The fill-on-account-select flag is not set, and 551 // (a) The fill-on-account-select flag is not set, and
459 // (b) The username element isn't prefilled 552 // (b) The username element isn't prefilled
460 // 553 //
461 // If (a) is false, then just mark the username element as autofilled if the 554 // If (a) is false, then just mark the username element as autofilled if the
462 // user is not in the "no highlighting" group and return so the fill step is 555 // user is not in the "no highlighting" group and return so the fill step is
463 // skipped. 556 // skipped.
464 // 557 //
465 // If there is no autocompletable username field, and (a) is false, then the 558 // If there is no autocompletable username field, and (a) is false, then the
466 // username element cannot be autofilled, but the user should still be able to 559 // username element cannot be autofilled, but the user should still be able to
467 // select to fill the password element, so the password element must be marked 560 // select to fill the password element, so the password element must be marked
468 // as autofilled and the fill step should also be skipped if the user is not 561 // as autofilled and the fill step should also be skipped if the user is not
469 // in the "no highlighting" group. 562 // in the "no highlighting" group.
470 // 563 //
471 // In all other cases, do nothing. 564 // In all other cases, do nothing.
472 bool form_has_fillable_username = form_contains_fillable_username_field && 565 bool form_has_fillable_username = !username_field_name.empty() &&
473 IsElementAutocompletable(username_element); 566 IsElementAutocompletable(username_element);
474 567
475 if (ShouldFillOnAccountSelect()) { 568 if (ShouldFillOnAccountSelect()) {
476 if (!ShouldHighlightFields()) { 569 if (!ShouldHighlightFields()) {
477 return false; 570 return false;
478 } 571 }
479 572
480 if (form_has_fillable_username) { 573 if (form_has_fillable_username) {
481 username_element.setAutofilled(true); 574 username_element.setAutofilled(true);
482 } else if (username_element.isNull() || 575 } else if (username_element.isNull() ||
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
856 return false; 949 return false;
857 950
858 // If autocomplete='off' is set on the form elements, no suggestion dialog 951 // If autocomplete='off' is set on the form elements, no suggestion dialog
859 // should be shown. However, return |true| to indicate that this is a known 952 // should be shown. However, return |true| to indicate that this is a known
860 // password form and that the request to show suggestions has been handled (as 953 // password form and that the request to show suggestions has been handled (as
861 // a no-op). 954 // a no-op).
862 if (!element.isTextField() || !IsElementAutocompletable(element) || 955 if (!element.isTextField() || !IsElementAutocompletable(element) ||
863 !IsElementAutocompletable(password_info->password_field)) 956 !IsElementAutocompletable(password_info->password_field))
864 return true; 957 return true;
865 958
866 if (element.nameForAutofill().isEmpty()) 959 if (element.nameForAutofill().isEmpty() &&
960 !DoesFormContainAmbiguousOrEmptyNames(password_info->fill_data)) {
867 return false; // If the field has no name, then we won't have values. 961 return false; // If the field has no name, then we won't have values.
962 }
868 963
869 // Don't attempt to autofill with values that are too large. 964 // Don't attempt to autofill with values that are too large.
870 if (element.value().length() > kMaximumTextSizeForAutocomplete) 965 if (element.value().length() > kMaximumTextSizeForAutocomplete)
871 return false; 966 return false;
872 967
873 bool username_is_available = 968 bool username_is_available =
874 !username_element->isNull() && IsElementEditable(*username_element); 969 !username_element->isNull() && IsElementEditable(*username_element);
875 // If the element is a password field, a popup should only be shown if there 970 // If the element is a password field, a popup should only be shown if there
876 // is no username or the corresponding username element is not editable since 971 // is no username or the corresponding username element is not editable since
877 // it is only in that case that the username element does not have a 972 // it is only in that case that the username element does not have a
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
1229 } 1324 }
1230 1325
1231 // This is a new navigation, so require a new user gesture before filling in 1326 // This is a new navigation, so require a new user gesture before filling in
1232 // passwords. 1327 // passwords.
1233 gatekeeper_.Reset(); 1328 gatekeeper_.Reset();
1234 } 1329 }
1235 1330
1236 void PasswordAutofillAgent::OnFillPasswordForm( 1331 void PasswordAutofillAgent::OnFillPasswordForm(
1237 int key, 1332 int key,
1238 const PasswordFormFillData& form_data) { 1333 const PasswordFormFillData& form_data) {
1239 1334 bool ambiguous_or_empty_names =
1335 DoesFormContainAmbiguousOrEmptyNames(form_data);
1240 FormElementsList forms; 1336 FormElementsList forms;
1241 FindFormElements(render_frame(), form_data, &forms); 1337 FindFormElements(render_frame(), form_data, ambiguous_or_empty_names, &forms);
1242 FormElementsList::iterator iter; 1338 FormElementsList::iterator iter;
1243 for (iter = forms.begin(); iter != forms.end(); ++iter) { 1339 for (iter = forms.begin(); iter != forms.end(); ++iter) {
1244 // Attach autocomplete listener to enable selecting alternate logins. 1340 // Attach autocomplete listener to enable selecting alternate logins.
1245 blink::WebInputElement username_element, password_element; 1341 blink::WebInputElement username_element, password_element;
1246 1342
1247 // Check whether the password form has a username input field. 1343 base::string16 username_field_name, password_field_name;
1344 password_field_name =
1345 FieldName(form_data.password_field, ambiguous_or_empty_names);
1248 bool form_contains_fillable_username_field = 1346 bool form_contains_fillable_username_field =
1249 FillDataContainsFillableUsername(form_data); 1347 FillDataContainsFillableUsername(form_data);
1250 if (form_contains_fillable_username_field) { 1348 if (form_contains_fillable_username_field)
1251 username_element = 1349 username_field_name =
1252 (*iter)[form_data.username_field.name]; 1350 FieldName(form_data.username_field, ambiguous_or_empty_names);
1351
1352 // Check whether the password form has a username input field.
1353 if (!username_field_name.empty()) {
1354 username_element = (*iter)[username_field_name];
1253 } 1355 }
1254 1356
1255 // No password field, bail out. 1357 // No password field, bail out.
1256 if (form_data.password_field.name.empty()) 1358 if (password_field_name.empty())
1257 break; 1359 break;
1258 1360
1259 // We might have already filled this form if there are two <form> elements 1361 // We might have already filled this form if there are two <form> elements
1260 // with identical markup. 1362 // with identical markup.
1261 if (login_to_password_info_.find(username_element) != 1363 if (login_to_password_info_.find(username_element) !=
1262 login_to_password_info_.end()) 1364 login_to_password_info_.end())
1263 continue; 1365 continue;
1264 1366
1265 // Get pointer to password element. (We currently only support single 1367 // Get pointer to password element. (We currently only support single
1266 // password forms). 1368 // password forms).
1267 password_element = (*iter)[form_data.password_field.name]; 1369 password_element = (*iter)[password_field_name];
1268 1370
1269 // If wait_for_username is true, we don't want to initially fill the form 1371 // If wait_for_username is true, we don't want to initially fill the form
1270 // until the user types in a valid username. 1372 // until the user types in a valid username.
1271 if (!form_data.wait_for_username) { 1373 if (!form_data.wait_for_username) {
1272 FillFormOnPasswordReceived( 1374 FillFormOnPasswordReceived(
1273 form_data, 1375 form_data,
1274 username_element, 1376 username_element,
1275 password_element, 1377 password_element,
1276 &nonscript_modified_values_, 1378 &nonscript_modified_values_,
1277 base::Bind(&PasswordValueGatekeeper::RegisterElement, 1379 base::Bind(&PasswordValueGatekeeper::RegisterElement,
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
1478 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::DidStopLoading() { 1580 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::DidStopLoading() {
1479 agent_->DidStopLoading(); 1581 agent_->DidStopLoading();
1480 } 1582 }
1481 1583
1482 void PasswordAutofillAgent::LegacyPasswordAutofillAgent:: 1584 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::
1483 DidStartProvisionalLoad(blink::WebLocalFrame* navigated_frame) { 1585 DidStartProvisionalLoad(blink::WebLocalFrame* navigated_frame) {
1484 agent_->LegacyDidStartProvisionalLoad(navigated_frame); 1586 agent_->LegacyDidStartProvisionalLoad(navigated_frame);
1485 } 1587 }
1486 1588
1487 } // namespace autofill 1589 } // namespace autofill
OLDNEW
« no previous file with comments | « chrome/test/data/password/ambiguous_password_form.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698