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: Fixes from gcasto 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 29 matching lines...) Expand all
55 // necessary form elements. To avoid having to look these up again when we want 57 // necessary form elements. To avoid having to look these up again when we want
56 // to fill the form, the FindFormElements function stores the pointers 58 // to fill the form, the FindFormElements function stores the pointers
57 // in a FormElements* result, referenced to ensure they are safe to use. 59 // in a FormElements* result, referenced to ensure they are safe to use.
58 struct FormElements { 60 struct FormElements {
59 blink::WebFormElement form_element; 61 blink::WebFormElement form_element;
60 FormInputElementMap input_elements; 62 FormInputElementMap input_elements;
61 }; 63 };
62 64
63 typedef std::vector<FormElements*> FormElementsList; 65 typedef std::vector<FormElements*> FormElementsList;
64 66
67 bool ShouldFillOnAccountSelect() {
68 if (CommandLine::ForCurrentProcess()->HasSwitch(
69 switches::kEnableFillOnAccountSelect)) {
70 return true;
71 }
72
73 // This is made explicit in anticiption of experimental groups being added.
74 if (CommandLine::ForCurrentProcess()->HasSwitch(
75 switches::kDisableFillOnAccountSelect)) {
76 return false;
77 }
78
79 // TODO(jww): Add experimental groups check here.
80
81 return false;
82 }
83
65 // Helper to search the given form element for the specified input elements 84 // Helper to search the given form element for the specified input elements
66 // in |data|, and add results to |result|. 85 // in |data|, and add results to |result|.
67 static bool FindFormInputElements(blink::WebFormElement* fe, 86 static bool FindFormInputElements(blink::WebFormElement* fe,
68 const FormData& data, 87 const FormData& data,
69 FormElements* result) { 88 FormElements* result) {
70 // Loop through the list of elements we need to find on the form in order to 89 // Loop through the list of elements we need to find on the form in order to
71 // autofill it. If we don't find any one of them, abort processing this 90 // autofill it. If we don't find any one of them, abort processing this
72 // form; it can't be the right one. 91 // form; it can't be the right one.
73 for (size_t j = 0; j < data.fields.size(); j++) { 92 for (size_t j = 0; j < data.fields.size(); j++) {
74 blink::WebVector<blink::WebNode> temp_elements; 93 blink::WebVector<blink::WebNode> temp_elements;
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 return false; 315 return false;
297 316
298 blink::WebInputElement password = password_info.password_field; 317 blink::WebInputElement password = password_info.password_field;
299 if (!IsElementEditable(password)) 318 if (!IsElementEditable(password))
300 return false; 319 return false;
301 320
302 blink::WebInputElement username = element; // We need a non-const. 321 blink::WebInputElement username = element; // We need a non-const.
303 322
304 // Do not set selection when ending an editing session, otherwise it can 323 // Do not set selection when ending an editing session, otherwise it can
305 // mess with focus. 324 // mess with focus.
306 FillUserNameAndPassword(&username, 325 FillUserNameAndPassword(
307 &password, 326 &username, &password, fill_data, EXACT_USERNAME_MATCH);
308 fill_data,
309 true /* exact_username_match */,
310 false /* set_selection */);
311 return true; 327 return true;
312 } 328 }
313 329
314 bool PasswordAutofillAgent::TextDidChangeInTextField( 330 bool PasswordAutofillAgent::TextDidChangeInTextField(
315 const blink::WebInputElement& element) { 331 const blink::WebInputElement& element) {
316 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 332 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083
317 blink::WebInputElement mutable_element = element; // We need a non-const. 333 blink::WebInputElement mutable_element = element; // We need a non-const.
318 334
319 if (element.isPasswordField()) { 335 if (element.isPasswordField()) {
320 // Some login forms have event handlers that put a hash of the password into 336 // Some login forms have event handlers that put a hash of the password into
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 form_elements->input_elements[form_data.basic_data.fields[0].name]; 823 form_elements->input_elements[form_data.basic_data.fields[0].name];
808 824
809 // Get pointer to password element. (We currently only support single 825 // Get pointer to password element. (We currently only support single
810 // password forms). 826 // password forms).
811 blink::WebInputElement password_element = 827 blink::WebInputElement password_element =
812 form_elements->input_elements[form_data.basic_data.fields[1].name]; 828 form_elements->input_elements[form_data.basic_data.fields[1].name];
813 829
814 // If wait_for_username is true, we don't want to initially fill the form 830 // If wait_for_username is true, we don't want to initially fill the form
815 // until the user types in a valid username. 831 // until the user types in a valid username.
816 if (!form_data.wait_for_username) 832 if (!form_data.wait_for_username)
817 FillFormOnPasswordRecieved(form_data, username_element, password_element); 833 FillFormOnPasswordReceived(form_data, username_element, password_element);
818 834
819 // We might have already filled this form if there are two <form> elements 835 // We might have already filled this form if there are two <form> elements
820 // with identical markup. 836 // with identical markup.
821 if (login_to_password_info_.find(username_element) != 837 if (login_to_password_info_.find(username_element) !=
822 login_to_password_info_.end()) 838 login_to_password_info_.end())
823 continue; 839 continue;
824 840
825 PasswordInfo password_info; 841 PasswordInfo password_info;
826 password_info.fill_data = form_data; 842 password_info.fill_data = form_data;
827 password_info.password_field = password_element; 843 password_info.password_field = password_element;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
913 float scale = web_view_->pageScaleFactor(); 929 float scale = web_view_->pageScaleFactor();
914 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, 930 gfx::RectF bounding_box_scaled(bounding_box.x() * scale,
915 bounding_box.y() * scale, 931 bounding_box.y() * scale,
916 bounding_box.width() * scale, 932 bounding_box.width() * scale,
917 bounding_box.height() * scale); 933 bounding_box.height() * scale);
918 Send(new AutofillHostMsg_ShowPasswordSuggestions( 934 Send(new AutofillHostMsg_ShowPasswordSuggestions(
919 routing_id(), field, bounding_box_scaled, suggestions, realms)); 935 routing_id(), field, bounding_box_scaled, suggestions, realms));
920 return !suggestions.empty(); 936 return !suggestions.empty();
921 } 937 }
922 938
923 void PasswordAutofillAgent::FillFormOnPasswordRecieved( 939 void PasswordAutofillAgent::FillFormOnPasswordReceived(
924 const PasswordFormFillData& fill_data, 940 const PasswordFormFillData& fill_data,
925 blink::WebInputElement username_element, 941 blink::WebInputElement username_element,
926 blink::WebInputElement password_element) { 942 blink::WebInputElement password_element) {
927 // Do not fill if the password field is in an iframe. 943 // Do not fill if the password field is in an iframe.
928 DCHECK(password_element.document().frame()); 944 DCHECK(password_element.document().frame());
929 if (password_element.document().frame()->parent()) 945 if (password_element.document().frame()->parent())
930 return; 946 return;
931 947
932 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && 948 if (!ShouldIgnoreAutocompleteOffForPasswordFields() &&
933 !username_element.form().autoComplete()) 949 !username_element.form().autoComplete())
934 return; 950 return;
935 951
936 // If we can't modify the password, don't try to set the username 952 // If we can't modify the password, don't try to set the username
937 if (!IsElementAutocompletable(password_element)) 953 if (!IsElementAutocompletable(password_element))
938 return; 954 return;
939 955
940 // Try to set the username to the preferred name, but only if the field 956 if (ShouldFillOnAccountSelect()) {
941 // can be set and isn't prefilled. 957 username_element.setAutofilled(true);
958 return;
959 }
Garrett Casto 2014/09/12 19:08:28 This is going to break sites that hide the usernam
jww 2014/09/15 22:48:00 Hm, this is a tough one. I don't think this is saf
960
961 // Try to set the username to the preferred name, but only if the field can be
962 // set and isn't prefilled.
942 if (IsElementAutocompletable(username_element) && 963 if (IsElementAutocompletable(username_element) &&
943 username_element.value().isEmpty()) { 964 username_element.value().isEmpty()) {
944 // TODO(tkent): Check maxlength and pattern. 965 // TODO(tkent): Check maxlength and pattern.
945 username_element.setValue(fill_data.basic_data.fields[0].value, true); 966 username_element.setValue(fill_data.basic_data.fields[0].value, true);
946 } 967 }
947 968
948 // Fill if we have an exact match for the username. Note that this sets 969 // Fill if we have an exact match for the username. Note that this sets
949 // username to autofilled. 970 // username to autofilled.
950 FillUserNameAndPassword(&username_element, 971 FillUserNameAndPassword(
951 &password_element, 972 &username_element, &password_element, fill_data, EXACT_USERNAME_MATCH);
952 fill_data,
953 true /* exact_username_match */,
954 false /* set_selection */);
955 } 973 }
956 974
957 bool PasswordAutofillAgent::FillUserNameAndPassword( 975 bool PasswordAutofillAgent::FillUserNameAndPassword(
958 blink::WebInputElement* username_element, 976 blink::WebInputElement* username_element,
959 blink::WebInputElement* password_element, 977 blink::WebInputElement* password_element,
960 const PasswordFormFillData& fill_data, 978 const PasswordFormFillData& fill_data,
961 bool exact_username_match, 979 const int options) {
962 bool set_selection) { 980 bool exact_username_match = (options & EXACT_USERNAME_MATCH) != 0;
981 bool set_selection = (options & SET_SELECTION) != 0;
963 base::string16 current_username = username_element->value(); 982 base::string16 current_username = username_element->value();
964 // username and password will contain the match found if any. 983 // username and password will contain the match found if any.
965 base::string16 username; 984 base::string16 username;
966 base::string16 password; 985 base::string16 password;
967 986
968 // Look for any suitable matches to current field text. 987 // Look for any suitable matches to current field text.
969 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, 988 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value,
970 current_username, 989 current_username,
971 exact_username_match)) { 990 exact_username_match)) {
972 username = fill_data.basic_data.fields[0].value; 991 username = fill_data.basic_data.fields[0].value;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1057 username.selectionEnd() != static_cast<int>(username.value().length())) { 1076 username.selectionEnd() != static_cast<int>(username.value().length())) {
1058 return; 1077 return;
1059 } 1078 }
1060 1079
1061 // Show the popup with the list of available usernames. 1080 // Show the popup with the list of available usernames.
1062 ShowSuggestionPopup(fill_data, username, false); 1081 ShowSuggestionPopup(fill_data, username, false);
1063 1082
1064 #if !defined(OS_ANDROID) 1083 #if !defined(OS_ANDROID)
1065 // Fill the user and password field with the most relevant match. Android 1084 // Fill the user and password field with the most relevant match. Android
1066 // only fills in the fields after the user clicks on the suggestion popup. 1085 // only fills in the fields after the user clicks on the suggestion popup.
1067 FillUserNameAndPassword(&username, 1086 FillUserNameAndPassword(&username, &password, fill_data, SET_SELECTION);
1068 &password,
1069 fill_data,
1070 false /* exact_username_match */,
1071 true /* set_selection */);
1072 #endif 1087 #endif
1073 } 1088 }
1074 1089
1075 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { 1090 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) {
1076 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); 1091 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin();
1077 iter != login_to_password_info_.end();) { 1092 iter != login_to_password_info_.end();) {
1078 if (iter->first.document().frame() == frame) { 1093 if (iter->first.document().frame() == frame) {
1079 password_to_username_.erase(iter->second.password_field); 1094 password_to_username_.erase(iter->second.password_field);
1080 login_to_password_info_.erase(iter++); 1095 login_to_password_info_.erase(iter++);
1081 } else { 1096 } else {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1135 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); 1150 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form));
1136 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && 1151 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD &&
1137 password_form->password_value.empty() && 1152 password_form->password_value.empty() &&
1138 password_form->new_password_value.empty())) { 1153 password_form->new_password_value.empty())) {
1139 return; 1154 return;
1140 } 1155 }
1141 provisionally_saved_forms_[frame].reset(password_form.release()); 1156 provisionally_saved_forms_[frame].reset(password_form.release());
1142 } 1157 }
1143 1158
1144 } // namespace autofill 1159 } // 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