blob: 4b2a616119bc9f0f813c6470d373cba7f10cb3f0 [file] [log] [blame]
[email protected]c4a9e932011-03-05 04:05:551// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]679f128f2010-07-22 22:57:442// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]78192082011-01-29 05:43:445#include "chrome/renderer/autofill/autofill_agent.h"
[email protected]679f128f2010-07-22 22:57:446
[email protected]a1cb57f2011-09-28 22:41:297#include "base/bind.h"
[email protected]8704f89b2011-04-15 00:30:058#include "base/message_loop.h"
[email protected]1d14f582011-09-02 20:42:049#include "base/time.h"
[email protected]2377cafe2010-10-27 01:19:0810#include "base/utf_string_conversions.h"
[email protected]19d6e1e82011-01-26 05:08:5811#include "chrome/common/autofill_messages.h"
[email protected]2377cafe2010-10-27 01:19:0812#include "chrome/common/chrome_constants.h"
[email protected]aaa80c92011-09-16 00:23:5413#include "chrome/renderer/autofill/form_autofill_util.h"
[email protected]78192082011-01-29 05:43:4414#include "chrome/renderer/autofill/password_autofill_manager.h"
[email protected]a2ef54c2011-10-10 16:20:3115#include "content/public/renderer/render_view.h"
[email protected]679f128f2010-07-22 22:57:4416#include "grit/generated_resources.h"
[email protected]8bd0fe62011-01-17 06:44:3717#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
18#include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement.h"
19#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
[email protected]a22f7e02011-02-09 07:15:3520#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
[email protected]aaa80c92011-09-16 00:23:5421#include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h"
[email protected]97183052011-11-17 16:35:2222#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h"
[email protected]8bd0fe62011-01-17 06:44:3723#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
[email protected]b6d81262011-01-13 17:36:0924#include "ui/base/keycodes/keyboard_codes.h"
[email protected]c051a1b2011-01-21 23:30:1725#include "ui/base/l10n/l10n_util.h"
[email protected]6a8ddba52010-09-05 04:38:0626#include "webkit/glue/form_data.h"
[email protected]3eb5728c2011-06-20 22:32:2427#include "webkit/glue/form_data_predictions.h"
[email protected]6a8ddba52010-09-05 04:38:0628#include "webkit/glue/form_field.h"
[email protected]679f128f2010-07-22 22:57:4429#include "webkit/glue/password_form.h"
30
31using WebKit::WebFormControlElement;
32using WebKit::WebFormElement;
33using WebKit::WebFrame;
34using WebKit::WebInputElement;
[email protected]7aab84b2010-11-20 01:04:2635using WebKit::WebKeyboardEvent;
[email protected]679f128f2010-07-22 22:57:4436using WebKit::WebNode;
37using WebKit::WebString;
[email protected]2a5b1732011-04-01 23:55:5538using webkit_glue::FormData;
[email protected]3eb5728c2011-06-20 22:32:2439using webkit_glue::FormDataPredictions;
[email protected]679f128f2010-07-22 22:57:4440
[email protected]e47aec52010-08-12 00:50:3041namespace {
42
43// The size above which we stop triggering autofill for an input text field
44// (so to avoid sending long strings through IPC).
[email protected]663bd9e2011-03-21 01:07:0145const size_t kMaximumTextSizeForAutofill = 1000;
[email protected]e47aec52010-08-12 00:50:3046
47} // namespace
48
[email protected]78192082011-01-29 05:43:4449namespace autofill {
50
[email protected]663bd9e2011-03-21 01:07:0151AutofillAgent::AutofillAgent(
[email protected]a2ef54c2011-10-10 16:20:3152 content::RenderView* render_view,
[email protected]c4a9e932011-03-05 04:05:5553 PasswordAutofillManager* password_autofill_manager)
[email protected]3a034ebb2011-10-03 19:19:4454 : content::RenderViewObserver(render_view),
[email protected]78192082011-01-29 05:43:4455 password_autofill_manager_(password_autofill_manager),
[email protected]679f128f2010-07-22 22:57:4456 autofill_query_id_(0),
57 autofill_action_(AUTOFILL_NONE),
[email protected]6bcd58a2010-11-25 02:31:2058 display_warning_if_disabled_(false),
[email protected]d77ddc8062010-11-24 01:14:0659 was_query_node_autofilled_(false),
[email protected]679f128f2010-07-22 22:57:4460 suggestions_clear_index_(-1),
[email protected]676126f72011-01-15 00:03:5161 suggestions_options_index_(-1),
[email protected]e4dce0af2011-09-19 22:22:2862 has_shown_autofill_popup_for_current_edit_(false),
[email protected]a1cb57f2011-09-28 22:41:2963 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
[email protected]a2ef54c2011-10-10 16:20:3164 render_view->GetWebView()->setAutofillClient(this);
[email protected]679f128f2010-07-22 22:57:4465}
66
[email protected]663bd9e2011-03-21 01:07:0167AutofillAgent::~AutofillAgent() {}
[email protected]d2f05d02011-01-27 18:51:0168
[email protected]663bd9e2011-03-21 01:07:0169bool AutofillAgent::OnMessageReceived(const IPC::Message& message) {
[email protected]676126f72011-01-15 00:03:5170 bool handled = true;
[email protected]663bd9e2011-03-21 01:07:0171 IPC_BEGIN_MESSAGE_MAP(AutofillAgent, message)
72 IPC_MESSAGE_HANDLER(AutofillMsg_SuggestionsReturned, OnSuggestionsReturned)
73 IPC_MESSAGE_HANDLER(AutofillMsg_FormDataFilled, OnFormDataFilled)
[email protected]3eb5728c2011-06-20 22:32:2474 IPC_MESSAGE_HANDLER(AutofillMsg_FieldTypePredictionsAvailable,
75 OnFieldTypePredictionsAvailable)
[email protected]3fd04002011-10-29 00:51:0476 IPC_MESSAGE_HANDLER(AutofillMsg_SelectAutofillSuggestionAtIndex,
77 OnSelectAutofillSuggestionAtIndex)
[email protected]676126f72011-01-15 00:03:5178 IPC_MESSAGE_UNHANDLED(handled = false)
79 IPC_END_MESSAGE_MAP()
80 return handled;
81}
82
[email protected]2fa18c22011-06-14 23:40:4383void AutofillAgent::DidFinishDocumentLoad(WebFrame* frame) {
[email protected]676126f72011-01-15 00:03:5184 // The document has now been fully loaded. Scan for forms to be sent up to
85 // the browser.
[email protected]2fa18c22011-06-14 23:40:4386 std::vector<webkit_glue::FormData> forms;
[email protected]aaa80c92011-09-16 00:23:5487 form_cache_.ExtractForms(*frame, &forms);
[email protected]2fa18c22011-06-14 23:40:4388
[email protected]1d14f582011-09-02 20:42:0489 if (!forms.empty()) {
90 Send(new AutofillHostMsg_FormsSeen(routing_id(), forms,
91 base::TimeTicks::Now()));
92 }
[email protected]676126f72011-01-15 00:03:5193}
94
[email protected]2fa18c22011-06-14 23:40:4395void AutofillAgent::FrameDetached(WebFrame* frame) {
[email protected]aaa80c92011-09-16 00:23:5496 form_cache_.ResetFrame(*frame);
[email protected]676126f72011-01-15 00:03:5197}
98
[email protected]2fa18c22011-06-14 23:40:4399void AutofillAgent::FrameWillClose(WebFrame* frame) {
[email protected]aaa80c92011-09-16 00:23:54100 form_cache_.ResetFrame(*frame);
[email protected]676126f72011-01-15 00:03:51101}
102
[email protected]2a5b1732011-04-01 23:55:55103void AutofillAgent::WillSubmitForm(WebFrame* frame,
104 const WebFormElement& form) {
105 FormData form_data;
[email protected]aaa80c92011-09-16 00:23:54106 if (WebFormElementToFormData(form,
107 WebFormControlElement(),
108 REQUIRE_AUTOCOMPLETE,
109 static_cast<ExtractMask>(
110 EXTRACT_VALUE | EXTRACT_OPTION_TEXT),
111 &form_data,
112 NULL)) {
[email protected]1d14f582011-09-02 20:42:04113 Send(new AutofillHostMsg_FormSubmitted(routing_id(), form_data,
114 base::TimeTicks::Now()));
[email protected]2a5b1732011-04-01 23:55:55115 }
116}
117
[email protected]663bd9e2011-03-21 01:07:01118bool AutofillAgent::InputElementClicked(const WebInputElement& element,
[email protected]78192082011-01-29 05:43:44119 bool was_focused,
120 bool is_focused) {
[email protected]676126f72011-01-15 00:03:51121 if (was_focused)
122 ShowSuggestions(element, true, false, true);
[email protected]2fa18c22011-06-14 23:40:43123
[email protected]676126f72011-01-15 00:03:51124 return false;
125}
126
[email protected]65ec8db2011-11-04 14:50:44127bool AutofillAgent::InputElementLostFocus() {
[email protected]97183052011-11-17 16:35:22128 Send(new AutofillHostMsg_HideAutofillPopup(routing_id()));
129
[email protected]65ec8db2011-11-04 14:50:44130 return false;
131}
132
[email protected]3d07d6b2011-07-13 00:25:00133void AutofillAgent::didAcceptAutofillSuggestion(const WebNode& node,
[email protected]2fa18c22011-06-14 23:40:43134 const WebString& value,
135 const WebString& label,
[email protected]78192082011-01-29 05:43:44136 int unique_id,
137 unsigned index) {
[email protected]663bd9e2011-03-21 01:07:01138 if (password_autofill_manager_->DidAcceptAutofillSuggestion(node, value))
[email protected]b43c1352011-03-04 23:55:34139 return;
140
[email protected]676126f72011-01-15 00:03:51141 if (suggestions_options_index_ != -1 &&
142 index == static_cast<unsigned>(suggestions_options_index_)) {
[email protected]663bd9e2011-03-21 01:07:01143 // User selected 'Autofill Options'.
144 Send(new AutofillHostMsg_ShowAutofillDialog(routing_id()));
[email protected]676126f72011-01-15 00:03:51145 } else if (suggestions_clear_index_ != -1 &&
146 index == static_cast<unsigned>(suggestions_clear_index_)) {
147 // User selected 'Clear form'.
[email protected]829245b2011-09-07 21:18:32148 DCHECK(node == autofill_query_element_);
[email protected]aaa80c92011-09-16 00:23:54149 form_cache_.ClearFormWithElement(autofill_query_element_);
[email protected]676126f72011-01-15 00:03:51150 } else if (!unique_id) {
151 // User selected an Autocomplete entry, so we fill directly.
152 WebInputElement element = node.toConst<WebInputElement>();
153
154 string16 substring = value;
155 substring = substring.substr(0, element.maxLength());
[email protected]3b3b94d2011-03-10 09:52:20156 element.setValue(substring, true);
[email protected]676126f72011-01-15 00:03:51157 } else {
158 // Fill the values for the whole form.
[email protected]663bd9e2011-03-21 01:07:01159 FillAutofillFormData(node, unique_id, AUTOFILL_FILL);
[email protected]676126f72011-01-15 00:03:51160 }
161
162 suggestions_clear_index_ = -1;
163 suggestions_options_index_ = -1;
164}
165
[email protected]3d07d6b2011-07-13 00:25:00166void AutofillAgent::didSelectAutofillSuggestion(const WebNode& node,
[email protected]2fa18c22011-06-14 23:40:43167 const WebString& value,
168 const WebString& label,
[email protected]78192082011-01-29 05:43:44169 int unique_id) {
[email protected]676126f72011-01-15 00:03:51170 DCHECK_GE(unique_id, 0);
[email protected]663bd9e2011-03-21 01:07:01171 if (password_autofill_manager_->DidSelectAutofillSuggestion(node))
[email protected]fc1964a2011-01-20 19:33:07172 return;
[email protected]676126f72011-01-15 00:03:51173
[email protected]3d07d6b2011-07-13 00:25:00174 didClearAutofillSelection(node);
[email protected]663bd9e2011-03-21 01:07:01175 FillAutofillFormData(node, unique_id, AUTOFILL_PREVIEW);
[email protected]676126f72011-01-15 00:03:51176}
177
[email protected]3d07d6b2011-07-13 00:25:00178void AutofillAgent::didClearAutofillSelection(const WebNode& node) {
[email protected]6075d0502011-09-13 02:10:21179 if (password_autofill_manager_->DidClearAutofillSelection(node))
180 return;
181
[email protected]091b2222011-09-14 02:52:55182 if (!autofill_query_element_.isNull() && node == autofill_query_element_) {
[email protected]aaa80c92011-09-16 00:23:54183 ClearPreviewedFormWithElement(autofill_query_element_,
184 was_query_node_autofilled_);
[email protected]091b2222011-09-14 02:52:55185 } else {
186 // TODO(isherman): There seem to be rare cases where this code *is*
187 // reachable: see [ http://crbug.com/96321#c6 ]. Ideally we would
188 // understand those cases and fix the code to avoid them. However, so far I
189 // have been unable to reproduce such a case locally. If you hit this
190 // NOTREACHED(), please file a bug against me.
191 NOTREACHED();
192 }
[email protected]676126f72011-01-15 00:03:51193}
194
[email protected]2fa18c22011-06-14 23:40:43195void AutofillAgent::removeAutocompleteSuggestion(const WebString& name,
196 const WebString& value) {
[email protected]679f128f2010-07-22 22:57:44197 // The index of clear & options will have shifted down.
198 if (suggestions_clear_index_ != -1)
199 suggestions_clear_index_--;
200 if (suggestions_options_index_ != -1)
201 suggestions_options_index_--;
202
[email protected]663bd9e2011-03-21 01:07:01203 Send(new AutofillHostMsg_RemoveAutocompleteEntry(routing_id(), name, value));
[email protected]679f128f2010-07-22 22:57:44204}
205
[email protected]2fa18c22011-06-14 23:40:43206void AutofillAgent::textFieldDidEndEditing(const WebInputElement& element) {
[email protected]78192082011-01-29 05:43:44207 password_autofill_manager_->TextFieldDidEndEditing(element);
[email protected]7d24db72011-08-26 06:02:31208 has_shown_autofill_popup_for_current_edit_ = false;
[email protected]676126f72011-01-15 00:03:51209}
210
[email protected]2fa18c22011-06-14 23:40:43211void AutofillAgent::textFieldDidChange(const WebInputElement& element) {
[email protected]663bd9e2011-03-21 01:07:01212 // We post a task for doing the Autofill as the caret position is not set
[email protected]676126f72011-01-15 00:03:51213 // properly at this point (http://bugs.webkit.org/show_bug.cgi?id=16976) and
214 // it is needed to trigger autofill.
[email protected]a1cb57f2011-09-28 22:41:29215 weak_ptr_factory_.InvalidateWeakPtrs();
[email protected]676126f72011-01-15 00:03:51216 MessageLoop::current()->PostTask(
217 FROM_HERE,
[email protected]a1cb57f2011-09-28 22:41:29218 base::Bind(&AutofillAgent::TextFieldDidChangeImpl,
219 weak_ptr_factory_.GetWeakPtr(), element));
[email protected]676126f72011-01-15 00:03:51220}
221
[email protected]2fa18c22011-06-14 23:40:43222void AutofillAgent::TextFieldDidChangeImpl(const WebInputElement& element) {
[email protected]78192082011-01-29 05:43:44223 if (password_autofill_manager_->TextDidChangeInTextField(element))
[email protected]676126f72011-01-15 00:03:51224 return;
225
226 ShowSuggestions(element, false, true, false);
[email protected]7d24db72011-08-26 06:02:31227
228 webkit_glue::FormData form;
229 webkit_glue::FormField field;
[email protected]283ba4ca2011-09-22 05:25:08230 if (FindFormAndFieldForInputElement(element, &form, &field, REQUIRE_NONE)) {
[email protected]1d14f582011-09-02 20:42:04231 Send(new AutofillHostMsg_TextFieldDidChange(routing_id(), form, field,
232 base::TimeTicks::Now()));
233 }
[email protected]676126f72011-01-15 00:03:51234}
235
[email protected]2fa18c22011-06-14 23:40:43236void AutofillAgent::textFieldDidReceiveKeyDown(const WebInputElement& element,
237 const WebKeyboardEvent& event) {
[email protected]78192082011-01-29 05:43:44238 if (password_autofill_manager_->TextFieldHandlingKeyDown(element, event))
[email protected]fc1964a2011-01-20 19:33:07239 return;
[email protected]676126f72011-01-15 00:03:51240
241 if (event.windowsKeyCode == ui::VKEY_DOWN ||
242 event.windowsKeyCode == ui::VKEY_UP)
243 ShowSuggestions(element, true, true, true);
244}
245
[email protected]663bd9e2011-03-21 01:07:01246void AutofillAgent::OnSuggestionsReturned(int query_id,
[email protected]78192082011-01-29 05:43:44247 const std::vector<string16>& values,
248 const std::vector<string16>& labels,
249 const std::vector<string16>& icons,
250 const std::vector<int>& unique_ids) {
[email protected]a2ef54c2011-10-10 16:20:31251 WebKit::WebView* web_view = render_view()->GetWebView();
[email protected]679f128f2010-07-22 22:57:44252 if (!web_view || query_id != autofill_query_id_)
253 return;
254
[email protected]43138472010-08-17 22:45:45255 if (values.empty()) {
256 // No suggestions, any popup currently showing is obsolete.
257 web_view->hidePopups();
[email protected]679f128f2010-07-22 22:57:44258 return;
[email protected]43138472010-08-17 22:45:45259 }
[email protected]679f128f2010-07-22 22:57:44260
261 std::vector<string16> v(values);
262 std::vector<string16> l(labels);
[email protected]a53e06832010-07-28 22:46:41263 std::vector<string16> i(icons);
[email protected]679f128f2010-07-22 22:57:44264 std::vector<int> ids(unique_ids);
265 int separator_index = -1;
266
[email protected]7d24db72011-08-26 06:02:31267 DCHECK_GT(ids.size(), 0U);
[email protected]cd0a3b72011-08-02 06:16:19268 if (!autofill_query_element_.isNull() &&
269 !autofill_query_element_.autoComplete()) {
270 // If autofill is disabled and we had suggestions, show a warning instead.
271 v.assign(1, l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED));
272 l.assign(1, string16());
273 i.assign(1, string16());
274 ids.assign(1, -1);
275 } else if (ids[0] < 0 && ids.size() > 1) {
[email protected]1866d062010-11-16 06:19:56276 // If we received a warning instead of suggestions from autofill but regular
277 // suggestions from autocomplete, don't show the autofill warning.
278 v.erase(v.begin());
279 l.erase(l.begin());
280 i.erase(i.begin());
281 ids.erase(ids.begin());
282 }
283
[email protected]6bcd58a2010-11-25 02:31:20284 // If we were about to show a warning and we shouldn't, don't.
285 if (ids[0] < 0 && !display_warning_if_disabled_)
286 return;
287
[email protected]663bd9e2011-03-21 01:07:01288 // Only include "Autofill Options" special menu item if we have Autofill
[email protected]4f03a2d32010-12-01 01:49:36289 // items, identified by |unique_ids| having at least one valid value.
290 bool has_autofill_item = false;
291 for (size_t i = 0; i < ids.size(); ++i) {
292 if (ids[i] > 0) {
293 has_autofill_item = true;
294 break;
295 }
296 }
297
[email protected]679f128f2010-07-22 22:57:44298 // The form has been auto-filled, so give the user the chance to clear the
299 // form. Append the 'Clear form' menu item.
[email protected]4f03a2d32010-12-01 01:49:36300 if (has_autofill_item &&
[email protected]aaa80c92011-09-16 00:23:54301 FormWithElementIsAutofilled(autofill_query_element_)) {
[email protected]679f128f2010-07-22 22:57:44302 v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM));
303 l.push_back(string16());
[email protected]a53e06832010-07-28 22:46:41304 i.push_back(string16());
[email protected]679f128f2010-07-22 22:57:44305 ids.push_back(0);
306 suggestions_clear_index_ = v.size() - 1;
[email protected]1866d062010-11-16 06:19:56307 separator_index = v.size() - 1;
[email protected]679f128f2010-07-22 22:57:44308 }
309
[email protected]4f03a2d32010-12-01 01:49:36310 if (has_autofill_item) {
[email protected]2377cafe2010-10-27 01:19:08311 // Append the 'Chrome Autofill options' menu item;
312 v.push_back(l10n_util::GetStringFUTF16(IDS_AUTOFILL_OPTIONS_POPUP,
313 WideToUTF16(chrome::kBrowserAppName)));
[email protected]679f128f2010-07-22 22:57:44314 l.push_back(string16());
[email protected]a53e06832010-07-28 22:46:41315 i.push_back(string16());
[email protected]679f128f2010-07-22 22:57:44316 ids.push_back(0);
317 suggestions_options_index_ = v.size() - 1;
318 separator_index = values.size();
319 }
320
321 // Send to WebKit for display.
[email protected]cd0a3b72011-08-02 06:16:19322 if (!v.empty() && !autofill_query_element_.isNull() &&
323 autofill_query_element_.isFocusable()) {
[email protected]3d07d6b2011-07-13 00:25:00324 web_view->applyAutofillSuggestions(
[email protected]cd0a3b72011-08-02 06:16:19325 autofill_query_element_, v, l, i, ids, separator_index);
[email protected]679f128f2010-07-22 22:57:44326 }
[email protected]468327f2010-10-04 20:02:29327
[email protected]7d24db72011-08-26 06:02:31328 Send(new AutofillHostMsg_DidShowAutofillSuggestions(
329 routing_id(),
330 has_autofill_item && !has_shown_autofill_popup_for_current_edit_));
331 has_shown_autofill_popup_for_current_edit_ |= has_autofill_item;
[email protected]679f128f2010-07-22 22:57:44332}
333
[email protected]663bd9e2011-03-21 01:07:01334void AutofillAgent::OnFormDataFilled(int query_id,
[email protected]78192082011-01-29 05:43:44335 const webkit_glue::FormData& form) {
[email protected]a2ef54c2011-10-10 16:20:31336 if (!render_view()->GetWebView() || query_id != autofill_query_id_)
[email protected]679f128f2010-07-22 22:57:44337 return;
338
339 switch (autofill_action_) {
340 case AUTOFILL_FILL:
[email protected]aaa80c92011-09-16 00:23:54341 FillForm(form, autofill_query_element_);
[email protected]1d14f582011-09-02 20:42:04342 Send(new AutofillHostMsg_DidFillAutofillFormData(routing_id(),
343 base::TimeTicks::Now()));
[email protected]679f128f2010-07-22 22:57:44344 break;
345 case AUTOFILL_PREVIEW:
[email protected]aaa80c92011-09-16 00:23:54346 PreviewForm(form, autofill_query_element_);
[email protected]7d24db72011-08-26 06:02:31347 Send(new AutofillHostMsg_DidPreviewAutofillFormData(routing_id()));
[email protected]679f128f2010-07-22 22:57:44348 break;
349 default:
350 NOTREACHED();
351 }
352 autofill_action_ = AUTOFILL_NONE;
[email protected]e47aec52010-08-12 00:50:30353}
354
[email protected]3eb5728c2011-06-20 22:32:24355void AutofillAgent::OnFieldTypePredictionsAvailable(
356 const std::vector<FormDataPredictions>& forms) {
357 for (size_t i = 0; i < forms.size(); ++i) {
[email protected]aaa80c92011-09-16 00:23:54358 form_cache_.ShowPredictions(forms[i]);
[email protected]3eb5728c2011-06-20 22:32:24359 }
360}
361
[email protected]3fd04002011-10-29 00:51:04362void AutofillAgent::OnSelectAutofillSuggestionAtIndex(int listIndex) {
363 NOTIMPLEMENTED();
364 // TODO(jrg): enable once changes land in WebKit
365 // render_view()->webview()->selectAutofillSuggestionAtIndex(listIndex);
366}
367
[email protected]663bd9e2011-03-21 01:07:01368void AutofillAgent::ShowSuggestions(const WebInputElement& element,
[email protected]78192082011-01-29 05:43:44369 bool autofill_on_empty_values,
370 bool requires_caret_at_end,
371 bool display_warning_if_disabled) {
[email protected]cd0a3b72011-08-02 06:16:19372 // If autocomplete is disabled at the form level, then we might want to show
373 // a warning in place of suggestions. However, if autocomplete is disabled
374 // specifically for this field, we never want to show a warning. Otherwise,
375 // we might interfere with custom popups (e.g. search suggestions) used by
376 // the website.
377 const WebFormElement form = element.form();
378 if (!element.isEnabled() || element.isReadOnly() ||
[email protected]a2f48892011-08-19 23:04:42379 (!element.autoComplete() && (form.isNull() || form.autoComplete())) ||
[email protected]62445812011-05-03 22:41:32380 !element.isTextField() || element.isPasswordField() ||
381 !element.suggestedValue().isEmpty())
[email protected]dc9144f2010-11-16 02:18:28382 return;
[email protected]dc9144f2010-11-16 02:18:28383
[email protected]1866d062010-11-16 06:19:56384 // If the field has no name, then we won't have values.
385 if (element.nameForAutofill().isEmpty())
[email protected]e47aec52010-08-12 00:50:30386 return;
387
388 // Don't attempt to autofill with values that are too large.
389 WebString value = element.value();
[email protected]663bd9e2011-03-21 01:07:01390 if (value.length() > kMaximumTextSizeForAutofill)
[email protected]e47aec52010-08-12 00:50:30391 return;
392
393 if (!autofill_on_empty_values && value.isEmpty())
394 return;
395
396 if (requires_caret_at_end &&
397 (element.selectionStart() != element.selectionEnd() ||
[email protected]1866d062010-11-16 06:19:56398 element.selectionEnd() != static_cast<int>(value.length())))
[email protected]e47aec52010-08-12 00:50:30399 return;
[email protected]e47aec52010-08-12 00:50:30400
[email protected]663bd9e2011-03-21 01:07:01401 QueryAutofillSuggestions(element, display_warning_if_disabled);
[email protected]77bb0da2010-11-20 01:55:30402}
403
[email protected]cd0a3b72011-08-02 06:16:19404void AutofillAgent::QueryAutofillSuggestions(const WebInputElement& element,
[email protected]78192082011-01-29 05:43:44405 bool display_warning_if_disabled) {
[email protected]77bb0da2010-11-20 01:55:30406 static int query_counter = 0;
407 autofill_query_id_ = query_counter++;
[email protected]cd0a3b72011-08-02 06:16:19408 autofill_query_element_ = element;
[email protected]6bcd58a2010-11-25 02:31:20409 display_warning_if_disabled_ = display_warning_if_disabled;
[email protected]77bb0da2010-11-20 01:55:30410
[email protected]3bb80e42010-11-29 22:27:16411 webkit_glue::FormData form;
[email protected]77bb0da2010-11-20 01:55:30412 webkit_glue::FormField field;
[email protected]283ba4ca2011-09-22 05:25:08413 if (!FindFormAndFieldForInputElement(element, &form, &field,
414 REQUIRE_AUTOCOMPLETE)) {
[email protected]7837be62011-01-18 23:45:08415 // If we didn't find the cached form, at least let autocomplete have a shot
416 // at providing suggestions.
[email protected]aaa80c92011-09-16 00:23:54417 WebFormControlElementToFormField(element, EXTRACT_VALUE, &field);
[email protected]7837be62011-01-18 23:45:08418 }
[email protected]77bb0da2010-11-20 01:55:30419
[email protected]97183052011-11-17 16:35:22420 // TODO(csharp): Stop using the hardcoded value once the WebKit change to
421 // expose the position lands.
422 // gfx::Rect bounding_box(autofill_query_element_.boundsInRootViewSpace());
423 gfx::Rect bounding_box(26, 51, 155, 22);
424
[email protected]663bd9e2011-03-21 01:07:01425 Send(new AutofillHostMsg_QueryFormFieldAutofill(
[email protected]97183052011-11-17 16:35:22426 routing_id(), autofill_query_id_, form, field, bounding_box));
[email protected]e47aec52010-08-12 00:50:30427}
428
[email protected]663bd9e2011-03-21 01:07:01429void AutofillAgent::FillAutofillFormData(const WebNode& node,
[email protected]78192082011-01-29 05:43:44430 int unique_id,
[email protected]663bd9e2011-03-21 01:07:01431 AutofillAction action) {
[email protected]679f128f2010-07-22 22:57:44432 static int query_counter = 0;
433 autofill_query_id_ = query_counter++;
434
435 webkit_glue::FormData form;
[email protected]3bb80e42010-11-29 22:27:16436 webkit_glue::FormField field;
[email protected]283ba4ca2011-09-22 05:25:08437 if (!FindFormAndFieldForInputElement(node.toConst<WebInputElement>(), &form,
438 &field, REQUIRE_AUTOCOMPLETE)) {
[email protected]679f128f2010-07-22 22:57:44439 return;
[email protected]283ba4ca2011-09-22 05:25:08440 }
[email protected]679f128f2010-07-22 22:57:44441
442 autofill_action_ = action;
[email protected]e2aaa812011-03-08 18:46:04443 was_query_node_autofilled_ = field.is_autofilled;
[email protected]663bd9e2011-03-21 01:07:01444 Send(new AutofillHostMsg_FillAutofillFormData(
[email protected]676126f72011-01-15 00:03:51445 routing_id(), autofill_query_id_, form, field, unique_id));
[email protected]679f128f2010-07-22 22:57:44446}
447
[email protected]78192082011-01-29 05:43:44448} // namespace autofill