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

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

Issue 557703002: Refactoring PasswordAutofillAgent::FillUserNameAndPassword function. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
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
« no previous file with comments | « components/autofill/content/renderer/password_autofill_agent.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h" 9 #include "base/message_loop/message_loop.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 // Returns |true| if the given element is both editable and has permission to be 185 // Returns |true| if the given element is both editable and has permission to be
186 // autocompleted. The latter can be either because there is no 186 // autocompleted. The latter can be either because there is no
187 // autocomplete='off' set for the element, or because the flag is set to ignore 187 // autocomplete='off' set for the element, or because the flag is set to ignore
188 // autocomplete='off'. Otherwise, returns |false|. 188 // autocomplete='off'. Otherwise, returns |false|.
189 bool IsElementAutocompletable(const blink::WebInputElement& element) { 189 bool IsElementAutocompletable(const blink::WebInputElement& element) {
190 return IsElementEditable(element) && 190 return IsElementEditable(element) &&
191 (ShouldIgnoreAutocompleteOffForPasswordFields() || 191 (ShouldIgnoreAutocompleteOffForPasswordFields() ||
192 element.autoComplete()); 192 element.autoComplete());
193 } 193 }
194 194
195 // Returns |true| if element1 and element2 are IsElementAutocompletable.
196 // Otherwise returns |false|.
197 bool IsElementsAutocompletable(const blink::WebInputElement& element1,
Mike West 2014/09/18 10:25:14 Nit: _Are_ElementsAutocompletable.
198 const blink::WebInputElement& element2) {
199 return IsElementAutocompletable(element1) &&
200 IsElementAutocompletable(element2);
201 }
202
195 // Returns true if the password specified in |form| is a default value. 203 // Returns true if the password specified in |form| is a default value.
196 bool PasswordValueIsDefault(const PasswordForm& form, 204 bool PasswordValueIsDefault(const PasswordForm& form,
197 blink::WebFormElement form_element) { 205 blink::WebFormElement form_element) {
198 blink::WebVector<blink::WebNode> temp_elements; 206 blink::WebVector<blink::WebNode> temp_elements;
199 form_element.getNamedElements(form.password_element, temp_elements); 207 form_element.getNamedElements(form.password_element, temp_elements);
200 208
201 // We are loose in our definition here and will return true if any of the 209 // We are loose in our definition here and will return true if any of the
202 // appropriately named elements match the element to be saved. Currently 210 // appropriately named elements match the element to be saved. Currently
203 // we ignore filling passwords where naming is ambigious anyway. 211 // we ignore filling passwords where naming is ambigious anyway.
204 for (size_t i = 0; i < temp_elements.size(); ++i) { 212 for (size_t i = 0; i < temp_elements.size(); ++i) {
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 blink::WebInputElement password = iter->second.password_field; 356 blink::WebInputElement password = iter->second.password_field;
349 if (password.isAutofilled()) { 357 if (password.isAutofilled()) {
350 password.setValue(base::string16(), true); 358 password.setValue(base::string16(), true);
351 password.setAutofilled(false); 359 password.setAutofilled(false);
352 } 360 }
353 361
354 // If wait_for_username is true we will fill when the username loses focus. 362 // If wait_for_username is true we will fill when the username loses focus.
355 if (iter->second.fill_data.wait_for_username) 363 if (iter->second.fill_data.wait_for_username)
356 return false; 364 return false;
357 365
358 if (!element.isText() || !IsElementAutocompletable(element) || 366 if (!element.isText() || !IsElementsAutocompletable(element, password)) {
359 !IsElementAutocompletable(password)) {
360 return false; 367 return false;
361 } 368 }
362 369
363 // Don't inline autocomplete if the user is deleting, that would be confusing. 370 // Don't inline autocomplete if the user is deleting, that would be confusing.
364 // But refresh the popup. Note, since this is ours, return true to signal 371 // But refresh the popup. Note, since this is ours, return true to signal
365 // no further processing is required. 372 // no further processing is required.
366 if (iter->second.backspace_pressed_last) { 373 if (iter->second.backspace_pressed_last) {
367 ShowSuggestionPopup(iter->second.fill_data, element, false); 374 ShowSuggestionPopup(iter->second.fill_data, element, false);
368 return true; 375 return true;
369 } 376 }
(...skipping 29 matching lines...) Expand all
399 } 406 }
400 407
401 bool PasswordAutofillAgent::FillSuggestion( 408 bool PasswordAutofillAgent::FillSuggestion(
402 const blink::WebNode& node, 409 const blink::WebNode& node,
403 const blink::WebString& username, 410 const blink::WebString& username,
404 const blink::WebString& password) { 411 const blink::WebString& password) {
405 blink::WebInputElement username_element; 412 blink::WebInputElement username_element;
406 PasswordInfo* password_info; 413 PasswordInfo* password_info;
407 414
408 if (!FindLoginInfo(node, &username_element, &password_info) || 415 if (!FindLoginInfo(node, &username_element, &password_info) ||
409 !IsElementAutocompletable(username_element) || 416 !IsElementsAutocompletable(username_element,
410 !IsElementAutocompletable(password_info->password_field)) { 417 password_info->password_field)) {
411 return false; 418 return false;
412 } 419 }
413 420
414 password_info->password_was_edited_last = false; 421 password_info->password_was_edited_last = false;
415 username_element.setValue(username, true); 422 username_element.setValue(username, true);
416 username_element.setAutofilled(true); 423 username_element.setAutofilled(true);
417 username_element.setSelectionRange(username.length(), username.length()); 424 username_element.setSelectionRange(username.length(), username.length());
418 425
419 password_info->password_field.setValue(password, true); 426 password_info->password_field.setValue(password, true);
420 password_info->password_field.setAutofilled(true); 427 password_info->password_field.setAutofilled(true);
421 428
422 return true; 429 return true;
423 } 430 }
424 431
425 bool PasswordAutofillAgent::PreviewSuggestion( 432 bool PasswordAutofillAgent::PreviewSuggestion(
426 const blink::WebNode& node, 433 const blink::WebNode& node,
427 const blink::WebString& username, 434 const blink::WebString& username,
428 const blink::WebString& password) { 435 const blink::WebString& password) {
429 blink::WebInputElement username_element; 436 blink::WebInputElement username_element;
430 PasswordInfo* password_info; 437 PasswordInfo* password_info;
431 438
432 if (!FindLoginInfo(node, &username_element, &password_info) || 439 if (!FindLoginInfo(node, &username_element, &password_info) ||
433 !IsElementAutocompletable(username_element) || 440 !IsElementsAutocompletable(username_element,
434 !IsElementAutocompletable(password_info->password_field)) { 441 password_info->password_field)) {
435 return false; 442 return false;
436 } 443 }
437 444
438 was_username_autofilled_ = username_element.isAutofilled(); 445 was_username_autofilled_ = username_element.isAutofilled();
439 username_selection_start_ = username_element.selectionStart(); 446 username_selection_start_ = username_element.selectionStart();
440 username_element.setSuggestedValue(username); 447 username_element.setSuggestedValue(username);
441 username_element.setAutofilled(true); 448 username_element.setAutofilled(true);
442 username_element.setSelectionRange( 449 username_element.setSelectionRange(
443 username_selection_start_, 450 username_selection_start_,
444 username_element.suggestedValue().length()); 451 username_element.suggestedValue().length());
(...skipping 21 matching lines...) Expand all
466 bool show_all) { 473 bool show_all) {
467 LoginToPasswordInfoMap::const_iterator iter = 474 LoginToPasswordInfoMap::const_iterator iter =
468 login_to_password_info_.find(element); 475 login_to_password_info_.find(element);
469 if (iter == login_to_password_info_.end()) 476 if (iter == login_to_password_info_.end())
470 return false; 477 return false;
471 478
472 // If autocomplete='off' is set on the form elements, no suggestion dialog 479 // If autocomplete='off' is set on the form elements, no suggestion dialog
473 // should be shown. However, return |true| to indicate that this is a known 480 // should be shown. However, return |true| to indicate that this is a known
474 // password form and that the request to show suggestions has been handled (as 481 // password form and that the request to show suggestions has been handled (as
475 // a no-op). 482 // a no-op).
476 if (!IsElementAutocompletable(element) || 483 if (!IsElementsAutocompletable(element, iter->second.password_field))
477 !IsElementAutocompletable(iter->second.password_field))
478 return true; 484 return true;
479 485
480 return ShowSuggestionPopup(iter->second.fill_data, element, show_all); 486 return ShowSuggestionPopup(iter->second.fill_data, element, show_all);
481 } 487 }
482 488
483 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( 489 bool PasswordAutofillAgent::OriginCanAccessPasswordManager(
484 const blink::WebSecurityOrigin& origin) { 490 const blink::WebSecurityOrigin& origin) {
485 return origin.canAccessPasswordManager(); 491 return origin.canAccessPasswordManager();
486 } 492 }
487 493
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after
958 blink::WebInputElement* username_element, 964 blink::WebInputElement* username_element,
959 blink::WebInputElement* password_element, 965 blink::WebInputElement* password_element,
960 const PasswordFormFillData& fill_data, 966 const PasswordFormFillData& fill_data,
961 bool exact_username_match, 967 bool exact_username_match,
962 bool set_selection) { 968 bool set_selection) {
963 base::string16 current_username = username_element->value(); 969 base::string16 current_username = username_element->value();
964 // username and password will contain the match found if any. 970 // username and password will contain the match found if any.
965 base::string16 username; 971 base::string16 username;
966 base::string16 password; 972 base::string16 password;
967 973
974 // Don't fill username if password can't be set.
975 if (!IsElementAutocompletable(*password_element))
vabr (Chromium) 2014/09/18 09:14:24 Since you asked explicitly: yes, moving this check
Deepak 2014/09/18 09:35:13 Thanks.
976 return false;
977
968 // Look for any suitable matches to current field text. 978 // Look for any suitable matches to current field text.
969 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, 979 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value,
970 current_username, 980 current_username,
971 exact_username_match)) { 981 exact_username_match)) {
972 username = fill_data.basic_data.fields[0].value; 982 username = fill_data.basic_data.fields[0].value;
973 password = fill_data.basic_data.fields[1].value; 983 password = fill_data.basic_data.fields[1].value;
974 } else { 984 } else {
975 // Scan additional logins for a match. 985 // Scan additional logins for a match.
976 PasswordFormFillData::LoginCollection::const_iterator iter; 986 CheckLoginCollectionForMatch(
977 for (iter = fill_data.additional_logins.begin(); 987 fill_data, current_username, exact_username_match, username, password);
978 iter != fill_data.additional_logins.end(); 988 // Check possible usernames.
979 ++iter) { 989 if (username.empty() && password.empty())
980 if (DoUsernamesMatch( 990 CheckUsernamesCollectionForMatch(fill_data,
981 iter->first, current_username, exact_username_match)) { 991 current_username,
982 username = iter->first; 992 exact_username_match,
983 password = iter->second.password; 993 username,
984 break; 994 password);
985 } 995 }
986 }
987 996
988 // Check possible usernames.
989 if (username.empty() && password.empty()) {
990 for (PasswordFormFillData::UsernamesCollection::const_iterator iter =
991 fill_data.other_possible_usernames.begin();
992 iter != fill_data.other_possible_usernames.end();
993 ++iter) {
994 for (size_t i = 0; i < iter->second.size(); ++i) {
995 if (DoUsernamesMatch(
996 iter->second[i], current_username, exact_username_match)) {
997 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED;
998 username = iter->second[i];
999 password = iter->first.password;
1000 break;
1001 }
1002 }
1003 if (!username.empty() && !password.empty())
1004 break;
1005 }
1006 }
1007 }
1008 if (password.empty()) 997 if (password.empty())
1009 return false; // No match was found. 998 return false; // No match was found.
1010 999
1011 // TODO(tkent): Check maxlength and pattern for both username and password 1000 // TODO(tkent): Check maxlength and pattern for both username and password
1012 // fields. 1001 // fields.
1013 1002
1014 // Don't fill username if password can't be set.
1015 if (!IsElementAutocompletable(*password_element)) {
1016 return false;
1017 }
1018
1019 // Input matches the username, fill in required values. 1003 // Input matches the username, fill in required values.
1020 if (IsElementAutocompletable(*username_element)) { 1004 if (IsElementAutocompletable(*username_element)) {
1021 username_element->setValue(username, true); 1005 username_element->setValue(username, true);
1022 username_element->setAutofilled(true); 1006 username_element->setAutofilled(true);
1023 1007
1024 if (set_selection) { 1008 if (set_selection) {
1025 username_element->setSelectionRange(current_username.length(), 1009 username_element->setSelectionRange(current_username.length(),
1026 username.length()); 1010 username.length());
1027 } 1011 }
1028 } else if (current_username != username) { 1012 } else if (current_username != username) {
1029 // If the username can't be filled and it doesn't match a saved password 1013 // If the username can't be filled and it doesn't match a saved password
1030 // as is, don't autofill a password. 1014 // as is, don't autofill a password.
1031 return false; 1015 return false;
1032 } 1016 }
1033
1034 // Wait to fill in the password until a user gesture occurs. This is to make 1017 // Wait to fill in the password until a user gesture occurs. This is to make
1035 // sure that we do not fill in the DOM with a password until we believe the 1018 // sure that we do not fill in the DOM with a password until we believe the
1036 // user is intentionally interacting with the page. 1019 // user is intentionally interacting with the page.
1037 password_element->setSuggestedValue(password); 1020 password_element->setSuggestedValue(password);
1038 gatekeeper_.RegisterElement(password_element); 1021 gatekeeper_.RegisterElement(password_element);
1039 1022
1040 password_element->setAutofilled(true); 1023 password_element->setAutofilled(true);
1041 return true; 1024 return true;
1042 } 1025 }
1043 1026
1027 // Check additional names for match.
1028 void PasswordAutofillAgent::CheckLoginCollectionForMatch(
vabr (Chromium) 2014/09/18 09:14:24 Why separating the code into the two functions her
Deepak 2014/09/18 09:35:13 ok, I will make this again inline as earlier.
1029 const PasswordFormFillData& fill_data,
1030 const base::string16 current_username,
1031 const bool exact_username_match,
1032 base::string16& username,
1033 base::string16& password) {
1034 for (PasswordFormFillData::LoginCollection::const_iterator iter =
1035 fill_data.additional_logins.begin();
1036 iter != fill_data.additional_logins.end();
1037 ++iter) {
1038 if (DoUsernamesMatch(iter->first, current_username, exact_username_match)) {
1039 username = iter->first;
1040 password = iter->second.password;
1041 break;
1042 }
1043 }
1044 }
1045
1046 // Check possible usernames.
1047 void PasswordAutofillAgent::CheckUsernamesCollectionForMatch(
1048 const PasswordFormFillData& fill_data,
1049 const base::string16 current_username,
1050 const bool exact_username_match,
1051 base::string16& username,
1052 base::string16& password) {
1053 for (PasswordFormFillData::UsernamesCollection::const_iterator iter =
1054 fill_data.other_possible_usernames.begin();
1055 iter != fill_data.other_possible_usernames.end();
1056 ++iter) {
1057 for (size_t i = 0; i < iter->second.size(); ++i) {
1058 if (DoUsernamesMatch(
1059 iter->second[i], current_username, exact_username_match)) {
1060 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED;
1061 username = iter->second[i];
1062 password = iter->first.password;
1063 break;
1064 }
1065 }
1066 if (!username.empty() && !password.empty())
1067 break;
1068 }
1069 }
1070
1044 void PasswordAutofillAgent::PerformInlineAutocomplete( 1071 void PasswordAutofillAgent::PerformInlineAutocomplete(
1045 const blink::WebInputElement& username_input, 1072 const blink::WebInputElement& username_input,
1046 const blink::WebInputElement& password_input, 1073 const blink::WebInputElement& password_input,
1047 const PasswordFormFillData& fill_data) { 1074 const PasswordFormFillData& fill_data) {
1048 DCHECK(!fill_data.wait_for_username); 1075 DCHECK(!fill_data.wait_for_username);
1049 1076
1050 // We need non-const versions of the username and password inputs. 1077 // We need non-const versions of the username and password inputs.
1051 blink::WebInputElement username = username_input; 1078 blink::WebInputElement username = username_input;
1052 blink::WebInputElement password = password_input; 1079 blink::WebInputElement password = password_input;
1053 1080
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1135 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); 1162 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form));
1136 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && 1163 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD &&
1137 password_form->password_value.empty() && 1164 password_form->password_value.empty() &&
1138 password_form->new_password_value.empty())) { 1165 password_form->new_password_value.empty())) {
1139 return; 1166 return;
1140 } 1167 }
1141 provisionally_saved_forms_[frame].reset(password_form.release()); 1168 provisionally_saved_forms_[frame].reset(password_form.release());
1142 } 1169 }
1143 1170
1144 } // namespace autofill 1171 } // namespace autofill
OLDNEW
« no previous file with comments | « components/autofill/content/renderer/password_autofill_agent.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698