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 // Returns |true| if the given element is both editable and has permission to be |
| 186 // autocompleted. The latter can be either because there is no |
| 187 // autocomplete='off' set for the element, or because the flag is set to ignore |
| 188 // autocomplete='off'. Otherwise, returns |false|. |
| 189 bool IsElementAutocompletable(const blink::WebInputElement& element) { |
| 190 return IsElementEditable(element) && |
| 191 (ShouldIgnoreAutocompleteOffForPasswordFields() || |
| 192 element.autoComplete()); |
| 193 } |
| 194 |
184 } // namespace | 195 } // namespace |
185 | 196 |
186 //////////////////////////////////////////////////////////////////////////////// | 197 //////////////////////////////////////////////////////////////////////////////// |
187 // PasswordAutofillAgent, public: | 198 // PasswordAutofillAgent, public: |
188 | 199 |
189 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) | 200 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) |
190 : content::RenderViewObserver(render_view), | 201 : content::RenderViewObserver(render_view), |
191 usernames_usage_(NOTHING_TO_AUTOFILL), | 202 usernames_usage_(NOTHING_TO_AUTOFILL), |
192 web_view_(render_view->GetWebView()), | 203 web_view_(render_view->GetWebView()), |
193 gesture_handler_(new AutofillWebUserGestureHandler(this)), | 204 gesture_handler_(new AutofillWebUserGestureHandler(this)), |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 SetElementAutofilled(&username, false); | 254 SetElementAutofilled(&username, false); |
244 if (password.isAutofilled()) { | 255 if (password.isAutofilled()) { |
245 password.setValue(base::string16()); | 256 password.setValue(base::string16()); |
246 SetElementAutofilled(&password, false); | 257 SetElementAutofilled(&password, false); |
247 } | 258 } |
248 | 259 |
249 // If wait_for_username is true we will fill when the username loses focus. | 260 // If wait_for_username is true we will fill when the username loses focus. |
250 if (iter->second.fill_data.wait_for_username) | 261 if (iter->second.fill_data.wait_for_username) |
251 return false; | 262 return false; |
252 | 263 |
253 if (!IsElementEditable(element) || !element.isText() || | 264 if (!element.isText() || !IsElementAutocompletable(element) || |
254 (!ShouldIgnoreAutocompleteOffForPasswordFields() && | 265 !IsElementAutocompletable(password)) { |
255 !element.autoComplete())) { | |
256 return false; | 266 return false; |
257 } | 267 } |
258 | 268 |
259 // Don't inline autocomplete if the user is deleting, that would be confusing. | 269 // 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 | 270 // But refresh the popup. Note, since this is ours, return true to signal |
261 // no further processing is required. | 271 // no further processing is required. |
262 if (iter->second.backspace_pressed_last) { | 272 if (iter->second.backspace_pressed_last) { |
263 ShowSuggestionPopup(iter->second.fill_data, username); | 273 ShowSuggestionPopup(iter->second.fill_data, username); |
264 return true; | 274 return true; |
265 } | 275 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 return FindLoginInfo(node, &input, &password); | 328 return FindLoginInfo(node, &input, &password); |
319 } | 329 } |
320 | 330 |
321 bool PasswordAutofillAgent::ShowSuggestions( | 331 bool PasswordAutofillAgent::ShowSuggestions( |
322 const blink::WebInputElement& element) { | 332 const blink::WebInputElement& element) { |
323 LoginToPasswordInfoMap::const_iterator iter = | 333 LoginToPasswordInfoMap::const_iterator iter = |
324 login_to_password_info_.find(element); | 334 login_to_password_info_.find(element); |
325 if (iter == login_to_password_info_.end()) | 335 if (iter == login_to_password_info_.end()) |
326 return false; | 336 return false; |
327 | 337 |
| 338 // If autocomplete='off' is set on the form elements, no suggestion dialog |
| 339 // should be shown. However, return |true| to indicate that this is a known |
| 340 // password form and that the request to show suggestions has been handled (as |
| 341 // a no-op). |
| 342 if (!IsElementAutocompletable(element) || |
| 343 !IsElementAutocompletable(iter->second.password_field)) |
| 344 return true; |
| 345 |
328 return ShowSuggestionPopup(iter->second.fill_data, element); | 346 return ShowSuggestionPopup(iter->second.fill_data, element); |
329 } | 347 } |
330 | 348 |
331 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( | 349 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( |
332 const blink::WebSecurityOrigin& origin) { | 350 const blink::WebSecurityOrigin& origin) { |
333 return origin.canAccessPasswordManager(); | 351 return origin.canAccessPasswordManager(); |
334 } | 352 } |
335 | 353 |
336 void PasswordAutofillAgent::OnDynamicFormsSeen(blink::WebFrame* frame) { | 354 void PasswordAutofillAgent::OnDynamicFormsSeen(blink::WebFrame* frame) { |
337 SendPasswordForms(frame, false /* only_visible */); | 355 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. | 656 // Do not fill if the password field is in an iframe. |
639 DCHECK(password_element.document().frame()); | 657 DCHECK(password_element.document().frame()); |
640 if (password_element.document().frame()->parent()) | 658 if (password_element.document().frame()->parent()) |
641 return; | 659 return; |
642 | 660 |
643 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && | 661 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && |
644 !username_element.form().autoComplete()) | 662 !username_element.form().autoComplete()) |
645 return; | 663 return; |
646 | 664 |
647 // If we can't modify the password, don't try to set the username | 665 // If we can't modify the password, don't try to set the username |
648 if (!IsElementEditable(password_element) || | 666 if (!IsElementAutocompletable(password_element)) |
649 (!ShouldIgnoreAutocompleteOffForPasswordFields() && | |
650 !password_element.autoComplete())) | |
651 return; | 667 return; |
652 | 668 |
653 // Try to set the username to the preferred name, but only if the field | 669 // Try to set the username to the preferred name, but only if the field |
654 // can be set and isn't prefilled. | 670 // can be set and isn't prefilled. |
655 if (IsElementEditable(username_element) && | 671 if (IsElementAutocompletable(username_element) && |
656 (ShouldIgnoreAutocompleteOffForPasswordFields() || | |
657 username_element.autoComplete()) && | |
658 username_element.value().isEmpty()) { | 672 username_element.value().isEmpty()) { |
659 // TODO(tkent): Check maxlength and pattern. | 673 // TODO(tkent): Check maxlength and pattern. |
660 username_element.setValue(fill_data.basic_data.fields[0].value); | 674 username_element.setValue(fill_data.basic_data.fields[0].value); |
661 } | 675 } |
662 | 676 |
663 // Fill if we have an exact match for the username. Note that this sets | 677 // Fill if we have an exact match for the username. Note that this sets |
664 // username to autofilled. | 678 // username to autofilled. |
665 FillUserNameAndPassword(&username_element, &password_element, fill_data, | 679 FillUserNameAndPassword(&username_element, &password_element, fill_data, |
666 true /* exact_username_match */, | 680 true /* exact_username_match */, |
667 false /* set_selection */); | 681 false /* set_selection */); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 } | 729 } |
716 } | 730 } |
717 } | 731 } |
718 if (password.empty()) | 732 if (password.empty()) |
719 return false; // No match was found. | 733 return false; // No match was found. |
720 | 734 |
721 // TODO(tkent): Check maxlength and pattern for both username and password | 735 // TODO(tkent): Check maxlength and pattern for both username and password |
722 // fields. | 736 // fields. |
723 | 737 |
724 // Don't fill username if password can't be set. | 738 // Don't fill username if password can't be set. |
725 if (!IsElementEditable(*password_element) || | 739 if (!IsElementAutocompletable(*password_element)) { |
726 (!ShouldIgnoreAutocompleteOffForPasswordFields() && | |
727 !password_element->autoComplete())) { | |
728 return false; | 740 return false; |
729 } | 741 } |
730 | 742 |
731 // Input matches the username, fill in required values. | 743 // Input matches the username, fill in required values. |
732 if (IsElementEditable(*username_element) && | 744 if (IsElementAutocompletable(*username_element)) { |
733 (ShouldIgnoreAutocompleteOffForPasswordFields() || | |
734 username_element->autoComplete())) { | |
735 username_element->setValue(username); | 745 username_element->setValue(username); |
736 SetElementAutofilled(username_element, true); | 746 SetElementAutofilled(username_element, true); |
737 | 747 |
738 if (set_selection) { | 748 if (set_selection) { |
739 username_element->setSelectionRange(current_username.length(), | 749 username_element->setSelectionRange(current_username.length(), |
740 username.length()); | 750 username.length()); |
741 } | 751 } |
742 } else if (current_username != username) { | 752 } else if (current_username != username) { |
743 // If the username can't be filled and it doesn't match a saved password | 753 // If the username can't be filled and it doesn't match a saved password |
744 // as is, don't autofill a password. | 754 // as is, don't autofill a password. |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
840 } | 850 } |
841 | 851 |
842 PasswordAutofillAgent::AutofillWebUserGestureHandler:: | 852 PasswordAutofillAgent::AutofillWebUserGestureHandler:: |
843 AutofillWebUserGestureHandler(PasswordAutofillAgent* agent) | 853 AutofillWebUserGestureHandler(PasswordAutofillAgent* agent) |
844 : agent_(agent) {} | 854 : agent_(agent) {} |
845 | 855 |
846 PasswordAutofillAgent::AutofillWebUserGestureHandler:: | 856 PasswordAutofillAgent::AutofillWebUserGestureHandler:: |
847 ~AutofillWebUserGestureHandler() {} | 857 ~AutofillWebUserGestureHandler() {} |
848 | 858 |
849 } // namespace autofill | 859 } // namespace autofill |
OLD | NEW |