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

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

Issue 492043003: Fill on account select in the password manager (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Re-added check that form contains a username field. Created 6 years, 1 month 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
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/command_line.h"
8 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h" 10 #include "base/message_loop/message_loop.h"
10 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
11 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
12 #include "components/autofill/content/common/autofill_messages.h" 13 #include "components/autofill/content/common/autofill_messages.h"
13 #include "components/autofill/content/renderer/form_autofill_util.h" 14 #include "components/autofill/content/renderer/form_autofill_util.h"
14 #include "components/autofill/content/renderer/password_form_conversion_utils.h" 15 #include "components/autofill/content/renderer/password_form_conversion_utils.h"
15 #include "components/autofill/content/renderer/renderer_save_password_progress_l ogger.h" 16 #include "components/autofill/content/renderer/renderer_save_password_progress_l ogger.h"
17 #include "components/autofill/core/common/autofill_switches.h"
16 #include "components/autofill/core/common/form_field_data.h" 18 #include "components/autofill/core/common/form_field_data.h"
17 #include "components/autofill/core/common/password_form.h" 19 #include "components/autofill/core/common/password_form.h"
18 #include "components/autofill/core/common/password_form_fill_data.h" 20 #include "components/autofill/core/common/password_form_fill_data.h"
19 #include "content/public/renderer/document_state.h" 21 #include "content/public/renderer/document_state.h"
20 #include "content/public/renderer/navigation_state.h" 22 #include "content/public/renderer/navigation_state.h"
21 #include "content/public/renderer/render_view.h" 23 #include "content/public/renderer/render_view.h"
22 #include "third_party/WebKit/public/platform/WebVector.h" 24 #include "third_party/WebKit/public/platform/WebVector.h"
23 #include "third_party/WebKit/public/web/WebAutofillClient.h" 25 #include "third_party/WebKit/public/web/WebAutofillClient.h"
24 #include "third_party/WebKit/public/web/WebDocument.h" 26 #include "third_party/WebKit/public/web/WebDocument.h"
25 #include "third_party/WebKit/public/web/WebElement.h" 27 #include "third_party/WebKit/public/web/WebElement.h"
26 #include "third_party/WebKit/public/web/WebFormElement.h" 28 #include "third_party/WebKit/public/web/WebFormElement.h"
27 #include "third_party/WebKit/public/web/WebInputEvent.h" 29 #include "third_party/WebKit/public/web/WebInputEvent.h"
28 #include "third_party/WebKit/public/web/WebLocalFrame.h" 30 #include "third_party/WebKit/public/web/WebLocalFrame.h"
29 #include "third_party/WebKit/public/web/WebNode.h" 31 #include "third_party/WebKit/public/web/WebNode.h"
30 #include "third_party/WebKit/public/web/WebNodeList.h" 32 #include "third_party/WebKit/public/web/WebNodeList.h"
31 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" 33 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
32 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" 34 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
33 #include "third_party/WebKit/public/web/WebView.h" 35 #include "third_party/WebKit/public/web/WebView.h"
34 #include "ui/base/page_transition_types.h" 36 #include "ui/base/page_transition_types.h"
35 #include "ui/events/keycodes/keyboard_codes.h" 37 #include "ui/events/keycodes/keyboard_codes.h"
36 #include "url/gurl.h" 38 #include "url/gurl.h"
37 39
38 namespace autofill { 40 namespace autofill {
39 namespace { 41 namespace {
40 42
43 enum FillUserNameAndPasswordOptions {
44 EXACT_USERNAME_MATCH = 1 << 0,
45 SET_SELECTION = 1 << 1,
46 FILL_PREFERRED_USERNAME = 1 << 2
Garrett Casto 2014/11/23 07:49:48 Looks like FILL_PREFERRED_USERNAME isn't used curr
jww 2014/11/25 02:46:26 Done.
47 };
48
41 // The size above which we stop triggering autocomplete. 49 // The size above which we stop triggering autocomplete.
42 static const size_t kMaximumTextSizeForAutocomplete = 1000; 50 static const size_t kMaximumTextSizeForAutocomplete = 1000;
43 51
44 // Maps element names to the actual elements to simplify form filling. 52 // Maps element names to the actual elements to simplify form filling.
45 typedef std::map<base::string16, blink::WebInputElement> FormInputElementMap; 53 typedef std::map<base::string16, blink::WebInputElement> FormInputElementMap;
46 54
47 // Use the shorter name when referencing SavePasswordProgressLogger::StringID 55 // Use the shorter name when referencing SavePasswordProgressLogger::StringID
48 // values to spare line breaks. The code provides enough context for that 56 // values to spare line breaks. The code provides enough context for that
49 // already. 57 // already.
50 typedef SavePasswordProgressLogger Logger; 58 typedef SavePasswordProgressLogger Logger;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 // iteration remain in the result set. 116 // iteration remain in the result set.
109 // Note: clear will remove a reference from each InputElement. 117 // Note: clear will remove a reference from each InputElement.
110 if (!found_input) { 118 if (!found_input) {
111 result->input_elements.clear(); 119 result->input_elements.clear();
112 return false; 120 return false;
113 } 121 }
114 122
115 return true; 123 return true;
116 } 124 }
117 125
126 bool ShouldFillOnAccountSelect() {
127 if (CommandLine::ForCurrentProcess()->HasSwitch(
128 switches::kEnableFillOnAccountSelect)) {
129 return true;
130 }
131
132 // This is made explicit in anticiption of experimental groups being added.
133 if (CommandLine::ForCurrentProcess()->HasSwitch(
134 switches::kDisableFillOnAccountSelect)) {
135 return false;
136 }
137
138 // TODO(jww): Add experimental groups check here.
Garrett Casto 2014/11/23 07:49:48 When I said splitting off the CL into two, what I
jww 2014/11/25 02:46:26 Got it. I'll probably still commit without the exp
139
140 return false;
141 }
142
118 // Helper to search the given form element for the specified input elements in 143 // Helper to search the given form element for the specified input elements in
119 // |data|, and add results to |result|. 144 // |data|, and add results to |result|.
120 bool FindFormInputElements(blink::WebFormElement* form_element, 145 bool FindFormInputElements(blink::WebFormElement* form_element,
121 const FormData& data, 146 const FormData& data,
122 FormElements* result) { 147 FormElements* result) {
123 const bool username_is_present = !data.fields[0].name.empty(); 148 const bool username_is_present = !data.fields[0].name.empty();
124 149
125 // Loop through the list of elements we need to find on the form in order to 150 // Loop through the list of elements we need to find on the form in order to
126 // autofill it. If we don't find any one of them, abort processing this 151 // autofill it. If we don't find any one of them, abort processing this
127 // form; it can't be the right one. 152 // form; it can't be the right one.
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 } 307 }
283 } 308 }
284 309
285 return false; 310 return false;
286 } 311 }
287 312
288 // This function attempts to fill |username_element| and |password_element| 313 // This function attempts to fill |username_element| and |password_element|
289 // with values from |fill_data|. The |password_element| will only have the 314 // with values from |fill_data|. The |password_element| will only have the
290 // |suggestedValue| set, and will be registered for copying that to the real 315 // |suggestedValue| set, and will be registered for copying that to the real
291 // value through |registration_callback|. The function returns true when 316 // value through |registration_callback|. The function returns true when
292 // selected username comes from |fill_data.other_possible_usernames|. 317 // selected username comes from |fill_data.other_possible_usernames|. |options|
318 // should be a bitwise mask of FillUserNameAndPasswordOptions values.
293 bool FillUserNameAndPassword( 319 bool FillUserNameAndPassword(
294 blink::WebInputElement* username_element, 320 blink::WebInputElement* username_element,
295 blink::WebInputElement* password_element, 321 blink::WebInputElement* password_element,
296 const PasswordFormFillData& fill_data, 322 const PasswordFormFillData& fill_data,
297 bool exact_username_match, 323 const int options,
298 bool set_selection,
299 base::Callback<void(blink::WebInputElement*)> registration_callback) { 324 base::Callback<void(blink::WebInputElement*)> registration_callback) {
325 bool exact_username_match = (options & EXACT_USERNAME_MATCH) != 0;
326 bool set_selection = (options & SET_SELECTION) != 0;
300 bool other_possible_username_selected = false; 327 bool other_possible_username_selected = false;
301 // Don't fill username if password can't be set. 328 // Don't fill username if password can't be set.
302 if (!IsElementAutocompletable(*password_element)) 329 if (!IsElementAutocompletable(*password_element))
303 return false; 330 return false;
304 331
305 base::string16 current_username; 332 base::string16 current_username;
306 if (!username_element->isNull()) { 333 if (!username_element->isNull()) {
307 current_username = username_element->value(); 334 current_username = username_element->value();
308 } 335 }
309 336
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 } 411 }
385 412
386 // Attempts to fill |username_element| and |password_element| with the 413 // Attempts to fill |username_element| and |password_element| with the
387 // |fill_data|. Will use the data corresponding to the preferred username, 414 // |fill_data|. Will use the data corresponding to the preferred username,
388 // unless the |username_element| already has a value set. In that case, 415 // unless the |username_element| already has a value set. In that case,
389 // attempts to fill the password matching the already filled username, if 416 // attempts to fill the password matching the already filled username, if
390 // such a password exists. The |password_element| will have the 417 // such a password exists. The |password_element| will have the
391 // |suggestedValue| set, and |suggestedValue| will be registered for copying to 418 // |suggestedValue| set, and |suggestedValue| will be registered for copying to
392 // the real value through |registration_callback|. Returns true when the 419 // the real value through |registration_callback|. Returns true when the
393 // username gets selected from |other_possible_usernames|, else returns false. 420 // username gets selected from |other_possible_usernames|, else returns false.
394 bool FillFormOnPasswordRecieved( 421 bool FillFormOnPasswordReceived(
395 const PasswordFormFillData& fill_data, 422 const PasswordFormFillData& fill_data,
396 blink::WebInputElement username_element, 423 blink::WebInputElement username_element,
397 blink::WebInputElement password_element, 424 blink::WebInputElement password_element,
398 base::Callback<void(blink::WebInputElement*)> registration_callback) { 425 base::Callback<void(blink::WebInputElement*)> registration_callback) {
399 // Do not fill if the password field is in an iframe. 426 // Do not fill if the password field is in an iframe.
400 DCHECK(password_element.document().frame()); 427 DCHECK(password_element.document().frame());
401 if (password_element.document().frame()->parent()) 428 if (password_element.document().frame()->parent())
402 return false; 429 return false;
403 430
404 // If we can't modify the password, don't try to set the username 431 // If we can't modify the password, don't try to set the username
405 if (!IsElementAutocompletable(password_element)) 432 if (!IsElementAutocompletable(password_element))
406 return false; 433 return false;
407 434
408 bool form_contains_username_field = FillDataContainsUsername(fill_data); 435 bool form_contains_username_field = FillDataContainsUsername(fill_data);
409 // Try to set the username to the preferred name, but only if the field 436 // If the form contains a username field, try to set the username to the
410 // can be set and isn't prefilled. 437 // preferred name, but only if:
411 if (form_contains_username_field && 438 // (a) The username element is autocompletable, and
412 IsElementAutocompletable(username_element) && 439 // (b) The fill-on-account-select flag is not set, and
413 username_element.value().isEmpty()) { 440 // (c) The username element isn't prefilled
414 // TODO(tkent): Check maxlength and pattern. 441 //
415 username_element.setValue(fill_data.basic_data.fields[0].value, true); 442 // If (a) is true but (b) is false, then just mark the username element as
443 // autofilled and return so the fill step is skipped.
444 //
445 // If (a) is false but (b) is true, then the username element should not be
446 // autofilled, but the user should still be able to select to fill the
447 // password element, so the password element must be marked as autofilled and
448 // the fill step should also be skipped.
449 //
450 // In all other cases, do nothing.
451 if (form_contains_username_field) {
452 if (IsElementAutocompletable(username_element)) {
453 if (ShouldFillOnAccountSelect()) {
454 username_element.setAutofilled(true);
455 return false;
456 } else if (username_element.value().isEmpty()) {
457 // TODO(tkent): Check maxlength and pattern.
458 username_element.setValue(fill_data.basic_data.fields[0].value, true);
459 }
460 } else if (ShouldFillOnAccountSelect()) {
461 password_element.setAutofilled(true);
462 return false;
463 }
416 } 464 }
417 465
418 // Fill if we have an exact match for the username. Note that this sets 466 // Fill if we have an exact match for the username. Note that this sets
419 // username to autofilled. 467 // username to autofilled.
420 return FillUserNameAndPassword(&username_element, 468 return FillUserNameAndPassword(
421 &password_element, 469 &username_element, &password_element, fill_data,
422 fill_data, 470 EXACT_USERNAME_MATCH | FILL_PREFERRED_USERNAME, registration_callback);
423 true /* exact_username_match */,
424 false /* set_selection */,
425 registration_callback);
426 } 471 }
427 472
428 // Takes a |map| with pointers as keys and linked_ptr as values, and returns 473 // Takes a |map| with pointers as keys and linked_ptr as values, and returns
429 // true if |key| is not NULL and |map| contains a non-NULL entry for |key|. 474 // true if |key| is not NULL and |map| contains a non-NULL entry for |key|.
430 // Makes sure not to create an entry as a side effect of using the operator []. 475 // Makes sure not to create an entry as a side effect of using the operator [].
431 template <class Key, class Value> 476 template <class Key, class Value>
432 bool ContainsNonNullEntryForNonNullKey( 477 bool ContainsNonNullEntryForNonNullKey(
433 const std::map<Key*, linked_ptr<Value>>& map, 478 const std::map<Key*, linked_ptr<Value>>& map,
434 Key* key) { 479 Key* key) {
435 if (!key) 480 if (!key)
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 562
518 blink::WebInputElement password = password_info.password_field; 563 blink::WebInputElement password = password_info.password_field;
519 if (!IsElementEditable(password)) 564 if (!IsElementEditable(password))
520 return false; 565 return false;
521 566
522 blink::WebInputElement username = element; // We need a non-const. 567 blink::WebInputElement username = element; // We need a non-const.
523 568
524 // Do not set selection when ending an editing session, otherwise it can 569 // Do not set selection when ending an editing session, otherwise it can
525 // mess with focus. 570 // mess with focus.
526 if (FillUserNameAndPassword( 571 if (FillUserNameAndPassword(
527 &username, 572 &username, &password, fill_data, EXACT_USERNAME_MATCH,
528 &password,
529 fill_data,
530 true /* exact_username_match */,
531 false /* set_selection */,
532 base::Bind(&PasswordValueGatekeeper::RegisterElement, 573 base::Bind(&PasswordValueGatekeeper::RegisterElement,
533 base::Unretained(&gatekeeper_)))) { 574 base::Unretained(&gatekeeper_)))) {
534 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; 575 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED;
535 } 576 }
536 return true; 577 return true;
537 } 578 }
538 579
539 bool PasswordAutofillAgent::TextDidChangeInTextField( 580 bool PasswordAutofillAgent::TextDidChangeInTextField(
540 const blink::WebInputElement& element) { 581 const blink::WebInputElement& element) {
541 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 582 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 625
585 if (!element.isText() || !IsElementAutocompletable(element) || 626 if (!element.isText() || !IsElementAutocompletable(element) ||
586 !IsElementAutocompletable(password)) { 627 !IsElementAutocompletable(password)) {
587 return false; 628 return false;
588 } 629 }
589 630
590 // Don't inline autocomplete if the user is deleting, that would be confusing. 631 // Don't inline autocomplete if the user is deleting, that would be confusing.
591 // But refresh the popup. Note, since this is ours, return true to signal 632 // But refresh the popup. Note, since this is ours, return true to signal
592 // no further processing is required. 633 // no further processing is required.
593 if (iter->second.backspace_pressed_last) { 634 if (iter->second.backspace_pressed_last) {
594 ShowSuggestionPopup(iter->second.fill_data, element, false); 635 ShowSuggestionPopup(iter->second.fill_data, element, false, false);
595 return true; 636 return true;
596 } 637 }
597 638
598 blink::WebString name = element.nameForAutofill(); 639 blink::WebString name = element.nameForAutofill();
599 if (name.isEmpty()) 640 if (name.isEmpty())
600 return false; // If the field has no name, then we won't have values. 641 return false; // If the field has no name, then we won't have values.
601 642
602 // Don't attempt to autofill with values that are too large. 643 // Don't attempt to autofill with values that are too large.
603 if (element.value().length() > kMaximumTextSizeForAutocomplete) 644 if (element.value().length() > kMaximumTextSizeForAutocomplete)
604 return false; 645 return false;
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 const blink::WebNode& node) { 722 const blink::WebNode& node) {
682 blink::WebInputElement username_element; 723 blink::WebInputElement username_element;
683 PasswordInfo* password_info; 724 PasswordInfo* password_info;
684 if (!FindLoginInfo(node, &username_element, &password_info)) 725 if (!FindLoginInfo(node, &username_element, &password_info))
685 return false; 726 return false;
686 727
687 ClearPreview(&username_element, &password_info->password_field); 728 ClearPreview(&username_element, &password_info->password_field);
688 return true; 729 return true;
689 } 730 }
690 731
732 PasswordAutofillAgent::LoginToPasswordInfoMap::iterator
733 PasswordAutofillAgent::FindPasswordInfoForElement(
734 const blink::WebInputElement& element) {
735 const blink::WebInputElement* username_element;
736 if (!element.isPasswordField()) {
737 username_element = &element;
738 } else {
739 PasswordToLoginMap::const_iterator password_iter =
740 password_to_username_.find(element);
741 if (password_iter == password_to_username_.end())
742 return login_to_password_info_.end();
743 username_element = &password_iter->second;
744 }
745
746 return login_to_password_info_.find(*username_element);
747 }
748
691 bool PasswordAutofillAgent::ShowSuggestions( 749 bool PasswordAutofillAgent::ShowSuggestions(
692 const blink::WebInputElement& element, 750 const blink::WebInputElement& element,
693 bool show_all) { 751 bool show_all) {
694 LoginToPasswordInfoMap::const_iterator iter = 752 LoginToPasswordInfoMap::const_iterator iter =
695 login_to_password_info_.find(element); 753 FindPasswordInfoForElement(element);
696 if (iter == login_to_password_info_.end()) 754 if (iter == login_to_password_info_.end())
697 return false; 755 return false;
698 756
699 // If autocomplete='off' is set on the form elements, no suggestion dialog 757 // If autocomplete='off' is set on the form elements, no suggestion dialog
700 // should be shown. However, return |true| to indicate that this is a known 758 // should be shown. However, return |true| to indicate that this is a known
701 // password form and that the request to show suggestions has been handled (as 759 // password form and that the request to show suggestions has been handled (as
702 // a no-op). 760 // a no-op).
703 if (!IsElementAutocompletable(element) || 761 if (!IsElementAutocompletable(element) ||
704 !IsElementAutocompletable(iter->second.password_field)) 762 !IsElementAutocompletable(iter->second.password_field))
705 return true; 763 return true;
706 764
707 return ShowSuggestionPopup(iter->second.fill_data, element, show_all); 765 // Chrome should never show more than one account for a password element since
766 // this implies that the username element cannot be modified. Thus even if
767 // |show_all| is true, check if the element in question is a password element
768 // for the call to ShowSuggestionPopup.
769 return ShowSuggestionPopup(iter->second.fill_data, iter->first,
770 show_all && !element.isPasswordField(),
771 element.isPasswordField());
708 } 772 }
709 773
710 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( 774 bool PasswordAutofillAgent::OriginCanAccessPasswordManager(
711 const blink::WebSecurityOrigin& origin) { 775 const blink::WebSecurityOrigin& origin) {
712 return origin.canAccessPasswordManager(); 776 return origin.canAccessPasswordManager();
713 } 777 }
714 778
715 void PasswordAutofillAgent::OnDynamicFormsSeen(blink::WebFrame* frame) { 779 void PasswordAutofillAgent::OnDynamicFormsSeen(blink::WebFrame* frame) {
716 SendPasswordForms(frame, false /* only_visible */); 780 SendPasswordForms(frame, false /* only_visible */);
717 } 781 }
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
1047 break; 1111 break;
1048 1112
1049 // Get pointer to password element. (We currently only support single 1113 // Get pointer to password element. (We currently only support single
1050 // password forms). 1114 // password forms).
1051 password_element = 1115 password_element =
1052 form_elements->input_elements[form_data.basic_data.fields[1].name]; 1116 form_elements->input_elements[form_data.basic_data.fields[1].name];
1053 1117
1054 // If wait_for_username is true, we don't want to initially fill the form 1118 // If wait_for_username is true, we don't want to initially fill the form
1055 // until the user types in a valid username. 1119 // until the user types in a valid username.
1056 if (!form_data.wait_for_username && 1120 if (!form_data.wait_for_username &&
1057 FillFormOnPasswordRecieved( 1121 FillFormOnPasswordReceived(
1058 form_data, 1122 form_data, username_element, password_element,
1059 username_element,
1060 password_element,
1061 base::Bind(&PasswordValueGatekeeper::RegisterElement, 1123 base::Bind(&PasswordValueGatekeeper::RegisterElement,
1062 base::Unretained(&gatekeeper_)))) { 1124 base::Unretained(&gatekeeper_)))) {
1063 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; 1125 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED;
1064 } 1126 }
1065 // We might have already filled this form if there are two <form> elements 1127 // We might have already filled this form if there are two <form> elements
1066 // with identical markup. 1128 // with identical markup.
1067 if (login_to_password_info_.find(username_element) != 1129 if (login_to_password_info_.find(username_element) !=
1068 login_to_password_info_.end()) 1130 login_to_password_info_.end())
1069 continue; 1131 continue;
1070 1132
(...skipping 13 matching lines...) Expand all
1084 //////////////////////////////////////////////////////////////////////////////// 1146 ////////////////////////////////////////////////////////////////////////////////
1085 // PasswordAutofillAgent, private: 1147 // PasswordAutofillAgent, private:
1086 1148
1087 PasswordAutofillAgent::PasswordInfo::PasswordInfo() 1149 PasswordAutofillAgent::PasswordInfo::PasswordInfo()
1088 : backspace_pressed_last(false), password_was_edited_last(false) { 1150 : backspace_pressed_last(false), password_was_edited_last(false) {
1089 } 1151 }
1090 1152
1091 bool PasswordAutofillAgent::ShowSuggestionPopup( 1153 bool PasswordAutofillAgent::ShowSuggestionPopup(
1092 const PasswordFormFillData& fill_data, 1154 const PasswordFormFillData& fill_data,
1093 const blink::WebInputElement& user_input, 1155 const blink::WebInputElement& user_input,
1094 bool show_all) { 1156 bool show_all,
1157 bool show_on_password_field) {
1095 blink::WebFrame* frame = user_input.document().frame(); 1158 blink::WebFrame* frame = user_input.document().frame();
1096 if (!frame) 1159 if (!frame)
1097 return false; 1160 return false;
1098 1161
1099 blink::WebView* webview = frame->view(); 1162 blink::WebView* webview = frame->view();
1100 if (!webview) 1163 if (!webview)
1101 return false; 1164 return false;
1102 1165
1103 FormData form; 1166 FormData form;
1104 FormFieldData field; 1167 FormFieldData field;
1105 FindFormAndFieldForFormControlElement( 1168 FindFormAndFieldForFormControlElement(
1106 user_input, &form, &field, REQUIRE_NONE); 1169 user_input, &form, &field, REQUIRE_NONE);
1107 1170
1108 blink::WebInputElement selected_element = user_input; 1171 blink::WebInputElement selected_element = user_input;
1172 if (show_on_password_field) {
1173 LoginToPasswordInfoMap::const_iterator iter =
1174 login_to_password_info_.find(user_input);
1175 DCHECK(iter != login_to_password_info_.end());
1176 selected_element = iter->second.password_field;
1177 }
1109 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); 1178 gfx::Rect bounding_box(selected_element.boundsInViewportSpace());
1110 1179
1111 LoginToPasswordInfoKeyMap::const_iterator key_it = 1180 LoginToPasswordInfoKeyMap::const_iterator key_it =
1112 login_to_password_info_key_.find(user_input); 1181 login_to_password_info_key_.find(user_input);
1113 DCHECK(key_it != login_to_password_info_key_.end()); 1182 DCHECK(key_it != login_to_password_info_key_.end());
1114 1183
1115 float scale = web_view_->pageScaleFactor(); 1184 float scale = web_view_->pageScaleFactor();
1116 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, 1185 gfx::RectF bounding_box_scaled(bounding_box.x() * scale,
1117 bounding_box.y() * scale, 1186 bounding_box.y() * scale,
1118 bounding_box.width() * scale, 1187 bounding_box.width() * scale,
1119 bounding_box.height() * scale); 1188 bounding_box.height() * scale);
1189 int options = 0;
1190 if (show_all)
1191 options |= ShowPasswordSuggestionsOptions::SHOW_ALL;
1192 if (show_on_password_field)
1193 options |= ShowPasswordSuggestionsOptions::IS_PASSWORD_FIELD;
1120 Send(new AutofillHostMsg_ShowPasswordSuggestions( 1194 Send(new AutofillHostMsg_ShowPasswordSuggestions(
1121 routing_id(), key_it->second, field.text_direction, user_input.value(), 1195 routing_id(), key_it->second, field.text_direction, user_input.value(),
1122 show_all, bounding_box_scaled)); 1196 options, bounding_box_scaled));
1123 1197
1124 bool suggestions_present = false; 1198 bool suggestions_present = false;
1125 if (GetSuggestionsStats(fill_data, user_input.value(), show_all, 1199 if (GetSuggestionsStats(fill_data, user_input.value(), show_all,
1126 &suggestions_present)) { 1200 &suggestions_present)) {
1127 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN; 1201 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN;
1128 } 1202 }
1129 return suggestions_present; 1203 return suggestions_present;
1130 } 1204 }
1131 1205
1132 void PasswordAutofillAgent::PerformInlineAutocomplete( 1206 void PasswordAutofillAgent::PerformInlineAutocomplete(
1133 const blink::WebInputElement& username_input, 1207 const blink::WebInputElement& username_input,
1134 const blink::WebInputElement& password_input, 1208 const blink::WebInputElement& password_input,
1135 const PasswordFormFillData& fill_data) { 1209 const PasswordFormFillData& fill_data) {
1136 DCHECK(!fill_data.wait_for_username); 1210 DCHECK(!fill_data.wait_for_username);
1137 1211
1138 // We need non-const versions of the username and password inputs. 1212 // We need non-const versions of the username and password inputs.
1139 blink::WebInputElement username = username_input; 1213 blink::WebInputElement username = username_input;
1140 blink::WebInputElement password = password_input; 1214 blink::WebInputElement password = password_input;
1141 1215
1142 // Don't inline autocomplete if the caret is not at the end. 1216 // Don't inline autocomplete if the caret is not at the end.
1143 // TODO(jcivelli): is there a better way to test the caret location? 1217 // TODO(jcivelli): is there a better way to test the caret location?
1144 if (username.selectionStart() != username.selectionEnd() || 1218 if (username.selectionStart() != username.selectionEnd() ||
1145 username.selectionEnd() != static_cast<int>(username.value().length())) { 1219 username.selectionEnd() != static_cast<int>(username.value().length())) {
1146 return; 1220 return;
1147 } 1221 }
1148 1222
1149 // Show the popup with the list of available usernames. 1223 // Show the popup with the list of available usernames.
1150 ShowSuggestionPopup(fill_data, username, false); 1224 ShowSuggestionPopup(fill_data, username, false, false);
1151 1225
1152 #if !defined(OS_ANDROID) 1226 #if !defined(OS_ANDROID)
1153 // Fill the user and password field with the most relevant match. Android 1227 // Fill the user and password field with the most relevant match. Android
1154 // only fills in the fields after the user clicks on the suggestion popup. 1228 // only fills in the fields after the user clicks on the suggestion popup.
1155 if (FillUserNameAndPassword( 1229 if (FillUserNameAndPassword(
1156 &username, 1230 &username, &password, fill_data, SET_SELECTION,
1157 &password,
1158 fill_data,
1159 false /* exact_username_match */,
1160 true /* set_selection */,
1161 base::Bind(&PasswordValueGatekeeper::RegisterElement, 1231 base::Bind(&PasswordValueGatekeeper::RegisterElement,
1162 base::Unretained(&gatekeeper_)))) { 1232 base::Unretained(&gatekeeper_)))) {
1163 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; 1233 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED;
1164 } 1234 }
1165 #endif 1235 #endif
1166 } 1236 }
1167 1237
1168 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { 1238 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) {
1169 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); 1239 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin();
1170 iter != login_to_password_info_.end();) { 1240 iter != login_to_password_info_.end();) {
(...skipping 21 matching lines...) Expand all
1192 blink::WebInputElement* found_input, 1262 blink::WebInputElement* found_input,
1193 PasswordInfo** found_password) { 1263 PasswordInfo** found_password) {
1194 if (!node.isElementNode()) 1264 if (!node.isElementNode())
1195 return false; 1265 return false;
1196 1266
1197 blink::WebElement element = node.toConst<blink::WebElement>(); 1267 blink::WebElement element = node.toConst<blink::WebElement>();
1198 if (!element.hasHTMLTagName("input")) 1268 if (!element.hasHTMLTagName("input"))
1199 return false; 1269 return false;
1200 1270
1201 blink::WebInputElement input = element.to<blink::WebInputElement>(); 1271 blink::WebInputElement input = element.to<blink::WebInputElement>();
1202 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(input); 1272 LoginToPasswordInfoMap::iterator iter = FindPasswordInfoForElement(input);
1203 if (iter == login_to_password_info_.end()) 1273 if (iter == login_to_password_info_.end())
1204 return false; 1274 return false;
1205 1275
1206 *found_input = input; 1276 *found_input = input;
1207 *found_password = &iter->second; 1277 *found_password = &iter->second;
1208 return true; 1278 return true;
1209 } 1279 }
1210 1280
1211 void PasswordAutofillAgent::ClearPreview( 1281 void PasswordAutofillAgent::ClearPreview(
1212 blink::WebInputElement* username, 1282 blink::WebInputElement* username,
(...skipping 25 matching lines...) Expand all
1238 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); 1308 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form));
1239 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && 1309 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD &&
1240 password_form->password_value.empty() && 1310 password_form->password_value.empty() &&
1241 password_form->new_password_value.empty())) { 1311 password_form->new_password_value.empty())) {
1242 return; 1312 return;
1243 } 1313 }
1244 provisionally_saved_forms_[frame].reset(password_form.release()); 1314 provisionally_saved_forms_[frame].reset(password_form.release());
1245 } 1315 }
1246 1316
1247 } // namespace autofill 1317 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698