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/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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |