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" |
| 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_autofill_util.h" | 19 #include "components/autofill/core/common/password_autofill_util.h" |
| 18 #include "components/autofill/core/common/password_form.h" | 20 #include "components/autofill/core/common/password_form.h" |
| 19 #include "components/autofill/core/common/password_form_fill_data.h" | 21 #include "components/autofill/core/common/password_form_fill_data.h" |
| 20 #include "content/public/common/page_transition_types.h" | 22 #include "content/public/common/page_transition_types.h" |
| 21 #include "content/public/renderer/document_state.h" | 23 #include "content/public/renderer/document_state.h" |
| 22 #include "content/public/renderer/navigation_state.h" | 24 #include "content/public/renderer/navigation_state.h" |
| 23 #include "content/public/renderer/render_view.h" | 25 #include "content/public/renderer/render_view.h" |
| 24 #include "third_party/WebKit/public/platform/WebVector.h" | 26 #include "third_party/WebKit/public/platform/WebVector.h" |
| 25 #include "third_party/WebKit/public/web/WebAutofillClient.h" | 27 #include "third_party/WebKit/public/web/WebAutofillClient.h" |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 294 if (!IsElementEditable(password)) | 296 if (!IsElementEditable(password)) |
| 295 return false; | 297 return false; |
| 296 | 298 |
| 297 blink::WebInputElement username = element; // We need a non-const. | 299 blink::WebInputElement username = element; // We need a non-const. |
| 298 | 300 |
| 299 // Do not set selection when ending an editing session, otherwise it can | 301 // Do not set selection when ending an editing session, otherwise it can |
| 300 // mess with focus. | 302 // mess with focus. |
| 301 FillUserNameAndPassword(&username, | 303 FillUserNameAndPassword(&username, |
| 302 &password, | 304 &password, |
| 303 fill_data, | 305 fill_data, |
| 304 true /* exact_username_match */, | 306 EXACT_USERNAME_MATCH); |
| 305 false /* set_selection */); | |
| 306 return true; | 307 return true; |
| 307 } | 308 } |
| 308 | 309 |
| 309 bool PasswordAutofillAgent::TextDidChangeInTextField( | 310 bool PasswordAutofillAgent::TextDidChangeInTextField( |
| 310 const blink::WebInputElement& element) { | 311 const blink::WebInputElement& element) { |
| 311 if (element.isPasswordField()) { | 312 if (element.isPasswordField()) { |
| 312 // Some login forms have event handlers that put a hash of the password into | 313 // Some login forms have event handlers that put a hash of the password into |
| 313 // a hidden field and then clear the password (http://crbug.com/28910, | 314 // a hidden field and then clear the password (http://crbug.com/28910, |
| 314 // http://crbug.com/391693). This method gets called before any of those | 315 // http://crbug.com/391693). This method gets called before any of those |
| 315 // handlers run, so save away a copy of the password in case it gets lost. | 316 // handlers run, so save away a copy of the password in case it gets lost. |
| (...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 910 return; | 911 return; |
| 911 | 912 |
| 912 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && | 913 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && |
| 913 !username_element.form().autoComplete()) | 914 !username_element.form().autoComplete()) |
| 914 return; | 915 return; |
| 915 | 916 |
| 916 // If we can't modify the password, don't try to set the username | 917 // If we can't modify the password, don't try to set the username |
| 917 if (!IsElementAutocompletable(password_element)) | 918 if (!IsElementAutocompletable(password_element)) |
| 918 return; | 919 return; |
| 919 | 920 |
| 920 // Try to set the username to the preferred name, but only if the field | |
| 921 // can be set and isn't prefilled. | |
| 922 if (IsElementAutocompletable(username_element) && | |
| 923 username_element.value().isEmpty()) { | |
| 924 // TODO(tkent): Check maxlength and pattern. | |
| 925 username_element.setValue(fill_data.basic_data.fields[0].value, true); | |
| 926 } | |
| 927 | |
| 928 // Fill if we have an exact match for the username. Note that this sets | 921 // Fill if we have an exact match for the username. Note that this sets |
| 929 // username to autofilled. | 922 // username to autofilled. |
| 930 FillUserNameAndPassword(&username_element, | 923 FillUserNameAndPassword(&username_element, |
| 931 &password_element, | 924 &password_element, |
| 932 fill_data, | 925 fill_data, |
| 933 true /* exact_username_match */, | 926 EXACT_USERNAME_MATCH | FILL_PREFERRED_USERNAME); |
| 934 false /* set_selection */); | |
| 935 } | 927 } |
| 936 | 928 |
| 937 bool PasswordAutofillAgent::FillUserNameAndPassword( | 929 bool PasswordAutofillAgent::FillUserNameAndPassword( |
| 938 blink::WebInputElement* username_element, | 930 blink::WebInputElement* username_element, |
| 939 blink::WebInputElement* password_element, | 931 blink::WebInputElement* password_element, |
| 940 const PasswordFormFillData& fill_data, | 932 const PasswordFormFillData& fill_data, |
| 941 bool exact_username_match, | 933 const int options) { |
|
Garrett Casto
2014/09/08 21:27:20
So I think that the behavior if the username if al
jww
2014/09/09 01:40:34
I was admittedly a bit confused by your comment, b
| |
| 942 bool set_selection) { | 934 bool exact_username_match = (options & EXACT_USERNAME_MATCH) != 0; |
| 935 bool set_selection = (options & SET_SELECTION) != 0; | |
| 936 bool fill_preferred_username = (options & FILL_PREFERRED_USERNAME) != 0; | |
| 937 bool fill_on_account_select = CommandLine::ForCurrentProcess()->HasSwitch( | |
| 938 switches::kEnableFillOnAccountSelect); | |
|
Garrett Casto
2014/09/08 21:27:20
You should pull this out into a function so that w
jww
2014/09/09 01:40:34
Done.
| |
| 943 base::string16 current_username = username_element->value(); | 939 base::string16 current_username = username_element->value(); |
| 944 // username and password will contain the match found if any. | 940 // username and password will contain the match found if any. |
| 945 base::string16 username; | 941 base::string16 username; |
| 946 base::string16 password; | 942 base::string16 password; |
| 947 | 943 |
| 944 // Try to set the username to the preferred name, but only if the field | |
| 945 // can be set and isn't prefilled. If FILL_PREFERRED_USERNAME | |
| 946 // is set, set |current_username| to the preferred value, but don't set the | |
| 947 // element's value. This is done so that even if values aren't actually | |
| 948 // filled, if there is a valid value to fill with, the elements will be | |
| 949 // properly marked as autofilled later. | |
| 950 if (fill_preferred_username && | |
| 951 IsElementAutocompletable(*username_element) && | |
| 952 username_element->value().isEmpty()) { | |
| 953 current_username = fill_data.basic_data.fields[0].value; | |
| 954 if (!fill_on_account_select) { | |
| 955 // TODO(tkent): Check maxlength and pattern. | |
| 956 username_element->setValue(current_username, true); | |
| 957 } | |
| 958 } | |
| 959 | |
| 948 // Look for any suitable matches to current field text. | 960 // Look for any suitable matches to current field text. |
| 949 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, | 961 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, |
| 950 current_username, | 962 current_username, |
| 951 exact_username_match)) { | 963 exact_username_match)) { |
| 952 username = fill_data.basic_data.fields[0].value; | 964 username = fill_data.basic_data.fields[0].value; |
| 953 password = fill_data.basic_data.fields[1].value; | 965 password = fill_data.basic_data.fields[1].value; |
| 954 } else { | 966 } else { |
| 955 // Scan additional logins for a match. | 967 // Scan additional logins for a match. |
| 956 PasswordFormFillData::LoginCollection::const_iterator iter; | 968 PasswordFormFillData::LoginCollection::const_iterator iter; |
| 957 for (iter = fill_data.additional_logins.begin(); | 969 for (iter = fill_data.additional_logins.begin(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 991 // TODO(tkent): Check maxlength and pattern for both username and password | 1003 // TODO(tkent): Check maxlength and pattern for both username and password |
| 992 // fields. | 1004 // fields. |
| 993 | 1005 |
| 994 // Don't fill username if password can't be set. | 1006 // Don't fill username if password can't be set. |
| 995 if (!IsElementAutocompletable(*password_element)) { | 1007 if (!IsElementAutocompletable(*password_element)) { |
| 996 return false; | 1008 return false; |
| 997 } | 1009 } |
| 998 | 1010 |
| 999 // Input matches the username, fill in required values. | 1011 // Input matches the username, fill in required values. |
| 1000 if (IsElementAutocompletable(*username_element)) { | 1012 if (IsElementAutocompletable(*username_element)) { |
| 1001 username_element->setValue(username, true); | |
| 1002 username_element->setAutofilled(true); | 1013 username_element->setAutofilled(true); |
| 1003 | 1014 |
| 1004 if (set_selection) { | 1015 if (!fill_on_account_select) { |
| 1005 username_element->setSelectionRange(current_username.length(), | 1016 username_element->setValue(username, true); |
| 1006 username.length()); | 1017 |
| 1018 if (set_selection) { | |
| 1019 username_element->setSelectionRange(current_username.length(), | |
| 1020 username.length()); | |
| 1021 } | |
| 1007 } | 1022 } |
| 1008 } else if (current_username != username) { | 1023 } else if (current_username != username) { |
| 1009 // If the username can't be filled and it doesn't match a saved password | 1024 // If the username can't be filled and it doesn't match a saved password |
| 1010 // as is, don't autofill a password. | 1025 // as is, don't autofill a password. |
| 1011 return false; | 1026 return false; |
| 1012 } | 1027 } |
| 1013 | 1028 |
| 1014 // Wait to fill in the password until a user gesture occurs. This is to make | 1029 // Wait to fill in the password until a user gesture occurs. This is to make |
| 1015 // sure that we do not fill in the DOM with a password until we believe the | 1030 // sure that we do not fill in the DOM with a password until we believe the |
| 1016 // user is intentionally interacting with the page. | 1031 // user is intentionally interacting with the page. |
| 1017 password_element->setSuggestedValue(password); | 1032 if (!fill_on_account_select) { |
| 1033 password_element->setSuggestedValue(password); | |
| 1034 } | |
| 1018 gatekeeper_.RegisterElement(password_element); | 1035 gatekeeper_.RegisterElement(password_element); |
| 1019 | 1036 |
| 1020 password_element->setAutofilled(true); | 1037 password_element->setAutofilled(true); |
| 1021 return true; | 1038 return true; |
| 1022 } | 1039 } |
| 1023 | 1040 |
| 1024 void PasswordAutofillAgent::PerformInlineAutocomplete( | 1041 void PasswordAutofillAgent::PerformInlineAutocomplete( |
| 1025 const blink::WebInputElement& username_input, | 1042 const blink::WebInputElement& username_input, |
| 1026 const blink::WebInputElement& password_input, | 1043 const blink::WebInputElement& password_input, |
| 1027 const PasswordFormFillData& fill_data) { | 1044 const PasswordFormFillData& fill_data) { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1040 | 1057 |
| 1041 // Show the popup with the list of available usernames. | 1058 // Show the popup with the list of available usernames. |
| 1042 ShowSuggestionPopup(fill_data, username, false); | 1059 ShowSuggestionPopup(fill_data, username, false); |
| 1043 | 1060 |
| 1044 #if !defined(OS_ANDROID) | 1061 #if !defined(OS_ANDROID) |
| 1045 // Fill the user and password field with the most relevant match. Android | 1062 // Fill the user and password field with the most relevant match. Android |
| 1046 // only fills in the fields after the user clicks on the suggestion popup. | 1063 // only fills in the fields after the user clicks on the suggestion popup. |
| 1047 FillUserNameAndPassword(&username, | 1064 FillUserNameAndPassword(&username, |
| 1048 &password, | 1065 &password, |
| 1049 fill_data, | 1066 fill_data, |
| 1050 false /* exact_username_match */, | 1067 SET_SELECTION); |
| 1051 true /* set_selection */); | |
| 1052 #endif | 1068 #endif |
| 1053 } | 1069 } |
| 1054 | 1070 |
| 1055 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { | 1071 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { |
| 1056 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); | 1072 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); |
| 1057 iter != login_to_password_info_.end();) { | 1073 iter != login_to_password_info_.end();) { |
| 1058 if (iter->first.document().frame() == frame) | 1074 if (iter->first.document().frame() == frame) |
| 1059 login_to_password_info_.erase(iter++); | 1075 login_to_password_info_.erase(iter++); |
| 1060 else | 1076 else |
| 1061 ++iter; | 1077 ++iter; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1113 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); | 1129 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); |
| 1114 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && | 1130 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && |
| 1115 password_form->password_value.empty() && | 1131 password_form->password_value.empty() && |
| 1116 password_form->new_password_value.empty())) { | 1132 password_form->new_password_value.empty())) { |
| 1117 return; | 1133 return; |
| 1118 } | 1134 } |
| 1119 provisionally_saved_forms_[frame].reset(password_form.release()); | 1135 provisionally_saved_forms_[frame].reset(password_form.release()); |
| 1120 } | 1136 } |
| 1121 | 1137 |
| 1122 } // namespace autofill | 1138 } // namespace autofill |
| OLD | NEW |