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 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 | 211 |
212 } // namespace | 212 } // namespace |
213 | 213 |
214 //////////////////////////////////////////////////////////////////////////////// | 214 //////////////////////////////////////////////////////////////////////////////// |
215 // PasswordAutofillAgent, public: | 215 // PasswordAutofillAgent, public: |
216 | 216 |
217 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) | 217 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) |
218 : content::RenderViewObserver(render_view), | 218 : content::RenderViewObserver(render_view), |
219 usernames_usage_(NOTHING_TO_AUTOFILL), | 219 usernames_usage_(NOTHING_TO_AUTOFILL), |
220 web_view_(render_view->GetWebView()), | 220 web_view_(render_view->GetWebView()), |
| 221 was_password_autofilled_(false), |
| 222 is_password_previewed_(false), |
221 weak_ptr_factory_(this) { | 223 weak_ptr_factory_(this) { |
222 } | 224 } |
223 | 225 |
224 PasswordAutofillAgent::~PasswordAutofillAgent() {} | 226 PasswordAutofillAgent::~PasswordAutofillAgent() {} |
225 | 227 |
226 PasswordAutofillAgent::PasswordValueGatekeeper::PasswordValueGatekeeper() | 228 PasswordAutofillAgent::PasswordValueGatekeeper::PasswordValueGatekeeper() |
227 : was_user_gesture_seen_(false) {} | 229 : was_user_gesture_seen_(false) {} |
228 | 230 |
229 PasswordAutofillAgent::PasswordValueGatekeeper::~PasswordValueGatekeeper() {} | 231 PasswordAutofillAgent::PasswordValueGatekeeper::~PasswordValueGatekeeper() {} |
230 | 232 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 | 329 |
328 // Don't attempt to autofill with values that are too large. | 330 // Don't attempt to autofill with values that are too large. |
329 if (element.value().length() > kMaximumTextSizeForAutocomplete) | 331 if (element.value().length() > kMaximumTextSizeForAutocomplete) |
330 return false; | 332 return false; |
331 | 333 |
332 // The caret position should have already been updated. | 334 // The caret position should have already been updated. |
333 PerformInlineAutocomplete(element, password, iter->second.fill_data); | 335 PerformInlineAutocomplete(element, password, iter->second.fill_data); |
334 return true; | 336 return true; |
335 } | 337 } |
336 | 338 |
| 339 bool PasswordAutofillAgent::WasPasswordAutofilled() { |
| 340 return was_password_autofilled_; |
| 341 } |
| 342 |
| 343 bool PasswordAutofillAgent::IsPasswordPreviewed() { |
| 344 return is_password_previewed_; |
| 345 } |
| 346 |
337 bool PasswordAutofillAgent::TextFieldHandlingKeyDown( | 347 bool PasswordAutofillAgent::TextFieldHandlingKeyDown( |
338 const blink::WebInputElement& element, | 348 const blink::WebInputElement& element, |
339 const blink::WebKeyboardEvent& event) { | 349 const blink::WebKeyboardEvent& event) { |
340 // If using the new Autofill UI that lives in the browser, it will handle | 350 // If using the new Autofill UI that lives in the browser, it will handle |
341 // keypresses before this function. This is not currently an issue but if | 351 // keypresses before this function. This is not currently an issue but if |
342 // the keys handled there or here change, this issue may appear. | 352 // the keys handled there or here change, this issue may appear. |
343 | 353 |
344 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(element); | 354 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(element); |
345 if (iter == login_to_password_info_.end()) | 355 if (iter == login_to_password_info_.end()) |
346 return false; | 356 return false; |
347 | 357 |
348 int win_key_code = event.windowsKeyCode; | 358 int win_key_code = event.windowsKeyCode; |
349 iter->second.backspace_pressed_last = | 359 iter->second.backspace_pressed_last = |
350 (win_key_code == ui::VKEY_BACK || win_key_code == ui::VKEY_DELETE); | 360 (win_key_code == ui::VKEY_BACK || win_key_code == ui::VKEY_DELETE); |
351 return true; | 361 return true; |
352 } | 362 } |
353 | 363 |
354 bool PasswordAutofillAgent::DidAcceptAutofillSuggestion( | 364 bool PasswordAutofillAgent::DidSelectSuggestion( |
355 const blink::WebNode& node, | 365 const blink::WebNode& node, |
356 const blink::WebString& username) { | 366 const blink::WebString& username) { |
357 blink::WebInputElement input; | 367 blink::WebInputElement input; |
| 368 PasswordInfo password; |
| 369 if (!FindLoginInfo(node, &input, &password)) |
| 370 return false; |
| 371 |
| 372 // Set the incoming |username| as the suggested value for the text field and |
| 373 // |PreviewUserNameAndPassword| will do the rest. |
| 374 input.setSuggestedValue(username); |
| 375 is_password_previewed_ = PreviewUserNameAndPassword( |
| 376 &input, |
| 377 &password.password_field, |
| 378 password.fill_data, |
| 379 true /* exact_username_match */, |
| 380 true /* set_selection */); |
| 381 return is_password_previewed_; |
| 382 } |
| 383 |
| 384 bool PasswordAutofillAgent::DidAcceptSuggestion( |
| 385 const blink::WebNode& node, |
| 386 const blink::WebString& username) { |
| 387 blink::WebInputElement input; |
358 PasswordInfo password; | 388 PasswordInfo password; |
359 if (!FindLoginInfo(node, &input, &password)) | 389 if (!FindLoginInfo(node, &input, &password)) |
360 return false; | 390 return false; |
361 | 391 |
362 // Set the incoming |username| in the text field and |FillUserNameAndPassword| | 392 // Set the incoming |username| in the text field and |FillUserNameAndPassword| |
363 // will do the rest. | 393 // will do the rest. |
364 input.setValue(username, true); | 394 input.setValue(username, true); |
365 return FillUserNameAndPassword(&input, &password.password_field, | 395 return FillUserNameAndPassword(&input, &password.password_field, |
366 password.fill_data, | 396 password.fill_data, |
367 true /* exact_username_match */, | 397 true /* exact_username_match */, |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
743 username_element.setValue(fill_data.basic_data.fields[0].value, true); | 773 username_element.setValue(fill_data.basic_data.fields[0].value, true); |
744 } | 774 } |
745 | 775 |
746 // Fill if we have an exact match for the username. Note that this sets | 776 // Fill if we have an exact match for the username. Note that this sets |
747 // username to autofilled. | 777 // username to autofilled. |
748 FillUserNameAndPassword(&username_element, &password_element, fill_data, | 778 FillUserNameAndPassword(&username_element, &password_element, fill_data, |
749 true /* exact_username_match */, | 779 true /* exact_username_match */, |
750 false /* set_selection */); | 780 false /* set_selection */); |
751 } | 781 } |
752 | 782 |
753 bool PasswordAutofillAgent::FillUserNameAndPassword( | 783 void PasswordAutofillAgent::FindUserNameAndPassword( |
754 blink::WebInputElement* username_element, | 784 base::string16 current_username, |
755 blink::WebInputElement* password_element, | 785 base::string16* username, |
| 786 base::string16* password, |
756 const PasswordFormFillData& fill_data, | 787 const PasswordFormFillData& fill_data, |
757 bool exact_username_match, | 788 bool exact_username_match) { |
758 bool set_selection) { | |
759 base::string16 current_username = username_element->value(); | |
760 // username and password will contain the match found if any. | |
761 base::string16 username; | |
762 base::string16 password; | |
763 | |
764 // Look for any suitable matches to current field text. | 789 // Look for any suitable matches to current field text. |
765 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, current_username, | 790 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, current_username, |
766 exact_username_match)) { | 791 exact_username_match)) { |
767 username = fill_data.basic_data.fields[0].value; | 792 *username = fill_data.basic_data.fields[0].value; |
768 password = fill_data.basic_data.fields[1].value; | 793 *password = fill_data.basic_data.fields[1].value; |
769 } else { | 794 } else { |
770 // Scan additional logins for a match. | 795 // Scan additional logins for a match. |
771 PasswordFormFillData::LoginCollection::const_iterator iter; | 796 PasswordFormFillData::LoginCollection::const_iterator iter; |
772 for (iter = fill_data.additional_logins.begin(); | 797 for (iter = fill_data.additional_logins.begin(); |
773 iter != fill_data.additional_logins.end(); ++iter) { | 798 iter != fill_data.additional_logins.end(); ++iter) { |
774 if (DoUsernamesMatch(iter->first, current_username, | 799 if (DoUsernamesMatch(iter->first, current_username, |
775 exact_username_match)) { | 800 exact_username_match)) { |
776 username = iter->first; | 801 *username = iter->first; |
777 password = iter->second.password; | 802 *password = iter->second.password; |
778 break; | 803 break; |
779 } | 804 } |
780 } | 805 } |
781 | |
782 // Check possible usernames. | 806 // Check possible usernames. |
783 if (username.empty() && password.empty()) { | 807 if (username->empty() && password->empty()) { |
784 for (PasswordFormFillData::UsernamesCollection::const_iterator iter = | 808 for (PasswordFormFillData::UsernamesCollection::const_iterator iter = |
785 fill_data.other_possible_usernames.begin(); | 809 fill_data.other_possible_usernames.begin(); |
786 iter != fill_data.other_possible_usernames.end(); ++iter) { | 810 iter != fill_data.other_possible_usernames.end(); ++iter) { |
787 for (size_t i = 0; i < iter->second.size(); ++i) { | 811 for (size_t i = 0; i < iter->second.size(); ++i) { |
788 if (DoUsernamesMatch(iter->second[i], current_username, | 812 if (DoUsernamesMatch(iter->second[i], current_username, |
789 exact_username_match)) { | 813 exact_username_match)) { |
790 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | 814 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; |
791 username = iter->second[i]; | 815 *username = iter->second[i]; |
792 password = iter->first.password; | 816 *password = iter->first.password; |
793 break; | 817 break; |
794 } | 818 } |
795 } | 819 } |
796 if (!username.empty() && !password.empty()) | 820 if (!username->empty() && !password->empty()) |
797 break; | 821 break; |
798 } | 822 } |
799 } | 823 } |
800 } | 824 } |
| 825 } |
| 826 |
| 827 bool PasswordAutofillAgent::FillUserNameAndPassword( |
| 828 blink::WebInputElement* username_element, |
| 829 blink::WebInputElement* password_element, |
| 830 const PasswordFormFillData& fill_data, |
| 831 bool exact_username_match, |
| 832 bool set_selection) { |
| 833 base::string16 current_username = username_element->value(); |
| 834 // username and password will contain the match found if any. |
| 835 base::string16 username; |
| 836 base::string16 password; |
| 837 |
| 838 FindUserNameAndPassword (current_username, |
| 839 &username, |
| 840 &password, |
| 841 fill_data, |
| 842 exact_username_match); |
| 843 |
801 if (password.empty()) | 844 if (password.empty()) |
802 return false; // No match was found. | 845 return false; // No match was found. |
803 | 846 |
804 // TODO(tkent): Check maxlength and pattern for both username and password | 847 // TODO(tkent): Check maxlength and pattern for both username and password |
805 // fields. | 848 // fields. |
806 | 849 |
807 // Don't fill username if password can't be set. | 850 // Don't fill username if password can't be set. |
808 if (!IsElementAutocompletable(*password_element)) { | 851 if (!IsElementAutocompletable(*password_element)) { |
809 return false; | 852 return false; |
810 } | 853 } |
811 | 854 |
812 // Input matches the username, fill in required values. | 855 // Input matches the username, fill in required values. |
813 if (IsElementAutocompletable(*username_element)) { | 856 if (IsElementAutocompletable(*username_element)) { |
814 username_element->setValue(username, true); | 857 username_element->setValue(username, true); |
815 SetElementAutofilled(username_element, true); | 858 SetElementAutofilled(username_element, true); |
816 | 859 |
817 if (set_selection) { | 860 if (set_selection) { |
818 username_element->setSelectionRange(current_username.length(), | 861 username_element->setSelectionRange(current_username.length(), |
819 username.length()); | 862 username.length()); |
820 } | 863 } |
821 } else if (current_username != username) { | 864 } else if (current_username != username) { |
822 // If the username can't be filled and it doesn't match a saved password | 865 // If the username can't be filled and it doesn't match a saved password |
823 // as is, don't autofill a password. | 866 // as is, don't autofill a password. |
824 return false; | 867 return false; |
825 } | 868 } |
826 | 869 |
| 870 was_password_autofilled_ = password_element->isAutofilled(); |
827 // TODO(vabr): The "gatekeeper" feature is currently disabled on mobile. | 871 // TODO(vabr): The "gatekeeper" feature is currently disabled on mobile. |
828 // http://crbug.com/345510#c13 | 872 // http://crbug.com/345510#c13 |
829 #if !defined(OS_ANDROID) || !defined(OS_IOS) | 873 #if !defined(OS_ANDROID) || !defined(OS_IOS) |
830 // Wait to fill in the password until a user gesture occurs. This is to make | 874 // Wait to fill in the password until a user gesture occurs. This is to make |
831 // sure that we do not fill in the DOM with a password until we believe the | 875 // sure that we do not fill in the DOM with a password until we believe the |
832 // user is intentionally interacting with the page. | 876 // user is intentionally interacting with the page. |
833 password_element->setSuggestedValue(password); | 877 password_element->setSuggestedValue(password); |
834 gatekeeper_.RegisterElement(password_element); | 878 gatekeeper_.RegisterElement(password_element); |
835 #else | 879 #else |
836 password_element->setValue(password); | 880 password_element->setValue(password); |
837 #endif | 881 #endif |
838 | 882 |
839 // Note: Don't call SetElementAutofilled() here, as that dispatches an | 883 // Note: Don't call SetElementAutofilled() here, as that dispatches an |
840 // onChange event in JavaScript, which is not appropriate for the password | 884 // onChange event in JavaScript, which is not appropriate for the password |
841 // element if a user gesture has not yet occured. | 885 // element if a user gesture has not yet occured. |
842 password_element->setAutofilled(true); | 886 password_element->setAutofilled(true); |
843 return true; | 887 return true; |
844 } | 888 } |
845 | 889 |
| 890 bool PasswordAutofillAgent::PreviewUserNameAndPassword( |
| 891 blink::WebInputElement* username_element, |
| 892 blink::WebInputElement* password_element, |
| 893 const PasswordFormFillData& fill_data, |
| 894 bool exact_username_match, |
| 895 bool set_selection) { |
| 896 base::string16 current_username = username_element->suggestedValue(); |
| 897 // username and password will contain the match found if any. |
| 898 base::string16 username; |
| 899 base::string16 password; |
| 900 |
| 901 FindUserNameAndPassword (current_username, |
| 902 &username, |
| 903 &password, |
| 904 fill_data, |
| 905 exact_username_match); |
| 906 |
| 907 if (password.empty()) |
| 908 return false; // No match was found. |
| 909 |
| 910 // TODO(tkent): Check maxlength and pattern for both username and password |
| 911 // fields. |
| 912 |
| 913 // Don't preview username if password can't be set. |
| 914 if (!IsElementAutocompletable(*password_element)) { |
| 915 return false; |
| 916 } |
| 917 |
| 918 // Input matches the username, preview required values. |
| 919 if (IsElementAutocompletable(*username_element)) { |
| 920 username_element->setSuggestedValue(username); |
| 921 username_element->setAutofilled(true); |
| 922 |
| 923 if (set_selection) { |
| 924 username_element->setSelectionRange(current_username.length(), |
| 925 username.length()); |
| 926 } |
| 927 } else if (current_username != username) { |
| 928 return false; |
| 929 } |
| 930 |
| 931 was_password_autofilled_ = password_element->isAutofilled(); |
| 932 password_element->setSuggestedValue(password); |
| 933 password_element->setAutofilled(true); |
| 934 return true; |
| 935 } |
| 936 |
846 void PasswordAutofillAgent::PerformInlineAutocomplete( | 937 void PasswordAutofillAgent::PerformInlineAutocomplete( |
847 const blink::WebInputElement& username_input, | 938 const blink::WebInputElement& username_input, |
848 const blink::WebInputElement& password_input, | 939 const blink::WebInputElement& password_input, |
849 const PasswordFormFillData& fill_data) { | 940 const PasswordFormFillData& fill_data) { |
850 DCHECK(!fill_data.wait_for_username); | 941 DCHECK(!fill_data.wait_for_username); |
851 | 942 |
852 // We need non-const versions of the username and password inputs. | 943 // We need non-const versions of the username and password inputs. |
853 blink::WebInputElement username = username_input; | 944 blink::WebInputElement username = username_input; |
854 blink::WebInputElement password = password_input; | 945 blink::WebInputElement password = password_input; |
855 | 946 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
905 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(input); | 996 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(input); |
906 if (iter == login_to_password_info_.end()) | 997 if (iter == login_to_password_info_.end()) |
907 return false; | 998 return false; |
908 | 999 |
909 *found_input = input; | 1000 *found_input = input; |
910 *found_password = iter->second; | 1001 *found_password = iter->second; |
911 return true; | 1002 return true; |
912 } | 1003 } |
913 | 1004 |
914 } // namespace autofill | 1005 } // namespace autofill |
OLD | NEW |