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

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

Issue 10024059: DataList UI (Chromium part) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed Created 8 years, 8 months 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/time.h" 9 #include "base/time.h"
10 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
11 #include "chrome/common/autofill_messages.h" 11 #include "chrome/common/autofill_messages.h"
12 #include "chrome/common/chrome_constants.h" 12 #include "chrome/common/chrome_constants.h"
13 #include "chrome/renderer/autofill/form_autofill_util.h" 13 #include "chrome/renderer/autofill/form_autofill_util.h"
14 #include "chrome/renderer/autofill/password_autofill_manager.h" 14 #include "chrome/renderer/autofill/password_autofill_manager.h"
15 #include "content/public/renderer/render_view.h" 15 #include "content/public/renderer/render_view.h"
16 #include "grit/chromium_strings.h" 16 #include "grit/chromium_strings.h"
17 #include "grit/generated_resources.h" 17 #include "grit/generated_resources.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDataListElement.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" 20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement .h" 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement .h"
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" 23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" 24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h"
25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeCollection.h"
26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebOptionElement.h"
23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" 27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
24 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
25 #include "ui/base/keycodes/keyboard_codes.h" 28 #include "ui/base/keycodes/keyboard_codes.h"
26 #include "ui/base/l10n/l10n_util.h" 29 #include "ui/base/l10n/l10n_util.h"
27 #include "webkit/forms/form_data.h" 30 #include "webkit/forms/form_data.h"
28 #include "webkit/forms/form_data_predictions.h" 31 #include "webkit/forms/form_data_predictions.h"
29 #include "webkit/forms/form_field.h" 32 #include "webkit/forms/form_field.h"
30 #include "webkit/forms/password_form.h" 33 #include "webkit/forms/password_form.h"
31 34
35 using WebKit::WebAutofillClient;
36 using WebKit::WebDataListElement;
32 using WebKit::WebFormControlElement; 37 using WebKit::WebFormControlElement;
33 using WebKit::WebFormElement; 38 using WebKit::WebFormElement;
34 using WebKit::WebFrame; 39 using WebKit::WebFrame;
35 using WebKit::WebInputElement; 40 using WebKit::WebInputElement;
36 using WebKit::WebKeyboardEvent; 41 using WebKit::WebKeyboardEvent;
37 using WebKit::WebNode; 42 using WebKit::WebNode;
43 using WebKit::WebNodeCollection;
44 using WebKit::WebOptionElement;
38 using WebKit::WebString; 45 using WebKit::WebString;
39 using webkit::forms::FormData; 46 using webkit::forms::FormData;
40 using webkit::forms::FormDataPredictions; 47 using webkit::forms::FormDataPredictions;
41 48
42 namespace { 49 namespace {
43 50
44 // The size above which we stop triggering autofill for an input text field 51 // The size above which we stop triggering autofill for an input text field
45 // (so to avoid sending long strings through IPC). 52 // (so to avoid sending long strings through IPC).
46 const size_t kMaximumTextSizeForAutofill = 1000; 53 const size_t kMaximumTextSizeForAutofill = 1000;
47 54
55 void AppendDataListSuggestions(const WebKit::WebInputElement& element,
56 std::vector<string16>* values,
57 std::vector<string16>* labels,
58 std::vector<string16>* icons,
59 std::vector<int>* item_ids) {
60 WebDataListElement dataList = element.dataList();
61 if (dataList.isNull())
62 return;
63
64 WebNodeCollection options = dataList.options();
65 WebOptionElement option = options.firstItem().to<WebOptionElement>();
66 while (!option.isNull()) {
67 values->push_back(option.value());
68 if (option.value() != option.label())
69 labels->push_back(option.label());
70 else
71 labels->push_back(string16());
72 icons->push_back(string16());
73 item_ids->push_back(WebAutofillClient::DataListEntryMenuItemID);
74 option = options.nextItem().to<WebOptionElement>();
75 }
76 }
77
48 } // namespace 78 } // namespace
49 79
50 namespace autofill { 80 namespace autofill {
51 81
52 AutofillAgent::AutofillAgent( 82 AutofillAgent::AutofillAgent(
53 content::RenderView* render_view, 83 content::RenderView* render_view,
54 PasswordAutofillManager* password_autofill_manager) 84 PasswordAutofillManager* password_autofill_manager)
55 : content::RenderViewObserver(render_view), 85 : content::RenderViewObserver(render_view),
56 password_autofill_manager_(password_autofill_manager), 86 password_autofill_manager_(password_autofill_manager),
57 autofill_query_id_(0), 87 autofill_query_id_(0),
58 autofill_action_(AUTOFILL_NONE), 88 autofill_action_(AUTOFILL_NONE),
59 display_warning_if_disabled_(false), 89 display_warning_if_disabled_(false),
60 was_query_node_autofilled_(false), 90 was_query_node_autofilled_(false),
61 suggestions_clear_index_(-1),
62 suggestions_options_index_(-1),
63 has_shown_autofill_popup_for_current_edit_(false), 91 has_shown_autofill_popup_for_current_edit_(false),
64 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { 92 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
65 render_view->GetWebView()->setAutofillClient(this); 93 render_view->GetWebView()->setAutofillClient(this);
66 } 94 }
67 95
68 AutofillAgent::~AutofillAgent() {} 96 AutofillAgent::~AutofillAgent() {}
69 97
70 bool AutofillAgent::OnMessageReceived(const IPC::Message& message) { 98 bool AutofillAgent::OnMessageReceived(const IPC::Message& message) {
71 bool handled = true; 99 bool handled = true;
72 IPC_BEGIN_MESSAGE_MAP(AutofillAgent, message) 100 IPC_BEGIN_MESSAGE_MAP(AutofillAgent, message)
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 167
140 bool AutofillAgent::InputElementLostFocus() { 168 bool AutofillAgent::InputElementLostFocus() {
141 Send(new AutofillHostMsg_HideAutofillPopup(routing_id())); 169 Send(new AutofillHostMsg_HideAutofillPopup(routing_id()));
142 170
143 return false; 171 return false;
144 } 172 }
145 173
146 void AutofillAgent::didAcceptAutofillSuggestion(const WebNode& node, 174 void AutofillAgent::didAcceptAutofillSuggestion(const WebNode& node,
147 const WebString& value, 175 const WebString& value,
148 const WebString& label, 176 const WebString& label,
149 int unique_id, 177 int item_id,
150 unsigned index) { 178 unsigned index) {
151 if (password_autofill_manager_->DidAcceptAutofillSuggestion(node, value)) 179 if (password_autofill_manager_->DidAcceptAutofillSuggestion(node, value))
152 return; 180 return;
153 181
154 DCHECK(node == autofill_query_element_); 182 DCHECK(node == element_);
155 183
156 if (suggestions_options_index_ != -1 && 184 switch (item_id) {
157 index == static_cast<unsigned>(suggestions_options_index_)) { 185 case WebAutofillClient::WarningMessageMenuItemID:
158 // User selected 'Autofill Options'. 186 case WebAutofillClient::SeparatorMenuItemID:
159 Send(new AutofillHostMsg_ShowAutofillDialog(routing_id())); 187 NOTREACHED();
160 } else if (suggestions_clear_index_ != -1 && 188 break;
161 index == static_cast<unsigned>(suggestions_clear_index_)) { 189 case WebAutofillClient::AutofillOptionsMenuItemID:
162 // User selected 'Clear form'. 190 // User selected 'Autofill Options'.
163 form_cache_.ClearFormWithElement(autofill_query_element_); 191 Send(new AutofillHostMsg_ShowAutofillDialog(routing_id()));
164 } else if (!unique_id) { 192 break;
165 // User selected an Autocomplete entry, so we fill directly. 193 case WebAutofillClient::ClearFormMenuItemID:
166 WebInputElement element = node.toConst<WebInputElement>(); 194 // User selected 'Clear form'.
167 SetNodeText(value, &element); 195 form_cache_.ClearFormWithElement(element_);
168 } else { 196 break;
169 // Fill the values for the whole form. 197 case WebAutofillClient::AutocompleteEntryMenuItemID:
170 FillAutofillFormData(node, unique_id, AUTOFILL_FILL); 198 case WebAutofillClient::PasswordEntryMenuItemID:
199 case WebAutofillClient::DataListEntryMenuItemID:
200 // User selected an Autocomplete or password or datalist entry, so we
201 // fill directly.
202 SetNodeText(value, &element_);
203 break;
204 default:
205 // A positive item_id is a unique id for an autofill (vs. autocomplete)
206 // suggestion.
207 DCHECK_GT(item_id, 0);
208 // Fill the values for the whole form.
209 FillAutofillFormData(node, item_id, AUTOFILL_FILL);
171 } 210 }
172
173 suggestions_clear_index_ = -1;
174 suggestions_options_index_ = -1;
175 } 211 }
176 212
177 void AutofillAgent::didSelectAutofillSuggestion(const WebNode& node, 213 void AutofillAgent::didSelectAutofillSuggestion(const WebNode& node,
178 const WebString& value, 214 const WebString& value,
179 const WebString& label, 215 const WebString& label,
180 int unique_id) { 216 int item_id) {
181 DCHECK_GE(unique_id, 0);
182 if (password_autofill_manager_->DidSelectAutofillSuggestion(node)) 217 if (password_autofill_manager_->DidSelectAutofillSuggestion(node))
183 return; 218 return;
184 219
185 didClearAutofillSelection(node); 220 didClearAutofillSelection(node);
186 FillAutofillFormData(node, unique_id, AUTOFILL_PREVIEW); 221
222 if (item_id > 0)
223 FillAutofillFormData(node, item_id, AUTOFILL_PREVIEW);
187 } 224 }
188 225
189 void AutofillAgent::didClearAutofillSelection(const WebNode& node) { 226 void AutofillAgent::didClearAutofillSelection(const WebNode& node) {
190 if (password_autofill_manager_->DidClearAutofillSelection(node)) 227 if (password_autofill_manager_->DidClearAutofillSelection(node))
191 return; 228 return;
192 229
193 if (!autofill_query_element_.isNull() && node == autofill_query_element_) { 230 if (!element_.isNull() && node == element_) {
194 ClearPreviewedFormWithElement(autofill_query_element_, 231 ClearPreviewedFormWithElement(element_, was_query_node_autofilled_);
195 was_query_node_autofilled_);
196 } else { 232 } else {
197 // TODO(isherman): There seem to be rare cases where this code *is* 233 // TODO(isherman): There seem to be rare cases where this code *is*
198 // reachable: see [ http://crbug.com/96321#c6 ]. Ideally we would 234 // reachable: see [ http://crbug.com/96321#c6 ]. Ideally we would
199 // understand those cases and fix the code to avoid them. However, so far I 235 // understand those cases and fix the code to avoid them. However, so far I
200 // have been unable to reproduce such a case locally. If you hit this 236 // have been unable to reproduce such a case locally. If you hit this
201 // NOTREACHED(), please file a bug against me. 237 // NOTREACHED(), please file a bug against me.
202 NOTREACHED(); 238 NOTREACHED();
203 } 239 }
204 } 240 }
205 241
206 void AutofillAgent::removeAutocompleteSuggestion(const WebString& name, 242 void AutofillAgent::removeAutocompleteSuggestion(const WebString& name,
207 const WebString& value) { 243 const WebString& value) {
208 // The index of clear & options will have shifted down.
209 if (suggestions_clear_index_ != -1)
210 suggestions_clear_index_--;
211 if (suggestions_options_index_ != -1)
212 suggestions_options_index_--;
213
214 Send(new AutofillHostMsg_RemoveAutocompleteEntry(routing_id(), name, value)); 244 Send(new AutofillHostMsg_RemoveAutocompleteEntry(routing_id(), name, value));
215 } 245 }
216 246
217 void AutofillAgent::textFieldDidEndEditing(const WebInputElement& element) { 247 void AutofillAgent::textFieldDidEndEditing(const WebInputElement& element) {
218 password_autofill_manager_->TextFieldDidEndEditing(element); 248 password_autofill_manager_->TextFieldDidEndEditing(element);
219 has_shown_autofill_popup_for_current_edit_ = false; 249 has_shown_autofill_popup_for_current_edit_ = false;
220 Send(new AutofillHostMsg_DidEndTextFieldEditing(routing_id())); 250 Send(new AutofillHostMsg_DidEndTextFieldEditing(routing_id()));
221 } 251 }
222 252
223 void AutofillAgent::textFieldDidChange(const WebInputElement& element) { 253 void AutofillAgent::textFieldDidChange(const WebInputElement& element) {
224 // We post a task for doing the Autofill as the caret position is not set 254 // We post a task for doing the Autofill as the caret position is not set
225 // properly at this point (http://bugs.webkit.org/show_bug.cgi?id=16976) and 255 // properly at this point (http://bugs.webkit.org/show_bug.cgi?id=16976) and
226 // it is needed to trigger autofill. 256 // it is needed to trigger autofill.
227 weak_ptr_factory_.InvalidateWeakPtrs(); 257 weak_ptr_factory_.InvalidateWeakPtrs();
228 MessageLoop::current()->PostTask( 258 MessageLoop::current()->PostTask(
229 FROM_HERE, 259 FROM_HERE,
230 base::Bind(&AutofillAgent::TextFieldDidChangeImpl, 260 base::Bind(&AutofillAgent::TextFieldDidChangeImpl,
231 weak_ptr_factory_.GetWeakPtr(), element)); 261 weak_ptr_factory_.GetWeakPtr(), element));
232 } 262 }
233 263
234 void AutofillAgent::TextFieldDidChangeImpl(const WebInputElement& element) { 264 void AutofillAgent::TextFieldDidChangeImpl(const WebInputElement& element) {
235 if (password_autofill_manager_->TextDidChangeInTextField(element)) { 265 if (password_autofill_manager_->TextDidChangeInTextField(element)) {
236 autofill_query_element_ = element; 266 element_ = element;
237 return; 267 return;
238 } 268 }
239 269
240 ShowSuggestions(element, false, true, false); 270 ShowSuggestions(element, false, true, false);
241 271
242 webkit::forms::FormData form; 272 webkit::forms::FormData form;
243 webkit::forms::FormField field; 273 webkit::forms::FormField field;
244 if (FindFormAndFieldForInputElement(element, &form, &field, REQUIRE_NONE)) { 274 if (FindFormAndFieldForInputElement(element, &form, &field, REQUIRE_NONE)) {
245 Send(new AutofillHostMsg_TextFieldDidChange(routing_id(), form, field, 275 Send(new AutofillHostMsg_TextFieldDidChange(routing_id(), form, field,
246 base::TimeTicks::Now())); 276 base::TimeTicks::Now()));
247 } 277 }
248 } 278 }
249 279
250 void AutofillAgent::textFieldDidReceiveKeyDown(const WebInputElement& element, 280 void AutofillAgent::textFieldDidReceiveKeyDown(const WebInputElement& element,
251 const WebKeyboardEvent& event) { 281 const WebKeyboardEvent& event) {
252 if (password_autofill_manager_->TextFieldHandlingKeyDown(element, event)) { 282 if (password_autofill_manager_->TextFieldHandlingKeyDown(element, event)) {
253 autofill_query_element_ = element; 283 element_ = element;
254 return; 284 return;
255 } 285 }
256 286
257 if (event.windowsKeyCode == ui::VKEY_DOWN || 287 if (event.windowsKeyCode == ui::VKEY_DOWN ||
258 event.windowsKeyCode == ui::VKEY_UP) 288 event.windowsKeyCode == ui::VKEY_UP)
259 ShowSuggestions(element, true, true, true); 289 ShowSuggestions(element, true, true, true);
260 } 290 }
261 291
262 void AutofillAgent::OnSuggestionsReturned(int query_id, 292 void AutofillAgent::OnSuggestionsReturned(int query_id,
263 const std::vector<string16>& values, 293 const std::vector<string16>& values,
264 const std::vector<string16>& labels, 294 const std::vector<string16>& labels,
265 const std::vector<string16>& icons, 295 const std::vector<string16>& icons,
266 const std::vector<int>& unique_ids) { 296 const std::vector<int>& unique_ids) {
267 WebKit::WebView* web_view = render_view()->GetWebView(); 297 WebKit::WebView* web_view = render_view()->GetWebView();
268 if (!web_view || query_id != autofill_query_id_) 298 if (!web_view || query_id != autofill_query_id_)
269 return; 299 return;
Ilya Sherman 2012/04/12 23:38:10 nit: It looks like |web_view| is no longer used in
keishi 2012/04/13 08:01:18 Done.
270 300
271 if (values.empty()) {
272 // No suggestions, any popup currently showing is obsolete.
273 web_view->hidePopups();
274 return;
275 }
276
277 std::vector<string16> v(values); 301 std::vector<string16> v(values);
278 std::vector<string16> l(labels); 302 std::vector<string16> l(labels);
279 std::vector<string16> i(icons); 303 std::vector<string16> i(icons);
280 std::vector<int> ids(unique_ids); 304 std::vector<int> ids(unique_ids);
281 int separator_index = -1;
282 305
283 DCHECK_GT(ids.size(), 0U); 306 if (!element_.isNull() && !element_.autoComplete()) {
284 if (!autofill_query_element_.isNull() &&
285 !autofill_query_element_.autoComplete()) {
286 // If autofill is disabled and we had suggestions, show a warning instead. 307 // If autofill is disabled and we had suggestions, show a warning instead.
Ilya Sherman 2012/04/12 23:38:10 The DCHECK_GT previously guaranteed that we had su
keishi 2012/04/13 08:01:18 Done.
287 v.assign(1, l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED)); 308 v.assign(1, l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED));
288 l.assign(1, string16()); 309 l.assign(1, string16());
289 i.assign(1, string16()); 310 i.assign(1, string16());
290 ids.assign(1, -1); 311 ids.assign(1, WebAutofillClient::WarningMessageMenuItemID);
291 } else if (ids[0] < 0 && ids.size() > 1) { 312 } else if (ids.size() > 1 &&
292 // If we received a warning instead of suggestions from autofill but regular 313 ids[0] == WebAutofillClient::WarningMessageMenuItemID) {
293 // suggestions from autocomplete, don't show the autofill warning. 314 // If we received an autofill warning plus some autocomplete suggestions,
315 // remove the autofill warning.
294 v.erase(v.begin()); 316 v.erase(v.begin());
295 l.erase(l.begin()); 317 l.erase(l.begin());
296 i.erase(i.begin()); 318 i.erase(i.begin());
297 ids.erase(ids.begin()); 319 ids.erase(ids.begin());
298 } 320 }
299 321
300 // If we were about to show a warning and we shouldn't, don't.
301 if (ids[0] < 0 && !display_warning_if_disabled_)
302 return;
303
304 // Only include "Autofill Options" special menu item if we have Autofill 322 // Only include "Autofill Options" special menu item if we have Autofill
305 // items, identified by |unique_ids| having at least one valid value. 323 // items, identified by |unique_ids| having at least one valid value.
306 bool has_autofill_item = false; 324 bool has_autofill_item = false;
325 bool has_warning_item = false;
307 for (size_t i = 0; i < ids.size(); ++i) { 326 for (size_t i = 0; i < ids.size(); ++i) {
308 if (ids[i] > 0) { 327 if (ids[i] > 0)
309 has_autofill_item = true; 328 has_autofill_item = true;
310 break; 329 else if (ids[i] == WebAutofillClient::WarningMessageMenuItemID) {
311 } 330 has_warning_item = true;
312 } 331 if (has_autofill_item && has_warning_item)
Ilya Sherman 2012/04/12 23:38:10 This case should be unreachable -- autofill items
keishi 2012/04/13 08:01:18 Done.
313 332 break;
314 // The form has been auto-filled, so give the user the chance to clear the
315 // form. Append the 'Clear form' menu item.
316 if (has_autofill_item &&
317 FormWithElementIsAutofilled(autofill_query_element_)) {
318 v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM));
319 l.push_back(string16());
320 i.push_back(string16());
321 ids.push_back(0);
322 suggestions_clear_index_ = v.size() - 1;
323 separator_index = v.size() - 1;
324 } 333 }
325 334
326 if (has_autofill_item) { 335 if (has_autofill_item) {
336 v.push_back(string16());
337 l.push_back(string16());
338 i.push_back(string16());
339 ids.push_back(WebAutofillClient::SeparatorMenuItemID);
340
341 if (FormWithElementIsAutofilled(element_)) {
342 // The form has been auto-filled, so give the user the chance to clear the
343 // form. Append the 'Clear form' menu item.
344 v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM));
345 l.push_back(string16());
346 i.push_back(string16());
347 ids.push_back(WebAutofillClient::ClearFormMenuItemID);
348 }
349
327 // Append the 'Chrome Autofill options' menu item; 350 // Append the 'Chrome Autofill options' menu item;
328 v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_OPTIONS_POPUP)); 351 v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_OPTIONS_POPUP));
329 l.push_back(string16()); 352 l.push_back(string16());
330 i.push_back(string16()); 353 i.push_back(string16());
331 ids.push_back(0); 354 ids.push_back(WebAutofillClient::AutofillOptionsMenuItemID);
332 suggestions_options_index_ = v.size() - 1; 355 }
333 separator_index = values.size(); 356
357 // If we were about to show a warning and we shouldn't, don't.
358 if (!display_warning_if_disabled_ && has_warning_item) {
359 v.clear();
360 l.clear();
361 i.clear();
362 ids.clear();
363 }
Ilya Sherman 2012/04/12 23:38:10 I don't think you need to move this logic from whe
keishi 2012/04/13 08:01:18 Done.
364
365 if (!element_.isNull() && element_.isFocusable())
366 CombineDataListEntriesAndShow(element_, v, l, i, ids, has_autofill_item);
367 }
368
369 void AutofillAgent::CombineDataListEntriesAndShow(
370 const WebKit::WebInputElement& element,
371 const std::vector<string16>& values,
372 const std::vector<string16>& labels,
373 const std::vector<string16>& icons,
374 const std::vector<int>& item_ids,
375 bool has_autofill_item) {
376 std::vector<string16> v;
377 std::vector<string16> l;
378 std::vector<string16> i;
379 std::vector<int> ids;
380
381 AppendDataListSuggestions(element, &v, &l, &i, &ids);
382
383 // If there are both <datalist> items and Autofill suggestions, add a
384 // separator between them.
385 if (!v.empty() && !values.empty()) {
386 v.push_back(string16());
387 l.push_back(string16());
388 i.push_back(string16());
389 ids.push_back(WebAutofillClient::SeparatorMenuItemID);
390 }
391
392 v.insert(v.end(), values.begin(), values.end());
393 l.insert(l.end(), labels.begin(), labels.end());
394 i.insert(i.end(), icons.begin(), icons.end());
395 ids.insert(ids.end(), item_ids.begin(), item_ids.end());
396
397 WebKit::WebView* web_view = render_view()->GetWebView();
398 if (!web_view)
399 return;
400
401 if (v.empty()) {
402 // No suggestions, any popup currently showing is obsolete.
403 web_view->hidePopups();
404 return;
334 } 405 }
335 406
336 // Send to WebKit for display. 407 // Send to WebKit for display.
337 if (!v.empty() && !autofill_query_element_.isNull() && 408 web_view->applyAutofillSuggestions(element, v, l, i, ids);
338 autofill_query_element_.isFocusable()) {
339 web_view->applyAutofillSuggestions(
340 autofill_query_element_, v, l, i, ids, separator_index);
341 }
342 409
343 Send(new AutofillHostMsg_DidShowAutofillSuggestions( 410 Send(new AutofillHostMsg_DidShowAutofillSuggestions(
344 routing_id(), 411 routing_id(),
345 has_autofill_item && !has_shown_autofill_popup_for_current_edit_)); 412 has_autofill_item && !has_shown_autofill_popup_for_current_edit_));
346 has_shown_autofill_popup_for_current_edit_ |= has_autofill_item; 413 has_shown_autofill_popup_for_current_edit_ |= has_autofill_item;
347 } 414 }
348 415
349 void AutofillAgent::OnFormDataFilled(int query_id, 416 void AutofillAgent::OnFormDataFilled(int query_id,
350 const webkit::forms::FormData& form) { 417 const webkit::forms::FormData& form) {
351 if (!render_view()->GetWebView() || query_id != autofill_query_id_) 418 if (!render_view()->GetWebView() || query_id != autofill_query_id_)
352 return; 419 return;
353 420
354 was_query_node_autofilled_ = autofill_query_element_.isAutofilled(); 421 was_query_node_autofilled_ = element_.isAutofilled();
355 422
356 switch (autofill_action_) { 423 switch (autofill_action_) {
357 case AUTOFILL_FILL: 424 case AUTOFILL_FILL:
358 FillForm(form, autofill_query_element_); 425 FillForm(form, element_);
359 Send(new AutofillHostMsg_DidFillAutofillFormData(routing_id(), 426 Send(new AutofillHostMsg_DidFillAutofillFormData(routing_id(),
360 base::TimeTicks::Now())); 427 base::TimeTicks::Now()));
361 break; 428 break;
362 case AUTOFILL_PREVIEW: 429 case AUTOFILL_PREVIEW:
363 didClearAutofillSelection(autofill_query_element_); 430 didClearAutofillSelection(element_);
364 431
365 PreviewForm(form, autofill_query_element_); 432 PreviewForm(form, element_);
366 Send(new AutofillHostMsg_DidPreviewAutofillFormData(routing_id())); 433 Send(new AutofillHostMsg_DidPreviewAutofillFormData(routing_id()));
367 break; 434 break;
368 default: 435 default:
369 NOTREACHED(); 436 NOTREACHED();
370 } 437 }
371 autofill_action_ = AUTOFILL_NONE; 438 autofill_action_ = AUTOFILL_NONE;
372 } 439 }
373 440
374 void AutofillAgent::OnFieldTypePredictionsAvailable( 441 void AutofillAgent::OnFieldTypePredictionsAvailable(
375 const std::vector<FormDataPredictions>& forms) { 442 const std::vector<FormDataPredictions>& forms) {
376 for (size_t i = 0; i < forms.size(); ++i) { 443 for (size_t i = 0; i < forms.size(); ++i) {
377 form_cache_.ShowPredictions(forms[i]); 444 form_cache_.ShowPredictions(forms[i]);
378 } 445 }
379 } 446 }
380 447
381 void AutofillAgent::OnSelectAutofillSuggestionAtIndex(int listIndex) { 448 void AutofillAgent::OnSelectAutofillSuggestionAtIndex(int listIndex) {
382 NOTIMPLEMENTED(); 449 NOTIMPLEMENTED();
383 // TODO(jrg): enable once changes land in WebKit 450 // TODO(jrg): enable once changes land in WebKit
384 // render_view()->webview()->selectAutofillSuggestionAtIndex(listIndex); 451 // render_view()->webview()->selectAutofillSuggestionAtIndex(listIndex);
385 } 452 }
386 453
387 void AutofillAgent::OnSetAutofillActionFill() { 454 void AutofillAgent::OnSetAutofillActionFill() {
388 autofill_action_ = AUTOFILL_FILL; 455 autofill_action_ = AUTOFILL_FILL;
389 } 456 }
390 457
391 void AutofillAgent::OnClearForm() { 458 void AutofillAgent::OnClearForm() {
392 form_cache_.ClearFormWithElement(autofill_query_element_); 459 form_cache_.ClearFormWithElement(element_);
393 } 460 }
394 461
395 void AutofillAgent::OnSetAutofillActionPreview() { 462 void AutofillAgent::OnSetAutofillActionPreview() {
396 autofill_action_ = AUTOFILL_PREVIEW; 463 autofill_action_ = AUTOFILL_PREVIEW;
397 } 464 }
398 465
399 void AutofillAgent::OnClearPreviewedForm() { 466 void AutofillAgent::OnClearPreviewedForm() {
400 didClearAutofillSelection(autofill_query_element_); 467 didClearAutofillSelection(element_);
401 } 468 }
402 469
403 void AutofillAgent::OnSetNodeText(const string16& value) { 470 void AutofillAgent::OnSetNodeText(const string16& value) {
404 SetNodeText(value, &autofill_query_element_); 471 SetNodeText(value, &element_);
405 } 472 }
406 473
407 void AutofillAgent::OnAcceptPasswordAutofillSuggestion(const string16& value) { 474 void AutofillAgent::OnAcceptPasswordAutofillSuggestion(const string16& value) {
408 // We need to make sure this is handled here because the browser process 475 // We need to make sure this is handled here because the browser process
409 // skipped it handling because it believed it would be handled here. If it 476 // skipped it handling because it believed it would be handled here. If it
410 // isn't handled here then the browser logic needs to be updated. 477 // isn't handled here then the browser logic needs to be updated.
411 bool handled = password_autofill_manager_->DidAcceptAutofillSuggestion( 478 bool handled = password_autofill_manager_->DidAcceptAutofillSuggestion(
412 autofill_query_element_, 479 element_,
413 value); 480 value);
414 DCHECK(handled); 481 DCHECK(handled);
415 } 482 }
416 483
417 void AutofillAgent::ShowSuggestions(const WebInputElement& element, 484 void AutofillAgent::ShowSuggestions(const WebInputElement& element,
418 bool autofill_on_empty_values, 485 bool autofill_on_empty_values,
419 bool requires_caret_at_end, 486 bool requires_caret_at_end,
420 bool display_warning_if_disabled) { 487 bool display_warning_if_disabled) {
421 // If autocomplete is disabled at the form level, then we might want to show 488 if (!element.isEnabled() || element.isReadOnly() || !element.isTextField() ||
422 // a warning in place of suggestions. However, if autocomplete is disabled 489 element.isPasswordField() || !element.suggestedValue().isEmpty())
423 // specifically for this field, we never want to show a warning. Otherwise,
424 // we might interfere with custom popups (e.g. search suggestions) used by
425 // the website.
426 const WebFormElement form = element.form();
427 if (!element.isEnabled() || element.isReadOnly() ||
428 (!element.autoComplete() && (form.isNull() || form.autoComplete())) ||
429 !element.isTextField() || element.isPasswordField() ||
430 !element.suggestedValue().isEmpty())
431 return;
432
433 // If the field has no name, then we won't have values.
434 if (element.nameForAutofill().isEmpty())
435 return; 490 return;
436 491
437 // Don't attempt to autofill with values that are too large or if filling 492 // Don't attempt to autofill with values that are too large or if filling
438 // criteria are not met. 493 // criteria are not met.
439 WebString value = element.value(); 494 WebString value = element.value();
440 if (value.length() > kMaximumTextSizeForAutofill || 495 if (value.length() > kMaximumTextSizeForAutofill ||
441 (!autofill_on_empty_values && value.isEmpty()) || 496 (!autofill_on_empty_values && value.isEmpty()) ||
442 (requires_caret_at_end && 497 (requires_caret_at_end &&
443 (element.selectionStart() != element.selectionEnd() || 498 (element.selectionStart() != element.selectionEnd() ||
444 element.selectionEnd() != static_cast<int>(value.length())))) { 499 element.selectionEnd() != static_cast<int>(value.length())))) {
445 // Any popup currently showing is obsolete. 500 // Any popup currently showing is obsolete.
446 WebKit::WebView* web_view = render_view()->GetWebView(); 501 WebKit::WebView* web_view = render_view()->GetWebView();
447 if (web_view) 502 if (web_view)
448 web_view->hidePopups(); 503 web_view->hidePopups();
449 504
450 return; 505 return;
451 } 506 }
452 507
508 element_ = element;
509
510 // If autocomplete is disabled at the form level, then we might want to show
511 // a warning in place of suggestions. However, if autocomplete is disabled
512 // specifically for this field, we never want to show a warning. Otherwise,
513 // we might interfere with custom popups (e.g. search suggestions) used by
514 // the website. Also, if the field has no name, then we won't have values.
515 const WebFormElement form = element.form();
516 if ((!element.autoComplete() && (form.isNull() || form.autoComplete())) ||
517 element.nameForAutofill().isEmpty()) {
518 CombineDataListEntriesAndShow(element, std::vector<string16>(),
519 std::vector<string16>(),
520 std::vector<string16>(),
521 std::vector<int>(), false);
522 return;
523 }
524
453 QueryAutofillSuggestions(element, display_warning_if_disabled); 525 QueryAutofillSuggestions(element, display_warning_if_disabled);
454 } 526 }
455 527
456 void AutofillAgent::QueryAutofillSuggestions(const WebInputElement& element, 528 void AutofillAgent::QueryAutofillSuggestions(const WebInputElement& element,
457 bool display_warning_if_disabled) { 529 bool display_warning_if_disabled) {
458 static int query_counter = 0; 530 static int query_counter = 0;
459 autofill_query_id_ = query_counter++; 531 autofill_query_id_ = query_counter++;
460 autofill_query_element_ = element;
461 display_warning_if_disabled_ = display_warning_if_disabled; 532 display_warning_if_disabled_ = display_warning_if_disabled;
462 533
463 webkit::forms::FormData form; 534 webkit::forms::FormData form;
464 webkit::forms::FormField field; 535 webkit::forms::FormField field;
465 if (!FindFormAndFieldForInputElement(element, &form, &field, 536 if (!FindFormAndFieldForInputElement(element, &form, &field,
466 REQUIRE_AUTOCOMPLETE)) { 537 REQUIRE_AUTOCOMPLETE)) {
467 // If we didn't find the cached form, at least let autocomplete have a shot 538 // If we didn't find the cached form, at least let autocomplete have a shot
468 // at providing suggestions. 539 // at providing suggestions.
469 WebFormControlElementToFormField(element, EXTRACT_VALUE, &field); 540 WebFormControlElementToFormField(element, EXTRACT_VALUE, &field);
470 } 541 }
471 542
472 gfx::Rect bounding_box(autofill_query_element_.boundsInViewportSpace()); 543 gfx::Rect bounding_box(element_.boundsInViewportSpace());
473 544
474 Send(new AutofillHostMsg_QueryFormFieldAutofill(routing_id(), 545 Send(new AutofillHostMsg_QueryFormFieldAutofill(routing_id(),
475 autofill_query_id_, 546 autofill_query_id_,
476 form, 547 form,
477 field, 548 field,
478 bounding_box, 549 bounding_box,
479 display_warning_if_disabled)); 550 display_warning_if_disabled));
480 } 551 }
481 552
482 void AutofillAgent::FillAutofillFormData(const WebNode& node, 553 void AutofillAgent::FillAutofillFormData(const WebNode& node,
483 int unique_id, 554 int unique_id,
484 AutofillAction action) { 555 AutofillAction action) {
556 DCHECK_GT(unique_id, 0);
557
485 static int query_counter = 0; 558 static int query_counter = 0;
486 autofill_query_id_ = query_counter++; 559 autofill_query_id_ = query_counter++;
487 560
488 webkit::forms::FormData form; 561 webkit::forms::FormData form;
489 webkit::forms::FormField field; 562 webkit::forms::FormField field;
490 if (!FindFormAndFieldForInputElement(node.toConst<WebInputElement>(), &form, 563 if (!FindFormAndFieldForInputElement(node.toConst<WebInputElement>(), &form,
491 &field, REQUIRE_AUTOCOMPLETE)) { 564 &field, REQUIRE_AUTOCOMPLETE)) {
492 return; 565 return;
493 } 566 }
494 567
495 autofill_action_ = action; 568 autofill_action_ = action;
496 Send(new AutofillHostMsg_FillAutofillFormData( 569 Send(new AutofillHostMsg_FillAutofillFormData(
497 routing_id(), autofill_query_id_, form, field, unique_id)); 570 routing_id(), autofill_query_id_, form, field, unique_id));
498 } 571 }
499 572
500 void AutofillAgent::SetNodeText(const string16& value, 573 void AutofillAgent::SetNodeText(const string16& value,
501 WebKit::WebInputElement* node) { 574 WebKit::WebInputElement* node) {
502 string16 substring = value; 575 string16 substring = value;
503 substring = substring.substr(0, node->maxLength()); 576 substring = substring.substr(0, node->maxLength());
504 577
505 node->setValue(substring, true); 578 node->setValue(substring, true);
506 } 579 }
507 580
508 } // namespace autofill 581 } // namespace autofill
OLDNEW
« no previous file with comments | « chrome/renderer/autofill/autofill_agent.h ('k') | chrome/renderer/autofill/password_autofill_manager.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698