Chromium Code Reviews| 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/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| 11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 12 #include "components/autofill/content/common/autofill_messages.h" | 12 #include "components/autofill/content/common/autofill_messages.h" |
| 13 #include "components/autofill/content/renderer/form_autofill_util.h" | 13 #include "components/autofill/content/renderer/form_autofill_util.h" |
| 14 #include "components/autofill/content/renderer/password_form_conversion_utils.h" | 14 #include "components/autofill/content/renderer/password_form_conversion_utils.h" |
| 15 #include "components/autofill/core/common/form_field_data.h" | 15 #include "components/autofill/core/common/form_field_data.h" |
| 16 #include "components/autofill/core/common/password_autofill_util.h" | 16 #include "components/autofill/core/common/password_autofill_util.h" |
| 17 #include "components/autofill/core/common/password_form.h" | 17 #include "components/autofill/core/common/password_form.h" |
| 18 #include "components/autofill/core/common/password_form_fill_data.h" | 18 #include "components/autofill/core/common/password_form_fill_data.h" |
| 19 #include "content/public/renderer/render_view.h" | 19 #include "content/public/renderer/render_view.h" |
| 20 #include "third_party/WebKit/public/platform/WebVector.h" | 20 #include "third_party/WebKit/public/platform/WebVector.h" |
| 21 #include "third_party/WebKit/public/web/WebAutofillClient.h" | 21 #include "third_party/WebKit/public/web/WebAutofillClient.h" |
| 22 #include "third_party/WebKit/public/web/WebDocument.h" | 22 #include "third_party/WebKit/public/web/WebDocument.h" |
| 23 #include "third_party/WebKit/public/web/WebElement.h" | 23 #include "third_party/WebKit/public/web/WebElement.h" |
| 24 #include "third_party/WebKit/public/web/WebFormElement.h" | 24 #include "third_party/WebKit/public/web/WebFormElement.h" |
| 25 #include "third_party/WebKit/public/web/WebFrame.h" | 25 #include "third_party/WebKit/public/web/WebFrame.h" |
| 26 #include "third_party/WebKit/public/web/WebInputEvent.h" | 26 #include "third_party/WebKit/public/web/WebInputEvent.h" |
| 27 #include "third_party/WebKit/public/web/WebNode.h" | 27 #include "third_party/WebKit/public/web/WebNode.h" |
| 28 #include "third_party/WebKit/public/web/WebNodeList.h" | 28 #include "third_party/WebKit/public/web/WebNodeList.h" |
| 29 #include "third_party/WebKit/public/web/WebPasswordFormData.h" | |
| 29 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" | 30 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" |
| 30 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" | 31 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" |
| 31 #include "third_party/WebKit/public/web/WebView.h" | 32 #include "third_party/WebKit/public/web/WebView.h" |
| 32 #include "ui/events/keycodes/keyboard_codes.h" | 33 #include "ui/events/keycodes/keyboard_codes.h" |
| 33 | 34 |
| 34 namespace autofill { | 35 namespace autofill { |
| 35 namespace { | 36 namespace { |
| 36 | 37 |
| 37 // The size above which we stop triggering autocomplete. | 38 // The size above which we stop triggering autocomplete. |
| 38 static const size_t kMaximumTextSizeForAutocomplete = 1000; | 39 static const size_t kMaximumTextSizeForAutocomplete = 1000; |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 174 } | 175 } |
| 175 | 176 |
| 176 bool DoUsernamesMatch(const base::string16& username1, | 177 bool DoUsernamesMatch(const base::string16& username1, |
| 177 const base::string16& username2, | 178 const base::string16& username2, |
| 178 bool exact_match) { | 179 bool exact_match) { |
| 179 if (exact_match) | 180 if (exact_match) |
| 180 return username1 == username2; | 181 return username1 == username2; |
| 181 return StartsWith(username1, username2, true); | 182 return StartsWith(username1, username2, true); |
| 182 } | 183 } |
| 183 | 184 |
| 185 bool IsElementAutocompletable(const blink::WebInputElement& element) { | |
|
Ilya Sherman
2013/12/27 23:17:09
nit: Docs, please.
jww
2013/12/31 00:33:05
Done.
| |
| 186 return IsElementEditable(element) && | |
| 187 (ShouldIgnoreAutocompleteOffForPasswordFields() || | |
| 188 element.autoComplete()); | |
| 189 } | |
| 190 | |
| 184 } // namespace | 191 } // namespace |
| 185 | 192 |
| 186 //////////////////////////////////////////////////////////////////////////////// | 193 //////////////////////////////////////////////////////////////////////////////// |
| 187 // PasswordAutofillAgent, public: | 194 // PasswordAutofillAgent, public: |
| 188 | 195 |
| 189 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) | 196 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) |
| 190 : content::RenderViewObserver(render_view), | 197 : content::RenderViewObserver(render_view), |
| 191 usernames_usage_(NOTHING_TO_AUTOFILL), | 198 usernames_usage_(NOTHING_TO_AUTOFILL), |
| 192 web_view_(render_view->GetWebView()), | 199 web_view_(render_view->GetWebView()), |
| 193 gesture_handler_(new AutofillWebUserGestureHandler(this)), | 200 gesture_handler_(new AutofillWebUserGestureHandler(this)), |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 243 SetElementAutofilled(&username, false); | 250 SetElementAutofilled(&username, false); |
| 244 if (password.isAutofilled()) { | 251 if (password.isAutofilled()) { |
| 245 password.setValue(base::string16()); | 252 password.setValue(base::string16()); |
| 246 SetElementAutofilled(&password, false); | 253 SetElementAutofilled(&password, false); |
| 247 } | 254 } |
| 248 | 255 |
| 249 // If wait_for_username is true we will fill when the username loses focus. | 256 // If wait_for_username is true we will fill when the username loses focus. |
| 250 if (iter->second.fill_data.wait_for_username) | 257 if (iter->second.fill_data.wait_for_username) |
| 251 return false; | 258 return false; |
| 252 | 259 |
| 253 if (!IsElementEditable(element) || !element.isText() || | 260 if (!element.isText() || !IsElementAutocompletable(element)) { |
| 254 (!ShouldIgnoreAutocompleteOffForPasswordFields() && | |
| 255 !element.autoComplete())) { | |
| 256 return false; | 261 return false; |
| 257 } | 262 } |
| 258 | 263 |
| 259 // Don't inline autocomplete if the user is deleting, that would be confusing. | 264 // Don't inline autocomplete if the user is deleting, that would be confusing. |
| 260 // But refresh the popup. Note, since this is ours, return true to signal | 265 // But refresh the popup. Note, since this is ours, return true to signal |
| 261 // no further processing is required. | 266 // no further processing is required. |
| 262 if (iter->second.backspace_pressed_last) { | 267 if (iter->second.backspace_pressed_last) { |
| 263 ShowSuggestionPopup(iter->second.fill_data, username); | 268 ShowSuggestionPopup(iter->second.fill_data, username); |
| 264 return true; | 269 return true; |
| 265 } | 270 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 318 return FindLoginInfo(node, &input, &password); | 323 return FindLoginInfo(node, &input, &password); |
| 319 } | 324 } |
| 320 | 325 |
| 321 bool PasswordAutofillAgent::ShowSuggestions( | 326 bool PasswordAutofillAgent::ShowSuggestions( |
| 322 const blink::WebInputElement& element) { | 327 const blink::WebInputElement& element) { |
| 323 LoginToPasswordInfoMap::const_iterator iter = | 328 LoginToPasswordInfoMap::const_iterator iter = |
| 324 login_to_password_info_.find(element); | 329 login_to_password_info_.find(element); |
| 325 if (iter == login_to_password_info_.end()) | 330 if (iter == login_to_password_info_.end()) |
| 326 return false; | 331 return false; |
| 327 | 332 |
| 333 // If autocomplete='off' is set on the form, we don't want to actually show a | |
| 334 // suggestion dialog, so we return "true," prentending we've done so. | |
|
Ilya Sherman
2013/12/27 23:17:09
nit: "prentending" -> "pretending"
Ilya Sherman
2013/12/27 23:17:09
nit: Please avoid the pronoun "we" in comments (ac
jww
2013/12/31 00:33:05
Done.
| |
| 335 if (!IsElementAutocompletable(element) || | |
| 336 !IsElementAutocompletable(iter->second.password_field)) | |
| 337 return true; | |
| 338 | |
| 328 return ShowSuggestionPopup(iter->second.fill_data, element); | 339 return ShowSuggestionPopup(iter->second.fill_data, element); |
| 329 } | 340 } |
| 330 | 341 |
| 331 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( | 342 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( |
| 332 const blink::WebSecurityOrigin& origin) { | 343 const blink::WebSecurityOrigin& origin) { |
| 333 return origin.canAccessPasswordManager(); | 344 return origin.canAccessPasswordManager(); |
| 334 } | 345 } |
| 335 | 346 |
| 336 void PasswordAutofillAgent::OnDynamicFormsSeen(blink::WebFrame* frame) { | 347 void PasswordAutofillAgent::OnDynamicFormsSeen(blink::WebFrame* frame) { |
| 337 SendPasswordForms(frame, false /* only_visible */); | 348 SendPasswordForms(frame, false /* only_visible */); |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 638 // Do not fill if the password field is in an iframe. | 649 // Do not fill if the password field is in an iframe. |
| 639 DCHECK(password_element.document().frame()); | 650 DCHECK(password_element.document().frame()); |
| 640 if (password_element.document().frame()->parent()) | 651 if (password_element.document().frame()->parent()) |
| 641 return; | 652 return; |
| 642 | 653 |
| 643 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && | 654 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && |
| 644 !username_element.form().autoComplete()) | 655 !username_element.form().autoComplete()) |
| 645 return; | 656 return; |
| 646 | 657 |
| 647 // If we can't modify the password, don't try to set the username | 658 // If we can't modify the password, don't try to set the username |
| 648 if (!IsElementEditable(password_element) || | 659 if (!IsElementAutocompletable(password_element)) |
| 649 (!ShouldIgnoreAutocompleteOffForPasswordFields() && | |
| 650 !password_element.autoComplete())) | |
| 651 return; | 660 return; |
| 652 | 661 |
| 653 // Try to set the username to the preferred name, but only if the field | 662 // Try to set the username to the preferred name, but only if the field |
| 654 // can be set and isn't prefilled. | 663 // can be set and isn't prefilled. |
| 655 if (IsElementEditable(username_element) && | 664 if (IsElementAutocompletable(username_element) && |
| 656 (ShouldIgnoreAutocompleteOffForPasswordFields() || | |
| 657 username_element.autoComplete()) && | |
| 658 username_element.value().isEmpty()) { | 665 username_element.value().isEmpty()) { |
| 659 // TODO(tkent): Check maxlength and pattern. | 666 // TODO(tkent): Check maxlength and pattern. |
| 660 username_element.setValue(fill_data.basic_data.fields[0].value); | 667 username_element.setValue(fill_data.basic_data.fields[0].value); |
| 661 } | 668 } |
| 662 | 669 |
| 663 // Fill if we have an exact match for the username. Note that this sets | 670 // Fill if we have an exact match for the username. Note that this sets |
| 664 // username to autofilled. | 671 // username to autofilled. |
| 665 FillUserNameAndPassword(&username_element, &password_element, fill_data, | 672 FillUserNameAndPassword(&username_element, &password_element, fill_data, |
| 666 true /* exact_username_match */, | 673 true /* exact_username_match */, |
| 667 false /* set_selection */); | 674 false /* set_selection */); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 715 } | 722 } |
| 716 } | 723 } |
| 717 } | 724 } |
| 718 if (password.empty()) | 725 if (password.empty()) |
| 719 return false; // No match was found. | 726 return false; // No match was found. |
| 720 | 727 |
| 721 // TODO(tkent): Check maxlength and pattern for both username and password | 728 // TODO(tkent): Check maxlength and pattern for both username and password |
| 722 // fields. | 729 // fields. |
| 723 | 730 |
| 724 // Don't fill username if password can't be set. | 731 // Don't fill username if password can't be set. |
| 725 if (!IsElementEditable(*password_element) || | 732 if (!IsElementAutocompletable(*password_element)) { |
| 726 (!ShouldIgnoreAutocompleteOffForPasswordFields() && | |
| 727 !password_element->autoComplete())) { | |
| 728 return false; | 733 return false; |
| 729 } | 734 } |
| 730 | 735 |
| 731 // Input matches the username, fill in required values. | 736 // Input matches the username, fill in required values. |
| 732 if (IsElementEditable(*username_element) && | 737 if (IsElementAutocompletable(*username_element)) { |
| 733 (ShouldIgnoreAutocompleteOffForPasswordFields() || | |
| 734 username_element->autoComplete())) { | |
| 735 username_element->setValue(username); | 738 username_element->setValue(username); |
| 736 SetElementAutofilled(username_element, true); | 739 SetElementAutofilled(username_element, true); |
| 737 | 740 |
| 738 if (set_selection) { | 741 if (set_selection) { |
| 739 username_element->setSelectionRange(current_username.length(), | 742 username_element->setSelectionRange(current_username.length(), |
| 740 username.length()); | 743 username.length()); |
| 741 } | 744 } |
| 742 } else if (current_username != username) { | 745 } else if (current_username != username) { |
| 743 // If the username can't be filled and it doesn't match a saved password | 746 // If the username can't be filled and it doesn't match a saved password |
| 744 // as is, don't autofill a password. | 747 // as is, don't autofill a password. |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 840 } | 843 } |
| 841 | 844 |
| 842 PasswordAutofillAgent::AutofillWebUserGestureHandler:: | 845 PasswordAutofillAgent::AutofillWebUserGestureHandler:: |
| 843 AutofillWebUserGestureHandler(PasswordAutofillAgent* agent) | 846 AutofillWebUserGestureHandler(PasswordAutofillAgent* agent) |
| 844 : agent_(agent) {} | 847 : agent_(agent) {} |
| 845 | 848 |
| 846 PasswordAutofillAgent::AutofillWebUserGestureHandler:: | 849 PasswordAutofillAgent::AutofillWebUserGestureHandler:: |
| 847 ~AutofillWebUserGestureHandler() {} | 850 ~AutofillWebUserGestureHandler() {} |
| 848 | 851 |
| 849 } // namespace autofill | 852 } // namespace autofill |
| OLD | NEW |