Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/renderer/autofill/autofill_agent.h" | 5 #include "chrome/renderer/autofill/autofill_agent.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "base/string_split.h" | 10 #include "base/string_split.h" |
| 11 #include "base/time.h" | 11 #include "base/time.h" |
| 12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
| 13 #include "chrome/common/autofill_messages.h" | 13 #include "chrome/common/autofill_messages.h" |
| 14 #include "chrome/common/chrome_constants.h" | 14 #include "chrome/common/chrome_constants.h" |
| 15 #include "chrome/common/form_data.h" | 15 #include "chrome/common/form_data.h" |
| 16 #include "chrome/common/form_data_predictions.h" | 16 #include "chrome/common/form_data_predictions.h" |
| 17 #include "chrome/common/form_field_data.h" | 17 #include "chrome/common/form_field_data.h" |
| 18 #include "chrome/renderer/autofill/form_autofill_util.h" | 18 #include "chrome/renderer/autofill/form_autofill_util.h" |
| 19 #include "chrome/renderer/autofill/password_autofill_manager.h" | 19 #include "chrome/renderer/autofill/password_autofill_manager.h" |
| 20 #include "content/public/common/password_form.h" | 20 #include "content/public/common/password_form.h" |
| 21 #include "content/public/renderer/render_view.h" | 21 #include "content/public/renderer/render_view.h" |
| 22 #include "grit/chromium_strings.h" | 22 #include "grit/chromium_strings.h" |
| 23 #include "grit/generated_resources.h" | 23 #include "grit/generated_resources.h" |
| 24 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h" | 24 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h" |
| 25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | 25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
| 26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement .h" | 26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement .h" |
| 27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormElement.h" | |
| 27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 28 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
| 28 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" | 29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" |
| 29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" | 30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" |
| 30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeCollection.h" | 31 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeCollection.h" |
| 31 #include "third_party/WebKit/Source/WebKit/chromium/public/WebOptionElement.h" | 32 #include "third_party/WebKit/Source/WebKit/chromium/public/WebOptionElement.h" |
| 32 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 33 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
| 33 #include "ui/base/keycodes/keyboard_codes.h" | 34 #include "ui/base/keycodes/keyboard_codes.h" |
| 34 #include "ui/base/l10n/l10n_util.h" | 35 #include "ui/base/l10n/l10n_util.h" |
| 35 | 36 |
| 36 using WebKit::WebAutofillClient; | 37 using WebKit::WebAutofillClient; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 123 content::RenderView* render_view, | 124 content::RenderView* render_view, |
| 124 PasswordAutofillManager* password_autofill_manager) | 125 PasswordAutofillManager* password_autofill_manager) |
| 125 : content::RenderViewObserver(render_view), | 126 : content::RenderViewObserver(render_view), |
| 126 password_autofill_manager_(password_autofill_manager), | 127 password_autofill_manager_(password_autofill_manager), |
| 127 autofill_query_id_(0), | 128 autofill_query_id_(0), |
| 128 autofill_action_(AUTOFILL_NONE), | 129 autofill_action_(AUTOFILL_NONE), |
| 129 display_warning_if_disabled_(false), | 130 display_warning_if_disabled_(false), |
| 130 was_query_node_autofilled_(false), | 131 was_query_node_autofilled_(false), |
| 131 has_shown_autofill_popup_for_current_edit_(false), | 132 has_shown_autofill_popup_for_current_edit_(false), |
| 132 did_set_node_text_(false), | 133 did_set_node_text_(false), |
| 134 has_requested_autocomplete_(false), | |
| 133 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | 135 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
| 134 render_view->GetWebView()->setAutofillClient(this); | 136 render_view->GetWebView()->setAutofillClient(this); |
| 135 } | 137 } |
| 136 | 138 |
| 137 AutofillAgent::~AutofillAgent() {} | 139 AutofillAgent::~AutofillAgent() {} |
| 138 | 140 |
| 139 bool AutofillAgent::OnMessageReceived(const IPC::Message& message) { | 141 bool AutofillAgent::OnMessageReceived(const IPC::Message& message) { |
| 140 bool handled = true; | 142 bool handled = true; |
| 141 IPC_BEGIN_MESSAGE_MAP(AutofillAgent, message) | 143 IPC_BEGIN_MESSAGE_MAP(AutofillAgent, message) |
| 142 IPC_MESSAGE_HANDLER(AutofillMsg_SuggestionsReturned, OnSuggestionsReturned) | 144 IPC_MESSAGE_HANDLER(AutofillMsg_SuggestionsReturned, OnSuggestionsReturned) |
| 143 IPC_MESSAGE_HANDLER(AutofillMsg_FormDataFilled, OnFormDataFilled) | 145 IPC_MESSAGE_HANDLER(AutofillMsg_FormDataFilled, OnFormDataFilled) |
| 144 IPC_MESSAGE_HANDLER(AutofillMsg_FieldTypePredictionsAvailable, | 146 IPC_MESSAGE_HANDLER(AutofillMsg_FieldTypePredictionsAvailable, |
| 145 OnFieldTypePredictionsAvailable) | 147 OnFieldTypePredictionsAvailable) |
| 146 IPC_MESSAGE_HANDLER(AutofillMsg_SetAutofillActionFill, | 148 IPC_MESSAGE_HANDLER(AutofillMsg_SetAutofillActionFill, |
| 147 OnSetAutofillActionFill) | 149 OnSetAutofillActionFill) |
| 148 IPC_MESSAGE_HANDLER(AutofillMsg_ClearForm, | 150 IPC_MESSAGE_HANDLER(AutofillMsg_ClearForm, |
| 149 OnClearForm) | 151 OnClearForm) |
| 150 IPC_MESSAGE_HANDLER(AutofillMsg_SetAutofillActionPreview, | 152 IPC_MESSAGE_HANDLER(AutofillMsg_SetAutofillActionPreview, |
| 151 OnSetAutofillActionPreview) | 153 OnSetAutofillActionPreview) |
| 152 IPC_MESSAGE_HANDLER(AutofillMsg_ClearPreviewedForm, | 154 IPC_MESSAGE_HANDLER(AutofillMsg_ClearPreviewedForm, |
| 153 OnClearPreviewedForm) | 155 OnClearPreviewedForm) |
| 154 IPC_MESSAGE_HANDLER(AutofillMsg_SetNodeText, | 156 IPC_MESSAGE_HANDLER(AutofillMsg_SetNodeText, |
| 155 OnSetNodeText) | 157 OnSetNodeText) |
| 156 IPC_MESSAGE_HANDLER(AutofillMsg_AcceptDataListSuggestion, | 158 IPC_MESSAGE_HANDLER(AutofillMsg_AcceptDataListSuggestion, |
| 157 OnAcceptDataListSuggestion) | 159 OnAcceptDataListSuggestion) |
| 158 IPC_MESSAGE_HANDLER(AutofillMsg_AcceptPasswordAutofillSuggestion, | 160 IPC_MESSAGE_HANDLER(AutofillMsg_AcceptPasswordAutofillSuggestion, |
| 159 OnAcceptPasswordAutofillSuggestion) | 161 OnAcceptPasswordAutofillSuggestion) |
| 162 IPC_MESSAGE_HANDLER(AutofillMsg_RequestAutocompleteFinished, | |
| 163 OnRequestAutocompleteFinished) | |
| 160 IPC_MESSAGE_UNHANDLED(handled = false) | 164 IPC_MESSAGE_UNHANDLED(handled = false) |
| 161 IPC_END_MESSAGE_MAP() | 165 IPC_END_MESSAGE_MAP() |
| 162 return handled; | 166 return handled; |
| 163 } | 167 } |
| 164 | 168 |
| 165 void AutofillAgent::DidFinishDocumentLoad(WebFrame* frame) { | 169 void AutofillAgent::DidFinishDocumentLoad(WebFrame* frame) { |
| 166 // The document has now been fully loaded. Scan for forms to be sent up to | 170 // The document has now been fully loaded. Scan for forms to be sent up to |
| 167 // the browser. | 171 // the browser. |
| 168 std::vector<FormData> forms; | 172 std::vector<FormData> forms; |
| 169 form_cache_.ExtractForms(*frame, &forms); | 173 form_cache_.ExtractForms(*frame, &forms); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 204 Send(new AutofillHostMsg_HideAutofillPopup(routing_id())); | 208 Send(new AutofillHostMsg_HideAutofillPopup(routing_id())); |
| 205 } | 209 } |
| 206 | 210 |
| 207 void AutofillAgent::DidChangeScrollOffset(WebKit::WebFrame*) { | 211 void AutofillAgent::DidChangeScrollOffset(WebKit::WebFrame*) { |
| 208 // Any time the scroll offset changes, the page's content moves, so Autofill | 212 // Any time the scroll offset changes, the page's content moves, so Autofill |
| 209 // popups should be hidden. This is only needed for the new Autofill UI | 213 // popups should be hidden. This is only needed for the new Autofill UI |
| 210 // because WebKit already knows to hide the old UI when this occurs. | 214 // because WebKit already knows to hide the old UI when this occurs. |
| 211 Send(new AutofillHostMsg_HideAutofillPopup(routing_id())); | 215 Send(new AutofillHostMsg_HideAutofillPopup(routing_id())); |
| 212 } | 216 } |
| 213 | 217 |
| 218 void AutofillAgent::didRequestAutocomplete(WebKit::WebFrame* frame, | |
| 219 const WebFormElement& form) { | |
| 220 if (has_requested_autocomplete_) | |
| 221 return; | |
| 222 | |
| 223 // Cancel any pending autofill requests. | |
|
Ilya Sherman
2012/10/29 21:27:47
nit: "autofill" -> "Autofill"
Dan Beam
2012/10/29 23:08:24
D'oh, sorry, done.
| |
| 224 ++autofill_query_id_; | |
| 225 | |
| 226 // Any popup currently showing is obsolete. | |
| 227 HidePopups(); | |
| 228 | |
| 229 FormData form_data; | |
| 230 if (WebFormElementToFormData(form, | |
| 231 WebFormControlElement(), | |
| 232 REQUIRE_AUTOCOMPLETE, | |
| 233 EXTRACT_NONE, | |
| 234 &form_data, | |
| 235 NULL)) { | |
| 236 form_ = form; | |
| 237 has_requested_autocomplete_ = true; | |
| 238 Send(new AutofillHostMsg_RequestAutocomplete(routing_id(), form_data)); | |
| 239 } | |
| 240 } | |
| 241 | |
| 214 bool AutofillAgent::InputElementClicked(const WebInputElement& element, | 242 bool AutofillAgent::InputElementClicked(const WebInputElement& element, |
| 215 bool was_focused, | 243 bool was_focused, |
| 216 bool is_focused) { | 244 bool is_focused) { |
| 217 if (was_focused) | 245 if (was_focused) |
| 218 ShowSuggestions(element, true, false, true); | 246 ShowSuggestions(element, true, false, true); |
| 219 | 247 |
| 220 return false; | 248 return false; |
| 221 } | 249 } |
| 222 | 250 |
| 223 bool AutofillAgent::InputElementLostFocus() { | 251 bool AutofillAgent::InputElementLostFocus() { |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 567 void AutofillAgent::OnAcceptPasswordAutofillSuggestion(const string16& value) { | 595 void AutofillAgent::OnAcceptPasswordAutofillSuggestion(const string16& value) { |
| 568 // We need to make sure this is handled here because the browser process | 596 // We need to make sure this is handled here because the browser process |
| 569 // skipped it handling because it believed it would be handled here. If it | 597 // skipped it handling because it believed it would be handled here. If it |
| 570 // isn't handled here then the browser logic needs to be updated. | 598 // isn't handled here then the browser logic needs to be updated. |
| 571 bool handled = password_autofill_manager_->DidAcceptAutofillSuggestion( | 599 bool handled = password_autofill_manager_->DidAcceptAutofillSuggestion( |
| 572 element_, | 600 element_, |
| 573 value); | 601 value); |
| 574 DCHECK(handled); | 602 DCHECK(handled); |
| 575 } | 603 } |
| 576 | 604 |
| 605 void AutofillAgent::OnRequestAutocompleteFinished(int result) { | |
| 606 if (!has_requested_autocomplete_) | |
| 607 return; | |
|
Ilya Sherman
2012/10/29 21:27:47
nit: Can this be a DCHECK instead?
Dan Beam
2012/10/29 23:08:24
Done.
| |
| 608 | |
| 609 has_requested_autocomplete_ = false; | |
| 610 | |
| 611 if (result == WebFormElement::AutocompleteSuccess || | |
| 612 result == WebFormElement::AutocompleteError) { | |
| 613 form_.finishRequestAutocomplete( | |
| 614 static_cast<WebFormElement::AutocompleteResult>(result)); | |
| 615 } else { | |
| 616 NOTREACHED(); | |
| 617 } | |
|
Ilya Sherman
2012/10/29 21:27:47
Optional nit: Maybe write this as a DCHECK() + rem
Dan Beam
2012/10/29 23:08:24
Done.
| |
| 618 } | |
| 619 | |
| 577 void AutofillAgent::ShowSuggestions(const WebInputElement& element, | 620 void AutofillAgent::ShowSuggestions(const WebInputElement& element, |
| 578 bool autofill_on_empty_values, | 621 bool autofill_on_empty_values, |
| 579 bool requires_caret_at_end, | 622 bool requires_caret_at_end, |
| 580 bool display_warning_if_disabled) { | 623 bool display_warning_if_disabled) { |
| 581 if (!element.isEnabled() || element.isReadOnly() || !element.isTextField() || | 624 if (!element.isEnabled() || element.isReadOnly() || !element.isTextField() || |
| 582 element.isPasswordField() || !element.suggestedValue().isEmpty()) | 625 element.isPasswordField() || !element.suggestedValue().isEmpty()) |
| 583 return; | 626 return; |
| 584 | 627 |
| 585 // Don't attempt to autofill with values that are too large or if filling | 628 // Don't attempt to autofill with values that are too large or if filling |
| 586 // criteria are not met. | 629 // criteria are not met. |
| 587 WebString value = element.editingValue(); | 630 WebString value = element.editingValue(); |
| 588 if (value.length() > kMaximumTextSizeForAutofill || | 631 if (value.length() > kMaximumTextSizeForAutofill || |
| 589 (!autofill_on_empty_values && value.isEmpty()) || | 632 (!autofill_on_empty_values && value.isEmpty()) || |
| 590 (requires_caret_at_end && | 633 (requires_caret_at_end && |
| 591 (element.selectionStart() != element.selectionEnd() || | 634 (element.selectionStart() != element.selectionEnd() || |
| 592 element.selectionEnd() != static_cast<int>(value.length())))) { | 635 element.selectionEnd() != static_cast<int>(value.length())))) { |
| 593 // Any popup currently showing is obsolete. | 636 // Any popup currently showing is obsolete. |
| 594 WebKit::WebView* web_view = render_view()->GetWebView(); | 637 HidePopups(); |
| 595 if (web_view) | |
| 596 web_view->hidePopups(); | |
| 597 | |
| 598 return; | 638 return; |
| 599 } | 639 } |
| 600 | 640 |
| 601 element_ = element; | 641 element_ = element; |
| 602 | 642 |
| 603 // If autocomplete is disabled at the form level, then we might want to show | 643 // If autocomplete is disabled at the form level, then we might want to show |
| 604 // a warning in place of suggestions. However, if autocomplete is disabled | 644 // a warning in place of suggestions. However, if autocomplete is disabled |
| 605 // specifically for this field, we never want to show a warning. Otherwise, | 645 // specifically for this field, we never want to show a warning. Otherwise, |
| 606 // we might interfere with custom popups (e.g. search suggestions) used by | 646 // we might interfere with custom popups (e.g. search suggestions) used by |
| 607 // the website. Also, if the field has no name, then we won't have values. | 647 // the website. Also, if the field has no name, then we won't have values. |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 687 | 727 |
| 688 void AutofillAgent::SetNodeText(const string16& value, | 728 void AutofillAgent::SetNodeText(const string16& value, |
| 689 WebKit::WebInputElement* node) { | 729 WebKit::WebInputElement* node) { |
| 690 did_set_node_text_ = true; | 730 did_set_node_text_ = true; |
| 691 string16 substring = value; | 731 string16 substring = value; |
| 692 substring = substring.substr(0, node->maxLength()); | 732 substring = substring.substr(0, node->maxLength()); |
| 693 | 733 |
| 694 node->setEditingValue(substring); | 734 node->setEditingValue(substring); |
| 695 } | 735 } |
| 696 | 736 |
| 737 void AutofillAgent::HidePopups() { | |
| 738 WebKit::WebView* web_view = render_view()->GetWebView(); | |
| 739 if (web_view) | |
| 740 web_view->hidePopups(); | |
| 741 } | |
| 742 | |
| 697 } // namespace autofill | 743 } // namespace autofill |
| OLD | NEW |