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

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

Issue 56653002: [Password Autofill] Make better use of prefilled usernames. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 1 month 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/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 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 curr_elements->form_element = fe; 157 curr_elements->form_element = fe;
158 results->push_back(curr_elements.release()); 158 results->push_back(curr_elements.release());
159 } 159 }
160 } 160 }
161 } 161 }
162 162
163 bool IsElementEditable(const WebKit::WebInputElement& element) { 163 bool IsElementEditable(const WebKit::WebInputElement& element) {
164 return element.isEnabled() && !element.isReadOnly(); 164 return element.isEnabled() && !element.isReadOnly();
165 } 165 }
166 166
167 void FillForm(FormElements* fe, const FormData& data) {
168 if (!fe->form_element.autoComplete())
169 return;
170
171 std::map<base::string16, base::string16> data_map;
172 for (size_t i = 0; i < data.fields.size(); i++)
173 data_map[data.fields[i].name] = data.fields[i].value;
174
175 for (FormInputElementMap::iterator it = fe->input_elements.begin();
176 it != fe->input_elements.end(); ++it) {
177 WebKit::WebInputElement element = it->second;
178 // Don't fill a form that has pre-filled values distinct from the ones we
179 // want to fill with.
180 if (!element.value().isEmpty() && element.value() != data_map[it->first])
181 return;
182
183 // Don't fill forms with uneditable fields or fields with autocomplete
184 // disabled.
185 if (!IsElementEditable(element) || !element.autoComplete())
186 return;
187 }
188
189 for (FormInputElementMap::iterator it = fe->input_elements.begin();
190 it != fe->input_elements.end(); ++it) {
191 WebKit::WebInputElement element = it->second;
192
193 // TODO(tkent): Check maxlength and pattern.
194 element.setValue(data_map[it->first]);
195 element.setAutofilled(true);
196 element.dispatchFormControlChangeEvent();
197 }
198 }
199
200 void SetElementAutofilled(WebKit::WebInputElement* element, bool autofilled) { 167 void SetElementAutofilled(WebKit::WebInputElement* element, bool autofilled) {
201 if (element->isAutofilled() == autofilled) 168 if (element->isAutofilled() == autofilled)
202 return; 169 return;
203 element->setAutofilled(autofilled); 170 element->setAutofilled(autofilled);
204 // Notify any changeEvent listeners. 171 // Notify any changeEvent listeners.
205 element->dispatchFormControlChangeEvent(); 172 element->dispatchFormControlChangeEvent();
206 } 173 }
207 174
208 bool DoUsernamesMatch(const base::string16& username1, 175 bool DoUsernamesMatch(const base::string16& username1,
209 const base::string16& username2, 176 const base::string16& username2,
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_ABSENT; 476 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_ABSENT;
510 } 477 }
511 478
512 FormElementsList forms; 479 FormElementsList forms;
513 // We own the FormElements* in forms. 480 // We own the FormElements* in forms.
514 FindFormElements(render_view()->GetWebView(), form_data.basic_data, &forms); 481 FindFormElements(render_view()->GetWebView(), form_data.basic_data, &forms);
515 FormElementsList::iterator iter; 482 FormElementsList::iterator iter;
516 for (iter = forms.begin(); iter != forms.end(); ++iter) { 483 for (iter = forms.begin(); iter != forms.end(); ++iter) {
517 scoped_ptr<FormElements> form_elements(*iter); 484 scoped_ptr<FormElements> form_elements(*iter);
518 485
519 // If wait_for_username is true, we don't want to initially fill the form
520 // until the user types in a valid username.
521 if (!form_data.wait_for_username)
522 FillForm(form_elements.get(), form_data.basic_data);
523
524 // Attach autocomplete listener to enable selecting alternate logins. 486 // Attach autocomplete listener to enable selecting alternate logins.
525 // First, get pointers to username element. 487 // First, get pointers to username element.
526 WebKit::WebInputElement username_element = 488 WebKit::WebInputElement username_element =
527 form_elements->input_elements[form_data.basic_data.fields[0].name]; 489 form_elements->input_elements[form_data.basic_data.fields[0].name];
528 490
529 // Get pointer to password element. (We currently only support single 491 // Get pointer to password element. (We currently only support single
530 // password forms). 492 // password forms).
531 WebKit::WebInputElement password_element = 493 WebKit::WebInputElement password_element =
532 form_elements->input_elements[form_data.basic_data.fields[1].name]; 494 form_elements->input_elements[form_data.basic_data.fields[1].name];
533 495
496 // If wait_for_username is true, we don't want to initially fill the form
497 // until the user types in a valid username.
498 if (!form_data.wait_for_username)
499 FillFormOnPasswordRecieved(form_data, form_elements->form_element,
500 username_element, password_element);
Ilya Sherman 2013/11/04 23:10:48 nit: Please use curly braces to enclose the if-stm
Garrett Casto 2013/11/05 00:40:35 Do you know where this is spelled out? I was actua
Ilya Sherman 2013/11/05 01:25:11 The style guide is pretty flexible: "In general, c
501
534 // We might have already filled this form if there are two <form> elements 502 // We might have already filled this form if there are two <form> elements
535 // with identical markup. 503 // with identical markup.
536 if (login_to_password_info_.find(username_element) != 504 if (login_to_password_info_.find(username_element) !=
537 login_to_password_info_.end()) 505 login_to_password_info_.end())
538 continue; 506 continue;
539 507
540 PasswordInfo password_info; 508 PasswordInfo password_info;
541 password_info.fill_data = form_data; 509 password_info.fill_data = form_data;
542 password_info.password_field = password_element; 510 password_info.password_field = password_element;
543 login_to_password_info_[username_element] = password_info; 511 login_to_password_info_[username_element] = password_info;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 bounding_box.width() * scale, 586 bounding_box.width() * scale,
619 bounding_box.height() * scale); 587 bounding_box.height() * scale);
620 Send(new AutofillHostMsg_ShowPasswordSuggestions(routing_id(), 588 Send(new AutofillHostMsg_ShowPasswordSuggestions(routing_id(),
621 field, 589 field,
622 bounding_box_scaled, 590 bounding_box_scaled,
623 suggestions, 591 suggestions,
624 realms)); 592 realms));
625 return !suggestions.empty(); 593 return !suggestions.empty();
626 } 594 }
627 595
596 void PasswordAutofillAgent::FillFormOnPasswordRecieved(
597 const PasswordFormFillData& fill_data,
598 const WebKit::WebFormElement& form_element,
599 WebKit::WebInputElement username_element,
600 WebKit::WebInputElement password_element) {
601 if (!form_element.autoComplete())
602 return;
603
604 // If we can't modify the password, don't try to set the username
605 if (!IsElementEditable(password_element) || !password_element.autoComplete())
606 return;
607
608 // Try and set the username to the preferred name, but only if the field
609 // can be set and isn't prefilled.
610 if (IsElementEditable(username_element) &&
611 username_element.autoComplete() &&
612 username_element.value().isEmpty()) {
613 username_element.setValue(fill_data.basic_data.fields[0].value);
Ilya Sherman 2013/11/04 23:10:48 What happened to setAutofilled(), dispatchFormCont
Garrett Casto 2013/11/05 00:40:35 The TODO got lost, I'll add it back somewhere. The
Ilya Sherman 2013/11/05 01:25:11 Ah, sorry, I didn't read the SetElementAutofilled
614 }
615
616 // Fill if we have an exact match for the username.
617 FillUserNameAndPassword(&username_element, &password_element, fill_data,
618 true, false);
Ilya Sherman 2013/11/04 23:10:48 nit: The semantics of "true" and "false" are reall
Garrett Casto 2013/11/05 00:40:35 Done with comments for now.
Ilya Sherman 2013/11/05 01:25:11 Thanks :)
619 }
620
628 bool PasswordAutofillAgent::FillUserNameAndPassword( 621 bool PasswordAutofillAgent::FillUserNameAndPassword(
629 WebKit::WebInputElement* username_element, 622 WebKit::WebInputElement* username_element,
630 WebKit::WebInputElement* password_element, 623 WebKit::WebInputElement* password_element,
631 const PasswordFormFillData& fill_data, 624 const PasswordFormFillData& fill_data,
632 bool exact_username_match, 625 bool exact_username_match,
633 bool set_selection) { 626 bool set_selection) {
634 base::string16 current_username = username_element->value(); 627 base::string16 current_username = username_element->value();
635 // username and password will contain the match found if any. 628 // username and password will contain the match found if any.
636 base::string16 username; 629 base::string16 username;
637 base::string16 password; 630 base::string16 password;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 } 663 }
671 if (!username.empty() && !password.empty()) 664 if (!username.empty() && !password.empty())
672 break; 665 break;
673 } 666 }
674 } 667 }
675 } 668 }
676 if (password.empty()) 669 if (password.empty())
677 return false; // No match was found. 670 return false; // No match was found.
678 671
679 // Input matches the username, fill in required values. 672 // Input matches the username, fill in required values.
680 username_element->setValue(username); 673 username_element->setValue(username);
Ilya Sherman 2013/11/04 23:10:48 Is this safe for a potentially non-modifiable elem
Garrett Casto 2013/11/05 00:40:35 Depends on what you mean by safe. There is nothing
Ilya Sherman 2013/11/05 01:25:11 I'm not convinced that it's safe to assume that th
Garrett Casto 2013/11/05 01:56:39 Fixed.
681 674
682 if (set_selection) { 675 if (set_selection) {
683 username_element->setSelectionRange(current_username.length(), 676 username_element->setSelectionRange(current_username.length(),
684 username.length()); 677 username.length());
685 } 678 }
686 679
687 SetElementAutofilled(username_element, true); 680 SetElementAutofilled(username_element, true);
Ilya Sherman 2013/11/04 23:10:48 Likewise, is this safe for a potentially non-modif
Garrett Casto 2013/11/05 00:40:35 Similar to above, though it looks like this curren
Ilya Sherman 2013/11/05 01:25:11 It looks like an oversight to me too. And it defi
Garrett Casto 2013/11/05 01:56:39 Fixed.
688 if (IsElementEditable(*password_element)) 681 if (IsElementEditable(*password_element))
689 password_element->setValue(password); 682 password_element->setValue(password);
690 SetElementAutofilled(password_element, true); 683 SetElementAutofilled(password_element, true);
691 return true; 684 return true;
692 } 685 }
693 686
694 void PasswordAutofillAgent::PerformInlineAutocomplete( 687 void PasswordAutofillAgent::PerformInlineAutocomplete(
695 const WebKit::WebInputElement& username_input, 688 const WebKit::WebInputElement& username_input,
696 const WebKit::WebInputElement& password_input, 689 const WebKit::WebInputElement& password_input,
697 const PasswordFormFillData& fill_data) { 690 const PasswordFormFillData& fill_data) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(input); 736 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(input);
744 if (iter == login_to_password_info_.end()) 737 if (iter == login_to_password_info_.end())
745 return false; 738 return false;
746 739
747 *found_input = input; 740 *found_input = input;
748 *found_password = iter->second; 741 *found_password = iter->second;
749 return true; 742 return true;
750 } 743 }
751 744
752 } // namespace autofill 745 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698