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 10307004: Support datalist UI for <input type=email multiple> (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed nits Created 8 years, 7 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/string_util.h"
10 #include "base/string_split.h"
9 #include "base/time.h" 11 #include "base/time.h"
10 #include "base/utf_string_conversions.h" 12 #include "base/utf_string_conversions.h"
11 #include "chrome/common/autofill_messages.h" 13 #include "chrome/common/autofill_messages.h"
12 #include "chrome/common/chrome_constants.h" 14 #include "chrome/common/chrome_constants.h"
13 #include "chrome/renderer/autofill/form_autofill_util.h" 15 #include "chrome/renderer/autofill/form_autofill_util.h"
14 #include "chrome/renderer/autofill/password_autofill_manager.h" 16 #include "chrome/renderer/autofill/password_autofill_manager.h"
15 #include "content/public/renderer/render_view.h" 17 #include "content/public/renderer/render_view.h"
16 #include "grit/chromium_strings.h" 18 #include "grit/chromium_strings.h"
17 #include "grit/generated_resources.h" 19 #include "grit/generated_resources.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h" 20 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 54
53 void AppendDataListSuggestions(const WebKit::WebInputElement& element, 55 void AppendDataListSuggestions(const WebKit::WebInputElement& element,
54 std::vector<string16>* values, 56 std::vector<string16>* values,
55 std::vector<string16>* labels, 57 std::vector<string16>* labels,
56 std::vector<string16>* icons, 58 std::vector<string16>* icons,
57 std::vector<int>* item_ids) { 59 std::vector<int>* item_ids) {
58 WebNodeCollection options = element.dataListOptions(); 60 WebNodeCollection options = element.dataListOptions();
59 if (options.isNull()) 61 if (options.isNull())
60 return; 62 return;
61 63
64 string16 prefix = element.editingValue();
65 if (element.isMultiple() &&
66 element.formControlType() == WebString::fromUTF8("email")) {
67 std::vector<string16> parts;
68 base::SplitStringDontTrim(prefix, ',', &parts);
69 if (parts.size() > 0)
70 TrimWhitespace(parts[parts.size() - 1], TRIM_LEADING, &prefix);
71 }
62 for (WebOptionElement option = options.firstItem().to<WebOptionElement>(); 72 for (WebOptionElement option = options.firstItem().to<WebOptionElement>();
63 !option.isNull(); option = options.nextItem().to<WebOptionElement>()) { 73 !option.isNull(); option = options.nextItem().to<WebOptionElement>()) {
64 if (!StartsWith(option.value(), element.value(), false) || 74 if (!StartsWith(option.value(), prefix, false) ||
75 option.value() == prefix ||
65 !element.isValidValue(option.value())) 76 !element.isValidValue(option.value()))
66 continue; 77 continue;
67 78
68 values->push_back(option.value()); 79 values->push_back(option.value());
69 if (option.value() != option.label()) 80 if (option.value() != option.label())
70 labels->push_back(option.label()); 81 labels->push_back(option.label());
71 else 82 else
72 labels->push_back(string16()); 83 labels->push_back(string16());
73 icons->push_back(string16()); 84 icons->push_back(string16());
74 item_ids->push_back(WebAutofillClient::MenuItemIDDataListEntry); 85 item_ids->push_back(WebAutofillClient::MenuItemIDDataListEntry);
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 case WebAutofillClient::MenuItemIDAutofillOptions: 214 case WebAutofillClient::MenuItemIDAutofillOptions:
204 // User selected 'Autofill Options'. 215 // User selected 'Autofill Options'.
205 Send(new AutofillHostMsg_ShowAutofillDialog(routing_id())); 216 Send(new AutofillHostMsg_ShowAutofillDialog(routing_id()));
206 break; 217 break;
207 case WebAutofillClient::MenuItemIDClearForm: 218 case WebAutofillClient::MenuItemIDClearForm:
208 // User selected 'Clear form'. 219 // User selected 'Clear form'.
209 form_cache_.ClearFormWithElement(element_); 220 form_cache_.ClearFormWithElement(element_);
210 break; 221 break;
211 case WebAutofillClient::MenuItemIDAutocompleteEntry: 222 case WebAutofillClient::MenuItemIDAutocompleteEntry:
212 case WebAutofillClient::MenuItemIDPasswordEntry: 223 case WebAutofillClient::MenuItemIDPasswordEntry:
224 // User selected an Autocomplete or password entry, so we fill directly.
225 SetNodeText(value, &element_);
226 break;
213 case WebAutofillClient::MenuItemIDDataListEntry: 227 case WebAutofillClient::MenuItemIDDataListEntry:
214 // User selected an Autocomplete or password or datalist entry, so we 228 ApplyDataListSuggestionToValue(value);
215 // fill directly.
216 SetNodeText(value, &element_);
217 break; 229 break;
218 default: 230 default:
219 // A positive item_id is a unique id for an autofill (vs. autocomplete) 231 // A positive item_id is a unique id for an autofill (vs. autocomplete)
220 // suggestion. 232 // suggestion.
221 DCHECK_GT(item_id, 0); 233 DCHECK_GT(item_id, 0);
222 // Fill the values for the whole form. 234 // Fill the values for the whole form.
223 FillAutofillFormData(node, item_id, AUTOFILL_FILL); 235 FillAutofillFormData(node, item_id, AUTOFILL_FILL);
224 } 236 }
225 } 237 }
226 238
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 432
421 // Send to WebKit for display. 433 // Send to WebKit for display.
422 web_view->applyAutofillSuggestions(element, v, l, i, ids); 434 web_view->applyAutofillSuggestions(element, v, l, i, ids);
423 435
424 Send(new AutofillHostMsg_DidShowAutofillSuggestions( 436 Send(new AutofillHostMsg_DidShowAutofillSuggestions(
425 routing_id(), 437 routing_id(),
426 has_autofill_item && !has_shown_autofill_popup_for_current_edit_)); 438 has_autofill_item && !has_shown_autofill_popup_for_current_edit_));
427 has_shown_autofill_popup_for_current_edit_ |= has_autofill_item; 439 has_shown_autofill_popup_for_current_edit_ |= has_autofill_item;
428 } 440 }
429 441
442 void AutofillAgent::ApplyDataListSuggestionToValue(const string16& value) {
443 string16 new_value = value;
444 // If this element takes multiple values then replace the last part with
445 // the suggestion.
446 if (element_.isMultiple() &&
447 element_.formControlType() == WebString::fromUTF8("email")) {
448 std::vector<string16> parts;
449
450 base::SplitStringDontTrim(element_.editingValue(), ',', &parts);
451 if (parts.size() == 0)
452 parts.push_back(string16());
453
454 string16 last_part = parts.back();
455 // We want to keep just the leading whitespace.
456 for (size_t i = 0; i < last_part.size(); ++i) {
457 if (!IsWhitespace(last_part[i])) {
458 last_part = last_part.substr(0, i);
459 break;
460 }
461 }
462 last_part.append(value);
463 parts[parts.size() - 1] = last_part;
464
465 new_value = JoinString(parts, ',');
466 }
467 SetNodeText(new_value, &element_);
468 }
469
430 void AutofillAgent::OnFormDataFilled(int query_id, 470 void AutofillAgent::OnFormDataFilled(int query_id,
431 const webkit::forms::FormData& form) { 471 const webkit::forms::FormData& form) {
432 if (!render_view()->GetWebView() || query_id != autofill_query_id_) 472 if (!render_view()->GetWebView() || query_id != autofill_query_id_)
433 return; 473 return;
434 474
435 was_query_node_autofilled_ = element_.isAutofilled(); 475 was_query_node_autofilled_ = element_.isAutofilled();
436 476
437 switch (autofill_action_) { 477 switch (autofill_action_) {
438 case AUTOFILL_FILL: 478 case AUTOFILL_FILL:
439 FillForm(form, element_); 479 FillForm(form, element_);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 void AutofillAgent::ShowSuggestions(const WebInputElement& element, 536 void AutofillAgent::ShowSuggestions(const WebInputElement& element,
497 bool autofill_on_empty_values, 537 bool autofill_on_empty_values,
498 bool requires_caret_at_end, 538 bool requires_caret_at_end,
499 bool display_warning_if_disabled) { 539 bool display_warning_if_disabled) {
500 if (!element.isEnabled() || element.isReadOnly() || !element.isTextField() || 540 if (!element.isEnabled() || element.isReadOnly() || !element.isTextField() ||
501 element.isPasswordField() || !element.suggestedValue().isEmpty()) 541 element.isPasswordField() || !element.suggestedValue().isEmpty())
502 return; 542 return;
503 543
504 // Don't attempt to autofill with values that are too large or if filling 544 // Don't attempt to autofill with values that are too large or if filling
505 // criteria are not met. 545 // criteria are not met.
506 WebString value = element.value(); 546 WebString value = element.editingValue();
507 if (value.length() > kMaximumTextSizeForAutofill || 547 if (value.length() > kMaximumTextSizeForAutofill ||
508 (!autofill_on_empty_values && value.isEmpty()) || 548 (!autofill_on_empty_values && value.isEmpty()) ||
509 (requires_caret_at_end && 549 (requires_caret_at_end &&
510 (element.selectionStart() != element.selectionEnd() || 550 (element.selectionStart() != element.selectionEnd() ||
511 element.selectionEnd() != static_cast<int>(value.length())))) { 551 element.selectionEnd() != static_cast<int>(value.length())))) {
512 // Any popup currently showing is obsolete. 552 // Any popup currently showing is obsolete.
513 WebKit::WebView* web_view = render_view()->GetWebView(); 553 WebKit::WebView* web_view = render_view()->GetWebView();
514 if (web_view) 554 if (web_view)
515 web_view->hidePopups(); 555 web_view->hidePopups();
516 556
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 autofill_action_ = action; 620 autofill_action_ = action;
581 Send(new AutofillHostMsg_FillAutofillFormData( 621 Send(new AutofillHostMsg_FillAutofillFormData(
582 routing_id(), autofill_query_id_, form, field, unique_id)); 622 routing_id(), autofill_query_id_, form, field, unique_id));
583 } 623 }
584 624
585 void AutofillAgent::SetNodeText(const string16& value, 625 void AutofillAgent::SetNodeText(const string16& value,
586 WebKit::WebInputElement* node) { 626 WebKit::WebInputElement* node) {
587 string16 substring = value; 627 string16 substring = value;
588 substring = substring.substr(0, node->maxLength()); 628 substring = substring.substr(0, node->maxLength());
589 629
590 node->setValue(substring, true); 630 WebKit::WebView* web_view = render_view()->GetWebView();
631 if (!web_view)
632 return;
Ilya Sherman 2012/05/16 18:05:31 nit: I still don't see why we're checking for the
keishi 2012/05/17 02:24:09 Yes. Sorry I wasn't paying attention. Done.
633
634 node->setEditingValue(substring);
591 } 635 }
592 636
593 } // namespace autofill 637 } // namespace autofill
OLDNEW
« chrome/renderer/autofill/autofill_agent.h ('K') | « chrome/renderer/autofill/autofill_agent.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698