OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |