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

Side by Side Diff: chrome/renderer/form_manager.cc

Issue 6033010: Support autocompletion for HTMl5 tags:"email", "month" and "tel". (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Fix typo, format errors. Created 9 years, 11 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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/form_manager.h" 5 #include "chrome/renderer/form_manager.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/scoped_vector.h" 8 #include "base/scoped_vector.h"
9 #include "base/string_util.h" 9 #include "base/string_util.h"
10 #include "base/stl_util-inl.h" 10 #include "base/stl_util-inl.h"
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 // For select-one elements copy option strings. 266 // For select-one elements copy option strings.
267 WebVector<WebElement> list_items = select_element.listItems(); 267 WebVector<WebElement> list_items = select_element.listItems();
268 option_strings->reserve(list_items.size()); 268 option_strings->reserve(list_items.size());
269 for (size_t i = 0; i < list_items.size(); ++i) { 269 for (size_t i = 0; i < list_items.size(); ++i) {
270 if (list_items[i].hasTagName("option")) 270 if (list_items[i].hasTagName("option"))
271 option_strings->push_back(list_items[i].to<WebOptionElement>().value()); 271 option_strings->push_back(list_items[i].to<WebOptionElement>().value());
272 } 272 }
273 } 273 }
274 } 274 }
275 275
276 // In HTML5, email, month and tel are text input field to autocomplete.
277 static bool IsTextInput(const WebFormControlElement& element) {
278 static const char* type_names[] = {"text", "email", "tel", "month"};
279 for (size_t i = 0; i < sizeof(type_names)/sizeof(const char*); ++i) {
280 if (element.formControlType() == WebString::fromUTF8(type_names[i]))
281 return true;
282 }
283 return false;
284 }
285
276 } // namespace 286 } // namespace
277 287
278 struct FormManager::FormElement { 288 struct FormManager::FormElement {
279 WebKit::WebFormElement form_element; 289 WebKit::WebFormElement form_element;
280 std::vector<WebKit::WebFormControlElement> control_elements; 290 std::vector<WebKit::WebFormControlElement> control_elements;
281 std::vector<string16> control_values; 291 std::vector<string16> control_values;
282 }; 292 };
283 293
284 FormManager::FormManager() { 294 FormManager::FormManager() {
285 } 295 }
(...skipping 15 matching lines...) Expand all
301 field->set_name(element.nameForAutofill()); 311 field->set_name(element.nameForAutofill());
302 field->set_form_control_type(element.formControlType()); 312 field->set_form_control_type(element.formControlType());
303 313
304 if (extract_mask & EXTRACT_OPTIONS) { 314 if (extract_mask & EXTRACT_OPTIONS) {
305 // Set option strings on the field if available. 315 // Set option strings on the field if available.
306 std::vector<string16> option_strings; 316 std::vector<string16> option_strings;
307 GetOptionStringsFromElement(element, &option_strings); 317 GetOptionStringsFromElement(element, &option_strings);
308 field->set_option_strings(option_strings); 318 field->set_option_strings(option_strings);
309 } 319 }
310 320
311 if (element.formControlType() == WebString::fromUTF8("text")) { 321 if (IsTextInput(element)) {
312 const WebInputElement& input_element = element.toConst<WebInputElement>(); 322 const WebInputElement& input_element = element.toConst<WebInputElement>();
313 field->set_max_length(input_element.maxLength()); 323 field->set_max_length(input_element.maxLength());
314 field->set_autofilled(input_element.isAutofilled()); 324 field->set_autofilled(input_element.isAutofilled());
315 } 325 }
316 326
317 if (!(extract_mask & EXTRACT_VALUE)) 327 if (!(extract_mask & EXTRACT_VALUE))
318 return; 328 return;
319 329
320 // TODO(jhawkins): In WebKit, move value() and setValue() to 330 // TODO(jhawkins): In WebKit, move value() and setValue() to
321 // WebFormControlElement. 331 // WebFormControlElement.
322 string16 value; 332 string16 value;
323 if (element.formControlType() == WebString::fromUTF8("text") || 333 if (IsTextInput(element) ||
324 element.formControlType() == WebString::fromUTF8("hidden")) { 334 element.formControlType() == WebString::fromUTF8("hidden")) {
325 const WebInputElement& input_element = 335 const WebInputElement& input_element =
326 element.toConst<WebInputElement>(); 336 element.toConst<WebInputElement>();
327 value = input_element.value(); 337 value = input_element.value();
328 } else if (element.formControlType() == WebString::fromUTF8("select-one")) { 338 } else if (element.formControlType() == WebString::fromUTF8("select-one")) {
329 // TODO(jhawkins): This is ugly. WebSelectElement::value() is a non-const 339 // TODO(jhawkins): This is ugly. WebSelectElement::value() is a non-const
330 // method. Look into fixing this on the WebKit side. 340 // method. Look into fixing this on the WebKit side.
331 WebFormControlElement& e = const_cast<WebFormControlElement&>(element); 341 WebFormControlElement& e = const_cast<WebFormControlElement&>(element);
332 WebSelectElement select_element = e.to<WebSelectElement>(); 342 WebSelectElement select_element = e.to<WebSelectElement>();
333 value = select_element.value(); 343 value = select_element.value();
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 WebVector<WebFormControlElement> control_elements; 420 WebVector<WebFormControlElement> control_elements;
411 element.getFormControlElements(control_elements); 421 element.getFormControlElements(control_elements);
412 422
413 // A vector of bools that indicate whether each field in the form meets the 423 // A vector of bools that indicate whether each field in the form meets the
414 // requirements and thus will be in the resulting |form|. 424 // requirements and thus will be in the resulting |form|.
415 std::vector<bool> fields_extracted(control_elements.size(), false); 425 std::vector<bool> fields_extracted(control_elements.size(), false);
416 426
417 for (size_t i = 0; i < control_elements.size(); ++i) { 427 for (size_t i = 0; i < control_elements.size(); ++i) {
418 const WebFormControlElement& control_element = control_elements[i]; 428 const WebFormControlElement& control_element = control_elements[i];
419 429
420 if (requirements & REQUIRE_AUTOCOMPLETE && 430 if (requirements & REQUIRE_AUTOCOMPLETE && IsTextInput(control_element)) {
421 control_element.formControlType() == WebString::fromUTF8("text")) {
422 const WebInputElement& input_element = 431 const WebInputElement& input_element =
423 control_element.toConst<WebInputElement>(); 432 control_element.toConst<WebInputElement>();
424 if (!input_element.autoComplete()) 433 if (!input_element.autoComplete())
425 continue; 434 continue;
426 } 435 }
427 436
428 if (requirements & REQUIRE_ENABLED && !control_element.isEnabled()) 437 if (requirements & REQUIRE_ENABLED && !control_element.isEnabled())
429 continue; 438 continue;
430 439
431 // Create a new FormField, fill it out and map it to the field's name. 440 // Create a new FormField, fill it out and map it to the field's name.
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 return true; 633 return true;
625 } 634 }
626 635
627 bool FormManager::ClearFormWithNode(const WebNode& node) { 636 bool FormManager::ClearFormWithNode(const WebNode& node) {
628 FormElement* form_element = NULL; 637 FormElement* form_element = NULL;
629 if (!FindCachedFormElementWithNode(node, &form_element)) 638 if (!FindCachedFormElementWithNode(node, &form_element))
630 return false; 639 return false;
631 640
632 for (size_t i = 0; i < form_element->control_elements.size(); ++i) { 641 for (size_t i = 0; i < form_element->control_elements.size(); ++i) {
633 WebFormControlElement element = form_element->control_elements[i]; 642 WebFormControlElement element = form_element->control_elements[i];
634 if (element.formControlType() == WebString::fromUTF8("text")) { 643 if (IsTextInput(element)) {
635 644
636 WebInputElement input_element = element.to<WebInputElement>(); 645 WebInputElement input_element = element.to<WebInputElement>();
637 646
638 // We don't modify the value of disabled fields. 647 // We don't modify the value of disabled fields.
639 if (!input_element.isEnabled()) 648 if (!input_element.isEnabled())
640 continue; 649 continue;
641 650
642 input_element.setValue(string16()); 651 input_element.setValue(string16());
643 input_element.setAutofilled(false); 652 input_element.setAutofilled(false);
644 653
(...skipping 15 matching lines...) Expand all
660 bool FormManager::ClearPreviewedFormWithNode(const WebNode& node, 669 bool FormManager::ClearPreviewedFormWithNode(const WebNode& node,
661 bool was_autofilled) { 670 bool was_autofilled) {
662 FormElement* form_element = NULL; 671 FormElement* form_element = NULL;
663 if (!FindCachedFormElementWithNode(node, &form_element)) 672 if (!FindCachedFormElementWithNode(node, &form_element))
664 return false; 673 return false;
665 674
666 for (size_t i = 0; i < form_element->control_elements.size(); ++i) { 675 for (size_t i = 0; i < form_element->control_elements.size(); ++i) {
667 WebFormControlElement* element = &form_element->control_elements[i]; 676 WebFormControlElement* element = &form_element->control_elements[i];
668 677
669 // Only input elements can be previewed. 678 // Only input elements can be previewed.
670 if (element->formControlType() != WebString::fromUTF8("text")) 679 if (!IsTextInput(*element))
671 continue; 680 continue;
672 681
673 // If the input element has not been auto-filled, FormManager has not 682 // If the input element has not been auto-filled, FormManager has not
674 // previewed this field, so we have nothing to reset. 683 // previewed this field, so we have nothing to reset.
675 WebInputElement input_element = element->to<WebInputElement>(); 684 WebInputElement input_element = element->to<WebInputElement>();
676 if (!input_element.isAutofilled()) 685 if (!input_element.isAutofilled())
677 continue; 686 continue;
678 687
679 // There might be unrelated elements in this form which have already been 688 // There might be unrelated elements in this form which have already been
680 // auto-filled. For example, the user might have already filled the address 689 // auto-filled. For example, the user might have already filled the address
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 } 733 }
725 } 734 }
726 735
727 bool FormManager::FormWithNodeIsAutoFilled(const WebNode& node) { 736 bool FormManager::FormWithNodeIsAutoFilled(const WebNode& node) {
728 FormElement* form_element = NULL; 737 FormElement* form_element = NULL;
729 if (!FindCachedFormElementWithNode(node, &form_element)) 738 if (!FindCachedFormElementWithNode(node, &form_element))
730 return false; 739 return false;
731 740
732 for (size_t i = 0; i < form_element->control_elements.size(); ++i) { 741 for (size_t i = 0; i < form_element->control_elements.size(); ++i) {
733 WebFormControlElement element = form_element->control_elements[i]; 742 WebFormControlElement element = form_element->control_elements[i];
734 if (element.formControlType() != WebString::fromUTF8("text")) 743 if (!IsTextInput(element))
735 continue; 744 continue;
736 745
737 const WebInputElement& input_element = element.to<WebInputElement>(); 746 const WebInputElement& input_element = element.to<WebInputElement>();
738 if (input_element.isAutofilled()) 747 if (input_element.isAutofilled())
739 return true; 748 return true;
740 } 749 }
741 750
742 return false; 751 return false;
743 } 752 }
744 753
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
837 if (k >= data.fields.size()) 846 if (k >= data.fields.size())
838 continue; 847 continue;
839 848
840 DCHECK_EQ(data.fields[k].name(), element_name); 849 DCHECK_EQ(data.fields[k].name(), element_name);
841 850
842 bool is_initiating_node = false; 851 bool is_initiating_node = false;
843 852
844 // More than likely |requirements| will contain REQUIRE_AUTOCOMPLETE and/or 853 // More than likely |requirements| will contain REQUIRE_AUTOCOMPLETE and/or
845 // REQUIRE_EMPTY, which both require text form control elements, so special- 854 // REQUIRE_EMPTY, which both require text form control elements, so special-
846 // case this type of element. 855 // case this type of element.
847 if (element->formControlType() == WebString::fromUTF8("text")) { 856 if (IsTextInput(*element)) {
848 const WebInputElement& input_element = 857 const WebInputElement& input_element =
849 element->toConst<WebInputElement>(); 858 element->toConst<WebInputElement>();
850 859
851 // TODO(jhawkins): WebKit currently doesn't handle the autocomplete 860 // TODO(jhawkins): WebKit currently doesn't handle the autocomplete
852 // attribute for select control elements, but it probably should. 861 // attribute for select control elements, but it probably should.
853 if (requirements & REQUIRE_AUTOCOMPLETE && !input_element.autoComplete()) 862 if (requirements & REQUIRE_AUTOCOMPLETE && !input_element.autoComplete())
854 continue; 863 continue;
855 864
856 is_initiating_node = (input_element == node); 865 is_initiating_node = (input_element == node);
857 // Don't require the node that initiated the auto-fill process to be 866 // Don't require the node that initiated the auto-fill process to be
(...skipping 17 matching lines...) Expand all
875 delete callback; 884 delete callback;
876 } 885 }
877 886
878 void FormManager::FillFormField(WebFormControlElement* field, 887 void FormManager::FillFormField(WebFormControlElement* field,
879 const FormField* data, 888 const FormField* data,
880 bool is_initiating_node) { 889 bool is_initiating_node) {
881 // Nothing to fill. 890 // Nothing to fill.
882 if (data->value().empty()) 891 if (data->value().empty())
883 return; 892 return;
884 893
885 if (field->formControlType() == WebString::fromUTF8("text")) { 894 if (IsTextInput(*field)) {
886 WebInputElement input_element = field->to<WebInputElement>(); 895 WebInputElement input_element = field->to<WebInputElement>();
887 896
888 // If the maxlength attribute contains a negative value, maxLength() 897 // If the maxlength attribute contains a negative value, maxLength()
889 // returns the default maxlength value. 898 // returns the default maxlength value.
890 input_element.setValue(data->value().substr(0, input_element.maxLength())); 899 input_element.setValue(data->value().substr(0, input_element.maxLength()));
891 input_element.setAutofilled(true); 900 input_element.setAutofilled(true);
892 if (is_initiating_node) { 901 if (is_initiating_node) {
893 int length = input_element.value().length(); 902 int length = input_element.value().length();
894 input_element.setSelectionRange(length, length); 903 input_element.setSelectionRange(length, length);
895 } 904 }
896 } else if (field->formControlType() == WebString::fromUTF8("select-one")) { 905 } else if (field->formControlType() == WebString::fromUTF8("select-one")) {
897 WebSelectElement select_element = field->to<WebSelectElement>(); 906 WebSelectElement select_element = field->to<WebSelectElement>();
898 select_element.setValue(data->value()); 907 select_element.setValue(data->value());
899 } 908 }
900 } 909 }
901 910
902 void FormManager::PreviewFormField(WebFormControlElement* field, 911 void FormManager::PreviewFormField(WebFormControlElement* field,
903 const FormField* data, 912 const FormField* data,
904 bool is_initiating_node) { 913 bool is_initiating_node) {
905 // Nothing to preview. 914 // Nothing to preview.
906 if (data->value().empty()) 915 if (data->value().empty())
907 return; 916 return;
908 917
909 // Only preview input fields. 918 // Only preview input fields.
910 if (field->formControlType() != WebString::fromUTF8("text")) 919 if (!IsTextInput(*field))
911 return; 920 return;
912 921
913 WebInputElement input_element = field->to<WebInputElement>(); 922 WebInputElement input_element = field->to<WebInputElement>();
914 923
915 // If the maxlength attribute contains a negative value, maxLength() 924 // If the maxlength attribute contains a negative value, maxLength()
916 // returns the default maxlength value. 925 // returns the default maxlength value.
917 input_element.setSuggestedValue( 926 input_element.setSuggestedValue(
918 data->value().substr(0, input_element.maxLength())); 927 data->value().substr(0, input_element.maxLength()));
919 input_element.setAutofilled(true); 928 input_element.setAutofilled(true);
920 if (is_initiating_node) 929 if (is_initiating_node)
921 input_element.setSelectionRange(0, input_element.suggestedValue().length()); 930 input_element.setSelectionRange(0, input_element.suggestedValue().length());
922 } 931 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698