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" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 namespace { | 47 namespace { |
48 | 48 |
49 // The size above which we stop triggering autofill for an input text field | 49 // The size above which we stop triggering autofill for an input text field |
50 // (so to avoid sending long strings through IPC). | 50 // (so to avoid sending long strings through IPC). |
51 const size_t kMaximumTextSizeForAutofill = 1000; | 51 const size_t kMaximumTextSizeForAutofill = 1000; |
52 | 52 |
53 // The maximum number of data list elements to send to the browser process | 53 // The maximum number of data list elements to send to the browser process |
54 // via IPC (to prevent long IPC messages). | 54 // via IPC (to prevent long IPC messages). |
55 const size_t kMaximumDataListSizeForAutofill = 30; | 55 const size_t kMaximumDataListSizeForAutofill = 30; |
56 | 56 |
| 57 // A query counter for requests to show an interactive autocomplete UI. |
| 58 int request_autocomplete_query_id_ = 0; |
| 59 |
57 void AppendDataListSuggestions(const WebKit::WebInputElement& element, | 60 void AppendDataListSuggestions(const WebKit::WebInputElement& element, |
58 std::vector<string16>* values, | 61 std::vector<string16>* values, |
59 std::vector<string16>* labels, | 62 std::vector<string16>* labels, |
60 std::vector<string16>* icons, | 63 std::vector<string16>* icons, |
61 std::vector<int>* item_ids) { | 64 std::vector<int>* item_ids) { |
62 WebNodeCollection options = element.dataListOptions(); | 65 WebNodeCollection options = element.dataListOptions(); |
63 if (options.isNull()) | 66 if (options.isNull()) |
64 return; | 67 return; |
65 | 68 |
66 string16 prefix = element.editingValue(); | 69 string16 prefix = element.editingValue(); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 IPC_MESSAGE_HANDLER(AutofillMsg_SetAutofillActionPreview, | 155 IPC_MESSAGE_HANDLER(AutofillMsg_SetAutofillActionPreview, |
153 OnSetAutofillActionPreview) | 156 OnSetAutofillActionPreview) |
154 IPC_MESSAGE_HANDLER(AutofillMsg_ClearPreviewedForm, | 157 IPC_MESSAGE_HANDLER(AutofillMsg_ClearPreviewedForm, |
155 OnClearPreviewedForm) | 158 OnClearPreviewedForm) |
156 IPC_MESSAGE_HANDLER(AutofillMsg_SetNodeText, | 159 IPC_MESSAGE_HANDLER(AutofillMsg_SetNodeText, |
157 OnSetNodeText) | 160 OnSetNodeText) |
158 IPC_MESSAGE_HANDLER(AutofillMsg_AcceptDataListSuggestion, | 161 IPC_MESSAGE_HANDLER(AutofillMsg_AcceptDataListSuggestion, |
159 OnAcceptDataListSuggestion) | 162 OnAcceptDataListSuggestion) |
160 IPC_MESSAGE_HANDLER(AutofillMsg_AcceptPasswordAutofillSuggestion, | 163 IPC_MESSAGE_HANDLER(AutofillMsg_AcceptPasswordAutofillSuggestion, |
161 OnAcceptPasswordAutofillSuggestion) | 164 OnAcceptPasswordAutofillSuggestion) |
| 165 IPC_MESSAGE_HANDLER(AutofillMsg_RequestAutocompleteFinished, |
| 166 OnRequestAutocompleteFinished) |
162 IPC_MESSAGE_UNHANDLED(handled = false) | 167 IPC_MESSAGE_UNHANDLED(handled = false) |
163 IPC_END_MESSAGE_MAP() | 168 IPC_END_MESSAGE_MAP() |
164 return handled; | 169 return handled; |
165 } | 170 } |
166 | 171 |
167 void AutofillAgent::DidFinishDocumentLoad(WebFrame* frame) { | 172 void AutofillAgent::DidFinishDocumentLoad(WebFrame* frame) { |
168 // The document has now been fully loaded. Scan for forms to be sent up to | 173 // The document has now been fully loaded. Scan for forms to be sent up to |
169 // the browser. | 174 // the browser. |
170 std::vector<FormData> forms; | 175 std::vector<FormData> forms; |
171 form_cache_.ExtractForms(*frame, &forms); | 176 form_cache_.ExtractForms(*frame, &forms); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 Send(new AutofillHostMsg_HideAutofillPopup(routing_id())); | 211 Send(new AutofillHostMsg_HideAutofillPopup(routing_id())); |
207 } | 212 } |
208 | 213 |
209 void AutofillAgent::DidChangeScrollOffset(WebKit::WebFrame*) { | 214 void AutofillAgent::DidChangeScrollOffset(WebKit::WebFrame*) { |
210 // Any time the scroll offset changes, the page's content moves, so Autofill | 215 // Any time the scroll offset changes, the page's content moves, so Autofill |
211 // popups should be hidden. This is only needed for the new Autofill UI | 216 // popups should be hidden. This is only needed for the new Autofill UI |
212 // because WebKit already knows to hide the old UI when this occurs. | 217 // because WebKit already knows to hide the old UI when this occurs. |
213 Send(new AutofillHostMsg_HideAutofillPopup(routing_id())); | 218 Send(new AutofillHostMsg_HideAutofillPopup(routing_id())); |
214 } | 219 } |
215 | 220 |
| 221 void AutofillAgent::RequestAutocomplete(WebKit::WebFrame* frame, |
| 222 const WebFormElement& form) { |
| 223 request_autocomplete_query_id_ += 1; |
| 224 |
| 225 // Cancel any pending autofill requests. |
| 226 autofill_query_id_ += 1; |
| 227 |
| 228 // Any popup currently showing is obsolete. |
| 229 HidePopups(); |
| 230 |
| 231 FormData form_data; |
| 232 if (WebFormElementToFormData(form, |
| 233 WebFormControlElement(), |
| 234 REQUIRE_AUTOCOMPLETE, |
| 235 EXTRACT_NONE, |
| 236 &form_data, |
| 237 NULL)) { |
| 238 form_ = form; |
| 239 Send(new AutofillHostMsg_RequestAutocomplete( |
| 240 routing_id(), request_autocomplete_query_id_, form_data)); |
| 241 } |
| 242 } |
| 243 |
216 bool AutofillAgent::InputElementClicked(const WebInputElement& element, | 244 bool AutofillAgent::InputElementClicked(const WebInputElement& element, |
217 bool was_focused, | 245 bool was_focused, |
218 bool is_focused) { | 246 bool is_focused) { |
219 if (was_focused) | 247 if (was_focused) |
220 ShowSuggestions(element, true, false, true); | 248 ShowSuggestions(element, true, false, true); |
221 | 249 |
222 return false; | 250 return false; |
223 } | 251 } |
224 | 252 |
225 bool AutofillAgent::InputElementLostFocus() { | 253 bool AutofillAgent::InputElementLostFocus() { |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 void AutofillAgent::OnAcceptPasswordAutofillSuggestion(const string16& value) { | 603 void AutofillAgent::OnAcceptPasswordAutofillSuggestion(const string16& value) { |
576 // We need to make sure this is handled here because the browser process | 604 // We need to make sure this is handled here because the browser process |
577 // skipped it handling because it believed it would be handled here. If it | 605 // skipped it handling because it believed it would be handled here. If it |
578 // isn't handled here then the browser logic needs to be updated. | 606 // isn't handled here then the browser logic needs to be updated. |
579 bool handled = password_autofill_manager_->DidAcceptAutofillSuggestion( | 607 bool handled = password_autofill_manager_->DidAcceptAutofillSuggestion( |
580 element_, | 608 element_, |
581 value); | 609 value); |
582 DCHECK(handled); | 610 DCHECK(handled); |
583 } | 611 } |
584 | 612 |
| 613 void AutofillAgent::OnRequestAutocompleteFinished(int query_id, bool success) { |
| 614 DCHECK_GT(query_id, 0); |
| 615 if (query_id == request_autocomplete_query_id_) |
| 616 form_.dispatchAutocompleteEvent(success); |
| 617 } |
| 618 |
585 void AutofillAgent::ShowSuggestions(const WebInputElement& element, | 619 void AutofillAgent::ShowSuggestions(const WebInputElement& element, |
586 bool autofill_on_empty_values, | 620 bool autofill_on_empty_values, |
587 bool requires_caret_at_end, | 621 bool requires_caret_at_end, |
588 bool display_warning_if_disabled) { | 622 bool display_warning_if_disabled) { |
589 if (!element.isEnabled() || element.isReadOnly() || !element.isTextField() || | 623 if (!element.isEnabled() || element.isReadOnly() || !element.isTextField() || |
590 element.isPasswordField() || !element.suggestedValue().isEmpty()) | 624 element.isPasswordField() || !element.suggestedValue().isEmpty()) |
591 return; | 625 return; |
592 | 626 |
593 // Don't attempt to autofill with values that are too large or if filling | 627 // Don't attempt to autofill with values that are too large or if filling |
594 // criteria are not met. | 628 // criteria are not met. |
595 WebString value = element.editingValue(); | 629 WebString value = element.editingValue(); |
596 if (value.length() > kMaximumTextSizeForAutofill || | 630 if (value.length() > kMaximumTextSizeForAutofill || |
597 (!autofill_on_empty_values && value.isEmpty()) || | 631 (!autofill_on_empty_values && value.isEmpty()) || |
598 (requires_caret_at_end && | 632 (requires_caret_at_end && |
599 (element.selectionStart() != element.selectionEnd() || | 633 (element.selectionStart() != element.selectionEnd() || |
600 element.selectionEnd() != static_cast<int>(value.length())))) { | 634 element.selectionEnd() != static_cast<int>(value.length())))) { |
601 // Any popup currently showing is obsolete. | 635 // Any popup currently showing is obsolete. |
602 WebKit::WebView* web_view = render_view()->GetWebView(); | 636 HidePopups(); |
603 if (web_view) | |
604 web_view->hidePopups(); | |
605 | |
606 return; | 637 return; |
607 } | 638 } |
608 | 639 |
609 element_ = element; | 640 element_ = element; |
610 | 641 |
611 // If autocomplete is disabled at the form level, then we might want to show | 642 // If autocomplete is disabled at the form level, then we might want to show |
612 // a warning in place of suggestions. However, if autocomplete is disabled | 643 // a warning in place of suggestions. However, if autocomplete is disabled |
613 // specifically for this field, we never want to show a warning. Otherwise, | 644 // specifically for this field, we never want to show a warning. Otherwise, |
614 // we might interfere with custom popups (e.g. search suggestions) used by | 645 // we might interfere with custom popups (e.g. search suggestions) used by |
615 // the website. Also, if the field has no name, then we won't have values. | 646 // 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... |
695 | 726 |
696 void AutofillAgent::SetNodeText(const string16& value, | 727 void AutofillAgent::SetNodeText(const string16& value, |
697 WebKit::WebInputElement* node) { | 728 WebKit::WebInputElement* node) { |
698 did_set_node_text_ = true; | 729 did_set_node_text_ = true; |
699 string16 substring = value; | 730 string16 substring = value; |
700 substring = substring.substr(0, node->maxLength()); | 731 substring = substring.substr(0, node->maxLength()); |
701 | 732 |
702 node->setEditingValue(substring); | 733 node->setEditingValue(substring); |
703 } | 734 } |
704 | 735 |
| 736 void AutofillAgent::HidePopups() { |
| 737 WebKit::WebView* web_view = render_view()->GetWebView(); |
| 738 if (web_view) |
| 739 web_view->hidePopups(); |
| 740 } |
| 741 |
| 742 |
705 } // namespace autofill | 743 } // namespace autofill |
OLD | NEW |