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

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

Issue 414013003: Password autofill should not override explicitly typed password (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Removed unused #includes Created 6 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « components/autofill/content/renderer/password_autofill_agent.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
OLDNEW
« no previous file with comments | « components/autofill/content/renderer/password_autofill_agent.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698