Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(183)

Side by Side Diff: chrome/renderer/autofill/autofill_agent.cc

Issue 11270018: [autofill] Adding new API to request an interactive autocomplete UI flow. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: newest Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 10 matching lines...) Expand all
47 namespace { 48 namespace {
48 49
49 // The size above which we stop triggering autofill for an input text field 50 // The size above which we stop triggering autofill for an input text field
50 // (so to avoid sending long strings through IPC). 51 // (so to avoid sending long strings through IPC).
51 const size_t kMaximumTextSizeForAutofill = 1000; 52 const size_t kMaximumTextSizeForAutofill = 1000;
52 53
53 // The maximum number of data list elements to send to the browser process 54 // The maximum number of data list elements to send to the browser process
54 // via IPC (to prevent long IPC messages). 55 // via IPC (to prevent long IPC messages).
55 const size_t kMaximumDataListSizeForAutofill = 30; 56 const size_t kMaximumDataListSizeForAutofill = 30;
56 57
58 // A query counter for requests to show an interactive autocomplete UI.
59 int request_autocomplete_query_id_ = 0;
Ilya Sherman 2012/10/27 07:44:11 This should be a private member of the class. Als
Dan Beam 2012/10/29 19:17:05 I don't think this is relevant any more.
60
57 void AppendDataListSuggestions(const WebKit::WebInputElement& element, 61 void AppendDataListSuggestions(const WebKit::WebInputElement& element,
58 std::vector<string16>* values, 62 std::vector<string16>* values,
59 std::vector<string16>* labels, 63 std::vector<string16>* labels,
60 std::vector<string16>* icons, 64 std::vector<string16>* icons,
61 std::vector<int>* item_ids) { 65 std::vector<int>* item_ids) {
62 WebNodeCollection options = element.dataListOptions(); 66 WebNodeCollection options = element.dataListOptions();
63 if (options.isNull()) 67 if (options.isNull())
64 return; 68 return;
65 69
66 string16 prefix = element.editingValue(); 70 string16 prefix = element.editingValue();
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 IPC_MESSAGE_HANDLER(AutofillMsg_SetAutofillActionPreview, 156 IPC_MESSAGE_HANDLER(AutofillMsg_SetAutofillActionPreview,
153 OnSetAutofillActionPreview) 157 OnSetAutofillActionPreview)
154 IPC_MESSAGE_HANDLER(AutofillMsg_ClearPreviewedForm, 158 IPC_MESSAGE_HANDLER(AutofillMsg_ClearPreviewedForm,
155 OnClearPreviewedForm) 159 OnClearPreviewedForm)
156 IPC_MESSAGE_HANDLER(AutofillMsg_SetNodeText, 160 IPC_MESSAGE_HANDLER(AutofillMsg_SetNodeText,
157 OnSetNodeText) 161 OnSetNodeText)
158 IPC_MESSAGE_HANDLER(AutofillMsg_AcceptDataListSuggestion, 162 IPC_MESSAGE_HANDLER(AutofillMsg_AcceptDataListSuggestion,
159 OnAcceptDataListSuggestion) 163 OnAcceptDataListSuggestion)
160 IPC_MESSAGE_HANDLER(AutofillMsg_AcceptPasswordAutofillSuggestion, 164 IPC_MESSAGE_HANDLER(AutofillMsg_AcceptPasswordAutofillSuggestion,
161 OnAcceptPasswordAutofillSuggestion) 165 OnAcceptPasswordAutofillSuggestion)
166 IPC_MESSAGE_HANDLER(AutofillMsg_RequestAutocompleteFinished,
167 OnRequestAutocompleteFinished)
162 IPC_MESSAGE_UNHANDLED(handled = false) 168 IPC_MESSAGE_UNHANDLED(handled = false)
163 IPC_END_MESSAGE_MAP() 169 IPC_END_MESSAGE_MAP()
164 return handled; 170 return handled;
165 } 171 }
166 172
167 void AutofillAgent::DidFinishDocumentLoad(WebFrame* frame) { 173 void AutofillAgent::DidFinishDocumentLoad(WebFrame* frame) {
168 // The document has now been fully loaded. Scan for forms to be sent up to 174 // The document has now been fully loaded. Scan for forms to be sent up to
169 // the browser. 175 // the browser.
170 std::vector<FormData> forms; 176 std::vector<FormData> forms;
171 form_cache_.ExtractForms(*frame, &forms); 177 form_cache_.ExtractForms(*frame, &forms);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 Send(new AutofillHostMsg_HideAutofillPopup(routing_id())); 212 Send(new AutofillHostMsg_HideAutofillPopup(routing_id()));
207 } 213 }
208 214
209 void AutofillAgent::DidChangeScrollOffset(WebKit::WebFrame*) { 215 void AutofillAgent::DidChangeScrollOffset(WebKit::WebFrame*) {
210 // Any time the scroll offset changes, the page's content moves, so Autofill 216 // 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 217 // 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. 218 // because WebKit already knows to hide the old UI when this occurs.
213 Send(new AutofillHostMsg_HideAutofillPopup(routing_id())); 219 Send(new AutofillHostMsg_HideAutofillPopup(routing_id()));
214 } 220 }
215 221
222 void AutofillAgent::didRequestAutocomplete(WebKit::WebFrame* frame,
223 const WebFormElement& form) {
224 request_autocomplete_query_id_ += 1;
Evan Stade 2012/10/29 17:54:28 ++
Dan Beam 2012/10/29 19:17:05 Done.
225
226 // Cancel any pending autofill requests.
227 autofill_query_id_ += 1;
228
229 // Any popup currently showing is obsolete.
230 HidePopups();
231
232 FormData form_data;
233 if (WebFormElementToFormData(form,
234 WebFormControlElement(),
235 REQUIRE_AUTOCOMPLETE,
236 EXTRACT_NONE,
237 &form_data,
238 NULL)) {
239 form_ = form;
240 Send(new AutofillHostMsg_RequestAutocomplete(
241 routing_id(), request_autocomplete_query_id_, form_data));
242 }
243 }
244
216 bool AutofillAgent::InputElementClicked(const WebInputElement& element, 245 bool AutofillAgent::InputElementClicked(const WebInputElement& element,
217 bool was_focused, 246 bool was_focused,
218 bool is_focused) { 247 bool is_focused) {
219 if (was_focused) 248 if (was_focused)
220 ShowSuggestions(element, true, false, true); 249 ShowSuggestions(element, true, false, true);
221 250
222 return false; 251 return false;
223 } 252 }
224 253
225 bool AutofillAgent::InputElementLostFocus() { 254 bool AutofillAgent::InputElementLostFocus() {
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 void AutofillAgent::OnAcceptPasswordAutofillSuggestion(const string16& value) { 604 void AutofillAgent::OnAcceptPasswordAutofillSuggestion(const string16& value) {
576 // We need to make sure this is handled here because the browser process 605 // 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 606 // 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. 607 // isn't handled here then the browser logic needs to be updated.
579 bool handled = password_autofill_manager_->DidAcceptAutofillSuggestion( 608 bool handled = password_autofill_manager_->DidAcceptAutofillSuggestion(
580 element_, 609 element_,
581 value); 610 value);
582 DCHECK(handled); 611 DCHECK(handled);
583 } 612 }
584 613
614 void AutofillAgent::OnRequestAutocompleteFinished(int query_id, int result) {
615 DCHECK_GT(query_id, 0);
616 if (query_id != request_autocomplete_query_id_)
617 return;
618
619 if (result == WebFormElement::AutocompleteSuccess ||
620 result == WebFormElement::AutocompleteError) {
621 form_.finishRequestAutocomplete(
622 static_cast<WebFormElement::AutocompleteResult>(result));
623 } else {
624 NOTREACHED() << "Unknown autocomplete result.";
Ilya Sherman 2012/10/27 07:44:11 nit: Please remove the logged text; you can add it
Dan Beam 2012/10/29 19:17:05 Done.
625 }
626 }
627
585 void AutofillAgent::ShowSuggestions(const WebInputElement& element, 628 void AutofillAgent::ShowSuggestions(const WebInputElement& element,
586 bool autofill_on_empty_values, 629 bool autofill_on_empty_values,
587 bool requires_caret_at_end, 630 bool requires_caret_at_end,
588 bool display_warning_if_disabled) { 631 bool display_warning_if_disabled) {
589 if (!element.isEnabled() || element.isReadOnly() || !element.isTextField() || 632 if (!element.isEnabled() || element.isReadOnly() || !element.isTextField() ||
590 element.isPasswordField() || !element.suggestedValue().isEmpty()) 633 element.isPasswordField() || !element.suggestedValue().isEmpty())
591 return; 634 return;
592 635
593 // Don't attempt to autofill with values that are too large or if filling 636 // Don't attempt to autofill with values that are too large or if filling
594 // criteria are not met. 637 // criteria are not met.
595 WebString value = element.editingValue(); 638 WebString value = element.editingValue();
596 if (value.length() > kMaximumTextSizeForAutofill || 639 if (value.length() > kMaximumTextSizeForAutofill ||
597 (!autofill_on_empty_values && value.isEmpty()) || 640 (!autofill_on_empty_values && value.isEmpty()) ||
598 (requires_caret_at_end && 641 (requires_caret_at_end &&
599 (element.selectionStart() != element.selectionEnd() || 642 (element.selectionStart() != element.selectionEnd() ||
600 element.selectionEnd() != static_cast<int>(value.length())))) { 643 element.selectionEnd() != static_cast<int>(value.length())))) {
601 // Any popup currently showing is obsolete. 644 // Any popup currently showing is obsolete.
602 WebKit::WebView* web_view = render_view()->GetWebView(); 645 HidePopups();
603 if (web_view)
604 web_view->hidePopups();
605
606 return; 646 return;
607 } 647 }
608 648
609 element_ = element; 649 element_ = element;
610 650
611 // If autocomplete is disabled at the form level, then we might want to show 651 // 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 652 // a warning in place of suggestions. However, if autocomplete is disabled
613 // specifically for this field, we never want to show a warning. Otherwise, 653 // 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 654 // 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. 655 // 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
695 735
696 void AutofillAgent::SetNodeText(const string16& value, 736 void AutofillAgent::SetNodeText(const string16& value,
697 WebKit::WebInputElement* node) { 737 WebKit::WebInputElement* node) {
698 did_set_node_text_ = true; 738 did_set_node_text_ = true;
699 string16 substring = value; 739 string16 substring = value;
700 substring = substring.substr(0, node->maxLength()); 740 substring = substring.substr(0, node->maxLength());
701 741
702 node->setEditingValue(substring); 742 node->setEditingValue(substring);
703 } 743 }
704 744
745 void AutofillAgent::HidePopups() {
746 WebKit::WebView* web_view = render_view()->GetWebView();
747 if (web_view)
748 web_view->hidePopups();
Ilya Sherman 2012/10/27 07:44:11 You should also hide any popups that might be show
Dan Beam 2012/10/29 19:17:05 The code wasn't doing this before and I'm simply p
Ilya Sherman 2012/10/29 21:27:47 Feel free to file a bug against csharp@ and annota
Dan Beam 2012/10/29 23:08:23 https://chromiumcodereview.appspot.com/11273096/
749 }
750
Evan Stade 2012/10/29 17:54:28 extra newline
Dan Beam 2012/10/29 19:17:05 Done.
751
705 } // namespace autofill 752 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698