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_autofill_util.h" | 19 #include "components/autofill/core/common/password_autofill_util.h" |
18 #include "components/autofill/core/common/password_form.h" | 20 #include "components/autofill/core/common/password_form.h" |
19 #include "components/autofill/core/common/password_form_fill_data.h" | 21 #include "components/autofill/core/common/password_form_fill_data.h" |
20 #include "content/public/renderer/document_state.h" | 22 #include "content/public/renderer/document_state.h" |
21 #include "content/public/renderer/navigation_state.h" | 23 #include "content/public/renderer/navigation_state.h" |
22 #include "content/public/renderer/render_view.h" | 24 #include "content/public/renderer/render_view.h" |
23 #include "third_party/WebKit/public/platform/WebVector.h" | 25 #include "third_party/WebKit/public/platform/WebVector.h" |
24 #include "third_party/WebKit/public/web/WebAutofillClient.h" | 26 #include "third_party/WebKit/public/web/WebAutofillClient.h" |
25 #include "third_party/WebKit/public/web/WebDocument.h" | 27 #include "third_party/WebKit/public/web/WebDocument.h" |
26 #include "third_party/WebKit/public/web/WebElement.h" | 28 #include "third_party/WebKit/public/web/WebElement.h" |
27 #include "third_party/WebKit/public/web/WebFormElement.h" | 29 #include "third_party/WebKit/public/web/WebFormElement.h" |
28 #include "third_party/WebKit/public/web/WebInputEvent.h" | 30 #include "third_party/WebKit/public/web/WebInputEvent.h" |
29 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 31 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
30 #include "third_party/WebKit/public/web/WebNode.h" | 32 #include "third_party/WebKit/public/web/WebNode.h" |
31 #include "third_party/WebKit/public/web/WebNodeList.h" | 33 #include "third_party/WebKit/public/web/WebNodeList.h" |
32 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" | 34 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" |
33 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" | 35 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" |
34 #include "third_party/WebKit/public/web/WebView.h" | 36 #include "third_party/WebKit/public/web/WebView.h" |
35 #include "ui/base/page_transition_types.h" | 37 #include "ui/base/page_transition_types.h" |
36 #include "ui/events/keycodes/keyboard_codes.h" | 38 #include "ui/events/keycodes/keyboard_codes.h" |
37 #include "url/gurl.h" | 39 #include "url/gurl.h" |
38 | 40 |
39 namespace autofill { | 41 namespace autofill { |
40 namespace { | 42 namespace { |
41 | 43 |
44 enum FillUserNameAndPasswordOptions { | |
45 EXACT_USERNAME_MATCH = 1 << 0, | |
46 SET_SELECTION = 1 << 1, | |
47 FILL_PREFERRED_USERNAME = 1 << 2 | |
48 }; | |
49 | |
42 // The size above which we stop triggering autocomplete. | 50 // The size above which we stop triggering autocomplete. |
43 static const size_t kMaximumTextSizeForAutocomplete = 1000; | 51 static const size_t kMaximumTextSizeForAutocomplete = 1000; |
44 | 52 |
45 // Maps element names to the actual elements to simplify form filling. | 53 // Maps element names to the actual elements to simplify form filling. |
46 typedef std::map<base::string16, blink::WebInputElement> FormInputElementMap; | 54 typedef std::map<base::string16, blink::WebInputElement> FormInputElementMap; |
47 | 55 |
48 // Use the shorter name when referencing SavePasswordProgressLogger::StringID | 56 // Use the shorter name when referencing SavePasswordProgressLogger::StringID |
49 // values to spare line breaks. The code provides enough context for that | 57 // values to spare line breaks. The code provides enough context for that |
50 // already. | 58 // already. |
51 typedef SavePasswordProgressLogger Logger; | 59 typedef SavePasswordProgressLogger Logger; |
52 | 60 |
53 // Utility struct for form lookup and autofill. When we parse the DOM to look up | 61 // Utility struct for form lookup and autofill. When we parse the DOM to look up |
54 // a form, in addition to action and origin URL's we have to compare all | 62 // a form, in addition to action and origin URL's we have to compare all |
55 // necessary form elements. To avoid having to look these up again when we want | 63 // necessary form elements. To avoid having to look these up again when we want |
56 // to fill the form, the FindFormElements function stores the pointers | 64 // to fill the form, the FindFormElements function stores the pointers |
57 // in a FormElements* result, referenced to ensure they are safe to use. | 65 // in a FormElements* result, referenced to ensure they are safe to use. |
58 struct FormElements { | 66 struct FormElements { |
59 blink::WebFormElement form_element; | 67 blink::WebFormElement form_element; |
60 FormInputElementMap input_elements; | 68 FormInputElementMap input_elements; |
61 }; | 69 }; |
62 | 70 |
63 typedef std::vector<FormElements*> FormElementsList; | 71 typedef std::vector<FormElements*> FormElementsList; |
64 | 72 |
73 bool ShouldFillOnAccountSelect() { | |
74 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
75 switches::kEnableFillOnAccountSelect)) { | |
76 return true; | |
77 } | |
78 | |
79 // This is made explicit in anticiption of experimental groups being added. | |
80 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
81 switches::kDisableFillOnAccountSelect)) { | |
82 return false; | |
83 } | |
84 | |
85 // TODO(jww): Add experimental groups check here. | |
86 | |
87 return false; | |
88 } | |
89 | |
65 // Helper to search the given form element for the specified input elements | 90 // Helper to search the given form element for the specified input elements |
66 // in |data|, and add results to |result|. | 91 // in |data|, and add results to |result|. |
67 static bool FindFormInputElements(blink::WebFormElement* fe, | 92 static bool FindFormInputElements(blink::WebFormElement* fe, |
68 const FormData& data, | 93 const FormData& data, |
69 FormElements* result) { | 94 FormElements* result) { |
70 const bool username_is_present = !data.fields[0].name.empty(); | 95 const bool username_is_present = !data.fields[0].name.empty(); |
71 | 96 |
72 // Loop through the list of elements we need to find on the form in order to | 97 // Loop through the list of elements we need to find on the form in order to |
73 // autofill it. If we don't find any one of them, abort processing this | 98 // autofill it. If we don't find any one of them, abort processing this |
74 // form; it can't be the right one. | 99 // form; it can't be the right one. |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
274 } | 299 } |
275 } | 300 } |
276 | 301 |
277 return false; | 302 return false; |
278 } | 303 } |
279 | 304 |
280 // This function attempts to fill |username_element| and |password_element| | 305 // This function attempts to fill |username_element| and |password_element| |
281 // with values from |fill_data|. The |password_element| will only have the | 306 // with values from |fill_data|. The |password_element| will only have the |
282 // |suggestedValue| set, and will be registered for copying that to the real | 307 // |suggestedValue| set, and will be registered for copying that to the real |
283 // value through |registration_callback|. The function returns true when | 308 // value through |registration_callback|. The function returns true when |
284 // selected username comes from |fill_data.other_possible_usernames|. | 309 // selected username comes from |fill_data.other_possible_usernames|. |options| |
310 // should be a bitwise mask of FillUserNameAndPasswordOptions values. | |
285 bool FillUserNameAndPassword( | 311 bool FillUserNameAndPassword( |
286 blink::WebInputElement* username_element, | 312 blink::WebInputElement* username_element, |
287 blink::WebInputElement* password_element, | 313 blink::WebInputElement* password_element, |
288 const PasswordFormFillData& fill_data, | 314 const PasswordFormFillData& fill_data, |
289 bool exact_username_match, | 315 const int options, |
290 bool set_selection, | |
291 base::Callback<void(blink::WebInputElement*)> registration_callback) { | 316 base::Callback<void(blink::WebInputElement*)> registration_callback) { |
317 bool exact_username_match = (options & EXACT_USERNAME_MATCH) != 0; | |
318 bool set_selection = (options & SET_SELECTION) != 0; | |
292 bool other_possible_username_selected = false; | 319 bool other_possible_username_selected = false; |
293 // Don't fill username if password can't be set. | 320 // Don't fill username if password can't be set. |
294 if (!IsElementAutocompletable(*password_element)) | 321 if (!IsElementAutocompletable(*password_element)) |
295 return false; | 322 return false; |
296 | 323 |
297 base::string16 current_username; | 324 base::string16 current_username; |
298 if (!username_element->isNull()) { | 325 if (!username_element->isNull()) { |
299 current_username = username_element->value(); | 326 current_username = username_element->value(); |
300 } | 327 } |
301 | 328 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
376 } | 403 } |
377 | 404 |
378 // Attempts to fill |username_element| and |password_element| with the | 405 // Attempts to fill |username_element| and |password_element| with the |
379 // |fill_data|. Will use the data corresponding to the preferred username, | 406 // |fill_data|. Will use the data corresponding to the preferred username, |
380 // unless the |username_element| already has a value set. In that case, | 407 // unless the |username_element| already has a value set. In that case, |
381 // attempts to fill the password matching the already filled username, if | 408 // attempts to fill the password matching the already filled username, if |
382 // such a password exists. The |password_element| will have the | 409 // such a password exists. The |password_element| will have the |
383 // |suggestedValue| set, and |suggestedValue| will be registered for copying to | 410 // |suggestedValue| set, and |suggestedValue| will be registered for copying to |
384 // the real value through |registration_callback|. Returns true when the | 411 // the real value through |registration_callback|. Returns true when the |
385 // username gets selected from |other_possible_usernames|, else returns false. | 412 // username gets selected from |other_possible_usernames|, else returns false. |
386 bool FillFormOnPasswordRecieved( | 413 bool FillFormOnPasswordReceived( |
387 const PasswordFormFillData& fill_data, | 414 const PasswordFormFillData& fill_data, |
388 blink::WebInputElement username_element, | 415 blink::WebInputElement username_element, |
389 blink::WebInputElement password_element, | 416 blink::WebInputElement password_element, |
390 base::Callback<void(blink::WebInputElement*)> registration_callback) { | 417 base::Callback<void(blink::WebInputElement*)> registration_callback) { |
391 // Do not fill if the password field is in an iframe. | 418 // Do not fill if the password field is in an iframe. |
392 DCHECK(password_element.document().frame()); | 419 DCHECK(password_element.document().frame()); |
393 if (password_element.document().frame()->parent()) | 420 if (password_element.document().frame()->parent()) |
394 return false; | 421 return false; |
395 | 422 |
396 bool form_contains_username_field = FillDataContainsUsername(fill_data); | 423 bool form_contains_username_field = FillDataContainsUsername(fill_data); |
397 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && | 424 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && |
398 form_contains_username_field && !username_element.form().autoComplete()) | 425 form_contains_username_field && !username_element.form().autoComplete()) |
399 return false; | 426 return false; |
400 | 427 |
401 // If we can't modify the password, don't try to set the username | 428 // If we can't modify the password, don't try to set the username |
402 if (!IsElementAutocompletable(password_element)) | 429 if (!IsElementAutocompletable(password_element)) |
403 return false; | 430 return false; |
404 | 431 |
405 // Try to set the username to the preferred name, but only if the field | 432 // Try to set the username to the preferred name, but only if: |
406 // can be set and isn't prefilled. | 433 // (a) The username element is autocompletable, and |
407 if (form_contains_username_field && | 434 // (b) The fill-on-account-select flag is not set, and |
408 IsElementAutocompletable(username_element) && | 435 // (b) The username element isn't prefilled |
Garrett Casto
2014/11/04 23:35:30
Is that last line supposed to be (c)?
jww
2014/11/06 21:28:56
Yup :-)
| |
409 username_element.value().isEmpty()) { | 436 // |
410 // TODO(tkent): Check maxlength and pattern. | 437 // If (a) is true, but (b) is false, then just mark the username element as |
411 username_element.setValue(fill_data.basic_data.fields[0].value, true); | 438 // autofilled and return so the fill step is skipped. |
439 // | |
440 // If (a) is false, but (b) is true, then the username element should not be | |
441 // autofilled, but the user should still be able to select to fill the | |
442 // password element, so the password element must be marked as autofilled and | |
443 // the fill step should also be skipped. | |
444 if (IsElementAutocompletable(username_element)) { | |
Garrett Casto
2014/11/04 23:35:30
I think that you dropped the form_contains_usernam
jww
2014/11/06 21:28:56
Done.
Garrett Casto
2014/11/23 07:49:48
Can you add a test so that this would have been ca
jww
2014/11/25 02:46:25
Yup, unit tests are my next step.
| |
445 if (ShouldFillOnAccountSelect()) { | |
446 username_element.setAutofilled(true); | |
447 return false; | |
448 } else if (username_element.value().isEmpty()) { | |
449 // TODO(tkent): Check maxlength and pattern. | |
450 username_element.setValue(fill_data.basic_data.fields[0].value, true); | |
451 } | |
452 } else if (ShouldFillOnAccountSelect()) { | |
453 password_element.setAutofilled(true); | |
454 return false; | |
412 } | 455 } |
413 | 456 |
414 // Fill if we have an exact match for the username. Note that this sets | 457 // Fill if we have an exact match for the username. Note that this sets |
415 // username to autofilled. | 458 // username to autofilled. |
416 return FillUserNameAndPassword(&username_element, | 459 return FillUserNameAndPassword( |
417 &password_element, | 460 &username_element, &password_element, fill_data, |
418 fill_data, | 461 EXACT_USERNAME_MATCH | FILL_PREFERRED_USERNAME, registration_callback); |
419 true /* exact_username_match */, | |
420 false /* set_selection */, | |
421 registration_callback); | |
422 } | 462 } |
423 | 463 |
424 // Takes a |map| with pointers as keys and linked_ptr as values, and returns | 464 // Takes a |map| with pointers as keys and linked_ptr as values, and returns |
425 // true if |key| is not NULL and |map| contains a non-NULL entry for |key|. | 465 // true if |key| is not NULL and |map| contains a non-NULL entry for |key|. |
426 // Makes sure not to create an entry as a side effect of using the operator []. | 466 // Makes sure not to create an entry as a side effect of using the operator []. |
427 template <class Key, class Value> | 467 template <class Key, class Value> |
428 bool ContainsNonNullEntryForNonNullKey( | 468 bool ContainsNonNullEntryForNonNullKey( |
429 const std::map<Key*, linked_ptr<Value>>& map, | 469 const std::map<Key*, linked_ptr<Value>>& map, |
430 Key* key) { | 470 Key* key) { |
431 if (!key) | 471 if (!key) |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
513 | 553 |
514 blink::WebInputElement password = password_info.password_field; | 554 blink::WebInputElement password = password_info.password_field; |
515 if (!IsElementEditable(password)) | 555 if (!IsElementEditable(password)) |
516 return false; | 556 return false; |
517 | 557 |
518 blink::WebInputElement username = element; // We need a non-const. | 558 blink::WebInputElement username = element; // We need a non-const. |
519 | 559 |
520 // Do not set selection when ending an editing session, otherwise it can | 560 // Do not set selection when ending an editing session, otherwise it can |
521 // mess with focus. | 561 // mess with focus. |
522 if (FillUserNameAndPassword( | 562 if (FillUserNameAndPassword( |
523 &username, | 563 &username, &password, fill_data, EXACT_USERNAME_MATCH, |
524 &password, | |
525 fill_data, | |
526 true /* exact_username_match */, | |
527 false /* set_selection */, | |
528 base::Bind(&PasswordValueGatekeeper::RegisterElement, | 564 base::Bind(&PasswordValueGatekeeper::RegisterElement, |
529 base::Unretained(&gatekeeper_)))) { | 565 base::Unretained(&gatekeeper_)))) { |
530 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | 566 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; |
531 } | 567 } |
532 return true; | 568 return true; |
533 } | 569 } |
534 | 570 |
535 bool PasswordAutofillAgent::TextDidChangeInTextField( | 571 bool PasswordAutofillAgent::TextDidChangeInTextField( |
536 const blink::WebInputElement& element) { | 572 const blink::WebInputElement& element) { |
537 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 | 573 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
677 const blink::WebNode& node) { | 713 const blink::WebNode& node) { |
678 blink::WebInputElement username_element; | 714 blink::WebInputElement username_element; |
679 PasswordInfo* password_info; | 715 PasswordInfo* password_info; |
680 if (!FindLoginInfo(node, &username_element, &password_info)) | 716 if (!FindLoginInfo(node, &username_element, &password_info)) |
681 return false; | 717 return false; |
682 | 718 |
683 ClearPreview(&username_element, &password_info->password_field); | 719 ClearPreview(&username_element, &password_info->password_field); |
684 return true; | 720 return true; |
685 } | 721 } |
686 | 722 |
723 PasswordAutofillAgent::LoginToPasswordInfoMap::iterator | |
724 PasswordAutofillAgent::FindPasswordInfoForElement( | |
725 const blink::WebInputElement& element) { | |
726 const blink::WebInputElement* username_element; | |
Garrett Casto
2014/11/04 23:35:30
Why does this need to be a pointer?
jww
2014/11/06 21:28:56
I was trying to have only return statement, and si
| |
727 if (!element.isPasswordField()) { | |
728 username_element = &element; | |
729 } else { | |
730 PasswordToLoginMap::const_iterator password_iter = | |
731 password_to_username_.find(element); | |
Garrett Casto
2014/11/04 23:35:30
Where is this defined and populated?
jww
2014/11/06 21:28:57
It's defined in password_autofill_agent.h and it i
| |
732 if (password_iter == password_to_username_.end()) | |
733 return login_to_password_info_.end(); | |
734 username_element = &password_iter->second; | |
735 } | |
736 | |
737 return login_to_password_info_.find(*username_element); | |
738 } | |
739 | |
687 bool PasswordAutofillAgent::ShowSuggestions( | 740 bool PasswordAutofillAgent::ShowSuggestions( |
688 const blink::WebInputElement& element, | 741 const blink::WebInputElement& element, |
689 bool show_all) { | 742 bool show_all) { |
690 LoginToPasswordInfoMap::const_iterator iter = | 743 LoginToPasswordInfoMap::const_iterator iter = |
691 login_to_password_info_.find(element); | 744 FindPasswordInfoForElement(element); |
692 if (iter == login_to_password_info_.end()) | 745 if (iter == login_to_password_info_.end()) |
693 return false; | 746 return false; |
694 | 747 |
695 // If autocomplete='off' is set on the form elements, no suggestion dialog | 748 // If autocomplete='off' is set on the form elements, no suggestion dialog |
696 // should be shown. However, return |true| to indicate that this is a known | 749 // should be shown. However, return |true| to indicate that this is a known |
697 // password form and that the request to show suggestions has been handled (as | 750 // password form and that the request to show suggestions has been handled (as |
698 // a no-op). | 751 // a no-op). |
699 if (!IsElementAutocompletable(element) || | 752 if (!IsElementAutocompletable(element) || |
700 !IsElementAutocompletable(iter->second.password_field)) | 753 !IsElementAutocompletable(iter->second.password_field)) |
701 return true; | 754 return true; |
702 | 755 |
703 return ShowSuggestionPopup(iter->second.fill_data, element, show_all); | 756 // Chrome should never show more than one account for a password element since |
757 // this implies that the username element cannot be modified. Thus even if | |
758 // |show_all| is true, check if the element in question is a password element | |
759 // for the call to ShowSuggestionPopup. | |
760 return ShowSuggestionPopup(iter->second.fill_data, iter->first, | |
761 show_all && !element.isPasswordField(), | |
762 element.isPasswordField()); | |
Garrett Casto
2014/11/04 23:35:30
Is there any reason why you need the fourth parame
jww
2014/11/06 21:28:57
Yes, because we ultimately need the username as th
Garrett Casto
2014/11/23 07:49:48
I'm not sure that I understand why we need the use
jww
2014/11/25 02:46:25
I believe it's because the browser process can onl
| |
704 } | 763 } |
705 | 764 |
706 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( | 765 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( |
707 const blink::WebSecurityOrigin& origin) { | 766 const blink::WebSecurityOrigin& origin) { |
708 return origin.canAccessPasswordManager(); | 767 return origin.canAccessPasswordManager(); |
709 } | 768 } |
710 | 769 |
711 void PasswordAutofillAgent::OnDynamicFormsSeen(blink::WebFrame* frame) { | 770 void PasswordAutofillAgent::OnDynamicFormsSeen(blink::WebFrame* frame) { |
712 SendPasswordForms(frame, false /* only_visible */); | 771 SendPasswordForms(frame, false /* only_visible */); |
713 } | 772 } |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1042 break; | 1101 break; |
1043 | 1102 |
1044 // Get pointer to password element. (We currently only support single | 1103 // Get pointer to password element. (We currently only support single |
1045 // password forms). | 1104 // password forms). |
1046 password_element = | 1105 password_element = |
1047 form_elements->input_elements[form_data.basic_data.fields[1].name]; | 1106 form_elements->input_elements[form_data.basic_data.fields[1].name]; |
1048 | 1107 |
1049 // If wait_for_username is true, we don't want to initially fill the form | 1108 // If wait_for_username is true, we don't want to initially fill the form |
1050 // until the user types in a valid username. | 1109 // until the user types in a valid username. |
1051 if (!form_data.wait_for_username && | 1110 if (!form_data.wait_for_username && |
1052 FillFormOnPasswordRecieved( | 1111 FillFormOnPasswordReceived( |
1053 form_data, | 1112 form_data, username_element, password_element, |
1054 username_element, | |
1055 password_element, | |
1056 base::Bind(&PasswordValueGatekeeper::RegisterElement, | 1113 base::Bind(&PasswordValueGatekeeper::RegisterElement, |
1057 base::Unretained(&gatekeeper_)))) { | 1114 base::Unretained(&gatekeeper_)))) { |
1058 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | 1115 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; |
1059 } | 1116 } |
1060 // We might have already filled this form if there are two <form> elements | 1117 // We might have already filled this form if there are two <form> elements |
1061 // with identical markup. | 1118 // with identical markup. |
1062 if (login_to_password_info_.find(username_element) != | 1119 if (login_to_password_info_.find(username_element) != |
1063 login_to_password_info_.end()) | 1120 login_to_password_info_.end()) |
1064 continue; | 1121 continue; |
1065 | 1122 |
(...skipping 22 matching lines...) Expand all Loading... | |
1088 //////////////////////////////////////////////////////////////////////////////// | 1145 //////////////////////////////////////////////////////////////////////////////// |
1089 // PasswordAutofillAgent, private: | 1146 // PasswordAutofillAgent, private: |
1090 | 1147 |
1091 PasswordAutofillAgent::PasswordInfo::PasswordInfo() | 1148 PasswordAutofillAgent::PasswordInfo::PasswordInfo() |
1092 : backspace_pressed_last(false), password_was_edited_last(false) { | 1149 : backspace_pressed_last(false), password_was_edited_last(false) { |
1093 } | 1150 } |
1094 | 1151 |
1095 bool PasswordAutofillAgent::ShowSuggestionPopup( | 1152 bool PasswordAutofillAgent::ShowSuggestionPopup( |
1096 const PasswordFormFillData& fill_data, | 1153 const PasswordFormFillData& fill_data, |
1097 const blink::WebInputElement& user_input, | 1154 const blink::WebInputElement& user_input, |
1098 bool show_all) { | 1155 bool show_all, |
1156 bool show_on_password_field) { | |
1099 blink::WebFrame* frame = user_input.document().frame(); | 1157 blink::WebFrame* frame = user_input.document().frame(); |
1100 if (!frame) | 1158 if (!frame) |
1101 return false; | 1159 return false; |
1102 | 1160 |
1103 blink::WebView* webview = frame->view(); | 1161 blink::WebView* webview = frame->view(); |
1104 if (!webview) | 1162 if (!webview) |
1105 return false; | 1163 return false; |
1106 | 1164 |
1107 FormData form; | 1165 FormData form; |
1108 FormFieldData field; | 1166 FormFieldData field; |
1109 FindFormAndFieldForFormControlElement( | 1167 FindFormAndFieldForFormControlElement( |
1110 user_input, &form, &field, REQUIRE_NONE); | 1168 user_input, &form, &field, REQUIRE_NONE); |
1111 | 1169 |
1112 blink::WebInputElement selected_element = user_input; | 1170 blink::WebInputElement selected_element = user_input; |
1171 if (show_on_password_field) { | |
1172 LoginToPasswordInfoMap::const_iterator iter = | |
1173 login_to_password_info_.find(user_input); | |
1174 DCHECK(iter != login_to_password_info_.end()); | |
1175 selected_element = iter->second.password_field; | |
1176 } | |
1113 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); | 1177 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); |
1114 | 1178 |
1115 float scale = web_view_->pageScaleFactor(); | 1179 float scale = web_view_->pageScaleFactor(); |
1116 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, | 1180 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, |
1117 bounding_box.y() * scale, | 1181 bounding_box.y() * scale, |
1118 bounding_box.width() * scale, | 1182 bounding_box.width() * scale, |
1119 bounding_box.height() * scale); | 1183 bounding_box.height() * scale); |
1120 Send(new AutofillHostMsg_ShowPasswordSuggestions( | 1184 if (show_on_password_field) { |
1121 routing_id(), field, user_input.value(), show_all, bounding_box_scaled)); | 1185 Send(new AutofillHostMsg_ShowPasswordSuggestionsForPasswordField( |
1186 routing_id(), field, user_input.value(), show_all, | |
1187 bounding_box_scaled)); | |
1188 } else { | |
1189 Send(new AutofillHostMsg_ShowPasswordSuggestions( | |
1190 routing_id(), field, user_input.value(), show_all, | |
1191 bounding_box_scaled)); | |
1192 } | |
1122 | 1193 |
1123 bool suggestions_present = false; | 1194 bool suggestions_present = false; |
1124 if (GetSuggestionsStats(fill_data, user_input.value(), show_all, | 1195 if (GetSuggestionsStats(fill_data, user_input.value(), show_all, |
1125 &suggestions_present)) { | 1196 &suggestions_present)) { |
1126 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN; | 1197 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN; |
1127 } | 1198 } |
1128 return suggestions_present; | 1199 return suggestions_present; |
1129 } | 1200 } |
1130 | 1201 |
1131 void PasswordAutofillAgent::PerformInlineAutocomplete( | 1202 void PasswordAutofillAgent::PerformInlineAutocomplete( |
(...skipping 13 matching lines...) Expand all Loading... | |
1145 return; | 1216 return; |
1146 } | 1217 } |
1147 | 1218 |
1148 // Show the popup with the list of available usernames. | 1219 // Show the popup with the list of available usernames. |
1149 ShowSuggestionPopup(fill_data, username, false); | 1220 ShowSuggestionPopup(fill_data, username, false); |
1150 | 1221 |
1151 #if !defined(OS_ANDROID) | 1222 #if !defined(OS_ANDROID) |
1152 // Fill the user and password field with the most relevant match. Android | 1223 // Fill the user and password field with the most relevant match. Android |
1153 // only fills in the fields after the user clicks on the suggestion popup. | 1224 // only fills in the fields after the user clicks on the suggestion popup. |
1154 if (FillUserNameAndPassword( | 1225 if (FillUserNameAndPassword( |
1155 &username, | 1226 &username, &password, fill_data, SET_SELECTION, |
1156 &password, | |
1157 fill_data, | |
1158 false /* exact_username_match */, | |
1159 true /* set_selection */, | |
1160 base::Bind(&PasswordValueGatekeeper::RegisterElement, | 1227 base::Bind(&PasswordValueGatekeeper::RegisterElement, |
1161 base::Unretained(&gatekeeper_)))) { | 1228 base::Unretained(&gatekeeper_)))) { |
1162 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | 1229 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; |
1163 } | 1230 } |
1164 #endif | 1231 #endif |
1165 } | 1232 } |
1166 | 1233 |
1167 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { | 1234 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { |
1168 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); | 1235 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); |
1169 iter != login_to_password_info_.end();) { | 1236 iter != login_to_password_info_.end();) { |
(...skipping 20 matching lines...) Expand all Loading... | |
1190 blink::WebInputElement* found_input, | 1257 blink::WebInputElement* found_input, |
1191 PasswordInfo** found_password) { | 1258 PasswordInfo** found_password) { |
1192 if (!node.isElementNode()) | 1259 if (!node.isElementNode()) |
1193 return false; | 1260 return false; |
1194 | 1261 |
1195 blink::WebElement element = node.toConst<blink::WebElement>(); | 1262 blink::WebElement element = node.toConst<blink::WebElement>(); |
1196 if (!element.hasHTMLTagName("input")) | 1263 if (!element.hasHTMLTagName("input")) |
1197 return false; | 1264 return false; |
1198 | 1265 |
1199 blink::WebInputElement input = element.to<blink::WebInputElement>(); | 1266 blink::WebInputElement input = element.to<blink::WebInputElement>(); |
1200 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(input); | 1267 LoginToPasswordInfoMap::iterator iter = FindPasswordInfoForElement(input); |
1201 if (iter == login_to_password_info_.end()) | 1268 if (iter == login_to_password_info_.end()) |
1202 return false; | 1269 return false; |
1203 | 1270 |
1204 *found_input = input; | 1271 *found_input = input; |
1205 *found_password = &iter->second; | 1272 *found_password = &iter->second; |
1206 return true; | 1273 return true; |
1207 } | 1274 } |
1208 | 1275 |
1209 void PasswordAutofillAgent::ClearPreview( | 1276 void PasswordAutofillAgent::ClearPreview( |
1210 blink::WebInputElement* username, | 1277 blink::WebInputElement* username, |
(...skipping 25 matching lines...) Expand all Loading... | |
1236 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); | 1303 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); |
1237 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && | 1304 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && |
1238 password_form->password_value.empty() && | 1305 password_form->password_value.empty() && |
1239 password_form->new_password_value.empty())) { | 1306 password_form->new_password_value.empty())) { |
1240 return; | 1307 return; |
1241 } | 1308 } |
1242 provisionally_saved_forms_[frame].reset(password_form.release()); | 1309 provisionally_saved_forms_[frame].reset(password_form.release()); |
1243 } | 1310 } |
1244 | 1311 |
1245 } // namespace autofill | 1312 } // namespace autofill |
OLD | NEW |