Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Side by Side Diff: components/autofill/content/renderer/password_autofill_agent.cc

Issue 492043003: Fill on account select in the password manager (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « components/autofill/content/renderer/password_autofill_agent.h ('k') | components/autofill/core/common/autofill_switches.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698