| 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/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| 10 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
| 11 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 12 #include "components/autofill/content/common/autofill_messages.h" | 13 #include "components/autofill/content/common/autofill_messages.h" |
| 13 #include "components/autofill/content/renderer/form_autofill_util.h" | 14 #include "components/autofill/content/renderer/form_autofill_util.h" |
| 14 #include "components/autofill/content/renderer/password_form_conversion_utils.h" | 15 #include "components/autofill/content/renderer/password_form_conversion_utils.h" |
| 15 #include "components/autofill/content/renderer/renderer_save_password_progress_l
ogger.h" | 16 #include "components/autofill/content/renderer/renderer_save_password_progress_l
ogger.h" |
| 17 #include "components/autofill/core/common/autofill_switches.h" |
| 16 #include "components/autofill/core/common/form_field_data.h" | 18 #include "components/autofill/core/common/form_field_data.h" |
| 17 #include "components/autofill/core/common/password_form.h" | 19 #include "components/autofill/core/common/password_form.h" |
| 18 #include "components/autofill/core/common/password_form_fill_data.h" | 20 #include "components/autofill/core/common/password_form_fill_data.h" |
| 19 #include "content/public/renderer/document_state.h" | 21 #include "content/public/renderer/document_state.h" |
| 20 #include "content/public/renderer/navigation_state.h" | 22 #include "content/public/renderer/navigation_state.h" |
| 21 #include "content/public/renderer/render_view.h" | 23 #include "content/public/renderer/render_view.h" |
| 22 #include "third_party/WebKit/public/platform/WebVector.h" | 24 #include "third_party/WebKit/public/platform/WebVector.h" |
| 23 #include "third_party/WebKit/public/web/WebAutofillClient.h" | 25 #include "third_party/WebKit/public/web/WebAutofillClient.h" |
| 24 #include "third_party/WebKit/public/web/WebDocument.h" | 26 #include "third_party/WebKit/public/web/WebDocument.h" |
| 25 #include "third_party/WebKit/public/web/WebElement.h" | 27 #include "third_party/WebKit/public/web/WebElement.h" |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 // iteration remain in the result set. | 114 // iteration remain in the result set. |
| 113 // Note: clear will remove a reference from each InputElement. | 115 // Note: clear will remove a reference from each InputElement. |
| 114 if (!found_input) { | 116 if (!found_input) { |
| 115 result->input_elements.clear(); | 117 result->input_elements.clear(); |
| 116 return false; | 118 return false; |
| 117 } | 119 } |
| 118 | 120 |
| 119 return true; | 121 return true; |
| 120 } | 122 } |
| 121 | 123 |
| 124 bool ShouldFillOnAccountSelect() { |
| 125 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 126 switches::kEnableFillOnAccountSelect)) { |
| 127 return true; |
| 128 } |
| 129 |
| 130 // This is made explicit in anticiption of experimental groups being added. |
| 131 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 132 switches::kDisableFillOnAccountSelect)) { |
| 133 return false; |
| 134 } |
| 135 |
| 136 // TODO(jww): Add experimental groups check here. |
| 137 |
| 138 return false; |
| 139 } |
| 140 |
| 122 // Helper to search the given form element for the specified input elements in | 141 // Helper to search the given form element for the specified input elements in |
| 123 // |data|, and add results to |result|. | 142 // |data|, and add results to |result|. |
| 124 bool FindFormInputElements(blink::WebFormElement* form_element, | 143 bool FindFormInputElements(blink::WebFormElement* form_element, |
| 125 const PasswordFormFillData& data, | 144 const PasswordFormFillData& data, |
| 126 FormElements* result) { | 145 FormElements* result) { |
| 127 return FindFormInputElement(form_element, data.password_field, result) && | 146 return FindFormInputElement(form_element, data.password_field, result) && |
| 128 (!FillDataContainsUsername(data) || | 147 (!FillDataContainsUsername(data) || |
| 129 FindFormInputElement(form_element, data.username_field, result)); | 148 FindFormInputElement(form_element, data.username_field, result)); |
| 130 } | 149 } |
| 131 | 150 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 } | 292 } |
| 274 } | 293 } |
| 275 | 294 |
| 276 return false; | 295 return false; |
| 277 } | 296 } |
| 278 | 297 |
| 279 // This function attempts to fill |username_element| and |password_element| | 298 // This function attempts to fill |username_element| and |password_element| |
| 280 // with values from |fill_data|. The |password_element| will only have the | 299 // with values from |fill_data|. The |password_element| will only have the |
| 281 // |suggestedValue| set, and will be registered for copying that to the real | 300 // |suggestedValue| set, and will be registered for copying that to the real |
| 282 // value through |registration_callback|. The function returns true when | 301 // value through |registration_callback|. The function returns true when |
| 283 // selected username comes from |fill_data.other_possible_usernames|. | 302 // selected username comes from |fill_data.other_possible_usernames|. |options| |
| 303 // should be a bitwise mask of FillUserNameAndPasswordOptions values. |
| 284 bool FillUserNameAndPassword( | 304 bool FillUserNameAndPassword( |
| 285 blink::WebInputElement* username_element, | 305 blink::WebInputElement* username_element, |
| 286 blink::WebInputElement* password_element, | 306 blink::WebInputElement* password_element, |
| 287 const PasswordFormFillData& fill_data, | 307 const PasswordFormFillData& fill_data, |
| 288 bool exact_username_match, | 308 bool exact_username_match, |
| 289 bool set_selection, | 309 bool set_selection, |
| 290 base::Callback<void(blink::WebInputElement*)> registration_callback) { | 310 base::Callback<void(blink::WebInputElement*)> registration_callback) { |
| 291 bool other_possible_username_selected = false; | 311 bool other_possible_username_selected = false; |
| 292 // Don't fill username if password can't be set. | 312 // Don't fill username if password can't be set. |
| 293 if (!IsElementAutocompletable(*password_element)) | 313 if (!IsElementAutocompletable(*password_element)) |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 } | 394 } |
| 375 | 395 |
| 376 // Attempts to fill |username_element| and |password_element| with the | 396 // Attempts to fill |username_element| and |password_element| with the |
| 377 // |fill_data|. Will use the data corresponding to the preferred username, | 397 // |fill_data|. Will use the data corresponding to the preferred username, |
| 378 // unless the |username_element| already has a value set. In that case, | 398 // unless the |username_element| already has a value set. In that case, |
| 379 // attempts to fill the password matching the already filled username, if | 399 // attempts to fill the password matching the already filled username, if |
| 380 // such a password exists. The |password_element| will have the | 400 // such a password exists. The |password_element| will have the |
| 381 // |suggestedValue| set, and |suggestedValue| will be registered for copying to | 401 // |suggestedValue| set, and |suggestedValue| will be registered for copying to |
| 382 // the real value through |registration_callback|. Returns true when the | 402 // the real value through |registration_callback|. Returns true when the |
| 383 // username gets selected from |other_possible_usernames|, else returns false. | 403 // username gets selected from |other_possible_usernames|, else returns false. |
| 384 bool FillFormOnPasswordRecieved( | 404 bool FillFormOnPasswordReceived( |
| 385 const PasswordFormFillData& fill_data, | 405 const PasswordFormFillData& fill_data, |
| 386 blink::WebInputElement username_element, | 406 blink::WebInputElement username_element, |
| 387 blink::WebInputElement password_element, | 407 blink::WebInputElement password_element, |
| 388 base::Callback<void(blink::WebInputElement*)> registration_callback) { | 408 base::Callback<void(blink::WebInputElement*)> registration_callback) { |
| 389 // Do not fill if the password field is in an iframe. | 409 // Do not fill if the password field is in an iframe. |
| 390 DCHECK(password_element.document().frame()); | 410 DCHECK(password_element.document().frame()); |
| 391 if (password_element.document().frame()->parent()) | 411 if (password_element.document().frame()->parent()) |
| 392 return false; | 412 return false; |
| 393 | 413 |
| 394 // If we can't modify the password, don't try to set the username | 414 // If we can't modify the password, don't try to set the username |
| 395 if (!IsElementAutocompletable(password_element)) | 415 if (!IsElementAutocompletable(password_element)) |
| 396 return false; | 416 return false; |
| 397 | 417 |
| 398 bool form_contains_username_field = FillDataContainsUsername(fill_data); | 418 bool form_contains_username_field = FillDataContainsUsername(fill_data); |
| 399 // Try to set the username to the preferred name, but only if the field | 419 // If the form contains a username field, try to set the username to the |
| 400 // can be set and isn't prefilled. | 420 // preferred name, but only if: |
| 401 if (form_contains_username_field && | 421 // (a) The username element is autocompletable, and |
| 402 IsElementAutocompletable(username_element) && | 422 // (b) The fill-on-account-select flag is not set, and |
| 403 username_element.value().isEmpty()) { | 423 // (c) The username element isn't prefilled |
| 404 // TODO(tkent): Check maxlength and pattern. | 424 // |
| 405 username_element.setValue(fill_data.username_field.value, true); | 425 // If (a) is true but (b) is false, then just mark the username element as |
| 426 // autofilled and return so the fill step is skipped. |
| 427 // |
| 428 // If (a) is false but (b) is true, then the username element should not be |
| 429 // autofilled, but the user should still be able to select to fill the |
| 430 // password element, so the password element must be marked as autofilled and |
| 431 // the fill step should also be skipped. |
| 432 // |
| 433 // In all other cases, do nothing. |
| 434 if (form_contains_username_field) { |
| 435 if (IsElementAutocompletable(username_element)) { |
| 436 if (ShouldFillOnAccountSelect()) { |
| 437 username_element.setAutofilled(true); |
| 438 return false; |
| 439 } else if (username_element.value().isEmpty()) { |
| 440 // TODO(tkent): Check maxlength and pattern. |
| 441 username_element.setValue(fill_data.username_field.value, true); |
| 442 } |
| 443 } else if (ShouldFillOnAccountSelect()) { |
| 444 password_element.setAutofilled(true); |
| 445 return false; |
| 446 } |
| 406 } | 447 } |
| 407 | 448 |
| 408 // Fill if we have an exact match for the username. Note that this sets | 449 // Fill if we have an exact match for the username. Note that this sets |
| 409 // username to autofilled. | 450 // username to autofilled. |
| 410 return FillUserNameAndPassword(&username_element, | 451 return FillUserNameAndPassword(&username_element, |
| 411 &password_element, | 452 &password_element, |
| 412 fill_data, | 453 fill_data, |
| 413 true /* exact_username_match */, | 454 true /* exact_username_match */, |
| 414 false /* set_selection */, | 455 false /* set_selection */, |
| 415 registration_callback); | 456 registration_callback); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 507 | 548 |
| 508 blink::WebInputElement password = password_info.password_field; | 549 blink::WebInputElement password = password_info.password_field; |
| 509 if (!IsElementEditable(password)) | 550 if (!IsElementEditable(password)) |
| 510 return false; | 551 return false; |
| 511 | 552 |
| 512 blink::WebInputElement username = element; // We need a non-const. | 553 blink::WebInputElement username = element; // We need a non-const. |
| 513 | 554 |
| 514 // Do not set selection when ending an editing session, otherwise it can | 555 // Do not set selection when ending an editing session, otherwise it can |
| 515 // mess with focus. | 556 // mess with focus. |
| 516 if (FillUserNameAndPassword( | 557 if (FillUserNameAndPassword( |
| 517 &username, | 558 &username, &password, fill_data, true, false, |
| 518 &password, | |
| 519 fill_data, | |
| 520 true /* exact_username_match */, | |
| 521 false /* set_selection */, | |
| 522 base::Bind(&PasswordValueGatekeeper::RegisterElement, | 559 base::Bind(&PasswordValueGatekeeper::RegisterElement, |
| 523 base::Unretained(&gatekeeper_)))) { | 560 base::Unretained(&gatekeeper_)))) { |
| 524 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | 561 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; |
| 525 } | 562 } |
| 526 return true; | 563 return true; |
| 527 } | 564 } |
| 528 | 565 |
| 529 bool PasswordAutofillAgent::TextDidChangeInTextField( | 566 bool PasswordAutofillAgent::TextDidChangeInTextField( |
| 530 const blink::WebInputElement& element) { | 567 const blink::WebInputElement& element) { |
| 531 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 | 568 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 | 611 |
| 575 if (!element.isText() || !IsElementAutocompletable(element) || | 612 if (!element.isText() || !IsElementAutocompletable(element) || |
| 576 !IsElementAutocompletable(password)) { | 613 !IsElementAutocompletable(password)) { |
| 577 return false; | 614 return false; |
| 578 } | 615 } |
| 579 | 616 |
| 580 // Don't inline autocomplete if the user is deleting, that would be confusing. | 617 // Don't inline autocomplete if the user is deleting, that would be confusing. |
| 581 // But refresh the popup. Note, since this is ours, return true to signal | 618 // But refresh the popup. Note, since this is ours, return true to signal |
| 582 // no further processing is required. | 619 // no further processing is required. |
| 583 if (iter->second.backspace_pressed_last) { | 620 if (iter->second.backspace_pressed_last) { |
| 584 ShowSuggestionPopup(iter->second.fill_data, element, false); | 621 ShowSuggestionPopup(iter->second.fill_data, element, false, false); |
| 585 return true; | 622 return true; |
| 586 } | 623 } |
| 587 | 624 |
| 588 blink::WebString name = element.nameForAutofill(); | 625 blink::WebString name = element.nameForAutofill(); |
| 589 if (name.isEmpty()) | 626 if (name.isEmpty()) |
| 590 return false; // If the field has no name, then we won't have values. | 627 return false; // If the field has no name, then we won't have values. |
| 591 | 628 |
| 592 // Don't attempt to autofill with values that are too large. | 629 // Don't attempt to autofill with values that are too large. |
| 593 if (element.value().length() > kMaximumTextSizeForAutocomplete) | 630 if (element.value().length() > kMaximumTextSizeForAutocomplete) |
| 594 return false; | 631 return false; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 const blink::WebNode& node) { | 708 const blink::WebNode& node) { |
| 672 blink::WebInputElement username_element; | 709 blink::WebInputElement username_element; |
| 673 PasswordInfo* password_info; | 710 PasswordInfo* password_info; |
| 674 if (!FindLoginInfo(node, &username_element, &password_info)) | 711 if (!FindLoginInfo(node, &username_element, &password_info)) |
| 675 return false; | 712 return false; |
| 676 | 713 |
| 677 ClearPreview(&username_element, &password_info->password_field); | 714 ClearPreview(&username_element, &password_info->password_field); |
| 678 return true; | 715 return true; |
| 679 } | 716 } |
| 680 | 717 |
| 718 PasswordAutofillAgent::LoginToPasswordInfoMap::iterator |
| 719 PasswordAutofillAgent::FindPasswordInfoForElement( |
| 720 const blink::WebInputElement& element) { |
| 721 const blink::WebInputElement* username_element; |
| 722 if (!element.isPasswordField()) { |
| 723 username_element = &element; |
| 724 } else { |
| 725 PasswordToLoginMap::const_iterator password_iter = |
| 726 password_to_username_.find(element); |
| 727 if (password_iter == password_to_username_.end()) |
| 728 return login_to_password_info_.end(); |
| 729 username_element = &password_iter->second; |
| 730 } |
| 731 |
| 732 return login_to_password_info_.find(*username_element); |
| 733 } |
| 734 |
| 681 bool PasswordAutofillAgent::ShowSuggestions( | 735 bool PasswordAutofillAgent::ShowSuggestions( |
| 682 const blink::WebInputElement& element, | 736 const blink::WebInputElement& element, |
| 683 bool show_all) { | 737 bool show_all) { |
| 684 LoginToPasswordInfoMap::const_iterator iter = | 738 LoginToPasswordInfoMap::const_iterator iter = |
| 685 login_to_password_info_.find(element); | 739 FindPasswordInfoForElement(element); |
| 686 if (iter == login_to_password_info_.end()) | 740 if (iter == login_to_password_info_.end()) |
| 687 return false; | 741 return false; |
| 688 | 742 |
| 689 // If autocomplete='off' is set on the form elements, no suggestion dialog | 743 // If autocomplete='off' is set on the form elements, no suggestion dialog |
| 690 // should be shown. However, return |true| to indicate that this is a known | 744 // should be shown. However, return |true| to indicate that this is a known |
| 691 // password form and that the request to show suggestions has been handled (as | 745 // password form and that the request to show suggestions has been handled (as |
| 692 // a no-op). | 746 // a no-op). |
| 693 if (!IsElementAutocompletable(element) || | 747 if (!IsElementAutocompletable(element) || |
| 694 !IsElementAutocompletable(iter->second.password_field)) | 748 !IsElementAutocompletable(iter->second.password_field)) |
| 695 return true; | 749 return true; |
| 696 | 750 |
| 697 return ShowSuggestionPopup(iter->second.fill_data, element, show_all); | 751 // Chrome should never show more than one account for a password element since |
| 752 // this implies that the username element cannot be modified. Thus even if |
| 753 // |show_all| is true, check if the element in question is a password element |
| 754 // for the call to ShowSuggestionPopup. |
| 755 return ShowSuggestionPopup(iter->second.fill_data, iter->first, |
| 756 show_all && !element.isPasswordField(), |
| 757 element.isPasswordField()); |
| 698 } | 758 } |
| 699 | 759 |
| 700 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( | 760 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( |
| 701 const blink::WebSecurityOrigin& origin) { | 761 const blink::WebSecurityOrigin& origin) { |
| 702 return origin.canAccessPasswordManager(); | 762 return origin.canAccessPasswordManager(); |
| 703 } | 763 } |
| 704 | 764 |
| 705 void PasswordAutofillAgent::OnDynamicFormsSeen(blink::WebFrame* frame) { | 765 void PasswordAutofillAgent::OnDynamicFormsSeen(blink::WebFrame* frame) { |
| 706 SendPasswordForms(frame, false /* only_visible */); | 766 SendPasswordForms(frame, false /* only_visible */); |
| 707 } | 767 } |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1035 break; | 1095 break; |
| 1036 | 1096 |
| 1037 // Get pointer to password element. (We currently only support single | 1097 // Get pointer to password element. (We currently only support single |
| 1038 // password forms). | 1098 // password forms). |
| 1039 password_element = | 1099 password_element = |
| 1040 form_elements->input_elements[form_data.password_field.name]; | 1100 form_elements->input_elements[form_data.password_field.name]; |
| 1041 | 1101 |
| 1042 // If wait_for_username is true, we don't want to initially fill the form | 1102 // If wait_for_username is true, we don't want to initially fill the form |
| 1043 // until the user types in a valid username. | 1103 // until the user types in a valid username. |
| 1044 if (!form_data.wait_for_username && | 1104 if (!form_data.wait_for_username && |
| 1045 FillFormOnPasswordRecieved( | 1105 FillFormOnPasswordReceived( |
| 1046 form_data, | 1106 form_data, username_element, password_element, |
| 1047 username_element, | |
| 1048 password_element, | |
| 1049 base::Bind(&PasswordValueGatekeeper::RegisterElement, | 1107 base::Bind(&PasswordValueGatekeeper::RegisterElement, |
| 1050 base::Unretained(&gatekeeper_)))) { | 1108 base::Unretained(&gatekeeper_)))) { |
| 1051 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | 1109 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; |
| 1052 } | 1110 } |
| 1053 // We might have already filled this form if there are two <form> elements | 1111 // We might have already filled this form if there are two <form> elements |
| 1054 // with identical markup. | 1112 // with identical markup. |
| 1055 if (login_to_password_info_.find(username_element) != | 1113 if (login_to_password_info_.find(username_element) != |
| 1056 login_to_password_info_.end()) | 1114 login_to_password_info_.end()) |
| 1057 continue; | 1115 continue; |
| 1058 | 1116 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1072 //////////////////////////////////////////////////////////////////////////////// | 1130 //////////////////////////////////////////////////////////////////////////////// |
| 1073 // PasswordAutofillAgent, private: | 1131 // PasswordAutofillAgent, private: |
| 1074 | 1132 |
| 1075 PasswordAutofillAgent::PasswordInfo::PasswordInfo() | 1133 PasswordAutofillAgent::PasswordInfo::PasswordInfo() |
| 1076 : backspace_pressed_last(false), password_was_edited_last(false) { | 1134 : backspace_pressed_last(false), password_was_edited_last(false) { |
| 1077 } | 1135 } |
| 1078 | 1136 |
| 1079 bool PasswordAutofillAgent::ShowSuggestionPopup( | 1137 bool PasswordAutofillAgent::ShowSuggestionPopup( |
| 1080 const PasswordFormFillData& fill_data, | 1138 const PasswordFormFillData& fill_data, |
| 1081 const blink::WebInputElement& user_input, | 1139 const blink::WebInputElement& user_input, |
| 1082 bool show_all) { | 1140 bool show_all, |
| 1141 bool show_on_password_field) { |
| 1083 blink::WebFrame* frame = user_input.document().frame(); | 1142 blink::WebFrame* frame = user_input.document().frame(); |
| 1084 if (!frame) | 1143 if (!frame) |
| 1085 return false; | 1144 return false; |
| 1086 | 1145 |
| 1087 blink::WebView* webview = frame->view(); | 1146 blink::WebView* webview = frame->view(); |
| 1088 if (!webview) | 1147 if (!webview) |
| 1089 return false; | 1148 return false; |
| 1090 | 1149 |
| 1091 FormData form; | 1150 FormData form; |
| 1092 FormFieldData field; | 1151 FormFieldData field; |
| 1093 FindFormAndFieldForFormControlElement( | 1152 FindFormAndFieldForFormControlElement( |
| 1094 user_input, &form, &field, REQUIRE_NONE); | 1153 user_input, &form, &field, REQUIRE_NONE); |
| 1095 | 1154 |
| 1096 blink::WebInputElement selected_element = user_input; | 1155 blink::WebInputElement selected_element = user_input; |
| 1156 if (show_on_password_field) { |
| 1157 LoginToPasswordInfoMap::const_iterator iter = |
| 1158 login_to_password_info_.find(user_input); |
| 1159 DCHECK(iter != login_to_password_info_.end()); |
| 1160 selected_element = iter->second.password_field; |
| 1161 } |
| 1097 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); | 1162 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); |
| 1098 | 1163 |
| 1099 LoginToPasswordInfoKeyMap::const_iterator key_it = | 1164 LoginToPasswordInfoKeyMap::const_iterator key_it = |
| 1100 login_to_password_info_key_.find(user_input); | 1165 login_to_password_info_key_.find(user_input); |
| 1101 DCHECK(key_it != login_to_password_info_key_.end()); | 1166 DCHECK(key_it != login_to_password_info_key_.end()); |
| 1102 | 1167 |
| 1103 float scale = web_view_->pageScaleFactor(); | 1168 float scale = web_view_->pageScaleFactor(); |
| 1104 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, | 1169 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, |
| 1105 bounding_box.y() * scale, | 1170 bounding_box.y() * scale, |
| 1106 bounding_box.width() * scale, | 1171 bounding_box.width() * scale, |
| 1107 bounding_box.height() * scale); | 1172 bounding_box.height() * scale); |
| 1173 int options = 0; |
| 1174 if (show_all) |
| 1175 options |= ShowPasswordSuggestionsOptions::SHOW_ALL; |
| 1176 if (show_on_password_field) |
| 1177 options |= ShowPasswordSuggestionsOptions::IS_PASSWORD_FIELD; |
| 1108 Send(new AutofillHostMsg_ShowPasswordSuggestions( | 1178 Send(new AutofillHostMsg_ShowPasswordSuggestions( |
| 1109 routing_id(), key_it->second, field.text_direction, user_input.value(), | 1179 routing_id(), key_it->second, field.text_direction, user_input.value(), |
| 1110 show_all, bounding_box_scaled)); | 1180 options, bounding_box_scaled)); |
| 1111 | 1181 |
| 1112 bool suggestions_present = false; | 1182 bool suggestions_present = false; |
| 1113 if (GetSuggestionsStats(fill_data, user_input.value(), show_all, | 1183 if (GetSuggestionsStats(fill_data, user_input.value(), show_all, |
| 1114 &suggestions_present)) { | 1184 &suggestions_present)) { |
| 1115 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN; | 1185 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN; |
| 1116 } | 1186 } |
| 1117 return suggestions_present; | 1187 return suggestions_present; |
| 1118 } | 1188 } |
| 1119 | 1189 |
| 1120 void PasswordAutofillAgent::PerformInlineAutocomplete( | 1190 void PasswordAutofillAgent::PerformInlineAutocomplete( |
| 1121 const blink::WebInputElement& username_input, | 1191 const blink::WebInputElement& username_input, |
| 1122 const blink::WebInputElement& password_input, | 1192 const blink::WebInputElement& password_input, |
| 1123 const PasswordFormFillData& fill_data) { | 1193 const PasswordFormFillData& fill_data) { |
| 1124 DCHECK(!fill_data.wait_for_username); | 1194 DCHECK(!fill_data.wait_for_username); |
| 1125 | 1195 |
| 1126 // We need non-const versions of the username and password inputs. | 1196 // We need non-const versions of the username and password inputs. |
| 1127 blink::WebInputElement username = username_input; | 1197 blink::WebInputElement username = username_input; |
| 1128 blink::WebInputElement password = password_input; | 1198 blink::WebInputElement password = password_input; |
| 1129 | 1199 |
| 1130 // Don't inline autocomplete if the caret is not at the end. | 1200 // Don't inline autocomplete if the caret is not at the end. |
| 1131 // TODO(jcivelli): is there a better way to test the caret location? | 1201 // TODO(jcivelli): is there a better way to test the caret location? |
| 1132 if (username.selectionStart() != username.selectionEnd() || | 1202 if (username.selectionStart() != username.selectionEnd() || |
| 1133 username.selectionEnd() != static_cast<int>(username.value().length())) { | 1203 username.selectionEnd() != static_cast<int>(username.value().length())) { |
| 1134 return; | 1204 return; |
| 1135 } | 1205 } |
| 1136 | 1206 |
| 1137 // Show the popup with the list of available usernames. | 1207 // Show the popup with the list of available usernames. |
| 1138 ShowSuggestionPopup(fill_data, username, false); | 1208 ShowSuggestionPopup(fill_data, username, false, false); |
| 1139 | 1209 |
| 1140 #if !defined(OS_ANDROID) | 1210 #if !defined(OS_ANDROID) |
| 1141 // Fill the user and password field with the most relevant match. Android | 1211 // Fill the user and password field with the most relevant match. Android |
| 1142 // only fills in the fields after the user clicks on the suggestion popup. | 1212 // only fills in the fields after the user clicks on the suggestion popup. |
| 1143 if (FillUserNameAndPassword( | 1213 if (FillUserNameAndPassword( |
| 1144 &username, | 1214 &username, &password, fill_data, false, true, |
| 1145 &password, | |
| 1146 fill_data, | |
| 1147 false /* exact_username_match */, | |
| 1148 true /* set_selection */, | |
| 1149 base::Bind(&PasswordValueGatekeeper::RegisterElement, | 1215 base::Bind(&PasswordValueGatekeeper::RegisterElement, |
| 1150 base::Unretained(&gatekeeper_)))) { | 1216 base::Unretained(&gatekeeper_)))) { |
| 1151 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | 1217 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; |
| 1152 } | 1218 } |
| 1153 #endif | 1219 #endif |
| 1154 } | 1220 } |
| 1155 | 1221 |
| 1156 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { | 1222 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { |
| 1157 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); | 1223 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); |
| 1158 iter != login_to_password_info_.end();) { | 1224 iter != login_to_password_info_.end();) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1180 blink::WebInputElement* found_input, | 1246 blink::WebInputElement* found_input, |
| 1181 PasswordInfo** found_password) { | 1247 PasswordInfo** found_password) { |
| 1182 if (!node.isElementNode()) | 1248 if (!node.isElementNode()) |
| 1183 return false; | 1249 return false; |
| 1184 | 1250 |
| 1185 blink::WebElement element = node.toConst<blink::WebElement>(); | 1251 blink::WebElement element = node.toConst<blink::WebElement>(); |
| 1186 if (!element.hasHTMLTagName("input")) | 1252 if (!element.hasHTMLTagName("input")) |
| 1187 return false; | 1253 return false; |
| 1188 | 1254 |
| 1189 blink::WebInputElement input = element.to<blink::WebInputElement>(); | 1255 blink::WebInputElement input = element.to<blink::WebInputElement>(); |
| 1190 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(input); | 1256 LoginToPasswordInfoMap::iterator iter = FindPasswordInfoForElement(input); |
| 1191 if (iter == login_to_password_info_.end()) | 1257 if (iter == login_to_password_info_.end()) |
| 1192 return false; | 1258 return false; |
| 1193 | 1259 |
| 1194 *found_input = input; | 1260 *found_input = input; |
| 1195 *found_password = &iter->second; | 1261 *found_password = &iter->second; |
| 1196 return true; | 1262 return true; |
| 1197 } | 1263 } |
| 1198 | 1264 |
| 1199 void PasswordAutofillAgent::ClearPreview( | 1265 void PasswordAutofillAgent::ClearPreview( |
| 1200 blink::WebInputElement* username, | 1266 blink::WebInputElement* username, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1226 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); | 1292 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); |
| 1227 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && | 1293 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && |
| 1228 password_form->password_value.empty() && | 1294 password_form->password_value.empty() && |
| 1229 password_form->new_password_value.empty())) { | 1295 password_form->new_password_value.empty())) { |
| 1230 return; | 1296 return; |
| 1231 } | 1297 } |
| 1232 provisionally_saved_forms_[frame].reset(password_form.release()); | 1298 provisionally_saved_forms_[frame].reset(password_form.release()); |
| 1233 } | 1299 } |
| 1234 | 1300 |
| 1235 } // namespace autofill | 1301 } // namespace autofill |
| OLD | NEW |