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

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

Issue 208453002: Add "previewing on hover" support for password field. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update code as per Ilya's comment. Created 6 years, 9 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
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 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698