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 std::string group_name = | |
133 base::FieldTrialList::FindFullName(kFillOnAccountSelectFieldTrialName); | |
134 | |
135 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
136 switches::kDisableFillOnAccountSelect)) { | |
137 return false; | |
138 } | |
139 | |
140 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
141 switches::kEnableFillOnAccountSelect)) { | |
142 return true; | |
143 } | |
144 | |
145 return group_name == kFillOnAccountSelectFieldTrialEnabledGroup; | |
146 } | |
147 | |
124 // Helper to search the given form element for the specified input elements in | 148 // Helper to search the given form element for the specified input elements in |
125 // |data|, and add results to |result|. | 149 // |data|, and add results to |result|. |
126 bool FindFormInputElements(blink::WebFormElement* form_element, | 150 bool FindFormInputElements(blink::WebFormElement* form_element, |
127 const PasswordFormFillData& data, | 151 const PasswordFormFillData& data, |
128 FormElements* result) { | 152 FormElements* result) { |
129 return FindFormInputElement(form_element, data.password_field, result) && | 153 return FindFormInputElement(form_element, data.password_field, result) && |
130 (!FillDataContainsUsername(data) || | 154 (!FillDataContainsUsername(data) || |
131 FindFormInputElement(form_element, data.username_field, result)); | 155 FindFormInputElement(form_element, data.username_field, result)); |
132 } | 156 } |
133 | 157 |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
268 } | 292 } |
269 } | 293 } |
270 | 294 |
271 return false; | 295 return false; |
272 } | 296 } |
273 | 297 |
274 // This function attempts to fill |username_element| and |password_element| | 298 // This function attempts to fill |username_element| and |password_element| |
275 // 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 |
276 // |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 |
277 // value through |registration_callback|. The function returns true when | 301 // value through |registration_callback|. The function returns true when |
278 // 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. | |
279 bool FillUserNameAndPassword( | 304 bool FillUserNameAndPassword( |
280 blink::WebInputElement* username_element, | 305 blink::WebInputElement* username_element, |
281 blink::WebInputElement* password_element, | 306 blink::WebInputElement* password_element, |
282 const PasswordFormFillData& fill_data, | 307 const PasswordFormFillData& fill_data, |
283 bool exact_username_match, | 308 bool exact_username_match, |
284 bool set_selection, | 309 bool set_selection, |
285 base::Callback<void(blink::WebInputElement*)> registration_callback) { | 310 base::Callback<void(blink::WebInputElement*)> registration_callback) { |
286 bool other_possible_username_selected = false; | 311 bool other_possible_username_selected = false; |
287 // Don't fill username if password can't be set. | 312 // Don't fill username if password can't be set. |
288 if (!IsElementAutocompletable(*password_element)) | 313 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. | 409 // Do not fill if the password field is in an iframe. |
385 DCHECK(password_element.document().frame()); | 410 DCHECK(password_element.document().frame()); |
386 if (password_element.document().frame()->parent()) | 411 if (password_element.document().frame()->parent()) |
387 return false; | 412 return false; |
388 | 413 |
389 // 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 |
390 if (!IsElementAutocompletable(password_element)) | 415 if (!IsElementAutocompletable(password_element)) |
391 return false; | 416 return false; |
392 | 417 |
393 bool form_contains_username_field = FillDataContainsUsername(fill_data); | 418 bool form_contains_username_field = FillDataContainsUsername(fill_data); |
394 // 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 |
395 // can be set and isn't prefilled. | 420 // preferred name, but only if: |
396 if (form_contains_username_field && | 421 // (a) The username element is autocompletable, and |
397 IsElementAutocompletable(username_element) && | 422 // (b) The fill-on-account-select flag is not set, and |
398 username_element.value().isEmpty()) { | 423 // (c) The username element isn't prefilled |
399 // TODO(tkent): Check maxlength and pattern. | 424 // |
400 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 | |
vabr (Chromium)
2014/12/15 14:37:44
If line 443 corresponds to this sentence, then the
jww
2014/12/15 23:14:47
Yikes, good catch! The comment is wrong. It should
| |
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 } | |
401 } | 447 } |
402 | 448 |
403 // 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 |
404 // username to autofilled. | 450 // username to autofilled. |
405 return FillUserNameAndPassword(&username_element, | 451 return FillUserNameAndPassword(&username_element, |
406 &password_element, | 452 &password_element, |
407 fill_data, | 453 fill_data, |
408 true /* exact_username_match */, | 454 true /* exact_username_match */, |
409 false /* set_selection */, | 455 false /* set_selection */, |
410 registration_callback); | 456 registration_callback); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
502 | 548 |
503 blink::WebInputElement password = password_info.password_field; | 549 blink::WebInputElement password = password_info.password_field; |
504 if (!IsElementEditable(password)) | 550 if (!IsElementEditable(password)) |
505 return false; | 551 return false; |
506 | 552 |
507 blink::WebInputElement username = element; // We need a non-const. | 553 blink::WebInputElement username = element; // We need a non-const. |
508 | 554 |
509 // 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 |
510 // mess with focus. | 556 // mess with focus. |
511 if (FillUserNameAndPassword( | 557 if (FillUserNameAndPassword( |
512 &username, | 558 &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, | 559 base::Bind(&PasswordValueGatekeeper::RegisterElement, |
518 base::Unretained(&gatekeeper_)))) { | 560 base::Unretained(&gatekeeper_)))) { |
519 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | 561 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; |
520 } | 562 } |
521 return true; | 563 return true; |
522 } | 564 } |
523 | 565 |
524 bool PasswordAutofillAgent::TextDidChangeInTextField( | 566 bool PasswordAutofillAgent::TextDidChangeInTextField( |
525 const blink::WebInputElement& element) { | 567 const blink::WebInputElement& element) { |
526 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 | 568 // 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 | 610 |
569 if (!element.isText() || !IsElementAutocompletable(element) || | 611 if (!element.isText() || !IsElementAutocompletable(element) || |
570 !IsElementAutocompletable(password)) { | 612 !IsElementAutocompletable(password)) { |
571 return false; | 613 return false; |
572 } | 614 } |
573 | 615 |
574 // Don't inline autocomplete if the user is deleting, that would be confusing. | 616 // 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 | 617 // But refresh the popup. Note, since this is ours, return true to signal |
576 // no further processing is required. | 618 // no further processing is required. |
577 if (iter->second.backspace_pressed_last) { | 619 if (iter->second.backspace_pressed_last) { |
578 ShowSuggestionPopup(iter->second.fill_data, element, false); | 620 ShowSuggestionPopup(iter->second.fill_data, element, false, false); |
579 return true; | 621 return true; |
580 } | 622 } |
581 | 623 |
582 blink::WebString name = element.nameForAutofill(); | 624 blink::WebString name = element.nameForAutofill(); |
583 if (name.isEmpty()) | 625 if (name.isEmpty()) |
584 return false; // If the field has no name, then we won't have values. | 626 return false; // If the field has no name, then we won't have values. |
585 | 627 |
586 // Don't attempt to autofill with values that are too large. | 628 // Don't attempt to autofill with values that are too large. |
587 if (element.value().length() > kMaximumTextSizeForAutocomplete) | 629 if (element.value().length() > kMaximumTextSizeForAutocomplete) |
588 return false; | 630 return false; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
665 const blink::WebNode& node) { | 707 const blink::WebNode& node) { |
666 blink::WebInputElement username_element; | 708 blink::WebInputElement username_element; |
667 PasswordInfo* password_info; | 709 PasswordInfo* password_info; |
668 if (!FindLoginInfo(node, &username_element, &password_info)) | 710 if (!FindLoginInfo(node, &username_element, &password_info)) |
669 return false; | 711 return false; |
670 | 712 |
671 ClearPreview(&username_element, &password_info->password_field); | 713 ClearPreview(&username_element, &password_info->password_field); |
672 return true; | 714 return true; |
673 } | 715 } |
674 | 716 |
717 bool PasswordAutofillAgent::FindPasswordInfoForElement( | |
718 const blink::WebInputElement& element, | |
719 const blink::WebInputElement** username_element, | |
720 PasswordInfo** password_info) { | |
721 DCHECK(username_element && password_info); | |
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 false; | |
729 *username_element = &password_iter->second; | |
730 } | |
731 | |
732 LoginToPasswordInfoMap::iterator iter = | |
733 login_to_password_info_.find(**username_element); | |
734 | |
735 if (iter == login_to_password_info_.end()) | |
736 return false; | |
737 | |
738 *password_info = &iter->second; | |
739 return true; | |
740 } | |
741 | |
675 bool PasswordAutofillAgent::ShowSuggestions( | 742 bool PasswordAutofillAgent::ShowSuggestions( |
676 const blink::WebInputElement& element, | 743 const blink::WebInputElement& element, |
677 bool show_all) { | 744 bool show_all) { |
678 LoginToPasswordInfoMap::const_iterator iter = | 745 const blink::WebInputElement* username_element; |
679 login_to_password_info_.find(element); | 746 PasswordInfo* password_info; |
680 if (iter == login_to_password_info_.end()) | 747 if (!FindPasswordInfoForElement(element, &username_element, &password_info)) |
681 return false; | 748 return false; |
682 | 749 |
683 // If autocomplete='off' is set on the form elements, no suggestion dialog | 750 // 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 | 751 // 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 | 752 // password form and that the request to show suggestions has been handled (as |
686 // a no-op). | 753 // a no-op). |
687 if (!IsElementAutocompletable(element) || | 754 if (!IsElementAutocompletable(element) || |
688 !IsElementAutocompletable(iter->second.password_field)) | 755 !IsElementAutocompletable(password_info->password_field)) |
689 return true; | 756 return true; |
690 | 757 |
691 return ShowSuggestionPopup(iter->second.fill_data, element, show_all); | 758 // If the element is a password field, a popup should only be shown if the |
759 // corresponding username element is not editable since it is only in that | |
760 // case that the username element does not have a suggestions popup. | |
761 if (element.isPasswordField() && IsElementEditable(*username_element)) | |
vabr (Chromium)
2014/12/15 14:37:43
username_element.isNull() will still be true for f
jww
2014/12/15 23:14:46
Awesome, thanks!
| |
762 return true; | |
763 | |
764 // Chrome should never show more than one account for a password element since | |
765 // this implies that the username element cannot be modified. Thus even if | |
766 // |show_all| is true, check if the element in question is a password element | |
767 // for the call to ShowSuggestionPopup. | |
768 return ShowSuggestionPopup(password_info->fill_data, *username_element, | |
769 show_all && !element.isPasswordField(), | |
770 element.isPasswordField()); | |
692 } | 771 } |
693 | 772 |
694 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( | 773 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( |
695 const blink::WebSecurityOrigin& origin) { | 774 const blink::WebSecurityOrigin& origin) { |
696 return origin.canAccessPasswordManager(); | 775 return origin.canAccessPasswordManager(); |
697 } | 776 } |
698 | 777 |
699 void PasswordAutofillAgent::OnDynamicFormsSeen() { | 778 void PasswordAutofillAgent::OnDynamicFormsSeen() { |
700 SendPasswordForms(false /* only_visible */); | 779 SendPasswordForms(false /* only_visible */); |
701 } | 780 } |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1035 //////////////////////////////////////////////////////////////////////////////// | 1114 //////////////////////////////////////////////////////////////////////////////// |
1036 // PasswordAutofillAgent, private: | 1115 // PasswordAutofillAgent, private: |
1037 | 1116 |
1038 PasswordAutofillAgent::PasswordInfo::PasswordInfo() | 1117 PasswordAutofillAgent::PasswordInfo::PasswordInfo() |
1039 : backspace_pressed_last(false), password_was_edited_last(false) { | 1118 : backspace_pressed_last(false), password_was_edited_last(false) { |
1040 } | 1119 } |
1041 | 1120 |
1042 bool PasswordAutofillAgent::ShowSuggestionPopup( | 1121 bool PasswordAutofillAgent::ShowSuggestionPopup( |
1043 const PasswordFormFillData& fill_data, | 1122 const PasswordFormFillData& fill_data, |
1044 const blink::WebInputElement& user_input, | 1123 const blink::WebInputElement& user_input, |
1045 bool show_all) { | 1124 bool show_all, |
1125 bool show_on_password_field) { | |
1046 blink::WebFrame* frame = user_input.document().frame(); | 1126 blink::WebFrame* frame = user_input.document().frame(); |
1047 if (!frame) | 1127 if (!frame) |
1048 return false; | 1128 return false; |
1049 | 1129 |
1050 blink::WebView* webview = frame->view(); | 1130 blink::WebView* webview = frame->view(); |
1051 if (!webview) | 1131 if (!webview) |
1052 return false; | 1132 return false; |
1053 | 1133 |
1054 FormData form; | 1134 FormData form; |
1055 FormFieldData field; | 1135 FormFieldData field; |
1056 FindFormAndFieldForFormControlElement( | 1136 FindFormAndFieldForFormControlElement( |
1057 user_input, &form, &field, REQUIRE_NONE); | 1137 user_input, &form, &field, REQUIRE_NONE); |
1058 | 1138 |
1059 blink::WebInputElement selected_element = user_input; | 1139 blink::WebInputElement selected_element = user_input; |
1140 if (show_on_password_field) { | |
1141 LoginToPasswordInfoMap::const_iterator iter = | |
1142 login_to_password_info_.find(user_input); | |
1143 DCHECK(iter != login_to_password_info_.end()); | |
1144 selected_element = iter->second.password_field; | |
1145 } | |
1060 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); | 1146 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); |
1061 | 1147 |
1062 LoginToPasswordInfoKeyMap::const_iterator key_it = | 1148 LoginToPasswordInfoKeyMap::const_iterator key_it = |
1063 login_to_password_info_key_.find(user_input); | 1149 login_to_password_info_key_.find(user_input); |
1064 DCHECK(key_it != login_to_password_info_key_.end()); | 1150 DCHECK(key_it != login_to_password_info_key_.end()); |
1065 | 1151 |
1066 float scale = | 1152 float scale = |
1067 render_frame()->GetRenderView()->GetWebView()->pageScaleFactor(); | 1153 render_frame()->GetRenderView()->GetWebView()->pageScaleFactor(); |
1068 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, | 1154 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, |
1069 bounding_box.y() * scale, | 1155 bounding_box.y() * scale, |
1070 bounding_box.width() * scale, | 1156 bounding_box.width() * scale, |
1071 bounding_box.height() * scale); | 1157 bounding_box.height() * scale); |
1072 int options = 0; | 1158 int options = 0; |
1073 if (show_all) | 1159 if (show_all) |
1074 options |= SHOW_ALL; | 1160 options |= SHOW_ALL; |
1161 if (show_on_password_field) | |
1162 options |= IS_PASSWORD_FIELD; | |
1075 Send(new AutofillHostMsg_ShowPasswordSuggestions( | 1163 Send(new AutofillHostMsg_ShowPasswordSuggestions( |
1076 routing_id(), key_it->second, field.text_direction, user_input.value(), | 1164 routing_id(), key_it->second, field.text_direction, user_input.value(), |
1077 options, bounding_box_scaled)); | 1165 options, bounding_box_scaled)); |
1078 | 1166 |
1079 bool suggestions_present = false; | 1167 bool suggestions_present = false; |
1080 if (GetSuggestionsStats(fill_data, user_input.value(), show_all, | 1168 if (GetSuggestionsStats(fill_data, user_input.value(), show_all, |
1081 &suggestions_present)) { | 1169 &suggestions_present)) { |
1082 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN; | 1170 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN; |
1083 } | 1171 } |
1084 return suggestions_present; | 1172 return suggestions_present; |
(...skipping 10 matching lines...) Expand all Loading... | |
1095 blink::WebInputElement password = password_input; | 1183 blink::WebInputElement password = password_input; |
1096 | 1184 |
1097 // Don't inline autocomplete if the caret is not at the end. | 1185 // 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? | 1186 // TODO(jcivelli): is there a better way to test the caret location? |
1099 if (username.selectionStart() != username.selectionEnd() || | 1187 if (username.selectionStart() != username.selectionEnd() || |
1100 username.selectionEnd() != static_cast<int>(username.value().length())) { | 1188 username.selectionEnd() != static_cast<int>(username.value().length())) { |
1101 return; | 1189 return; |
1102 } | 1190 } |
1103 | 1191 |
1104 // Show the popup with the list of available usernames. | 1192 // Show the popup with the list of available usernames. |
1105 ShowSuggestionPopup(fill_data, username, false); | 1193 ShowSuggestionPopup(fill_data, username, false, false); |
1106 | 1194 |
1107 #if !defined(OS_ANDROID) | 1195 #if !defined(OS_ANDROID) |
1108 // Fill the user and password field with the most relevant match. Android | 1196 // 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. | 1197 // only fills in the fields after the user clicks on the suggestion popup. |
1110 if (FillUserNameAndPassword( | 1198 if (FillUserNameAndPassword( |
1111 &username, | 1199 &username, |
1112 &password, | 1200 &password, |
1113 fill_data, | 1201 fill_data, |
1114 false /* exact_username_match */, | 1202 false /* exact_username_match */, |
1115 true /* set_selection */, | 1203 true /* set selection */, |
1116 base::Bind(&PasswordValueGatekeeper::RegisterElement, | 1204 base::Bind(&PasswordValueGatekeeper::RegisterElement, |
1117 base::Unretained(&gatekeeper_)))) { | 1205 base::Unretained(&gatekeeper_)))) { |
1118 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | 1206 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; |
1119 } | 1207 } |
1120 #endif | 1208 #endif |
1121 } | 1209 } |
1122 | 1210 |
1123 void PasswordAutofillAgent::FrameClosing() { | 1211 void PasswordAutofillAgent::FrameClosing() { |
1124 for (auto const& iter : login_to_password_info_) { | 1212 for (auto const& iter : login_to_password_info_) { |
1125 login_to_password_info_key_.erase(iter.first); | 1213 login_to_password_info_key_.erase(iter.first); |
1126 password_to_username_.erase(iter.second.password_field); | 1214 password_to_username_.erase(iter.second.password_field); |
1127 } | 1215 } |
1128 login_to_password_info_.clear(); | 1216 login_to_password_info_.clear(); |
1129 provisionally_saved_form_.reset(); | 1217 provisionally_saved_form_.reset(); |
1130 } | 1218 } |
1131 | 1219 |
1132 bool PasswordAutofillAgent::FindLoginInfo(const blink::WebNode& node, | 1220 bool PasswordAutofillAgent::FindLoginInfo(const blink::WebNode& node, |
1133 blink::WebInputElement* found_input, | 1221 blink::WebInputElement* found_input, |
1134 PasswordInfo** found_password) { | 1222 PasswordInfo** found_password) { |
1135 if (!node.isElementNode()) | 1223 if (!node.isElementNode()) |
1136 return false; | 1224 return false; |
1137 | 1225 |
1138 blink::WebElement element = node.toConst<blink::WebElement>(); | 1226 blink::WebElement element = node.toConst<blink::WebElement>(); |
1139 if (!element.hasHTMLTagName("input")) | 1227 if (!element.hasHTMLTagName("input")) |
1140 return false; | 1228 return false; |
1141 | 1229 |
1142 blink::WebInputElement input = element.to<blink::WebInputElement>(); | 1230 *found_input = element.to<blink::WebInputElement>(); |
1143 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(input); | 1231 const blink::WebInputElement* username_element; // ignored |
1144 if (iter == login_to_password_info_.end()) | 1232 return FindPasswordInfoForElement(*found_input, &username_element, |
1145 return false; | 1233 found_password); |
1146 | |
1147 *found_input = input; | |
1148 *found_password = &iter->second; | |
1149 return true; | |
1150 } | 1234 } |
1151 | 1235 |
1152 void PasswordAutofillAgent::ClearPreview( | 1236 void PasswordAutofillAgent::ClearPreview( |
1153 blink::WebInputElement* username, | 1237 blink::WebInputElement* username, |
1154 blink::WebInputElement* password) { | 1238 blink::WebInputElement* password) { |
1155 if (!username->suggestedValue().isEmpty()) { | 1239 if (!username->suggestedValue().isEmpty()) { |
1156 username->setSuggestedValue(blink::WebString()); | 1240 username->setSuggestedValue(blink::WebString()); |
1157 username->setAutofilled(was_username_autofilled_); | 1241 username->setAutofilled(was_username_autofilled_); |
1158 username->setSelectionRange(username_selection_start_, | 1242 username->setSelectionRange(username_selection_start_, |
1159 username->value().length()); | 1243 username->value().length()); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1216 agent_->WillSendSubmitEvent(frame, form); | 1300 agent_->WillSendSubmitEvent(frame, form); |
1217 } | 1301 } |
1218 | 1302 |
1219 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::WillSubmitForm( | 1303 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::WillSubmitForm( |
1220 blink::WebLocalFrame* frame, | 1304 blink::WebLocalFrame* frame, |
1221 const blink::WebFormElement& form) { | 1305 const blink::WebFormElement& form) { |
1222 agent_->WillSubmitForm(frame, form); | 1306 agent_->WillSubmitForm(frame, form); |
1223 } | 1307 } |
1224 | 1308 |
1225 } // namespace autofill | 1309 } // namespace autofill |
OLD | NEW |