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/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" |
| 11 #include "base/metrics/field_trial.h" | |
| 10 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 11 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
| 12 #include "components/autofill/content/common/autofill_messages.h" | 14 #include "components/autofill/content/common/autofill_messages.h" |
| 13 #include "components/autofill/content/renderer/form_autofill_util.h" | 15 #include "components/autofill/content/renderer/form_autofill_util.h" |
| 14 #include "components/autofill/content/renderer/password_form_conversion_utils.h" | 16 #include "components/autofill/content/renderer/password_form_conversion_utils.h" |
| 15 #include "components/autofill/content/renderer/renderer_save_password_progress_l ogger.h" | 17 #include "components/autofill/content/renderer/renderer_save_password_progress_l ogger.h" |
| 16 #include "components/autofill/core/common/autofill_constants.h" | 18 #include "components/autofill/core/common/autofill_constants.h" |
| 19 #include "components/autofill/core/common/autofill_switches.h" | |
| 17 #include "components/autofill/core/common/form_field_data.h" | 20 #include "components/autofill/core/common/form_field_data.h" |
| 18 #include "components/autofill/core/common/password_form.h" | 21 #include "components/autofill/core/common/password_form.h" |
| 19 #include "components/autofill/core/common/password_form_fill_data.h" | 22 #include "components/autofill/core/common/password_form_fill_data.h" |
| 20 #include "content/public/renderer/document_state.h" | 23 #include "content/public/renderer/document_state.h" |
| 21 #include "content/public/renderer/navigation_state.h" | 24 #include "content/public/renderer/navigation_state.h" |
| 22 #include "content/public/renderer/render_frame.h" | 25 #include "content/public/renderer/render_frame.h" |
| 23 #include "content/public/renderer/render_view.h" | 26 #include "content/public/renderer/render_view.h" |
| 24 #include "third_party/WebKit/public/platform/WebVector.h" | 27 #include "third_party/WebKit/public/platform/WebVector.h" |
| 25 #include "third_party/WebKit/public/web/WebAutofillClient.h" | 28 #include "third_party/WebKit/public/web/WebAutofillClient.h" |
| 26 #include "third_party/WebKit/public/web/WebDocument.h" | 29 #include "third_party/WebKit/public/web/WebDocument.h" |
| 27 #include "third_party/WebKit/public/web/WebElement.h" | 30 #include "third_party/WebKit/public/web/WebElement.h" |
| 28 #include "third_party/WebKit/public/web/WebFormElement.h" | 31 #include "third_party/WebKit/public/web/WebFormElement.h" |
| 29 #include "third_party/WebKit/public/web/WebInputEvent.h" | 32 #include "third_party/WebKit/public/web/WebInputEvent.h" |
| 30 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 33 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
| 31 #include "third_party/WebKit/public/web/WebNode.h" | 34 #include "third_party/WebKit/public/web/WebNode.h" |
| 32 #include "third_party/WebKit/public/web/WebNodeList.h" | 35 #include "third_party/WebKit/public/web/WebNodeList.h" |
| 33 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" | 36 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" |
| 34 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" | 37 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" |
| 35 #include "third_party/WebKit/public/web/WebView.h" | 38 #include "third_party/WebKit/public/web/WebView.h" |
| 36 #include "ui/base/page_transition_types.h" | 39 #include "ui/base/page_transition_types.h" |
| 37 #include "ui/events/keycodes/keyboard_codes.h" | 40 #include "ui/events/keycodes/keyboard_codes.h" |
| 38 #include "url/gurl.h" | 41 #include "url/gurl.h" |
| 39 | 42 |
| 40 namespace autofill { | 43 namespace autofill { |
| 41 namespace { | 44 namespace { |
| 42 | 45 |
| 43 // The size above which we stop triggering autocomplete. | 46 // The size above which we stop triggering autocomplete. |
| 44 static const size_t kMaximumTextSizeForAutocomplete = 1000; | 47 static const size_t kMaximumTextSizeForAutocomplete = 1000; |
| 45 | 48 |
| 49 // Experiment information | |
| 50 const char kFillOnAccountSelectFieldTrialName[] = "FillOnAccountSelect"; | |
| 51 const char kFillOnAccountSelectFieldTrialEnabledGroup[] = "Enable"; | |
| 52 | |
| 46 // Maps element names to the actual elements to simplify form filling. | 53 // Maps element names to the actual elements to simplify form filling. |
| 47 typedef std::map<base::string16, blink::WebInputElement> FormInputElementMap; | 54 typedef std::map<base::string16, blink::WebInputElement> FormInputElementMap; |
| 48 | 55 |
| 49 // Use the shorter name when referencing SavePasswordProgressLogger::StringID | 56 // Use the shorter name when referencing SavePasswordProgressLogger::StringID |
| 50 // values to spare line breaks. The code provides enough context for that | 57 // values to spare line breaks. The code provides enough context for that |
| 51 // already. | 58 // already. |
| 52 typedef SavePasswordProgressLogger Logger; | 59 typedef SavePasswordProgressLogger Logger; |
| 53 | 60 |
| 54 // Utility struct for form lookup and autofill. When we parse the DOM to look up | 61 // Utility struct for form lookup and autofill. When we parse the DOM to look up |
| 55 // a form, in addition to action and origin URL's we have to compare all | 62 // a form, in addition to action and origin URL's we have to compare all |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 114 // iteration remain in the result set. | 121 // iteration remain in the result set. |
| 115 // Note: clear will remove a reference from each InputElement. | 122 // Note: clear will remove a reference from each InputElement. |
| 116 if (!found_input) { | 123 if (!found_input) { |
| 117 result->input_elements.clear(); | 124 result->input_elements.clear(); |
| 118 return false; | 125 return false; |
| 119 } | 126 } |
| 120 | 127 |
| 121 return true; | 128 return true; |
| 122 } | 129 } |
| 123 | 130 |
| 131 bool ShouldFillOnAccountSelect() { | |
| 132 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
| 133 switches::kDisableFillOnAccountSelect)) { | |
| 134 return false; | |
| 135 } | |
| 136 | |
| 137 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
| 138 switches::kEnableFillOnAccountSelect)) { | |
| 139 return true; | |
| 140 } | |
| 141 | |
| 142 std::string group_name = | |
| 143 base::FieldTrialList::FindFullName(kFillOnAccountSelectFieldTrialName); | |
|
Ilya Sherman
2014/12/11 23:28:55
You should query the field trial first, before che
jww
2014/12/12 00:17:43
Don't we want the opposite of that though? Namely,
Ilya Sherman
2014/12/12 00:25:50
The ordering should be
// Call FieldTrialList::Fi
jww
2014/12/12 00:54:55
Done.
| |
| 144 return group_name.compare(kFillOnAccountSelectFieldTrialEnabledGroup) == 0; | |
|
Ilya Sherman
2014/12/11 23:28:55
Optional nit: I think operator== is clearer here.
jww
2014/12/12 00:17:43
Done.
| |
| 145 } | |
| 146 | |
| 124 // Helper to search the given form element for the specified input elements in | 147 // Helper to search the given form element for the specified input elements in |
| 125 // |data|, and add results to |result|. | 148 // |data|, and add results to |result|. |
| 126 bool FindFormInputElements(blink::WebFormElement* form_element, | 149 bool FindFormInputElements(blink::WebFormElement* form_element, |
| 127 const PasswordFormFillData& data, | 150 const PasswordFormFillData& data, |
| 128 FormElements* result) { | 151 FormElements* result) { |
| 129 return FindFormInputElement(form_element, data.password_field, result) && | 152 return FindFormInputElement(form_element, data.password_field, result) && |
| 130 (!FillDataContainsUsername(data) || | 153 (!FillDataContainsUsername(data) || |
| 131 FindFormInputElement(form_element, data.username_field, result)); | 154 FindFormInputElement(form_element, data.username_field, result)); |
| 132 } | 155 } |
| 133 | 156 |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 268 } | 291 } |
| 269 } | 292 } |
| 270 | 293 |
| 271 return false; | 294 return false; |
| 272 } | 295 } |
| 273 | 296 |
| 274 // This function attempts to fill |username_element| and |password_element| | 297 // This function attempts to fill |username_element| and |password_element| |
| 275 // with values from |fill_data|. The |password_element| will only have the | 298 // with values from |fill_data|. The |password_element| will only have the |
| 276 // |suggestedValue| set, and will be registered for copying that to the real | 299 // |suggestedValue| set, and will be registered for copying that to the real |
| 277 // value through |registration_callback|. The function returns true when | 300 // value through |registration_callback|. The function returns true when |
| 278 // selected username comes from |fill_data.other_possible_usernames|. | 301 // selected username comes from |fill_data.other_possible_usernames|. |options| |
| 302 // should be a bitwise mask of FillUserNameAndPasswordOptions values. | |
| 279 bool FillUserNameAndPassword( | 303 bool FillUserNameAndPassword( |
| 280 blink::WebInputElement* username_element, | 304 blink::WebInputElement* username_element, |
| 281 blink::WebInputElement* password_element, | 305 blink::WebInputElement* password_element, |
| 282 const PasswordFormFillData& fill_data, | 306 const PasswordFormFillData& fill_data, |
| 283 bool exact_username_match, | 307 bool exact_username_match, |
| 284 bool set_selection, | 308 bool set_selection, |
| 285 base::Callback<void(blink::WebInputElement*)> registration_callback) { | 309 base::Callback<void(blink::WebInputElement*)> registration_callback) { |
| 286 bool other_possible_username_selected = false; | 310 bool other_possible_username_selected = false; |
| 287 // Don't fill username if password can't be set. | 311 // Don't fill username if password can't be set. |
| 288 if (!IsElementAutocompletable(*password_element)) | 312 if (!IsElementAutocompletable(*password_element)) |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 384 // Do not fill if the password field is in an iframe. | 408 // Do not fill if the password field is in an iframe. |
| 385 DCHECK(password_element.document().frame()); | 409 DCHECK(password_element.document().frame()); |
| 386 if (password_element.document().frame()->parent()) | 410 if (password_element.document().frame()->parent()) |
| 387 return false; | 411 return false; |
| 388 | 412 |
| 389 // If we can't modify the password, don't try to set the username | 413 // If we can't modify the password, don't try to set the username |
| 390 if (!IsElementAutocompletable(password_element)) | 414 if (!IsElementAutocompletable(password_element)) |
| 391 return false; | 415 return false; |
| 392 | 416 |
| 393 bool form_contains_username_field = FillDataContainsUsername(fill_data); | 417 bool form_contains_username_field = FillDataContainsUsername(fill_data); |
| 394 // Try to set the username to the preferred name, but only if the field | 418 // If the form contains a username field, try to set the username to the |
| 395 // can be set and isn't prefilled. | 419 // preferred name, but only if: |
| 396 if (form_contains_username_field && | 420 // (a) The username element is autocompletable, and |
| 397 IsElementAutocompletable(username_element) && | 421 // (b) The fill-on-account-select flag is not set, and |
| 398 username_element.value().isEmpty()) { | 422 // (c) The username element isn't prefilled |
| 399 // TODO(tkent): Check maxlength and pattern. | 423 // |
| 400 username_element.setValue(fill_data.username_field.value, true); | 424 // If (a) is true but (b) is false, then just mark the username element as |
| 425 // autofilled and return so the fill step is skipped. | |
| 426 // | |
| 427 // If (a) is false but (b) is true, then the username element should not be | |
| 428 // autofilled, but the user should still be able to select to fill the | |
| 429 // password element, so the password element must be marked as autofilled and | |
| 430 // the fill step should also be skipped. | |
| 431 // | |
| 432 // In all other cases, do nothing. | |
| 433 if (form_contains_username_field) { | |
| 434 if (IsElementAutocompletable(username_element)) { | |
| 435 if (ShouldFillOnAccountSelect()) { | |
| 436 username_element.setAutofilled(true); | |
| 437 return false; | |
| 438 } else if (username_element.value().isEmpty()) { | |
| 439 // TODO(tkent): Check maxlength and pattern. | |
| 440 username_element.setValue(fill_data.username_field.value, true); | |
| 441 } | |
| 442 } else if (ShouldFillOnAccountSelect()) { | |
| 443 password_element.setAutofilled(true); | |
| 444 return false; | |
| 445 } | |
| 401 } | 446 } |
| 402 | 447 |
| 403 // Fill if we have an exact match for the username. Note that this sets | 448 // Fill if we have an exact match for the username. Note that this sets |
| 404 // username to autofilled. | 449 // username to autofilled. |
| 405 return FillUserNameAndPassword(&username_element, | 450 return FillUserNameAndPassword(&username_element, |
| 406 &password_element, | 451 &password_element, |
| 407 fill_data, | 452 fill_data, |
| 408 true /* exact_username_match */, | 453 true /* exact_username_match */, |
| 409 false /* set_selection */, | 454 false /* set_selection */, |
| 410 registration_callback); | 455 registration_callback); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 502 | 547 |
| 503 blink::WebInputElement password = password_info.password_field; | 548 blink::WebInputElement password = password_info.password_field; |
| 504 if (!IsElementEditable(password)) | 549 if (!IsElementEditable(password)) |
| 505 return false; | 550 return false; |
| 506 | 551 |
| 507 blink::WebInputElement username = element; // We need a non-const. | 552 blink::WebInputElement username = element; // We need a non-const. |
| 508 | 553 |
| 509 // Do not set selection when ending an editing session, otherwise it can | 554 // Do not set selection when ending an editing session, otherwise it can |
| 510 // mess with focus. | 555 // mess with focus. |
| 511 if (FillUserNameAndPassword( | 556 if (FillUserNameAndPassword( |
| 512 &username, | 557 &username, &password, fill_data, true, false, |
| 513 &password, | |
| 514 fill_data, | |
| 515 true /* exact_username_match */, | |
| 516 false /* set_selection */, | |
| 517 base::Bind(&PasswordValueGatekeeper::RegisterElement, | 558 base::Bind(&PasswordValueGatekeeper::RegisterElement, |
| 518 base::Unretained(&gatekeeper_)))) { | 559 base::Unretained(&gatekeeper_)))) { |
| 519 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | 560 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; |
| 520 } | 561 } |
| 521 return true; | 562 return true; |
| 522 } | 563 } |
| 523 | 564 |
| 524 bool PasswordAutofillAgent::TextDidChangeInTextField( | 565 bool PasswordAutofillAgent::TextDidChangeInTextField( |
| 525 const blink::WebInputElement& element) { | 566 const blink::WebInputElement& element) { |
| 526 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 | 567 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 568 | 609 |
| 569 if (!element.isText() || !IsElementAutocompletable(element) || | 610 if (!element.isText() || !IsElementAutocompletable(element) || |
| 570 !IsElementAutocompletable(password)) { | 611 !IsElementAutocompletable(password)) { |
| 571 return false; | 612 return false; |
| 572 } | 613 } |
| 573 | 614 |
| 574 // Don't inline autocomplete if the user is deleting, that would be confusing. | 615 // Don't inline autocomplete if the user is deleting, that would be confusing. |
| 575 // But refresh the popup. Note, since this is ours, return true to signal | 616 // But refresh the popup. Note, since this is ours, return true to signal |
| 576 // no further processing is required. | 617 // no further processing is required. |
| 577 if (iter->second.backspace_pressed_last) { | 618 if (iter->second.backspace_pressed_last) { |
| 578 ShowSuggestionPopup(iter->second.fill_data, element, false); | 619 ShowSuggestionPopup(iter->second.fill_data, element, false, false); |
| 579 return true; | 620 return true; |
| 580 } | 621 } |
| 581 | 622 |
| 582 blink::WebString name = element.nameForAutofill(); | 623 blink::WebString name = element.nameForAutofill(); |
| 583 if (name.isEmpty()) | 624 if (name.isEmpty()) |
| 584 return false; // If the field has no name, then we won't have values. | 625 return false; // If the field has no name, then we won't have values. |
| 585 | 626 |
| 586 // Don't attempt to autofill with values that are too large. | 627 // Don't attempt to autofill with values that are too large. |
| 587 if (element.value().length() > kMaximumTextSizeForAutocomplete) | 628 if (element.value().length() > kMaximumTextSizeForAutocomplete) |
| 588 return false; | 629 return false; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 665 const blink::WebNode& node) { | 706 const blink::WebNode& node) { |
| 666 blink::WebInputElement username_element; | 707 blink::WebInputElement username_element; |
| 667 PasswordInfo* password_info; | 708 PasswordInfo* password_info; |
| 668 if (!FindLoginInfo(node, &username_element, &password_info)) | 709 if (!FindLoginInfo(node, &username_element, &password_info)) |
| 669 return false; | 710 return false; |
| 670 | 711 |
| 671 ClearPreview(&username_element, &password_info->password_field); | 712 ClearPreview(&username_element, &password_info->password_field); |
| 672 return true; | 713 return true; |
| 673 } | 714 } |
| 674 | 715 |
| 716 bool PasswordAutofillAgent::FindPasswordInfoForElement( | |
| 717 const blink::WebInputElement& element, | |
| 718 const blink::WebInputElement** username_element, | |
| 719 PasswordInfo** password_info) { | |
| 720 DCHECK(username_element && password_info); | |
| 721 if (!element.isPasswordField()) { | |
| 722 *username_element = &element; | |
| 723 } else { | |
| 724 PasswordToLoginMap::const_iterator password_iter = | |
| 725 password_to_username_.find(element); | |
| 726 if (password_iter == password_to_username_.end()) | |
| 727 return false; | |
| 728 *username_element = &password_iter->second; | |
| 729 } | |
| 730 | |
| 731 LoginToPasswordInfoMap::iterator iter = | |
| 732 login_to_password_info_.find(**username_element); | |
| 733 | |
| 734 if (iter == login_to_password_info_.end()) | |
| 735 return false; | |
| 736 | |
| 737 *password_info = &iter->second; | |
| 738 return true; | |
| 739 } | |
| 740 | |
| 675 bool PasswordAutofillAgent::ShowSuggestions( | 741 bool PasswordAutofillAgent::ShowSuggestions( |
| 676 const blink::WebInputElement& element, | 742 const blink::WebInputElement& element, |
| 677 bool show_all) { | 743 bool show_all) { |
| 678 LoginToPasswordInfoMap::const_iterator iter = | 744 const blink::WebInputElement* username_element; |
| 679 login_to_password_info_.find(element); | 745 PasswordInfo* password_info; |
| 680 if (iter == login_to_password_info_.end()) | 746 if (!FindPasswordInfoForElement(element, &username_element, &password_info)) |
| 681 return false; | 747 return false; |
| 682 | 748 |
| 683 // If autocomplete='off' is set on the form elements, no suggestion dialog | 749 // If autocomplete='off' is set on the form elements, no suggestion dialog |
| 684 // should be shown. However, return |true| to indicate that this is a known | 750 // should be shown. However, return |true| to indicate that this is a known |
| 685 // password form and that the request to show suggestions has been handled (as | 751 // password form and that the request to show suggestions has been handled (as |
| 686 // a no-op). | 752 // a no-op). |
| 687 if (!IsElementAutocompletable(element) || | 753 if (!IsElementAutocompletable(element) || |
| 688 !IsElementAutocompletable(iter->second.password_field)) | 754 !IsElementAutocompletable(password_info->password_field)) |
| 689 return true; | 755 return true; |
| 690 | 756 |
| 691 return ShowSuggestionPopup(iter->second.fill_data, element, show_all); | 757 // If the element is a password field, a popup should only be shown if the |
| 758 // corresponding username element is not editable since it is only in that | |
| 759 // case that the username element does not have a suggestions popup. | |
| 760 if (element.isPasswordField() && IsElementEditable(*username_element)) | |
| 761 return true; | |
| 762 | |
| 763 // Chrome should never show more than one account for a password element since | |
| 764 // this implies that the username element cannot be modified. Thus even if | |
| 765 // |show_all| is true, check if the element in question is a password element | |
| 766 // for the call to ShowSuggestionPopup. | |
| 767 return ShowSuggestionPopup(password_info->fill_data, *username_element, | |
| 768 show_all && !element.isPasswordField(), | |
| 769 element.isPasswordField()); | |
| 692 } | 770 } |
| 693 | 771 |
| 694 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( | 772 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( |
| 695 const blink::WebSecurityOrigin& origin) { | 773 const blink::WebSecurityOrigin& origin) { |
| 696 return origin.canAccessPasswordManager(); | 774 return origin.canAccessPasswordManager(); |
| 697 } | 775 } |
| 698 | 776 |
| 699 void PasswordAutofillAgent::OnDynamicFormsSeen() { | 777 void PasswordAutofillAgent::OnDynamicFormsSeen() { |
| 700 SendPasswordForms(false /* only_visible */); | 778 SendPasswordForms(false /* only_visible */); |
| 701 } | 779 } |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1035 //////////////////////////////////////////////////////////////////////////////// | 1113 //////////////////////////////////////////////////////////////////////////////// |
| 1036 // PasswordAutofillAgent, private: | 1114 // PasswordAutofillAgent, private: |
| 1037 | 1115 |
| 1038 PasswordAutofillAgent::PasswordInfo::PasswordInfo() | 1116 PasswordAutofillAgent::PasswordInfo::PasswordInfo() |
| 1039 : backspace_pressed_last(false), password_was_edited_last(false) { | 1117 : backspace_pressed_last(false), password_was_edited_last(false) { |
| 1040 } | 1118 } |
| 1041 | 1119 |
| 1042 bool PasswordAutofillAgent::ShowSuggestionPopup( | 1120 bool PasswordAutofillAgent::ShowSuggestionPopup( |
| 1043 const PasswordFormFillData& fill_data, | 1121 const PasswordFormFillData& fill_data, |
| 1044 const blink::WebInputElement& user_input, | 1122 const blink::WebInputElement& user_input, |
| 1045 bool show_all) { | 1123 bool show_all, |
| 1124 bool show_on_password_field) { | |
| 1046 blink::WebFrame* frame = user_input.document().frame(); | 1125 blink::WebFrame* frame = user_input.document().frame(); |
| 1047 if (!frame) | 1126 if (!frame) |
| 1048 return false; | 1127 return false; |
| 1049 | 1128 |
| 1050 blink::WebView* webview = frame->view(); | 1129 blink::WebView* webview = frame->view(); |
| 1051 if (!webview) | 1130 if (!webview) |
| 1052 return false; | 1131 return false; |
| 1053 | 1132 |
| 1054 FormData form; | 1133 FormData form; |
| 1055 FormFieldData field; | 1134 FormFieldData field; |
| 1056 FindFormAndFieldForFormControlElement( | 1135 FindFormAndFieldForFormControlElement( |
| 1057 user_input, &form, &field, REQUIRE_NONE); | 1136 user_input, &form, &field, REQUIRE_NONE); |
| 1058 | 1137 |
| 1059 blink::WebInputElement selected_element = user_input; | 1138 blink::WebInputElement selected_element = user_input; |
| 1139 if (show_on_password_field) { | |
| 1140 LoginToPasswordInfoMap::const_iterator iter = | |
| 1141 login_to_password_info_.find(user_input); | |
| 1142 DCHECK(iter != login_to_password_info_.end()); | |
| 1143 selected_element = iter->second.password_field; | |
| 1144 } | |
| 1060 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); | 1145 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); |
| 1061 | 1146 |
| 1062 LoginToPasswordInfoKeyMap::const_iterator key_it = | 1147 LoginToPasswordInfoKeyMap::const_iterator key_it = |
| 1063 login_to_password_info_key_.find(user_input); | 1148 login_to_password_info_key_.find(user_input); |
| 1064 DCHECK(key_it != login_to_password_info_key_.end()); | 1149 DCHECK(key_it != login_to_password_info_key_.end()); |
| 1065 | 1150 |
| 1066 float scale = | 1151 float scale = |
| 1067 render_frame()->GetRenderView()->GetWebView()->pageScaleFactor(); | 1152 render_frame()->GetRenderView()->GetWebView()->pageScaleFactor(); |
| 1068 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, | 1153 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, |
| 1069 bounding_box.y() * scale, | 1154 bounding_box.y() * scale, |
| 1070 bounding_box.width() * scale, | 1155 bounding_box.width() * scale, |
| 1071 bounding_box.height() * scale); | 1156 bounding_box.height() * scale); |
| 1072 int options = 0; | 1157 int options = 0; |
| 1073 if (show_all) | 1158 if (show_all) |
| 1074 options |= SHOW_ALL; | 1159 options |= SHOW_ALL; |
| 1160 if (show_on_password_field) | |
| 1161 options |= IS_PASSWORD_FIELD; | |
| 1075 Send(new AutofillHostMsg_ShowPasswordSuggestions( | 1162 Send(new AutofillHostMsg_ShowPasswordSuggestions( |
| 1076 routing_id(), key_it->second, field.text_direction, user_input.value(), | 1163 routing_id(), key_it->second, field.text_direction, user_input.value(), |
| 1077 options, bounding_box_scaled)); | 1164 options, bounding_box_scaled)); |
| 1078 | 1165 |
| 1079 bool suggestions_present = false; | 1166 bool suggestions_present = false; |
| 1080 if (GetSuggestionsStats(fill_data, user_input.value(), show_all, | 1167 if (GetSuggestionsStats(fill_data, user_input.value(), show_all, |
| 1081 &suggestions_present)) { | 1168 &suggestions_present)) { |
| 1082 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN; | 1169 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN; |
| 1083 } | 1170 } |
| 1084 return suggestions_present; | 1171 return suggestions_present; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1095 blink::WebInputElement password = password_input; | 1182 blink::WebInputElement password = password_input; |
| 1096 | 1183 |
| 1097 // Don't inline autocomplete if the caret is not at the end. | 1184 // Don't inline autocomplete if the caret is not at the end. |
| 1098 // TODO(jcivelli): is there a better way to test the caret location? | 1185 // TODO(jcivelli): is there a better way to test the caret location? |
| 1099 if (username.selectionStart() != username.selectionEnd() || | 1186 if (username.selectionStart() != username.selectionEnd() || |
| 1100 username.selectionEnd() != static_cast<int>(username.value().length())) { | 1187 username.selectionEnd() != static_cast<int>(username.value().length())) { |
| 1101 return; | 1188 return; |
| 1102 } | 1189 } |
| 1103 | 1190 |
| 1104 // Show the popup with the list of available usernames. | 1191 // Show the popup with the list of available usernames. |
| 1105 ShowSuggestionPopup(fill_data, username, false); | 1192 ShowSuggestionPopup(fill_data, username, false, false); |
| 1106 | 1193 |
| 1107 #if !defined(OS_ANDROID) | 1194 #if !defined(OS_ANDROID) |
| 1108 // Fill the user and password field with the most relevant match. Android | 1195 // Fill the user and password field with the most relevant match. Android |
| 1109 // only fills in the fields after the user clicks on the suggestion popup. | 1196 // only fills in the fields after the user clicks on the suggestion popup. |
| 1110 if (FillUserNameAndPassword( | 1197 if (FillUserNameAndPassword( |
| 1111 &username, | 1198 &username, |
| 1112 &password, | 1199 &password, |
| 1113 fill_data, | 1200 fill_data, |
| 1114 false /* exact_username_match */, | 1201 false /* exact_username_match */, |
| 1115 true /* set_selection */, | 1202 true /* set selection */, |
| 1116 base::Bind(&PasswordValueGatekeeper::RegisterElement, | 1203 base::Bind(&PasswordValueGatekeeper::RegisterElement, |
| 1117 base::Unretained(&gatekeeper_)))) { | 1204 base::Unretained(&gatekeeper_)))) { |
| 1118 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | 1205 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; |
| 1119 } | 1206 } |
| 1120 #endif | 1207 #endif |
| 1121 } | 1208 } |
| 1122 | 1209 |
| 1123 void PasswordAutofillAgent::FrameClosing() { | 1210 void PasswordAutofillAgent::FrameClosing() { |
| 1124 for (auto const& iter : login_to_password_info_) { | 1211 for (auto const& iter : login_to_password_info_) { |
| 1125 login_to_password_info_key_.erase(iter.first); | 1212 login_to_password_info_key_.erase(iter.first); |
| 1126 password_to_username_.erase(iter.second.password_field); | 1213 password_to_username_.erase(iter.second.password_field); |
| 1127 } | 1214 } |
| 1128 login_to_password_info_.clear(); | 1215 login_to_password_info_.clear(); |
| 1129 provisionally_saved_form_.reset(); | 1216 provisionally_saved_form_.reset(); |
| 1130 } | 1217 } |
| 1131 | 1218 |
| 1132 bool PasswordAutofillAgent::FindLoginInfo(const blink::WebNode& node, | 1219 bool PasswordAutofillAgent::FindLoginInfo(const blink::WebNode& node, |
| 1133 blink::WebInputElement* found_input, | 1220 blink::WebInputElement* found_input, |
| 1134 PasswordInfo** found_password) { | 1221 PasswordInfo** found_password) { |
| 1135 if (!node.isElementNode()) | 1222 if (!node.isElementNode()) |
| 1136 return false; | 1223 return false; |
| 1137 | 1224 |
| 1138 blink::WebElement element = node.toConst<blink::WebElement>(); | 1225 blink::WebElement element = node.toConst<blink::WebElement>(); |
| 1139 if (!element.hasHTMLTagName("input")) | 1226 if (!element.hasHTMLTagName("input")) |
| 1140 return false; | 1227 return false; |
| 1141 | 1228 |
| 1142 blink::WebInputElement input = element.to<blink::WebInputElement>(); | 1229 *found_input = element.to<blink::WebInputElement>(); |
| 1143 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(input); | 1230 const blink::WebInputElement* username_element; // ignored |
| 1144 if (iter == login_to_password_info_.end()) | 1231 return FindPasswordInfoForElement(*found_input, &username_element, |
| 1145 return false; | 1232 found_password); |
| 1146 | |
| 1147 *found_input = input; | |
| 1148 *found_password = &iter->second; | |
| 1149 return true; | |
| 1150 } | 1233 } |
| 1151 | 1234 |
| 1152 void PasswordAutofillAgent::ClearPreview( | 1235 void PasswordAutofillAgent::ClearPreview( |
| 1153 blink::WebInputElement* username, | 1236 blink::WebInputElement* username, |
| 1154 blink::WebInputElement* password) { | 1237 blink::WebInputElement* password) { |
| 1155 if (!username->suggestedValue().isEmpty()) { | 1238 if (!username->suggestedValue().isEmpty()) { |
| 1156 username->setSuggestedValue(blink::WebString()); | 1239 username->setSuggestedValue(blink::WebString()); |
| 1157 username->setAutofilled(was_username_autofilled_); | 1240 username->setAutofilled(was_username_autofilled_); |
| 1158 username->setSelectionRange(username_selection_start_, | 1241 username->setSelectionRange(username_selection_start_, |
| 1159 username->value().length()); | 1242 username->value().length()); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1216 agent_->WillSendSubmitEvent(frame, form); | 1299 agent_->WillSendSubmitEvent(frame, form); |
| 1217 } | 1300 } |
| 1218 | 1301 |
| 1219 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::WillSubmitForm( | 1302 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::WillSubmitForm( |
| 1220 blink::WebLocalFrame* frame, | 1303 blink::WebLocalFrame* frame, |
| 1221 const blink::WebFormElement& form) { | 1304 const blink::WebFormElement& form) { |
| 1222 agent_->WillSubmitForm(frame, form); | 1305 agent_->WillSubmitForm(frame, form); |
| 1223 } | 1306 } |
| 1224 | 1307 |
| 1225 } // namespace autofill | 1308 } // namespace autofill |
| OLD | NEW |