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/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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |