Chromium Code Reviews| 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 |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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |