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 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 elements_.clear(); | 266 elements_.clear(); |
| 267 } | 267 } |
| 268 | 268 |
| 269 void PasswordAutofillAgent::PasswordValueGatekeeper::Reset() { | 269 void PasswordAutofillAgent::PasswordValueGatekeeper::Reset() { |
| 270 was_user_gesture_seen_ = false; | 270 was_user_gesture_seen_ = false; |
| 271 elements_.clear(); | 271 elements_.clear(); |
| 272 } | 272 } |
| 273 | 273 |
| 274 void PasswordAutofillAgent::PasswordValueGatekeeper::ShowValue( | 274 void PasswordAutofillAgent::PasswordValueGatekeeper::ShowValue( |
| 275 blink::WebInputElement* element) { | 275 blink::WebInputElement* element) { |
| 276 if (!element->isNull() && !element->suggestedValue().isNull()) | 276 if (!element->isNull() && element->value().isNull() && |
|
engedy
2014/07/29 17:47:56
Could you please double-check that we first erase
vabr (Chromium)
2014/07/30 16:46:58
Great catch. Indeed, I broke this. It should be no
| |
| 277 !element->suggestedValue().isNull()) { | |
| 277 element->setValue(element->suggestedValue(), true); | 278 element->setValue(element->suggestedValue(), true); |
| 279 element->setSuggestedValue(blink::WebString()); | |
|
vabr (Chromium)
2014/07/30 16:46:58
I just discovered that setValue clears the suggest
| |
| 280 } | |
| 278 } | 281 } |
| 279 | 282 |
| 280 bool PasswordAutofillAgent::TextFieldDidEndEditing( | 283 bool PasswordAutofillAgent::TextFieldDidEndEditing( |
| 281 const blink::WebInputElement& element) { | 284 const blink::WebInputElement& element) { |
| 282 LoginToPasswordInfoMap::const_iterator iter = | 285 LoginToPasswordInfoMap::const_iterator iter = |
| 283 login_to_password_info_.find(element); | 286 login_to_password_info_.find(element); |
| 284 if (iter == login_to_password_info_.end()) | 287 if (iter == login_to_password_info_.end()) |
| 285 return false; | 288 return false; |
| 286 | 289 |
| 287 const PasswordFormFillData& fill_data = iter->second.fill_data; | 290 const PasswordFormFillData& fill_data = iter->second.fill_data; |
| 288 | 291 |
| 289 // If wait_for_username is false, we should have filled when the text changed. | 292 // If wait_for_username is false, we should have filled when the text changed. |
| 290 if (!fill_data.wait_for_username) | 293 if (!fill_data.wait_for_username) |
| 291 return false; | 294 return false; |
| 292 | 295 |
| 293 blink::WebInputElement password = iter->second.password_field; | 296 blink::WebInputElement password = iter->second.password_field; |
| 294 if (!IsElementEditable(password)) | 297 if (!IsElementEditable(password)) |
| 295 return false; | 298 return false; |
| 296 | 299 |
| 297 blink::WebInputElement username = element; // We need a non-const. | 300 blink::WebInputElement username = element; // We need a non-const. |
| 298 | 301 |
| 302 // Don't let autofill overwrite an explicit change made by the user. | |
| 303 if (iter->second.user_changed_password_more_recently_than_username) | |
|
engedy
2014/07/29 17:47:56
I have put some more though into this, I *think* t
vabr (Chromium)
2014/07/30 16:46:59
Your semantics sounds reasonable to me. I tried to
| |
| 304 return false; | |
| 305 | |
| 299 // Do not set selection when ending an editing session, otherwise it can | 306 // Do not set selection when ending an editing session, otherwise it can |
| 300 // mess with focus. | 307 // mess with focus. |
| 301 FillUserNameAndPassword(&username, | 308 FillUserNameAndPassword(&username, |
| 302 &password, | 309 &password, |
| 303 fill_data, | 310 fill_data, |
| 304 true /* exact_username_match */, | 311 true /* exact_username_match */, |
| 305 false /* set_selection */); | 312 false /* set_selection */); |
| 306 return true; | 313 return true; |
| 307 } | 314 } |
| 308 | 315 |
| 309 bool PasswordAutofillAgent::TextDidChangeInTextField( | 316 bool PasswordAutofillAgent::TextDidChangeInTextField( |
| 310 const blink::WebInputElement& element) { | 317 const blink::WebInputElement& element) { |
| 318 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 | |
| 319 blink::WebInputElement mutable_element = element; // We need a non-const. | |
| 320 | |
| 321 if (element.isPasswordField()) { | |
| 322 PasswordToLoginMap::iterator iter = password_to_username_.find(element); | |
| 323 if (iter != password_to_username_.end()) { | |
| 324 login_to_password_info_[iter->second] | |
| 325 .user_changed_password_more_recently_than_username = true; | |
| 326 mutable_element.setAutofilled(false); | |
| 327 } | |
| 328 return false; | |
| 329 } | |
| 330 | |
| 311 LoginToPasswordInfoMap::const_iterator iter = | 331 LoginToPasswordInfoMap::const_iterator iter = |
| 312 login_to_password_info_.find(element); | 332 login_to_password_info_.find(element); |
| 313 if (iter == login_to_password_info_.end()) | 333 if (iter == login_to_password_info_.end()) |
| 314 return false; | 334 return false; |
| 315 | 335 |
| 316 // The input text is being changed, so any autofilled password is now | 336 // The input text is being changed, so any autofilled password is now |
| 317 // outdated. | 337 // outdated. |
| 318 blink::WebInputElement username = element; // We need a non-const. | 338 mutable_element.setAutofilled(false); |
| 319 username.setAutofilled(false); | 339 login_to_password_info_[element] |
| 340 .user_changed_password_more_recently_than_username = false; | |
| 320 | 341 |
| 321 blink::WebInputElement password = iter->second.password_field; | 342 blink::WebInputElement password = iter->second.password_field; |
| 322 if (password.isAutofilled()) { | 343 if (password.isAutofilled()) { |
| 323 password.setValue(base::string16(), true); | 344 password.setValue(base::string16(), true); |
| 324 password.setAutofilled(false); | 345 password.setAutofilled(false); |
| 325 } | 346 } |
| 326 | 347 |
| 327 // If wait_for_username is true we will fill when the username loses focus. | 348 // If wait_for_username is true we will fill when the username loses focus. |
| 328 if (iter->second.fill_data.wait_for_username) | 349 if (iter->second.fill_data.wait_for_username) |
| 329 return false; | 350 return false; |
| 330 | 351 |
| 331 if (!element.isText() || !IsElementAutocompletable(element) || | 352 if (!element.isText() || !IsElementAutocompletable(element) || |
| 332 !IsElementAutocompletable(password)) { | 353 !IsElementAutocompletable(password)) { |
| 333 return false; | 354 return false; |
| 334 } | 355 } |
| 335 | 356 |
| 336 // Don't inline autocomplete if the user is deleting, that would be confusing. | 357 // Don't inline autocomplete if the user is deleting, that would be confusing. |
| 337 // But refresh the popup. Note, since this is ours, return true to signal | 358 // But refresh the popup. Note, since this is ours, return true to signal |
| 338 // no further processing is required. | 359 // no further processing is required. |
| 339 if (iter->second.backspace_pressed_last) { | 360 if (iter->second.backspace_pressed_last) { |
| 340 ShowSuggestionPopup(iter->second.fill_data, username, false); | 361 ShowSuggestionPopup(iter->second.fill_data, element, false); |
| 341 return true; | 362 return true; |
| 342 } | 363 } |
| 343 | 364 |
| 344 blink::WebString name = element.nameForAutofill(); | 365 blink::WebString name = element.nameForAutofill(); |
| 345 if (name.isEmpty()) | 366 if (name.isEmpty()) |
| 346 return false; // If the field has no name, then we won't have values. | 367 return false; // If the field has no name, then we won't have values. |
| 347 | 368 |
| 348 // Don't attempt to autofill with values that are too large. | 369 // Don't attempt to autofill with values that are too large. |
| 349 if (element.value().length() > kMaximumTextSizeForAutocomplete) | 370 if (element.value().length() > kMaximumTextSizeForAutocomplete) |
| 350 return false; | 371 return false; |
| 351 | 372 |
| 373 // Don't let autofill overwrite an explicit change made by the user. | |
| 374 if (iter->second.user_changed_password_more_recently_than_username) | |
| 375 return false; | |
| 376 | |
| 352 // The caret position should have already been updated. | 377 // The caret position should have already been updated. |
| 353 PerformInlineAutocomplete(element, password, iter->second.fill_data); | 378 PerformInlineAutocomplete(element, password, iter->second.fill_data); |
| 354 return true; | 379 return true; |
| 355 } | 380 } |
| 356 | 381 |
| 357 bool PasswordAutofillAgent::TextFieldHandlingKeyDown( | 382 bool PasswordAutofillAgent::TextFieldHandlingKeyDown( |
| 358 const blink::WebInputElement& element, | 383 const blink::WebInputElement& element, |
| 359 const blink::WebKeyboardEvent& event) { | 384 const blink::WebKeyboardEvent& event) { |
| 360 // If using the new Autofill UI that lives in the browser, it will handle | 385 // If using the new Autofill UI that lives in the browser, it will handle |
| 361 // keypresses before this function. This is not currently an issue but if | 386 // keypresses before this function. This is not currently an issue but if |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 783 // We might have already filled this form if there are two <form> elements | 808 // We might have already filled this form if there are two <form> elements |
| 784 // with identical markup. | 809 // with identical markup. |
| 785 if (login_to_password_info_.find(username_element) != | 810 if (login_to_password_info_.find(username_element) != |
| 786 login_to_password_info_.end()) | 811 login_to_password_info_.end()) |
| 787 continue; | 812 continue; |
| 788 | 813 |
| 789 PasswordInfo password_info; | 814 PasswordInfo password_info; |
| 790 password_info.fill_data = form_data; | 815 password_info.fill_data = form_data; |
| 791 password_info.password_field = password_element; | 816 password_info.password_field = password_element; |
| 792 login_to_password_info_[username_element] = password_info; | 817 login_to_password_info_[username_element] = password_info; |
| 818 password_to_username_[password_element] = username_element; | |
| 793 | 819 |
| 794 FormData form; | 820 FormData form; |
| 795 FormFieldData field; | 821 FormFieldData field; |
| 796 FindFormAndFieldForFormControlElement( | 822 FindFormAndFieldForFormControlElement( |
| 797 username_element, &form, &field, REQUIRE_NONE); | 823 username_element, &form, &field, REQUIRE_NONE); |
| 798 Send(new AutofillHostMsg_AddPasswordFormMapping( | 824 Send(new AutofillHostMsg_AddPasswordFormMapping( |
| 799 routing_id(), field, form_data)); | 825 routing_id(), field, form_data)); |
| 800 } | 826 } |
| 801 } | 827 } |
| 802 | 828 |
| 803 void PasswordAutofillAgent::OnSetLoggingState(bool active) { | 829 void PasswordAutofillAgent::OnSetLoggingState(bool active) { |
| 804 logging_state_active_ = active; | 830 logging_state_active_ = active; |
| 805 } | 831 } |
| 806 | 832 |
| 807 //////////////////////////////////////////////////////////////////////////////// | 833 //////////////////////////////////////////////////////////////////////////////// |
| 808 // PasswordAutofillAgent, private: | 834 // PasswordAutofillAgent, private: |
| 809 | 835 |
| 836 PasswordAutofillAgent::PasswordInfo::PasswordInfo() | |
| 837 : backspace_pressed_last(false), | |
| 838 user_changed_password_more_recently_than_username(false) { | |
| 839 } | |
| 840 | |
| 810 void PasswordAutofillAgent::GetSuggestions( | 841 void PasswordAutofillAgent::GetSuggestions( |
| 811 const PasswordFormFillData& fill_data, | 842 const PasswordFormFillData& fill_data, |
| 812 const base::string16& input, | 843 const base::string16& input, |
| 813 std::vector<base::string16>* suggestions, | 844 std::vector<base::string16>* suggestions, |
| 814 std::vector<base::string16>* realms, | 845 std::vector<base::string16>* realms, |
| 815 bool show_all) { | 846 bool show_all) { |
| 816 if (show_all || | 847 if (show_all || |
| 817 StartsWith(fill_data.basic_data.fields[0].value, input, false)) { | 848 StartsWith(fill_data.basic_data.fields[0].value, input, false)) { |
| 818 suggestions->push_back(fill_data.basic_data.fields[0].value); | 849 suggestions->push_back(fill_data.basic_data.fields[0].value); |
| 819 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm)); | 850 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm)); |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1027 &password, | 1058 &password, |
| 1028 fill_data, | 1059 fill_data, |
| 1029 false /* exact_username_match */, | 1060 false /* exact_username_match */, |
| 1030 true /* set_selection */); | 1061 true /* set_selection */); |
| 1031 #endif | 1062 #endif |
| 1032 } | 1063 } |
| 1033 | 1064 |
| 1034 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { | 1065 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { |
| 1035 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); | 1066 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); |
| 1036 iter != login_to_password_info_.end();) { | 1067 iter != login_to_password_info_.end();) { |
| 1037 if (iter->first.document().frame() == frame) | 1068 if (iter->first.document().frame() == frame) { |
| 1069 password_to_username_.erase(iter->second.password_field); | |
| 1038 login_to_password_info_.erase(iter++); | 1070 login_to_password_info_.erase(iter++); |
| 1039 else | 1071 } else { |
| 1040 ++iter; | 1072 ++iter; |
| 1073 } | |
| 1041 } | 1074 } |
| 1042 for (FrameToPasswordFormMap::iterator iter = | 1075 for (FrameToPasswordFormMap::iterator iter = |
| 1043 provisionally_saved_forms_.begin(); | 1076 provisionally_saved_forms_.begin(); |
| 1044 iter != provisionally_saved_forms_.end();) { | 1077 iter != provisionally_saved_forms_.end();) { |
| 1045 if (iter->first == frame) | 1078 if (iter->first == frame) |
| 1046 provisionally_saved_forms_.erase(iter++); | 1079 provisionally_saved_forms_.erase(iter++); |
| 1047 else | 1080 else |
| 1048 ++iter; | 1081 ++iter; |
| 1049 } | 1082 } |
| 1050 } | 1083 } |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 1078 username->setSelectionRange(username_selection_start_, | 1111 username->setSelectionRange(username_selection_start_, |
| 1079 username->value().length()); | 1112 username->value().length()); |
| 1080 } | 1113 } |
| 1081 if (!password->suggestedValue().isEmpty()) { | 1114 if (!password->suggestedValue().isEmpty()) { |
| 1082 password->setSuggestedValue(blink::WebString()); | 1115 password->setSuggestedValue(blink::WebString()); |
| 1083 password->setAutofilled(was_password_autofilled_); | 1116 password->setAutofilled(was_password_autofilled_); |
| 1084 } | 1117 } |
| 1085 } | 1118 } |
| 1086 | 1119 |
| 1087 } // namespace autofill | 1120 } // namespace autofill |
| OLD | NEW |