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