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/time.h" | 9 #include "base/time.h" |
10 #include "base/string_util.h" | |
11 #include "base/string_split.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" |
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
(...skipping 32 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)) |
65 continue; | 75 continue; |
66 | 76 |
67 values->push_back(option.value()); | 77 values->push_back(option.value()); |
68 if (option.value() != option.label()) | 78 if (option.value() != option.label()) |
69 labels->push_back(option.label()); | 79 labels->push_back(option.label()); |
70 else | 80 else |
71 labels->push_back(string16()); | 81 labels->push_back(string16()); |
72 icons->push_back(string16()); | 82 icons->push_back(string16()); |
73 item_ids->push_back(WebAutofillClient::MenuItemIDDataListEntry); | 83 item_ids->push_back(WebAutofillClient::MenuItemIDDataListEntry); |
74 } | 84 } |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
202 case WebAutofillClient::MenuItemIDAutofillOptions: | 212 case WebAutofillClient::MenuItemIDAutofillOptions: |
203 // User selected 'Autofill Options'. | 213 // User selected 'Autofill Options'. |
204 Send(new AutofillHostMsg_ShowAutofillDialog(routing_id())); | 214 Send(new AutofillHostMsg_ShowAutofillDialog(routing_id())); |
205 break; | 215 break; |
206 case WebAutofillClient::MenuItemIDClearForm: | 216 case WebAutofillClient::MenuItemIDClearForm: |
207 // User selected 'Clear form'. | 217 // User selected 'Clear form'. |
208 form_cache_.ClearFormWithElement(element_); | 218 form_cache_.ClearFormWithElement(element_); |
209 break; | 219 break; |
210 case WebAutofillClient::MenuItemIDAutocompleteEntry: | 220 case WebAutofillClient::MenuItemIDAutocompleteEntry: |
211 case WebAutofillClient::MenuItemIDPasswordEntry: | 221 case WebAutofillClient::MenuItemIDPasswordEntry: |
212 case WebAutofillClient::MenuItemIDDataListEntry: | 222 // User selected an Autocomplete or password entry, so we fill directly. |
213 // User selected an Autocomplete or password or datalist entry, so we | |
214 // fill directly. | |
215 SetNodeText(value, &element_); | 223 SetNodeText(value, &element_); |
216 break; | 224 break; |
225 case WebAutofillClient::MenuItemIDDataListEntry: { | |
226 string16 new_value = value; | |
227 // If this element takes multiple values then replace the last part with | |
228 // the suggestion. | |
229 if (element_.isMultiple() && | |
230 element_.formControlType() == WebString::fromUTF8("email")) { | |
231 std::vector<string16> parts; | |
232 | |
233 base::SplitStringDontTrim(element_.editingValue(), ',', &parts); | |
234 if (parts.size() == 0) | |
235 parts.push_back(string16()); | |
236 | |
237 string16 last_part = parts.back(); | |
238 // We want to keep just the leading whitespace. | |
239 for (size_t i = 0; i < last_part.size(); ++i) { | |
240 if (!IsWhitespace(last_part[i])) { | |
241 last_part = last_part.substr(0, i); | |
242 break; | |
243 } | |
244 } | |
245 last_part.append(value); | |
246 parts[parts.size() - 1] = last_part; | |
247 | |
248 new_value = JoinString(parts, ','); | |
249 } | |
250 SetNodeText(new_value, &element_); | |
251 break; | |
252 } | |
217 default: | 253 default: |
218 // A positive item_id is a unique id for an autofill (vs. autocomplete) | 254 // A positive item_id is a unique id for an autofill (vs. autocomplete) |
219 // suggestion. | 255 // suggestion. |
220 DCHECK_GT(item_id, 0); | 256 DCHECK_GT(item_id, 0); |
221 // Fill the values for the whole form. | 257 // Fill the values for the whole form. |
222 FillAutofillFormData(node, item_id, AUTOFILL_FILL); | 258 FillAutofillFormData(node, item_id, AUTOFILL_FILL); |
223 } | 259 } |
224 } | 260 } |
225 | 261 |
226 void AutofillAgent::didSelectAutofillSuggestion(const WebNode& node, | 262 void AutofillAgent::didSelectAutofillSuggestion(const WebNode& node, |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
406 l.insert(l.end(), labels.begin(), labels.end()); | 442 l.insert(l.end(), labels.begin(), labels.end()); |
407 i.insert(i.end(), icons.begin(), icons.end()); | 443 i.insert(i.end(), icons.begin(), icons.end()); |
408 ids.insert(ids.end(), item_ids.begin(), item_ids.end()); | 444 ids.insert(ids.end(), item_ids.begin(), item_ids.end()); |
409 | 445 |
410 WebKit::WebView* web_view = render_view()->GetWebView(); | 446 WebKit::WebView* web_view = render_view()->GetWebView(); |
411 if (!web_view) | 447 if (!web_view) |
412 return; | 448 return; |
413 | 449 |
414 if (v.empty()) { | 450 if (v.empty()) { |
415 // No suggestions, any popup currently showing is obsolete. | 451 // No suggestions, any popup currently showing is obsolete. |
416 web_view->hidePopups(); | 452 HidePopups(); |
417 return; | 453 return; |
418 } | 454 } |
419 | 455 |
420 // Send to WebKit for display. | 456 // Send to WebKit for display. |
421 web_view->applyAutofillSuggestions(element, v, l, i, ids); | 457 web_view->applyAutofillSuggestions(element, v, l, i, ids); |
422 | 458 |
423 Send(new AutofillHostMsg_DidShowAutofillSuggestions( | 459 Send(new AutofillHostMsg_DidShowAutofillSuggestions( |
424 routing_id(), | 460 routing_id(), |
425 has_autofill_item && !has_shown_autofill_popup_for_current_edit_)); | 461 has_autofill_item && !has_shown_autofill_popup_for_current_edit_)); |
426 has_shown_autofill_popup_for_current_edit_ |= has_autofill_item; | 462 has_shown_autofill_popup_for_current_edit_ |= has_autofill_item; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
495 void AutofillAgent::ShowSuggestions(const WebInputElement& element, | 531 void AutofillAgent::ShowSuggestions(const WebInputElement& element, |
496 bool autofill_on_empty_values, | 532 bool autofill_on_empty_values, |
497 bool requires_caret_at_end, | 533 bool requires_caret_at_end, |
498 bool display_warning_if_disabled) { | 534 bool display_warning_if_disabled) { |
499 if (!element.isEnabled() || element.isReadOnly() || !element.isTextField() || | 535 if (!element.isEnabled() || element.isReadOnly() || !element.isTextField() || |
500 element.isPasswordField() || !element.suggestedValue().isEmpty()) | 536 element.isPasswordField() || !element.suggestedValue().isEmpty()) |
501 return; | 537 return; |
502 | 538 |
503 // Don't attempt to autofill with values that are too large or if filling | 539 // Don't attempt to autofill with values that are too large or if filling |
504 // criteria are not met. | 540 // criteria are not met. |
505 WebString value = element.value(); | 541 WebString value = element.editingValue(); |
506 if (value.length() > kMaximumTextSizeForAutofill || | 542 if (value.length() > kMaximumTextSizeForAutofill || |
507 (!autofill_on_empty_values && value.isEmpty()) || | 543 (!autofill_on_empty_values && value.isEmpty()) || |
508 (requires_caret_at_end && | 544 (requires_caret_at_end && |
509 (element.selectionStart() != element.selectionEnd() || | 545 (element.selectionStart() != element.selectionEnd() || |
510 element.selectionEnd() != static_cast<int>(value.length())))) { | 546 element.selectionEnd() != static_cast<int>(value.length())))) { |
511 // Any popup currently showing is obsolete. | 547 // Any popup currently showing is obsolete. |
512 WebKit::WebView* web_view = render_view()->GetWebView(); | 548 HidePopups(); |
513 if (web_view) | |
514 web_view->hidePopups(); | |
515 | 549 |
516 return; | 550 return; |
517 } | 551 } |
518 | 552 |
519 element_ = element; | 553 element_ = element; |
520 | 554 |
521 // If autocomplete is disabled at the form level, then we might want to show | 555 // If autocomplete is disabled at the form level, then we might want to show |
522 // a warning in place of suggestions. However, if autocomplete is disabled | 556 // a warning in place of suggestions. However, if autocomplete is disabled |
523 // specifically for this field, we never want to show a warning. Otherwise, | 557 // specifically for this field, we never want to show a warning. Otherwise, |
524 // we might interfere with custom popups (e.g. search suggestions) used by | 558 // we might interfere with custom popups (e.g. search suggestions) used by |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
579 autofill_action_ = action; | 613 autofill_action_ = action; |
580 Send(new AutofillHostMsg_FillAutofillFormData( | 614 Send(new AutofillHostMsg_FillAutofillFormData( |
581 routing_id(), autofill_query_id_, form, field, unique_id)); | 615 routing_id(), autofill_query_id_, form, field, unique_id)); |
582 } | 616 } |
583 | 617 |
584 void AutofillAgent::SetNodeText(const string16& value, | 618 void AutofillAgent::SetNodeText(const string16& value, |
585 WebKit::WebInputElement* node) { | 619 WebKit::WebInputElement* node) { |
586 string16 substring = value; | 620 string16 substring = value; |
587 substring = substring.substr(0, node->maxLength()); | 621 substring = substring.substr(0, node->maxLength()); |
588 | 622 |
589 node->setValue(substring, true); | 623 WebKit::WebView* web_view = render_view()->GetWebView(); |
624 if (!web_view || !web_view->focusedFrame()) | |
625 return; | |
Ilya Sherman
2012/05/09 02:38:58
nit: This is no longer used...
| |
626 | |
627 node.document().frame().executeCommand(WebString::fromUTF8("selectAll")); | |
628 node.document().frame().executeCommand(WebString::fromUTF8("InsertText"), | |
629 substring); | |
630 weak_ptr_factory_.InvalidateWeakPtrs(); | |
631 MessageLoop::current()->PostTask(FROM_HERE, | |
632 base::Bind(&AutofillAgent::HidePopups, | |
633 weak_ptr_factory_.GetWeakPtr())); | |
634 } | |
635 | |
636 void AutofillAgent::HidePopups() { | |
637 WebKit::WebView* web_view = render_view()->GetWebView(); | |
638 if (web_view) | |
639 web_view->hidePopups(); | |
590 } | 640 } |
591 | 641 |
592 } // namespace autofill | 642 } // namespace autofill |
OLD | NEW |