Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / components / autofill / content / renderer / autofill_agent.cc
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
3 // found in the LICENSE file.
4
5 #include "components/autofill/content/renderer/autofill_agent.h"
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string_split.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/time/time.h"
14 #include "components/autofill/content/common/autofill_messages.h"
15 #include "components/autofill/content/renderer/form_autofill_util.h"
16 #include "components/autofill/content/renderer/page_click_tracker.h"
17 #include "components/autofill/content/renderer/password_autofill_agent.h"
18 #include "components/autofill/content/renderer/password_generation_agent.h"
19 #include "components/autofill/core/common/autofill_constants.h"
20 #include "components/autofill/core/common/autofill_data_validation.h"
21 #include "components/autofill/core/common/autofill_switches.h"
22 #include "components/autofill/core/common/form_data.h"
23 #include "components/autofill/core/common/form_data_predictions.h"
24 #include "components/autofill/core/common/form_field_data.h"
25 #include "components/autofill/core/common/password_form.h"
26 #include "components/autofill/core/common/web_element_descriptor.h"
27 #include "content/public/common/content_switches.h"
28 #include "content/public/common/ssl_status.h"
29 #include "content/public/common/url_constants.h"
30 #include "content/public/renderer/render_view.h"
31 #include "grit/component_strings.h"
32 #include "net/cert/cert_status_flags.h"
33 #include "third_party/WebKit/public/platform/WebRect.h"
34 #include "third_party/WebKit/public/platform/WebURLRequest.h"
35 #include "third_party/WebKit/public/web/WebDataSource.h"
36 #include "third_party/WebKit/public/web/WebDocument.h"
37 #include "third_party/WebKit/public/web/WebElementCollection.h"
38 #include "third_party/WebKit/public/web/WebFormControlElement.h"
39 #include "third_party/WebKit/public/web/WebFormElement.h"
40 #include "third_party/WebKit/public/web/WebFrame.h"
41 #include "third_party/WebKit/public/web/WebInputEvent.h"
42 #include "third_party/WebKit/public/web/WebNode.h"
43 #include "third_party/WebKit/public/web/WebOptionElement.h"
44 #include "third_party/WebKit/public/web/WebTextAreaElement.h"
45 #include "third_party/WebKit/public/web/WebView.h"
46 #include "ui/base/l10n/l10n_util.h"
47 #include "ui/events/keycodes/keyboard_codes.h"
48
49 using blink::WebAutofillClient;
50 using blink::WebElement;
51 using blink::WebElementCollection;
52 using blink::WebFormControlElement;
53 using blink::WebFormElement;
54 using blink::WebFrame;
55 using blink::WebInputElement;
56 using blink::WebKeyboardEvent;
57 using blink::WebNode;
58 using blink::WebOptionElement;
59 using blink::WebString;
60 using blink::WebTextAreaElement;
61 using blink::WebVector;
62
63 namespace autofill {
64
65 namespace {
66
67 // Gets all the data list values (with corresponding label) for the given
68 // element.
69 void GetDataListSuggestions(const WebInputElement& element,
70                             bool ignore_current_value,
71                             std::vector<base::string16>* values,
72                             std::vector<base::string16>* labels) {
73   WebElementCollection options = element.dataListOptions();
74   if (options.isNull())
75     return;
76
77   base::string16 prefix;
78   if (!ignore_current_value) {
79     prefix = element.editingValue();
80     if (element.isMultiple() &&
81         element.formControlType() == WebString::fromUTF8("email")) {
82       std::vector<base::string16> parts;
83       base::SplitStringDontTrim(prefix, ',', &parts);
84       if (parts.size() > 0) {
85         base::TrimWhitespace(parts[parts.size() - 1], base::TRIM_LEADING,
86                              &prefix);
87       }
88     }
89   }
90   for (WebOptionElement option = options.firstItem().to<WebOptionElement>();
91        !option.isNull(); option = options.nextItem().to<WebOptionElement>()) {
92     if (!StartsWith(option.value(), prefix, false) ||
93         option.value() == prefix ||
94         !element.isValidValue(option.value()))
95       continue;
96
97     values->push_back(option.value());
98     if (option.value() != option.label())
99       labels->push_back(option.label());
100     else
101       labels->push_back(base::string16());
102   }
103 }
104
105 // Trim the vector before sending it to the browser process to ensure we
106 // don't send too much data through the IPC.
107 void TrimStringVectorForIPC(std::vector<base::string16>* strings) {
108   // Limit the size of the vector.
109   if (strings->size() > kMaxListSize)
110     strings->resize(kMaxListSize);
111
112   // Limit the size of the strings in the vector.
113   for (size_t i = 0; i < strings->size(); ++i) {
114     if ((*strings)[i].length() > kMaxDataLength)
115       (*strings)[i].resize(kMaxDataLength);
116   }
117 }
118
119 }  // namespace
120
121 AutofillAgent::AutofillAgent(content::RenderView* render_view,
122                              PasswordAutofillAgent* password_autofill_agent,
123                              PasswordGenerationAgent* password_generation_agent)
124     : content::RenderViewObserver(render_view),
125       password_autofill_agent_(password_autofill_agent),
126       password_generation_agent_(password_generation_agent),
127       autofill_query_id_(0),
128       web_view_(render_view->GetWebView()),
129       display_warning_if_disabled_(false),
130       was_query_node_autofilled_(false),
131       has_shown_autofill_popup_for_current_edit_(false),
132       did_set_node_text_(false),
133       has_new_forms_for_browser_(false),
134       ignore_text_changes_(false),
135       is_popup_possibly_visible_(false),
136       weak_ptr_factory_(this) {
137   render_view->GetWebView()->setAutofillClient(this);
138
139   // The PageClickTracker is a RenderViewObserver, and hence will be freed when
140   // the RenderView is destroyed.
141   new PageClickTracker(render_view, this);
142 }
143
144 AutofillAgent::~AutofillAgent() {}
145
146 bool AutofillAgent::OnMessageReceived(const IPC::Message& message) {
147   bool handled = true;
148   IPC_BEGIN_MESSAGE_MAP(AutofillAgent, message)
149     IPC_MESSAGE_HANDLER(AutofillMsg_FillForm, OnFillForm)
150     IPC_MESSAGE_HANDLER(AutofillMsg_PreviewForm, OnPreviewForm)
151     IPC_MESSAGE_HANDLER(AutofillMsg_FieldTypePredictionsAvailable,
152                         OnFieldTypePredictionsAvailable)
153     IPC_MESSAGE_HANDLER(AutofillMsg_ClearForm, OnClearForm)
154     IPC_MESSAGE_HANDLER(AutofillMsg_ClearPreviewedForm, OnClearPreviewedForm)
155     IPC_MESSAGE_HANDLER(AutofillMsg_FillFieldWithValue, OnFillFieldWithValue)
156     IPC_MESSAGE_HANDLER(AutofillMsg_PreviewFieldWithValue,
157                         OnPreviewFieldWithValue)
158     IPC_MESSAGE_HANDLER(AutofillMsg_AcceptDataListSuggestion,
159                         OnAcceptDataListSuggestion)
160     IPC_MESSAGE_HANDLER(AutofillMsg_AcceptPasswordAutofillSuggestion,
161                         OnAcceptPasswordAutofillSuggestion)
162     IPC_MESSAGE_HANDLER(AutofillMsg_RequestAutocompleteResult,
163                         OnRequestAutocompleteResult)
164     IPC_MESSAGE_UNHANDLED(handled = false)
165   IPC_END_MESSAGE_MAP()
166   return handled;
167 }
168
169 void AutofillAgent::DidFinishDocumentLoad(WebFrame* frame) {
170   // Record timestamp on document load. This is used to record overhead of
171   // Autofill feature.
172   forms_seen_timestamp_ = base::TimeTicks::Now();
173
174   // The document has now been fully loaded.  Scan for forms to be sent up to
175   // the browser.
176   std::vector<FormData> forms;
177   bool has_more_forms = false;
178   if (!frame->parent()) {
179     form_elements_.clear();
180     has_more_forms = form_cache_.ExtractFormsAndFormElements(
181         *frame, kRequiredAutofillFields, &forms, &form_elements_);
182   } else {
183     form_cache_.ExtractForms(*frame, &forms);
184   }
185
186   autofill::FormsSeenState state = has_more_forms ?
187       autofill::PARTIAL_FORMS_SEEN : autofill::NO_SPECIAL_FORMS_SEEN;
188
189   // Always communicate to browser process for topmost frame.
190   if (!forms.empty() || !frame->parent()) {
191     Send(new AutofillHostMsg_FormsSeen(routing_id(), forms,
192                                        forms_seen_timestamp_,
193                                        state));
194   }
195 }
196
197 void AutofillAgent::FrameDetached(WebFrame* frame) {
198   form_cache_.ResetFrame(*frame);
199 }
200
201 void AutofillAgent::FrameWillClose(WebFrame* frame) {
202   if (in_flight_request_form_.isNull())
203     return;
204
205   for (WebFrame* temp = in_flight_request_form_.document().frame();
206        temp; temp = temp->parent()) {
207     if (temp == frame) {
208       Send(new AutofillHostMsg_CancelRequestAutocomplete(routing_id()));
209       break;
210     }
211   }
212 }
213
214 void AutofillAgent::WillSubmitForm(WebFrame* frame,
215                                    const WebFormElement& form) {
216   FormData form_data;
217   if (WebFormElementToFormData(form,
218                                WebFormControlElement(),
219                                REQUIRE_AUTOCOMPLETE,
220                                static_cast<ExtractMask>(
221                                    EXTRACT_VALUE | EXTRACT_OPTION_TEXT),
222                                &form_data,
223                                NULL)) {
224     Send(new AutofillHostMsg_FormSubmitted(routing_id(), form_data,
225                                            base::TimeTicks::Now()));
226   }
227 }
228
229 void AutofillAgent::ZoomLevelChanged() {
230   // Any time the zoom level changes, the page's content moves, so any Autofill
231   // popups should be hidden. This is only needed for the new Autofill UI
232   // because WebKit already knows to hide the old UI when this occurs.
233   HidePopup();
234 }
235
236 void AutofillAgent::FocusedNodeChanged(const WebNode& node) {
237   if (node.isNull() || !node.isElementNode())
238     return;
239
240   WebElement web_element = node.toConst<WebElement>();
241
242   if (!web_element.document().frame())
243       return;
244
245   const WebInputElement* element = toWebInputElement(&web_element);
246
247   if (!element || !element->isEnabled() || element->isReadOnly() ||
248       !element->isTextField() || element->isPasswordField())
249     return;
250
251   element_ = *element;
252 }
253
254 void AutofillAgent::OrientationChangeEvent(int orientation) {
255   HidePopup();
256 }
257
258 void AutofillAgent::DidChangeScrollOffset(WebFrame*) {
259   HidePopup();
260 }
261
262 void AutofillAgent::didRequestAutocomplete(WebFrame* frame,
263                                            const WebFormElement& form) {
264   // Disallow the dialog over non-https or broken https, except when the
265   // ignore SSL flag is passed. See http://crbug.com/272512.
266   // TODO(palmer): this should be moved to the browser process after frames
267   // get their own processes.
268   GURL url(frame->document().url());
269   content::SSLStatus ssl_status = render_view()->GetSSLStatusOfFrame(frame);
270   bool is_safe = url.SchemeIs(content::kHttpsScheme) &&
271       !net::IsCertStatusError(ssl_status.cert_status);
272   bool allow_unsafe = CommandLine::ForCurrentProcess()->HasSwitch(
273       ::switches::kReduceSecurityForTesting);
274
275   FormData form_data;
276   if (!in_flight_request_form_.isNull() ||
277       (!is_safe && !allow_unsafe) ||
278       !WebFormElementToFormData(form,
279                                 WebFormControlElement(),
280                                 REQUIRE_AUTOCOMPLETE,
281                                 EXTRACT_OPTIONS,
282                                 &form_data,
283                                 NULL)) {
284     WebFormElement(form).finishRequestAutocomplete(
285         WebFormElement::AutocompleteResultErrorDisabled);
286     return;
287   }
288
289   // Cancel any pending Autofill requests and hide any currently showing popups.
290   ++autofill_query_id_;
291   HidePopup();
292
293   in_flight_request_form_ = form;
294   Send(new AutofillHostMsg_RequestAutocomplete(routing_id(), form_data, url));
295 }
296
297 void AutofillAgent::setIgnoreTextChanges(bool ignore) {
298   ignore_text_changes_ = ignore;
299 }
300
301 void AutofillAgent::FormControlElementClicked(
302     const WebFormControlElement& element,
303     bool was_focused) {
304   const WebInputElement* input_element = toWebInputElement(&element);
305   if (!input_element && !IsTextAreaElement(element))
306     return;
307
308   if (was_focused)
309     ShowSuggestions(element, true, false, true, false);
310 }
311
312 void AutofillAgent::FormControlElementLostFocus() {
313   HidePopup();
314 }
315
316 void AutofillAgent::textFieldDidEndEditing(const WebInputElement& element) {
317   password_autofill_agent_->TextFieldDidEndEditing(element);
318   has_shown_autofill_popup_for_current_edit_ = false;
319   Send(new AutofillHostMsg_DidEndTextFieldEditing(routing_id()));
320 }
321
322 void AutofillAgent::textFieldDidChange(const WebFormControlElement& element) {
323   if (ignore_text_changes_)
324     return;
325
326   DCHECK(toWebInputElement(&element) || IsTextAreaElement(element));
327
328   if (did_set_node_text_) {
329     did_set_node_text_ = false;
330     return;
331   }
332
333   // We post a task for doing the Autofill as the caret position is not set
334   // properly at this point (http://bugs.webkit.org/show_bug.cgi?id=16976) and
335   // it is needed to trigger autofill.
336   weak_ptr_factory_.InvalidateWeakPtrs();
337   base::MessageLoop::current()->PostTask(
338       FROM_HERE,
339       base::Bind(&AutofillAgent::TextFieldDidChangeImpl,
340                  weak_ptr_factory_.GetWeakPtr(),
341                  element));
342 }
343
344 void AutofillAgent::TextFieldDidChangeImpl(
345     const WebFormControlElement& element) {
346   // If the element isn't focused then the changes don't matter. This check is
347   // required to properly handle IME interactions.
348   if (!element.focused())
349     return;
350
351   const WebInputElement* input_element = toWebInputElement(&element);
352   if (input_element) {
353     if (password_generation_agent_ &&
354         password_generation_agent_->TextDidChangeInTextField(*input_element)) {
355       return;
356     }
357
358     if (password_autofill_agent_->TextDidChangeInTextField(*input_element)) {
359       element_ = element;
360       return;
361     }
362   }
363
364   ShowSuggestions(element, false, true, false, false);
365
366   FormData form;
367   FormFieldData field;
368   if (FindFormAndFieldForFormControlElement(element,
369                                             &form,
370                                             &field,
371                                             REQUIRE_NONE)) {
372     Send(new AutofillHostMsg_TextFieldDidChange(routing_id(), form, field,
373                                                 base::TimeTicks::Now()));
374   }
375 }
376
377 void AutofillAgent::textFieldDidReceiveKeyDown(const WebInputElement& element,
378                                                const WebKeyboardEvent& event) {
379   if (password_autofill_agent_->TextFieldHandlingKeyDown(element, event)) {
380     element_ = element;
381     return;
382   }
383
384   if (event.windowsKeyCode == ui::VKEY_DOWN ||
385       event.windowsKeyCode == ui::VKEY_UP)
386     ShowSuggestions(element, true, true, true, false);
387 }
388
389 void AutofillAgent::openTextDataListChooser(const WebInputElement& element) {
390     ShowSuggestions(element, true, false, false, true);
391 }
392
393 void AutofillAgent::AcceptDataListSuggestion(
394     const base::string16& suggested_value) {
395   WebInputElement* input_element = toWebInputElement(&element_);
396   DCHECK(input_element);
397   base::string16 new_value = suggested_value;
398   // If this element takes multiple values then replace the last part with
399   // the suggestion.
400   if (input_element->isMultiple() &&
401       input_element->formControlType() == WebString::fromUTF8("email")) {
402     std::vector<base::string16> parts;
403
404     base::SplitStringDontTrim(input_element->editingValue(), ',', &parts);
405     if (parts.size() == 0)
406       parts.push_back(base::string16());
407
408     base::string16 last_part = parts.back();
409     // We want to keep just the leading whitespace.
410     for (size_t i = 0; i < last_part.size(); ++i) {
411       if (!IsWhitespace(last_part[i])) {
412         last_part = last_part.substr(0, i);
413         break;
414       }
415     }
416     last_part.append(suggested_value);
417     parts[parts.size() - 1] = last_part;
418
419     new_value = JoinString(parts, ',');
420   }
421   FillFieldWithValue(new_value, input_element);
422 }
423
424 void AutofillAgent::OnFieldTypePredictionsAvailable(
425     const std::vector<FormDataPredictions>& forms) {
426   for (size_t i = 0; i < forms.size(); ++i) {
427     form_cache_.ShowPredictions(forms[i]);
428   }
429 }
430
431 void AutofillAgent::OnFillForm(int query_id, const FormData& form) {
432   if (!render_view()->GetWebView() || query_id != autofill_query_id_)
433     return;
434
435   was_query_node_autofilled_ = element_.isAutofilled();
436   FillForm(form, element_);
437   Send(new AutofillHostMsg_DidFillAutofillFormData(routing_id(),
438                                                    base::TimeTicks::Now()));
439 }
440
441 void AutofillAgent::OnPreviewForm(int query_id, const FormData& form) {
442   if (!render_view()->GetWebView() || query_id != autofill_query_id_)
443     return;
444
445   was_query_node_autofilled_ = element_.isAutofilled();
446   PreviewForm(form, element_);
447   Send(new AutofillHostMsg_DidPreviewAutofillFormData(routing_id()));
448 }
449
450 void AutofillAgent::OnClearForm() {
451   form_cache_.ClearFormWithElement(element_);
452 }
453
454 void AutofillAgent::OnClearPreviewedForm() {
455   if (!element_.isNull()) {
456     if (password_autofill_agent_->DidClearAutofillSelection(element_))
457       return;
458
459     ClearPreviewedFormWithElement(element_, was_query_node_autofilled_);
460   } else {
461     // TODO(isherman): There seem to be rare cases where this code *is*
462     // reachable: see [ http://crbug.com/96321#c6 ].  Ideally we would
463     // understand those cases and fix the code to avoid them.  However, so far I
464     // have been unable to reproduce such a case locally.  If you hit this
465     // NOTREACHED(), please file a bug against me.
466     NOTREACHED();
467   }
468 }
469
470 void AutofillAgent::OnFillFieldWithValue(const base::string16& value) {
471   WebInputElement* input_element = toWebInputElement(&element_);
472   if (input_element)
473     FillFieldWithValue(value, input_element);
474 }
475
476 void AutofillAgent::OnPreviewFieldWithValue(const base::string16& value) {
477   WebInputElement* input_element = toWebInputElement(&element_);
478   if (input_element)
479     PreviewFieldWithValue(value, input_element);
480 }
481
482 void AutofillAgent::OnAcceptDataListSuggestion(const base::string16& value) {
483   AcceptDataListSuggestion(value);
484 }
485
486 void AutofillAgent::OnAcceptPasswordAutofillSuggestion(
487     const base::string16& username) {
488   // We need to make sure this is handled here because the browser process
489   // skipped it handling because it believed it would be handled here. If it
490   // isn't handled here then the browser logic needs to be updated.
491   bool handled = password_autofill_agent_->DidAcceptAutofillSuggestion(
492       element_,
493       username);
494   DCHECK(handled);
495 }
496
497 void AutofillAgent::OnRequestAutocompleteResult(
498     WebFormElement::AutocompleteResult result,
499     const FormData& form_data) {
500   if (in_flight_request_form_.isNull())
501     return;
502
503   if (result == WebFormElement::AutocompleteResultSuccess) {
504     FillFormIncludingNonFocusableElements(form_data, in_flight_request_form_);
505     if (!in_flight_request_form_.checkValidityWithoutDispatchingEvents())
506       result = WebFormElement::AutocompleteResultErrorInvalid;
507   }
508
509   in_flight_request_form_.finishRequestAutocomplete(result);
510   in_flight_request_form_.reset();
511 }
512
513 void AutofillAgent::ShowSuggestions(const WebFormControlElement& element,
514                                     bool autofill_on_empty_values,
515                                     bool requires_caret_at_end,
516                                     bool display_warning_if_disabled,
517                                     bool datalist_only) {
518   if (!element.isEnabled() || element.isReadOnly())
519     return;
520
521   const WebInputElement* input_element = toWebInputElement(&element);
522   if (input_element) {
523     if (!input_element->isTextField() || input_element->isPasswordField())
524       return;
525     if (!datalist_only && !input_element->suggestedValue().isEmpty())
526       return;
527   } else {
528     DCHECK(IsTextAreaElement(element));
529     if (!element.toConst<WebTextAreaElement>().suggestedValue().isEmpty())
530       return;
531   }
532
533   // Don't attempt to autofill with values that are too large or if filling
534   // criteria are not met.
535   WebString value = element.editingValue();
536   if (!datalist_only &&
537       (value.length() > kMaxDataLength ||
538        (!autofill_on_empty_values && value.isEmpty()) ||
539        (requires_caret_at_end &&
540         (element.selectionStart() != element.selectionEnd() ||
541          element.selectionEnd() != static_cast<int>(value.length()))))) {
542     // Any popup currently showing is obsolete.
543     HidePopup();
544     return;
545   }
546
547   element_ = element;
548   if (input_element &&
549       password_autofill_agent_->ShowSuggestions(*input_element)) {
550     is_popup_possibly_visible_ = true;
551     return;
552   }
553
554   // If autocomplete is disabled at the field level, ensure that the native
555   // UI won't try to show a warning, since that may conflict with a custom
556   // popup. Note that we cannot use the WebKit method element.autoComplete()
557   // as it does not allow us to distinguish the case where autocomplete is
558   // disabled for *both* the element and for the form.
559   const base::string16 autocomplete_attribute =
560       element.getAttribute("autocomplete");
561   if (LowerCaseEqualsASCII(autocomplete_attribute, "off"))
562     display_warning_if_disabled = false;
563
564   QueryAutofillSuggestions(element,
565                            display_warning_if_disabled,
566                            datalist_only);
567 }
568
569 void AutofillAgent::QueryAutofillSuggestions(
570     const WebFormControlElement& element,
571     bool display_warning_if_disabled,
572     bool datalist_only) {
573   if (!element.document().frame())
574     return;
575
576   DCHECK(toWebInputElement(&element) || IsTextAreaElement(element));
577
578   static int query_counter = 0;
579   autofill_query_id_ = query_counter++;
580   display_warning_if_disabled_ = display_warning_if_disabled;
581
582   // If autocomplete is disabled at the form level, we want to see if there
583   // would have been any suggestions were it enabled, so that we can show a
584   // warning.  Otherwise, we want to ignore fields that disable autocomplete, so
585   // that the suggestions list does not include suggestions for these form
586   // fields -- see comment 1 on http://crbug.com/69914
587   const RequirementsMask requirements =
588       element.autoComplete() ? REQUIRE_AUTOCOMPLETE : REQUIRE_NONE;
589
590   FormData form;
591   FormFieldData field;
592   if (!FindFormAndFieldForFormControlElement(element, &form, &field,
593                                              requirements)) {
594     // If we didn't find the cached form, at least let autocomplete have a shot
595     // at providing suggestions.
596     WebFormControlElementToFormField(element, EXTRACT_VALUE, &field);
597   }
598   if (datalist_only)
599     field.should_autocomplete = false;
600
601   gfx::RectF bounding_box_scaled =
602       GetScaledBoundingBox(web_view_->pageScaleFactor(), &element_);
603
604   const WebInputElement* input_element = toWebInputElement(&element);
605   if (input_element) {
606     // Find the datalist values and send them to the browser process.
607     std::vector<base::string16> data_list_values;
608     std::vector<base::string16> data_list_labels;
609     GetDataListSuggestions(*input_element,
610                            datalist_only,
611                            &data_list_values,
612                            &data_list_labels);
613     TrimStringVectorForIPC(&data_list_values);
614     TrimStringVectorForIPC(&data_list_labels);
615
616     Send(new AutofillHostMsg_SetDataList(routing_id(),
617                                          data_list_values,
618                                          data_list_labels));
619   }
620
621   is_popup_possibly_visible_ = true;
622   Send(new AutofillHostMsg_QueryFormFieldAutofill(routing_id(),
623                                                   autofill_query_id_,
624                                                   form,
625                                                   field,
626                                                   bounding_box_scaled,
627                                                   display_warning_if_disabled));
628 }
629
630 void AutofillAgent::FillFieldWithValue(const base::string16& value,
631                                        WebInputElement* node) {
632   did_set_node_text_ = true;
633   node->setEditingValue(value.substr(0, node->maxLength()));
634   node->setAutofilled(true);
635 }
636
637 void AutofillAgent::PreviewFieldWithValue(const base::string16& value,
638                                           WebInputElement* node) {
639   was_query_node_autofilled_ = element_.isAutofilled();
640   node->setSuggestedValue(value.substr(0, node->maxLength()));
641   node->setAutofilled(true);
642   node->setSelectionRange(node->value().length(),
643                           node->suggestedValue().length());
644 }
645
646 void AutofillAgent::HidePopup() {
647   if (!is_popup_possibly_visible_)
648     return;
649
650   if (!element_.isNull())
651     OnClearPreviewedForm();
652
653   is_popup_possibly_visible_ = false;
654   Send(new AutofillHostMsg_HidePopup(routing_id()));
655 }
656
657 // TODO(isherman): Decide if we want to support non-password autofill with AJAX.
658 void AutofillAgent::didAssociateFormControls(const WebVector<WebNode>& nodes) {
659   for (size_t i = 0; i < nodes.size(); ++i) {
660     WebFrame* frame = nodes[i].document().frame();
661     // Only monitors dynamic forms created in the top frame. Dynamic forms
662     // inserted in iframes are not captured yet.
663     if (frame && !frame->parent()) {
664       password_autofill_agent_->OnDynamicFormsSeen(frame);
665       return;
666     }
667   }
668 }
669
670 }  // namespace autofill