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

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: Further corrections 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 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 PasswordAutofillAgent::~PasswordAutofillAgent() { 239 PasswordAutofillAgent::~PasswordAutofillAgent() {
240 } 240 }
241 241
242 PasswordAutofillAgent::PasswordValueGatekeeper::PasswordValueGatekeeper() 242 PasswordAutofillAgent::PasswordValueGatekeeper::PasswordValueGatekeeper()
243 : was_user_gesture_seen_(false) { 243 : was_user_gesture_seen_(false) {
244 } 244 }
245 245
246 PasswordAutofillAgent::PasswordValueGatekeeper::~PasswordValueGatekeeper() { 246 PasswordAutofillAgent::PasswordValueGatekeeper::~PasswordValueGatekeeper() {
247 } 247 }
248 248
249 void PasswordAutofillAgent::PasswordValueGatekeeper::RegisterElement( 249 void PasswordAutofillAgent::PasswordValueGatekeeper::RegisterElementInfo(
250 blink::WebInputElement* element) { 250 PasswordInfo* element_info) {
251 if (was_user_gesture_seen_) 251 DCHECK(element_info);
252 ShowValue(element); 252 if (was_user_gesture_seen_) {
253 else 253 ShowValue(&element_info->password_field);
254 elements_.push_back(*element); 254 } else {
255 elements_info_.insert(element_info);
256 }
257 }
258
259 void PasswordAutofillAgent::PasswordValueGatekeeper::UnregisterElementInfo(
260 PasswordInfo* element_info) {
261 elements_info_.erase(element_info);
255 } 262 }
256 263
257 void PasswordAutofillAgent::PasswordValueGatekeeper::OnUserGesture() { 264 void PasswordAutofillAgent::PasswordValueGatekeeper::OnUserGesture() {
258 was_user_gesture_seen_ = true; 265 was_user_gesture_seen_ = true;
259 266
260 for (std::vector<blink::WebInputElement>::iterator it = elements_.begin(); 267 for (std::set<PasswordInfo*>::iterator it = elements_info_.begin();
261 it != elements_.end(); 268 it != elements_info_.end();
262 ++it) { 269 ++it) {
263 ShowValue(&(*it)); 270 if (!(*it)->wait_for_username_change)
engedy 2014/07/31 17:14:46 I would suggest keeping this logic out of Password
vabr (Chromium) 2014/08/04 15:10:07 I agree. I also realised that the callers, which n
271 ShowValue(&(*it)->password_field);
264 } 272 }
265 273
266 elements_.clear(); 274 elements_info_.clear();
267 } 275 }
268 276
269 void PasswordAutofillAgent::PasswordValueGatekeeper::Reset() { 277 void PasswordAutofillAgent::PasswordValueGatekeeper::Reset() {
270 was_user_gesture_seen_ = false; 278 was_user_gesture_seen_ = false;
271 elements_.clear(); 279 elements_info_.clear();
272 } 280 }
273 281
274 void PasswordAutofillAgent::PasswordValueGatekeeper::ShowValue( 282 void PasswordAutofillAgent::PasswordValueGatekeeper::ShowValue(
275 blink::WebInputElement* element) { 283 blink::WebInputElement* element) {
276 if (!element->isNull() && !element->suggestedValue().isNull()) 284 if (!element->isNull() && !element->suggestedValue().isEmpty())
277 element->setValue(element->suggestedValue(), true); 285 element->setValue(element->suggestedValue(), true);
278 } 286 }
279 287
280 bool PasswordAutofillAgent::TextFieldDidEndEditing( 288 bool PasswordAutofillAgent::TextFieldDidEndEditing(
281 const blink::WebInputElement& element) { 289 const blink::WebInputElement& element) {
282 LoginToPasswordInfoMap::const_iterator iter = 290 LoginToPasswordInfoMap::const_iterator iter =
283 login_to_password_info_.find(element); 291 login_to_password_info_.find(element);
284 if (iter == login_to_password_info_.end()) 292 if (iter == login_to_password_info_.end())
engedy 2014/07/31 17:14:46 nit: I would personally add an alias here and in T
vabr (Chromium) 2014/08/04 15:10:07 Done.
285 return false; 293 return false;
286 294
287 const PasswordFormFillData& fill_data = iter->second.fill_data; 295 // Don't let autofill overwrite an explicit change made by the user.
296 if (iter->second->wait_for_username_change)
297 return false;
288 298
289 // If wait_for_username is false, we should have filled when the text changed. 299 // If wait_for_username is false, we should have filled when the text changed.
290 if (!fill_data.wait_for_username) 300 if (!iter->second->fill_data.wait_for_username)
291 return false; 301 return false;
292 302
293 blink::WebInputElement password = iter->second.password_field; 303 if (!IsElementEditable(iter->second->password_field))
294 if (!IsElementEditable(password))
295 return false; 304 return false;
296 305
297 blink::WebInputElement username = element; // We need a non-const. 306 blink::WebInputElement username = element; // We need a non-const.
298 307
299 // Do not set selection when ending an editing session, otherwise it can 308 // Do not set selection when ending an editing session, otherwise it can
300 // mess with focus. 309 // mess with focus.
301 FillUserNameAndPassword(&username, 310 FillUserNameAndPassword(&username,
302 &password, 311 iter->second,
303 fill_data,
304 true /* exact_username_match */, 312 true /* exact_username_match */,
305 false /* set_selection */); 313 false /* set_selection */);
306 return true; 314 return true;
307 } 315 }
308 316
309 bool PasswordAutofillAgent::TextDidChangeInTextField( 317 bool PasswordAutofillAgent::TextDidChangeInTextField(
310 const blink::WebInputElement& element) { 318 const blink::WebInputElement& element) {
319 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083
320 blink::WebInputElement mutable_element = element; // We need a non-const.
321
311 if (element.isPasswordField()) { 322 if (element.isPasswordField()) {
312 // Some login forms have event handlers that put a hash of the password into 323 // Some login forms have event handlers that put a hash of the password into
313 // a hidden field and then clear the password (http://crbug.com/28910, 324 // a hidden field and then clear the password (http://crbug.com/28910,
314 // http://crbug.com/391693). This method gets called before any of those 325 // http://crbug.com/391693). This method gets called before any of those
315 // handlers run, so save away a copy of the password in case it gets lost. 326 // handlers run, so save away a copy of the password in case it gets lost.
316 // To honor the user having explicitly cleared the password, even an empty 327 // To honor the user having explicitly cleared the password, even an empty
317 // password will be saved here. 328 // password will be saved here.
318 ProvisionallySavePassword( 329 ProvisionallySavePassword(
319 element.document().frame(), element.form(), RESTRICTION_NONE); 330 element.document().frame(), element.form(), RESTRICTION_NONE);
331
332 PasswordToLoginMap::iterator iter = password_to_username_.find(element);
333 if (iter != password_to_username_.end()) {
334 // The user changed the password after it was autofilled. Flipping the
335 // flag below to true makes sure it is not overwritten by autofill
336 // re-firing for the same username.
337 login_to_password_info_[iter->second]->wait_for_username_change = true;
engedy 2014/07/31 17:14:46 Perhaps this would be caught by tests, but we shou
vabr (Chromium) 2014/08/04 15:10:06 I'm reasonably certain that TextDidChangeInTextFie
338 mutable_element.setAutofilled(false);
339 }
320 return false; 340 return false;
321 } 341 }
322 342
323 LoginToPasswordInfoMap::const_iterator iter = 343 LoginToPasswordInfoMap::const_iterator iter =
324 login_to_password_info_.find(element); 344 login_to_password_info_.find(element);
325 if (iter == login_to_password_info_.end()) 345 if (iter == login_to_password_info_.end())
326 return false; 346 return false;
327 347
328 // The input text is being changed, so any autofilled password is now 348 // The input text is being changed, so any autofilled password is now
329 // outdated. 349 // outdated.
330 blink::WebInputElement username = element; // We need a non-const. 350 mutable_element.setAutofilled(false);
331 username.setAutofilled(false); 351 iter->second->wait_for_username_change = false;
engedy 2014/07/31 17:14:46 Hmm, let us discuss this logic tomorrow in person,
vabr (Chromium) 2014/08/04 15:10:07 Acknowledged.
332 352
333 blink::WebInputElement password = iter->second.password_field; 353 blink::WebInputElement password = iter->second->password_field;
334 if (password.isAutofilled()) { 354 if (password.isAutofilled()) {
335 password.setValue(base::string16(), true); 355 password.setValue(base::string16(), true);
336 password.setAutofilled(false); 356 password.setAutofilled(false);
337 } 357 }
338 358
339 // If wait_for_username is true we will fill when the username loses focus. 359 // If wait_for_username is true we will fill when the username loses focus.
340 if (iter->second.fill_data.wait_for_username) 360 if (iter->second->fill_data.wait_for_username)
341 return false; 361 return false;
342 362
343 if (!element.isText() || !IsElementAutocompletable(element) || 363 if (!element.isText() || !IsElementAutocompletable(element) ||
344 !IsElementAutocompletable(password)) { 364 !IsElementAutocompletable(password)) {
345 return false; 365 return false;
346 } 366 }
347 367
348 // Don't inline autocomplete if the user is deleting, that would be confusing. 368 // Don't inline autocomplete if the user is deleting, that would be confusing.
349 // But refresh the popup. Note, since this is ours, return true to signal 369 // But refresh the popup. Note, since this is ours, return true to signal
350 // no further processing is required. 370 // no further processing is required.
351 if (iter->second.backspace_pressed_last) { 371 if (iter->second->backspace_pressed_last) {
352 ShowSuggestionPopup(iter->second.fill_data, username, false); 372 ShowSuggestionPopup(iter->second->fill_data, element, false);
353 return true; 373 return true;
354 } 374 }
355 375
356 blink::WebString name = element.nameForAutofill(); 376 blink::WebString name = element.nameForAutofill();
357 if (name.isEmpty()) 377 if (name.isEmpty())
358 return false; // If the field has no name, then we won't have values. 378 return false; // If the field has no name, then we won't have values.
359 379
360 // Don't attempt to autofill with values that are too large. 380 // Don't attempt to autofill with values that are too large.
361 if (element.value().length() > kMaximumTextSizeForAutocomplete) 381 if (element.value().length() > kMaximumTextSizeForAutocomplete)
362 return false; 382 return false;
363 383
364 // The caret position should have already been updated. 384 // The caret position should have already been updated.
365 PerformInlineAutocomplete(element, password, iter->second.fill_data); 385 PerformInlineAutocomplete(&mutable_element, iter->second);
366 return true; 386 return true;
367 } 387 }
368 388
369 bool PasswordAutofillAgent::TextFieldHandlingKeyDown( 389 bool PasswordAutofillAgent::TextFieldHandlingKeyDown(
370 const blink::WebInputElement& element, 390 const blink::WebInputElement& element,
371 const blink::WebKeyboardEvent& event) { 391 const blink::WebKeyboardEvent& event) {
372 // If using the new Autofill UI that lives in the browser, it will handle 392 // If using the new Autofill UI that lives in the browser, it will handle
373 // keypresses before this function. This is not currently an issue but if 393 // keypresses before this function. This is not currently an issue but if
374 // the keys handled there or here change, this issue may appear. 394 // the keys handled there or here change, this issue may appear.
375 395
376 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(element); 396 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(element);
377 if (iter == login_to_password_info_.end()) 397 if (iter == login_to_password_info_.end())
378 return false; 398 return false;
379 399
380 int win_key_code = event.windowsKeyCode; 400 int win_key_code = event.windowsKeyCode;
381 iter->second.backspace_pressed_last = 401 iter->second->backspace_pressed_last =
382 (win_key_code == ui::VKEY_BACK || win_key_code == ui::VKEY_DELETE); 402 (win_key_code == ui::VKEY_BACK || win_key_code == ui::VKEY_DELETE);
383 return true; 403 return true;
384 } 404 }
385 405
386 bool PasswordAutofillAgent::FillSuggestion( 406 bool PasswordAutofillAgent::FillSuggestion(
387 const blink::WebNode& node, 407 const blink::WebNode& node,
388 const blink::WebString& username, 408 const blink::WebString& username,
389 const blink::WebString& password) { 409 const blink::WebString& password) {
390 blink::WebInputElement username_element; 410 blink::WebInputElement username_element;
391 PasswordInfo password_info; 411 PasswordInfo* password_info;
392 412
393 if (!FindLoginInfo(node, &username_element, &password_info) || 413 if (!FindLoginInfo(node, &username_element, &password_info) ||
394 !IsElementAutocompletable(username_element) || 414 !IsElementAutocompletable(username_element) ||
395 !IsElementAutocompletable(password_info.password_field)) { 415 !IsElementAutocompletable(password_info->password_field)) {
396 return false; 416 return false;
397 } 417 }
398 418
399 base::string16 current_username = username_element.value(); 419 if (username_element.value() != username_element.value())
420 password_info->wait_for_username_change = false;
400 username_element.setValue(username, true); 421 username_element.setValue(username, true);
401 username_element.setAutofilled(true); 422 username_element.setAutofilled(true);
402 username_element.setSelectionRange(username.length(), username.length()); 423 username_element.setSelectionRange(username.length(), username.length());
403 424
404 password_info.password_field.setValue(password, true); 425 password_info->password_field.setValue(password, true);
405 password_info.password_field.setAutofilled(true); 426 password_info->password_field.setAutofilled(true);
406 427
407 return true; 428 return true;
408 } 429 }
409 430
410 bool PasswordAutofillAgent::PreviewSuggestion( 431 bool PasswordAutofillAgent::PreviewSuggestion(
411 const blink::WebNode& node, 432 const blink::WebNode& node,
412 const blink::WebString& username, 433 const blink::WebString& username,
413 const blink::WebString& password) { 434 const blink::WebString& password) {
414 blink::WebInputElement username_element; 435 blink::WebInputElement username_element;
415 PasswordInfo password_info; 436 PasswordInfo* password_info;
416 437
417 if (!FindLoginInfo(node, &username_element, &password_info) || 438 if (!FindLoginInfo(node, &username_element, &password_info) ||
418 !IsElementAutocompletable(username_element) || 439 !IsElementAutocompletable(username_element) ||
419 !IsElementAutocompletable(password_info.password_field)) { 440 !IsElementAutocompletable(password_info->password_field)) {
420 return false; 441 return false;
421 } 442 }
422 443
423 was_username_autofilled_ = username_element.isAutofilled(); 444 was_username_autofilled_ = username_element.isAutofilled();
424 username_selection_start_ = username_element.selectionStart(); 445 username_selection_start_ = username_element.selectionStart();
425 username_element.setSuggestedValue(username); 446 username_element.setSuggestedValue(username);
426 username_element.setAutofilled(true); 447 username_element.setAutofilled(true);
427 username_element.setSelectionRange( 448 username_element.setSelectionRange(
428 username_selection_start_, 449 username_selection_start_,
429 username_element.suggestedValue().length()); 450 username_element.suggestedValue().length());
430 451
431 was_password_autofilled_ = password_info.password_field.isAutofilled(); 452 was_password_autofilled_ = password_info->password_field.isAutofilled();
432 password_info.password_field.setSuggestedValue(password); 453 password_info->password_field.setSuggestedValue(password);
433 password_info.password_field.setAutofilled(true); 454 password_info->password_field.setAutofilled(true);
434 455
435 return true; 456 return true;
436 } 457 }
437 458
438 bool PasswordAutofillAgent::DidClearAutofillSelection( 459 bool PasswordAutofillAgent::DidClearAutofillSelection(
439 const blink::WebNode& node) { 460 const blink::WebNode& node) {
440 blink::WebInputElement username_element; 461 blink::WebInputElement username_element;
441 PasswordInfo password_info; 462 PasswordInfo* password_info;
442 if (!FindLoginInfo(node, &username_element, &password_info)) 463 if (!FindLoginInfo(node, &username_element, &password_info))
443 return false; 464 return false;
444 465
445 ClearPreview(&username_element, &password_info.password_field); 466 ClearPreview(&username_element, &password_info->password_field);
446 return true; 467 return true;
447 } 468 }
448 469
449 bool PasswordAutofillAgent::ShowSuggestions( 470 bool PasswordAutofillAgent::ShowSuggestions(
450 const blink::WebInputElement& element, 471 const blink::WebInputElement& element,
451 bool show_all) { 472 bool show_all) {
452 LoginToPasswordInfoMap::const_iterator iter = 473 LoginToPasswordInfoMap::const_iterator iter =
453 login_to_password_info_.find(element); 474 login_to_password_info_.find(element);
454 if (iter == login_to_password_info_.end()) 475 if (iter == login_to_password_info_.end())
455 return false; 476 return false;
456 477
457 // If autocomplete='off' is set on the form elements, no suggestion dialog 478 // If autocomplete='off' is set on the form elements, no suggestion dialog
458 // should be shown. However, return |true| to indicate that this is a known 479 // should be shown. However, return |true| to indicate that this is a known
459 // password form and that the request to show suggestions has been handled (as 480 // password form and that the request to show suggestions has been handled (as
460 // a no-op). 481 // a no-op).
461 if (!IsElementAutocompletable(element) || 482 if (!IsElementAutocompletable(element) ||
462 !IsElementAutocompletable(iter->second.password_field)) 483 !IsElementAutocompletable(iter->second->password_field))
463 return true; 484 return true;
464 485
465 return ShowSuggestionPopup(iter->second.fill_data, element, show_all); 486 return ShowSuggestionPopup(iter->second->fill_data, element, show_all);
466 } 487 }
467 488
468 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( 489 bool PasswordAutofillAgent::OriginCanAccessPasswordManager(
469 const blink::WebSecurityOrigin& origin) { 490 const blink::WebSecurityOrigin& origin) {
470 return origin.canAccessPasswordManager(); 491 return origin.canAccessPasswordManager();
471 } 492 }
472 493
473 void PasswordAutofillAgent::OnDynamicFormsSeen(blink::WebFrame* frame) { 494 void PasswordAutofillAgent::OnDynamicFormsSeen(blink::WebFrame* frame) {
474 SendPasswordForms(frame, false /* only_visible */); 495 SendPasswordForms(frame, false /* only_visible */);
475 } 496 }
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 // Attach autocomplete listener to enable selecting alternate logins. 810 // Attach autocomplete listener to enable selecting alternate logins.
790 // First, get pointers to username element. 811 // First, get pointers to username element.
791 blink::WebInputElement username_element = 812 blink::WebInputElement username_element =
792 form_elements->input_elements[form_data.basic_data.fields[0].name]; 813 form_elements->input_elements[form_data.basic_data.fields[0].name];
793 814
794 // Get pointer to password element. (We currently only support single 815 // Get pointer to password element. (We currently only support single
795 // password forms). 816 // password forms).
796 blink::WebInputElement password_element = 817 blink::WebInputElement password_element =
797 form_elements->input_elements[form_data.basic_data.fields[1].name]; 818 form_elements->input_elements[form_data.basic_data.fields[1].name];
798 819
799 // If wait_for_username is true, we don't want to initially fill the form
800 // until the user types in a valid username.
801 if (!form_data.wait_for_username)
802 FillFormOnPasswordRecieved(form_data, username_element, password_element);
803
804 // We might have already filled this form if there are two <form> elements 820 // We might have already filled this form if there are two <form> elements
805 // with identical markup. 821 // with identical markup.
806 if (login_to_password_info_.find(username_element) != 822 if (login_to_password_info_.find(username_element) !=
807 login_to_password_info_.end()) 823 login_to_password_info_.end())
808 continue; 824 continue;
809 825
810 PasswordInfo password_info; 826 scoped_ptr<PasswordInfo> password_info(new PasswordInfo);
811 password_info.fill_data = form_data; 827 password_info->fill_data = form_data;
812 password_info.password_field = password_element; 828 password_info->password_field = password_element;
813 login_to_password_info_[username_element] = password_info; 829 login_to_password_info_[username_element] = password_info.get();
830 password_to_username_[password_element] = username_element;
831 // If wait_for_username is true, we don't want to initially fill the form
832 // until the user types in a valid username.
833 if (!form_data.wait_for_username)
834 FillFormOnPasswordRecieved(&username_element, password_info.get());
835 password_infos_[username_element.document().frame()].push_back(
836 make_linked_ptr(password_info.release()));
814 837
815 FormData form; 838 FormData form;
816 FormFieldData field; 839 FormFieldData field;
817 FindFormAndFieldForFormControlElement( 840 FindFormAndFieldForFormControlElement(
818 username_element, &form, &field, REQUIRE_NONE); 841 username_element, &form, &field, REQUIRE_NONE);
819 Send(new AutofillHostMsg_AddPasswordFormMapping( 842 Send(new AutofillHostMsg_AddPasswordFormMapping(
820 routing_id(), field, form_data)); 843 routing_id(), field, form_data));
821 } 844 }
822 } 845 }
823 846
824 void PasswordAutofillAgent::OnSetLoggingState(bool active) { 847 void PasswordAutofillAgent::OnSetLoggingState(bool active) {
825 logging_state_active_ = active; 848 logging_state_active_ = active;
826 } 849 }
827 850
828 //////////////////////////////////////////////////////////////////////////////// 851 ////////////////////////////////////////////////////////////////////////////////
829 // PasswordAutofillAgent, private: 852 // PasswordAutofillAgent, private:
830 853
854 PasswordAutofillAgent::PasswordInfo::PasswordInfo()
855 : backspace_pressed_last(false), wait_for_username_change(false) {
856 }
857
831 void PasswordAutofillAgent::GetSuggestions( 858 void PasswordAutofillAgent::GetSuggestions(
832 const PasswordFormFillData& fill_data, 859 const PasswordFormFillData& fill_data,
833 const base::string16& input, 860 const base::string16& input,
834 std::vector<base::string16>* suggestions, 861 std::vector<base::string16>* suggestions,
835 std::vector<base::string16>* realms, 862 std::vector<base::string16>* realms,
836 bool show_all) { 863 bool show_all) {
837 if (show_all || 864 if (show_all ||
838 StartsWith(fill_data.basic_data.fields[0].value, input, false)) { 865 StartsWith(fill_data.basic_data.fields[0].value, input, false)) {
839 suggestions->push_back(fill_data.basic_data.fields[0].value); 866 suggestions->push_back(fill_data.basic_data.fields[0].value);
840 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm)); 867 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm));
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
894 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, 921 gfx::RectF bounding_box_scaled(bounding_box.x() * scale,
895 bounding_box.y() * scale, 922 bounding_box.y() * scale,
896 bounding_box.width() * scale, 923 bounding_box.width() * scale,
897 bounding_box.height() * scale); 924 bounding_box.height() * scale);
898 Send(new AutofillHostMsg_ShowPasswordSuggestions( 925 Send(new AutofillHostMsg_ShowPasswordSuggestions(
899 routing_id(), field, bounding_box_scaled, suggestions, realms)); 926 routing_id(), field, bounding_box_scaled, suggestions, realms));
900 return !suggestions.empty(); 927 return !suggestions.empty();
901 } 928 }
902 929
903 void PasswordAutofillAgent::FillFormOnPasswordRecieved( 930 void PasswordAutofillAgent::FillFormOnPasswordRecieved(
904 const PasswordFormFillData& fill_data, 931 blink::WebInputElement* username_element,
905 blink::WebInputElement username_element, 932 PasswordInfo* password_info) {
906 blink::WebInputElement password_element) { 933 blink::WebInputElement* password_element = &password_info->password_field;
907 // Do not fill if the password field is in an iframe. 934 // Do not fill if the password field is in an iframe.
908 DCHECK(password_element.document().frame()); 935 DCHECK(password_element->document().frame());
909 if (password_element.document().frame()->parent()) 936 if (password_element->document().frame()->parent())
910 return; 937 return;
911 938
912 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && 939 if (!ShouldIgnoreAutocompleteOffForPasswordFields() &&
913 !username_element.form().autoComplete()) 940 !username_element->form().autoComplete())
914 return; 941 return;
915 942
916 // If we can't modify the password, don't try to set the username 943 // If we can't modify the password, don't try to set the username
917 if (!IsElementAutocompletable(password_element)) 944 if (!IsElementAutocompletable(*password_element))
918 return; 945 return;
919 946
920 // Try to set the username to the preferred name, but only if the field 947 // Try to set the username to the preferred name, but only if the field
921 // can be set and isn't prefilled. 948 // can be set and isn't prefilled.
922 if (IsElementAutocompletable(username_element) && 949 if (IsElementAutocompletable(*username_element) &&
923 username_element.value().isEmpty()) { 950 username_element->value().isEmpty()) {
924 // TODO(tkent): Check maxlength and pattern. 951 // TODO(tkent): Check maxlength and pattern.
925 username_element.setValue(fill_data.basic_data.fields[0].value, true); 952 username_element->setValue(
953 password_info->fill_data.basic_data.fields[0].value, true);
926 } 954 }
927 955
928 // Fill if we have an exact match for the username. Note that this sets 956 // Fill if we have an exact match for the username. Note that this sets
929 // username to autofilled. 957 // username to autofilled.
930 FillUserNameAndPassword(&username_element, 958 FillUserNameAndPassword(username_element,
931 &password_element, 959 password_info,
932 fill_data,
933 true /* exact_username_match */, 960 true /* exact_username_match */,
934 false /* set_selection */); 961 false /* set_selection */);
935 } 962 }
936 963
937 bool PasswordAutofillAgent::FillUserNameAndPassword( 964 bool PasswordAutofillAgent::FillUserNameAndPassword(
938 blink::WebInputElement* username_element, 965 blink::WebInputElement* username_element,
939 blink::WebInputElement* password_element, 966 PasswordInfo* password_info,
940 const PasswordFormFillData& fill_data,
941 bool exact_username_match, 967 bool exact_username_match,
942 bool set_selection) { 968 bool set_selection) {
969 blink::WebInputElement password_element = password_info->password_field;
970 const PasswordFormFillData& fill_data = password_info->fill_data;
943 base::string16 current_username = username_element->value(); 971 base::string16 current_username = username_element->value();
944 // username and password will contain the match found if any. 972 // username and password will contain the match found if any.
945 base::string16 username; 973 base::string16 username;
946 base::string16 password; 974 base::string16 password;
947 975
948 // Look for any suitable matches to current field text. 976 // Look for any suitable matches to current field text.
949 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, 977 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value,
950 current_username, 978 current_username,
951 exact_username_match)) { 979 exact_username_match)) {
952 username = fill_data.basic_data.fields[0].value; 980 username = fill_data.basic_data.fields[0].value;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
985 } 1013 }
986 } 1014 }
987 } 1015 }
988 if (password.empty()) 1016 if (password.empty())
989 return false; // No match was found. 1017 return false; // No match was found.
990 1018
991 // TODO(tkent): Check maxlength and pattern for both username and password 1019 // TODO(tkent): Check maxlength and pattern for both username and password
992 // fields. 1020 // fields.
993 1021
994 // Don't fill username if password can't be set. 1022 // Don't fill username if password can't be set.
995 if (!IsElementAutocompletable(*password_element)) { 1023 if (!IsElementAutocompletable(password_element)) {
996 return false; 1024 return false;
997 } 1025 }
998 1026
999 // Input matches the username, fill in required values. 1027 // Input matches the username, fill in required values.
1000 if (IsElementAutocompletable(*username_element)) { 1028 if (IsElementAutocompletable(*username_element)) {
1001 username_element->setValue(username, true); 1029 username_element->setValue(username, true);
1002 username_element->setAutofilled(true); 1030 username_element->setAutofilled(true);
1003 1031
1004 if (set_selection) { 1032 if (set_selection) {
1005 username_element->setSelectionRange(current_username.length(), 1033 username_element->setSelectionRange(current_username.length(),
1006 username.length()); 1034 username.length());
1007 } 1035 }
1008 } else if (current_username != username) { 1036 } else if (current_username != username) {
1009 // If the username can't be filled and it doesn't match a saved password 1037 // If the username can't be filled and it doesn't match a saved password
1010 // as is, don't autofill a password. 1038 // as is, don't autofill a password.
1011 return false; 1039 return false;
1012 } 1040 }
1013 1041
1014 // Wait to fill in the password until a user gesture occurs. This is to make 1042 // Wait to fill in the password until a user gesture occurs. This is to make
1015 // sure that we do not fill in the DOM with a password until we believe the 1043 // sure that we do not fill in the DOM with a password until we believe the
1016 // user is intentionally interacting with the page. 1044 // user is intentionally interacting with the page.
1017 password_element->setSuggestedValue(password); 1045 password_element.setSuggestedValue(password);
1018 gatekeeper_.RegisterElement(password_element); 1046 gatekeeper_.RegisterElementInfo(password_info);
1019 1047
1020 password_element->setAutofilled(true); 1048 password_element.setAutofilled(true);
1021 return true; 1049 return true;
1022 } 1050 }
1023 1051
1024 void PasswordAutofillAgent::PerformInlineAutocomplete( 1052 void PasswordAutofillAgent::PerformInlineAutocomplete(
1025 const blink::WebInputElement& username_input, 1053 blink::WebInputElement* username,
1026 const blink::WebInputElement& password_input, 1054 PasswordInfo* password_info) {
1027 const PasswordFormFillData& fill_data) { 1055 DCHECK(!password_info->fill_data.wait_for_username);
1028 DCHECK(!fill_data.wait_for_username);
1029 1056
1030 // We need non-const versions of the username and password inputs. 1057 blink::WebInputElement password = password_info->password_field;
1031 blink::WebInputElement username = username_input;
1032 blink::WebInputElement password = password_input;
1033 1058
1034 // Don't inline autocomplete if the caret is not at the end. 1059 // Don't inline autocomplete if the caret is not at the end.
1035 // TODO(jcivelli): is there a better way to test the caret location? 1060 // TODO(jcivelli): is there a better way to test the caret location?
1036 if (username.selectionStart() != username.selectionEnd() || 1061 if (username->selectionStart() != username->selectionEnd() ||
1037 username.selectionEnd() != static_cast<int>(username.value().length())) { 1062 username->selectionEnd() !=
1063 static_cast<int>(username->value().length())) {
1038 return; 1064 return;
1039 } 1065 }
1040 1066
1041 // Show the popup with the list of available usernames. 1067 // Show the popup with the list of available usernames.
1042 ShowSuggestionPopup(fill_data, username, false); 1068 ShowSuggestionPopup(password_info->fill_data, *username, false);
1043 1069
1044 #if !defined(OS_ANDROID) 1070 #if !defined(OS_ANDROID)
1045 // Fill the user and password field with the most relevant match. Android 1071 // Fill the user and password field with the most relevant match. Android
1046 // only fills in the fields after the user clicks on the suggestion popup. 1072 // only fills in the fields after the user clicks on the suggestion popup.
1047 FillUserNameAndPassword(&username, 1073 FillUserNameAndPassword(username,
1048 &password, 1074 password_info,
1049 fill_data,
1050 false /* exact_username_match */, 1075 false /* exact_username_match */,
1051 true /* set_selection */); 1076 true /* set_selection */);
1052 #endif 1077 #endif
1053 } 1078 }
1054 1079
1055 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { 1080 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) {
1056 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); 1081 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin();
1057 iter != login_to_password_info_.end();) { 1082 iter != login_to_password_info_.end();) {
1058 if (iter->first.document().frame() == frame) 1083 if (iter->first.document().frame() == frame) {
1084 password_to_username_.erase(iter->second->password_field);
1085 gatekeeper_.UnregisterElementInfo(iter->second);
1059 login_to_password_info_.erase(iter++); 1086 login_to_password_info_.erase(iter++);
1060 else 1087 } else {
1061 ++iter; 1088 ++iter;
1089 }
1062 } 1090 }
1091 password_infos_.erase(frame);
1063 for (FrameToPasswordFormMap::iterator iter = 1092 for (FrameToPasswordFormMap::iterator iter =
1064 provisionally_saved_forms_.begin(); 1093 provisionally_saved_forms_.begin();
1065 iter != provisionally_saved_forms_.end();) { 1094 iter != provisionally_saved_forms_.end();) {
1066 if (iter->first == frame) 1095 if (iter->first == frame)
1067 provisionally_saved_forms_.erase(iter++); 1096 provisionally_saved_forms_.erase(iter++);
1068 else 1097 else
1069 ++iter; 1098 ++iter;
1070 } 1099 }
1071 } 1100 }
1072 1101
1073 bool PasswordAutofillAgent::FindLoginInfo(const blink::WebNode& node, 1102 bool PasswordAutofillAgent::FindLoginInfo(const blink::WebNode& node,
1074 blink::WebInputElement* found_input, 1103 blink::WebInputElement* found_input,
1075 PasswordInfo* found_password) { 1104 PasswordInfo** found_password) {
1076 if (!node.isElementNode()) 1105 if (!node.isElementNode())
1077 return false; 1106 return false;
1078 1107
1079 blink::WebElement element = node.toConst<blink::WebElement>(); 1108 blink::WebElement element = node.toConst<blink::WebElement>();
1080 if (!element.hasHTMLTagName("input")) 1109 if (!element.hasHTMLTagName("input"))
1081 return false; 1110 return false;
1082 1111
1083 blink::WebInputElement input = element.to<blink::WebInputElement>(); 1112 blink::WebInputElement input = element.to<blink::WebInputElement>();
1084 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(input); 1113 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(input);
1085 if (iter == login_to_password_info_.end()) 1114 if (iter == login_to_password_info_.end())
(...skipping 26 matching lines...) Expand all
1112 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); 1141 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form));
1113 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && 1142 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD &&
1114 password_form->password_value.empty() && 1143 password_form->password_value.empty() &&
1115 password_form->new_password_value.empty())) { 1144 password_form->new_password_value.empty())) {
1116 return; 1145 return;
1117 } 1146 }
1118 provisionally_saved_forms_[frame].reset(password_form.release()); 1147 provisionally_saved_forms_[frame].reset(password_form.release());
1119 } 1148 }
1120 1149
1121 } // namespace autofill 1150 } // 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