OLD | NEW |
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 Loading... |
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 any password field within |control_elements| is supplied with |
| 106 // either |autocomplete='current-password'| or |autocomplete='new-password'| |
| 107 // attribute. |
| 108 bool HasPasswordWithAutocompleteAttribute( |
| 109 const std::vector<blink::WebFormControlElement>& control_elements) { |
| 110 for (const blink::WebFormControlElement& control_element : control_elements) { |
| 111 if (!control_element.hasHTMLTagName("input")) |
| 112 continue; |
| 113 |
| 114 const blink::WebInputElement input_element = |
| 115 control_element.toConst<blink::WebInputElement>(); |
| 116 if (input_element.isPasswordField() && |
| 117 (HasAutocompleteAttributeValue(input_element, "current-password") || |
| 118 HasAutocompleteAttributeValue(input_element, "new-password"))) |
| 119 return true; |
| 120 } |
| 121 |
| 122 return false; |
| 123 } |
| 124 |
| 125 // Returns the |field|'s autofillable name. If |ambiguous_or_empty_names| is set |
| 126 // to true returns a dummy name instead. |
| 127 base::string16 FieldName(const FormFieldData& field, |
| 128 bool ambiguous_or_empty_names) { |
| 129 return ambiguous_or_empty_names |
| 130 ? IsPasswordField(field) ? base::ASCIIToUTF16(kDummyPasswordField) |
| 131 : base::ASCIIToUTF16(kDummyUsernameField) |
| 132 : field.name; |
| 133 } |
| 134 |
87 // Utility function to find the unique entry of |control_elements| for the | 135 // 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 | 136 // specified input |field|. On successful find, adds it to |result| and returns |
89 // |true|. Otherwise clears the references from each |HTMLInputElement| from | 137 // |true|. Otherwise clears the references from each |HTMLInputElement| from |
90 // |result| and returns |false|. | 138 // |result| and returns |false|. |
91 bool FindFormInputElement( | 139 bool FindFormInputElement( |
92 const std::vector<blink::WebFormControlElement>& control_elements, | 140 const std::vector<blink::WebFormControlElement>& control_elements, |
93 const FormFieldData& field, | 141 const FormFieldData& field, |
| 142 bool ambiguous_or_empty_names, |
94 FormInputElementMap* result) { | 143 FormInputElementMap* result) { |
95 // Match the first input element, if any. | 144 // 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; | 145 bool found_input = false; |
99 for (size_t i = 0; i < control_elements.size(); ++i) { | 146 bool is_password_field = IsPasswordField(field); |
100 if (control_elements[i].nameForAutofill() != field.name) | 147 bool does_password_field_has_ambigous_or_empty_name = |
| 148 ambiguous_or_empty_names && is_password_field; |
| 149 bool ambiguous_and_multiple_password_fields_with_autocomplete = |
| 150 does_password_field_has_ambigous_or_empty_name && |
| 151 HasPasswordWithAutocompleteAttribute(control_elements); |
| 152 base::string16 field_name = FieldName(field, ambiguous_or_empty_names); |
| 153 for (const blink::WebFormControlElement& control_element : control_elements) { |
| 154 if (!ambiguous_or_empty_names && |
| 155 control_element.nameForAutofill() != field_name) { |
| 156 continue; |
| 157 } |
| 158 |
| 159 if (!control_element.hasHTMLTagName("input")) |
101 continue; | 160 continue; |
102 | 161 |
103 if (!control_elements[i].hasHTMLTagName("input")) | 162 // Only fill saved passwords into password fields and usernames into text |
| 163 // fields. |
| 164 const blink::WebInputElement input_element = |
| 165 control_element.toConst<blink::WebInputElement>(); |
| 166 if (input_element.isPasswordField() != is_password_field) |
104 continue; | 167 continue; |
105 | 168 |
| 169 // For change password form with ambiguous or empty names keep only the |
| 170 // first password field having |autocomplete='current-password'| attribute |
| 171 // set. Also make sure we avoid keeping password fields having |
| 172 // |autocomplete='new-password'| attribute set. |
| 173 if (ambiguous_and_multiple_password_fields_with_autocomplete && |
| 174 !HasAutocompleteAttributeValue(input_element, "current-password")) { |
| 175 continue; |
| 176 } |
| 177 |
106 // Check for a non-unique match. | 178 // Check for a non-unique match. |
107 if (found_input) { | 179 if (found_input) { |
| 180 // For change password form keep only the first password field entry. |
| 181 if (does_password_field_has_ambigous_or_empty_name) |
| 182 continue; |
| 183 |
108 found_input = false; | 184 found_input = false; |
109 break; | 185 break; |
110 } | 186 } |
111 | 187 |
112 // Only fill saved passwords into password fields and usernames into | 188 (*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; | 189 found_input = true; |
122 } | 190 } |
123 | 191 |
124 // A required element was not found. This is not the right form. | 192 // 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 | 193 // Make sure no input elements from a partially matched form in this |
126 // iteration remain in the result set. | 194 // iteration remain in the result set. |
127 // Note: clear will remove a reference from each InputElement. | 195 // Note: clear will remove a reference from each InputElement. |
128 if (!found_input) { | 196 if (!found_input) { |
129 result->clear(); | 197 result->clear(); |
130 return false; | 198 return false; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 | 240 |
173 return group_name != | 241 return group_name != |
174 kFillOnAccountSelectFieldTrialEnabledWithNoHighlightGroup; | 242 kFillOnAccountSelectFieldTrialEnabledWithNoHighlightGroup; |
175 } | 243 } |
176 | 244 |
177 // Helper to search through |control_elements| for the specified input elements | 245 // Helper to search through |control_elements| for the specified input elements |
178 // in |data|, and add results to |result|. | 246 // in |data|, and add results to |result|. |
179 bool FindFormInputElements( | 247 bool FindFormInputElements( |
180 const std::vector<blink::WebFormControlElement>& control_elements, | 248 const std::vector<blink::WebFormControlElement>& control_elements, |
181 const PasswordFormFillData& data, | 249 const PasswordFormFillData& data, |
| 250 bool ambiguous_or_empty_names, |
182 FormInputElementMap* result) { | 251 FormInputElementMap* result) { |
183 return FindFormInputElement(control_elements, data.password_field, result) && | 252 return FindFormInputElement(control_elements, data.password_field, |
| 253 ambiguous_or_empty_names, result) && |
184 (!FillDataContainsFillableUsername(data) || | 254 (!FillDataContainsFillableUsername(data) || |
185 FindFormInputElement(control_elements, data.username_field, result)); | 255 FindFormInputElement(control_elements, data.username_field, |
| 256 ambiguous_or_empty_names, result)); |
186 } | 257 } |
187 | 258 |
188 // Helper to locate form elements identified by |data|. | 259 // Helper to locate form elements identified by |data|. |
189 void FindFormElements(content::RenderFrame* render_frame, | 260 void FindFormElements(content::RenderFrame* render_frame, |
190 const PasswordFormFillData& data, | 261 const PasswordFormFillData& data, |
| 262 bool ambiguous_or_empty_names, |
191 FormElementsList* results) { | 263 FormElementsList* results) { |
192 DCHECK(results); | 264 DCHECK(results); |
193 | 265 |
194 blink::WebDocument doc = render_frame->GetWebFrame()->document(); | 266 blink::WebDocument doc = render_frame->GetWebFrame()->document(); |
195 if (!doc.isHTMLDocument()) | 267 if (!doc.isHTMLDocument()) |
196 return; | 268 return; |
197 | 269 |
198 if (data.origin != GetCanonicalOriginForDocument(doc)) | 270 if (data.origin != GetCanonicalOriginForDocument(doc)) |
199 return; | 271 return; |
200 | 272 |
201 blink::WebVector<blink::WebFormElement> forms; | 273 blink::WebVector<blink::WebFormElement> forms; |
202 doc.forms(forms); | 274 doc.forms(forms); |
203 | 275 |
204 for (size_t i = 0; i < forms.size(); ++i) { | 276 for (size_t i = 0; i < forms.size(); ++i) { |
205 blink::WebFormElement fe = forms[i]; | 277 blink::WebFormElement fe = forms[i]; |
206 | 278 |
207 // Action URL must match. | 279 // Action URL must match. |
208 if (data.action != GetCanonicalActionForForm(fe)) | 280 if (data.action != GetCanonicalActionForForm(fe)) |
209 continue; | 281 continue; |
210 | 282 |
211 std::vector<blink::WebFormControlElement> control_elements = | 283 std::vector<blink::WebFormControlElement> control_elements = |
212 ExtractAutofillableElementsInForm(fe); | 284 ExtractAutofillableElementsInForm(fe); |
213 FormInputElementMap cur_map; | 285 FormInputElementMap cur_map; |
214 if (FindFormInputElements(control_elements, data, &cur_map)) | 286 if (FindFormInputElements(control_elements, data, ambiguous_or_empty_names, |
| 287 &cur_map)) |
215 results->push_back(cur_map); | 288 results->push_back(cur_map); |
216 } | 289 } |
217 // If the element to be filled are not in a <form> element, the "action" and | 290 // If the element to be filled are not in a <form> element, the "action" and |
218 // origin should be the same. | 291 // origin should be the same. |
219 if (data.action != data.origin) | 292 if (data.action != data.origin) |
220 return; | 293 return; |
221 | 294 |
222 std::vector<blink::WebFormControlElement> control_elements = | 295 std::vector<blink::WebFormControlElement> control_elements = |
223 GetUnownedAutofillableFormFieldElements(doc.all(), nullptr); | 296 GetUnownedAutofillableFormFieldElements(doc.all(), nullptr); |
224 FormInputElementMap unowned_elements_map; | 297 FormInputElementMap unowned_elements_map; |
225 if (FindFormInputElements(control_elements, data, &unowned_elements_map)) | 298 if (FindFormInputElements(control_elements, data, ambiguous_or_empty_names, |
| 299 &unowned_elements_map)) |
226 results->push_back(unowned_elements_map); | 300 results->push_back(unowned_elements_map); |
227 } | 301 } |
228 | 302 |
229 bool IsElementEditable(const blink::WebInputElement& element) { | 303 bool IsElementEditable(const blink::WebInputElement& element) { |
230 return element.isEnabled() && !element.isReadOnly(); | 304 return element.isEnabled() && !element.isReadOnly(); |
231 } | 305 } |
232 | 306 |
233 bool DoUsernamesMatch(const base::string16& username1, | 307 bool DoUsernamesMatch(const base::string16& username1, |
234 const base::string16& username2, | 308 const base::string16& username2, |
235 bool exact_match) { | 309 bool exact_match) { |
236 if (exact_match) | 310 if (exact_match) |
237 return username1 == username2; | 311 return username1 == username2; |
238 return FieldIsSuggestionSubstringStartingOnTokenBoundary(username1, username2, | 312 return FieldIsSuggestionSubstringStartingOnTokenBoundary(username1, username2, |
239 true); | 313 true); |
240 } | 314 } |
241 | 315 |
242 // Returns |true| if the given element is editable. Otherwise, returns |false|. | 316 // Returns |true| if the given element is editable. Otherwise, returns |false|. |
243 bool IsElementAutocompletable(const blink::WebInputElement& element) { | 317 bool IsElementAutocompletable(const blink::WebInputElement& element) { |
244 return IsElementEditable(element); | 318 return IsElementEditable(element); |
245 } | 319 } |
246 | 320 |
247 // Return true if either password_value or new_password_value is not empty and | 321 // Return true if either password_value or new_password_value is not empty and |
248 // not default.i | 322 // not default. |
249 bool FormContainsNonDefaultPasswordValue(const PasswordForm& password_form) { | 323 bool FormContainsNonDefaultPasswordValue(const PasswordForm& password_form) { |
250 return (!password_form.password_value.empty() && | 324 return (!password_form.password_value.empty() && |
251 !password_form.password_value_is_default) || | 325 !password_form.password_value_is_default) || |
252 (!password_form.new_password_value.empty() && | 326 (!password_form.new_password_value.empty() && |
253 !password_form.new_password_value_is_default); | 327 !password_form.new_password_value_is_default); |
254 } | 328 } |
255 | 329 |
256 // Log a message including the name, method and action of |form|. | 330 // Log a message including the name, method and action of |form|. |
257 void LogHTMLForm(SavePasswordProgressLogger* logger, | 331 void LogHTMLForm(SavePasswordProgressLogger* logger, |
258 SavePasswordProgressLogger::StringID message_id, | 332 SavePasswordProgressLogger::StringID message_id, |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
446 if (!bottom_frame_origin.equals(cur_frame->securityOrigin().toString())) | 520 if (!bottom_frame_origin.equals(cur_frame->securityOrigin().toString())) |
447 return false; | 521 return false; |
448 } | 522 } |
449 | 523 |
450 // If we can't modify the password, don't try to set the username | 524 // If we can't modify the password, don't try to set the username |
451 if (!IsElementAutocompletable(password_element)) | 525 if (!IsElementAutocompletable(password_element)) |
452 return false; | 526 return false; |
453 | 527 |
454 bool form_contains_fillable_username_field = | 528 bool form_contains_fillable_username_field = |
455 FillDataContainsFillableUsername(fill_data); | 529 FillDataContainsFillableUsername(fill_data); |
| 530 bool ambiguous_or_empty_names = |
| 531 DoesFormContainAmbiguousOrEmptyNames(fill_data); |
| 532 base::string16 username_field_name; |
| 533 if (form_contains_fillable_username_field) |
| 534 username_field_name = |
| 535 FieldName(fill_data.username_field, ambiguous_or_empty_names); |
| 536 |
456 // If the form contains an autocompletable username field, try to set the | 537 // If the form contains an autocompletable username field, try to set the |
457 // username to the preferred name, but only if: | 538 // username to the preferred name, but only if: |
458 // (a) The fill-on-account-select flag is not set, and | 539 // (a) The fill-on-account-select flag is not set, and |
459 // (b) The username element isn't prefilled | 540 // (b) The username element isn't prefilled |
460 // | 541 // |
461 // If (a) is false, then just mark the username element as autofilled if the | 542 // 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 | 543 // user is not in the "no highlighting" group and return so the fill step is |
463 // skipped. | 544 // skipped. |
464 // | 545 // |
465 // If there is no autocompletable username field, and (a) is false, then the | 546 // 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 | 547 // 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 | 548 // 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 | 549 // as autofilled and the fill step should also be skipped if the user is not |
469 // in the "no highlighting" group. | 550 // in the "no highlighting" group. |
470 // | 551 // |
471 // In all other cases, do nothing. | 552 // In all other cases, do nothing. |
472 bool form_has_fillable_username = form_contains_fillable_username_field && | 553 bool form_has_fillable_username = !username_field_name.empty() && |
473 IsElementAutocompletable(username_element); | 554 IsElementAutocompletable(username_element); |
474 | 555 |
475 if (ShouldFillOnAccountSelect()) { | 556 if (ShouldFillOnAccountSelect()) { |
476 if (!ShouldHighlightFields()) { | 557 if (!ShouldHighlightFields()) { |
477 return false; | 558 return false; |
478 } | 559 } |
479 | 560 |
480 if (form_has_fillable_username) { | 561 if (form_has_fillable_username) { |
481 username_element.setAutofilled(true); | 562 username_element.setAutofilled(true); |
482 } else if (username_element.isNull() || | 563 } else if (username_element.isNull() || |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
856 return false; | 937 return false; |
857 | 938 |
858 // If autocomplete='off' is set on the form elements, no suggestion dialog | 939 // 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 | 940 // 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 | 941 // password form and that the request to show suggestions has been handled (as |
861 // a no-op). | 942 // a no-op). |
862 if (!element.isTextField() || !IsElementAutocompletable(element) || | 943 if (!element.isTextField() || !IsElementAutocompletable(element) || |
863 !IsElementAutocompletable(password_info->password_field)) | 944 !IsElementAutocompletable(password_info->password_field)) |
864 return true; | 945 return true; |
865 | 946 |
866 if (element.nameForAutofill().isEmpty()) | 947 if (element.nameForAutofill().isEmpty() && |
| 948 !DoesFormContainAmbiguousOrEmptyNames(password_info->fill_data)) { |
867 return false; // If the field has no name, then we won't have values. | 949 return false; // If the field has no name, then we won't have values. |
| 950 } |
868 | 951 |
869 // Don't attempt to autofill with values that are too large. | 952 // Don't attempt to autofill with values that are too large. |
870 if (element.value().length() > kMaximumTextSizeForAutocomplete) | 953 if (element.value().length() > kMaximumTextSizeForAutocomplete) |
871 return false; | 954 return false; |
872 | 955 |
873 bool username_is_available = | 956 bool username_is_available = |
874 !username_element->isNull() && IsElementEditable(*username_element); | 957 !username_element->isNull() && IsElementEditable(*username_element); |
875 // If the element is a password field, a popup should only be shown if there | 958 // 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 | 959 // 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 | 960 // 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 Loading... |
1229 } | 1312 } |
1230 | 1313 |
1231 // This is a new navigation, so require a new user gesture before filling in | 1314 // This is a new navigation, so require a new user gesture before filling in |
1232 // passwords. | 1315 // passwords. |
1233 gatekeeper_.Reset(); | 1316 gatekeeper_.Reset(); |
1234 } | 1317 } |
1235 | 1318 |
1236 void PasswordAutofillAgent::OnFillPasswordForm( | 1319 void PasswordAutofillAgent::OnFillPasswordForm( |
1237 int key, | 1320 int key, |
1238 const PasswordFormFillData& form_data) { | 1321 const PasswordFormFillData& form_data) { |
1239 | 1322 bool ambiguous_or_empty_names = |
| 1323 DoesFormContainAmbiguousOrEmptyNames(form_data); |
1240 FormElementsList forms; | 1324 FormElementsList forms; |
1241 FindFormElements(render_frame(), form_data, &forms); | 1325 FindFormElements(render_frame(), form_data, ambiguous_or_empty_names, &forms); |
1242 FormElementsList::iterator iter; | 1326 FormElementsList::iterator iter; |
1243 for (iter = forms.begin(); iter != forms.end(); ++iter) { | 1327 for (iter = forms.begin(); iter != forms.end(); ++iter) { |
1244 // Attach autocomplete listener to enable selecting alternate logins. | 1328 // Attach autocomplete listener to enable selecting alternate logins. |
1245 blink::WebInputElement username_element, password_element; | 1329 blink::WebInputElement username_element, password_element; |
1246 | 1330 |
1247 // Check whether the password form has a username input field. | 1331 base::string16 username_field_name, password_field_name; |
| 1332 password_field_name = |
| 1333 FieldName(form_data.password_field, ambiguous_or_empty_names); |
1248 bool form_contains_fillable_username_field = | 1334 bool form_contains_fillable_username_field = |
1249 FillDataContainsFillableUsername(form_data); | 1335 FillDataContainsFillableUsername(form_data); |
1250 if (form_contains_fillable_username_field) { | 1336 if (form_contains_fillable_username_field) |
1251 username_element = | 1337 username_field_name = |
1252 (*iter)[form_data.username_field.name]; | 1338 FieldName(form_data.username_field, ambiguous_or_empty_names); |
| 1339 |
| 1340 // Check whether the password form has a username input field. |
| 1341 if (!username_field_name.empty()) { |
| 1342 username_element = (*iter)[username_field_name]; |
1253 } | 1343 } |
1254 | 1344 |
1255 // No password field, bail out. | 1345 // No password field, bail out. |
1256 if (form_data.password_field.name.empty()) | 1346 if (password_field_name.empty()) |
1257 break; | 1347 break; |
1258 | 1348 |
1259 // We might have already filled this form if there are two <form> elements | 1349 // We might have already filled this form if there are two <form> elements |
1260 // with identical markup. | 1350 // with identical markup. |
1261 if (login_to_password_info_.find(username_element) != | 1351 if (login_to_password_info_.find(username_element) != |
1262 login_to_password_info_.end()) | 1352 login_to_password_info_.end()) |
1263 continue; | 1353 continue; |
1264 | 1354 |
1265 // Get pointer to password element. (We currently only support single | 1355 // Get pointer to password element. (We currently only support single |
1266 // password forms). | 1356 // password forms). |
1267 password_element = (*iter)[form_data.password_field.name]; | 1357 password_element = (*iter)[password_field_name]; |
1268 | 1358 |
1269 // If wait_for_username is true, we don't want to initially fill the form | 1359 // If wait_for_username is true, we don't want to initially fill the form |
1270 // until the user types in a valid username. | 1360 // until the user types in a valid username. |
1271 if (!form_data.wait_for_username) { | 1361 if (!form_data.wait_for_username) { |
1272 FillFormOnPasswordReceived( | 1362 FillFormOnPasswordReceived( |
1273 form_data, | 1363 form_data, |
1274 username_element, | 1364 username_element, |
1275 password_element, | 1365 password_element, |
1276 &nonscript_modified_values_, | 1366 &nonscript_modified_values_, |
1277 base::Bind(&PasswordValueGatekeeper::RegisterElement, | 1367 base::Bind(&PasswordValueGatekeeper::RegisterElement, |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1478 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::DidStopLoading() { | 1568 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::DidStopLoading() { |
1479 agent_->DidStopLoading(); | 1569 agent_->DidStopLoading(); |
1480 } | 1570 } |
1481 | 1571 |
1482 void PasswordAutofillAgent::LegacyPasswordAutofillAgent:: | 1572 void PasswordAutofillAgent::LegacyPasswordAutofillAgent:: |
1483 DidStartProvisionalLoad(blink::WebLocalFrame* navigated_frame) { | 1573 DidStartProvisionalLoad(blink::WebLocalFrame* navigated_frame) { |
1484 agent_->LegacyDidStartProvisionalLoad(navigated_frame); | 1574 agent_->LegacyDidStartProvisionalLoad(navigated_frame); |
1485 } | 1575 } |
1486 | 1576 |
1487 } // namespace autofill | 1577 } // namespace autofill |
OLD | NEW |