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

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 format errors and other naming issues. 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, all text fields except password are text input fields to
Ilya Sherman 2011/01/10 20:08:48 nit: I think the fragment "email, " in this senten
honten.org 2011/01/25 05:19:24 Done.
277 // autocomplete.
278 static bool IsTextInput(const WebInputElement& element) {
279 return element.isTextField() && !element.isPasswordField();
280 }
281
276 } // namespace 282 } // namespace
277 283
278 struct FormManager::FormElement { 284 struct FormManager::FormElement {
279 WebKit::WebFormElement form_element; 285 WebKit::WebFormElement form_element;
280 std::vector<WebKit::WebFormControlElement> control_elements; 286 std::vector<WebKit::WebFormControlElement> control_elements;
281 std::vector<string16> control_values; 287 std::vector<string16> control_values;
282 }; 288 };
283 289
284 FormManager::FormManager() { 290 FormManager::FormManager() {
285 } 291 }
(...skipping 15 matching lines...) Expand all
301 field->set_name(element.nameForAutofill()); 307 field->set_name(element.nameForAutofill());
302 field->set_form_control_type(element.formControlType()); 308 field->set_form_control_type(element.formControlType());
303 309
304 if (extract_mask & EXTRACT_OPTIONS) { 310 if (extract_mask & EXTRACT_OPTIONS) {
305 // Set option strings on the field if available. 311 // Set option strings on the field if available.
306 std::vector<string16> option_strings; 312 std::vector<string16> option_strings;
307 GetOptionStringsFromElement(element, &option_strings); 313 GetOptionStringsFromElement(element, &option_strings);
308 field->set_option_strings(option_strings); 314 field->set_option_strings(option_strings);
309 } 315 }
310 316
311 if (element.formControlType() == WebString::fromUTF8("text")) { 317 const WebInputElement& input_element = element.toConst<WebInputElement>();
Ilya Sherman 2011/01/10 20:08:48 I might be mistaken, but I think this conversion w
Ilya Sherman 2011/01/10 21:08:37 Yep, this conversion is just a static_cast, which
honten.org 2011/01/10 22:50:35 Ok, I'll ask him. On 2011/01/10 21:08:37, Ilya Sh
honten.org 2011/01/10 22:57:13 Darin, Could you tell me if there is a method Ily
dhollowa 2011/01/19 18:49:45 The test: element.hasTagName("input") should be su
darin (slow to review) 2011/01/19 22:04:18 I think you can use WebElement::hasTagName("input"
honten.org 2011/01/25 05:19:24 Now I changed to use toWebInputElement(). On 2011
312 const WebInputElement& input_element = element.toConst<WebInputElement>(); 318 if (IsTextInput(input_element)) {
313 field->set_max_length(input_element.maxLength()); 319 field->set_max_length(input_element.maxLength());
314 field->set_autofilled(input_element.isAutofilled()); 320 field->set_autofilled(input_element.isAutofilled());
315 } 321 }
316 322
317 if (!(extract_mask & EXTRACT_VALUE)) 323 if (!(extract_mask & EXTRACT_VALUE))
318 return; 324 return;
319 325
320 // TODO(jhawkins): In WebKit, move value() and setValue() to 326 // TODO(jhawkins): In WebKit, move value() and setValue() to
321 // WebFormControlElement. 327 // WebFormControlElement.
322 string16 value; 328 string16 value;
323 if (element.formControlType() == WebString::fromUTF8("text") || 329 if (IsTextInput(input_element) ||
324 element.formControlType() == WebString::fromUTF8("hidden")) { 330 element.formControlType() == WebString::fromUTF8("hidden")) {
325 const WebInputElement& input_element = 331 const WebInputElement& input_element =
326 element.toConst<WebInputElement>(); 332 element.toConst<WebInputElement>();
327 value = input_element.value(); 333 value = input_element.value();
328 } else if (element.formControlType() == WebString::fromUTF8("select-one")) { 334 } else if (element.formControlType() == WebString::fromUTF8("select-one")) {
329 // TODO(jhawkins): This is ugly. WebSelectElement::value() is a non-const 335 // TODO(jhawkins): This is ugly. WebSelectElement::value() is a non-const
330 // method. Look into fixing this on the WebKit side. 336 // method. Look into fixing this on the WebKit side.
331 WebFormControlElement& e = const_cast<WebFormControlElement&>(element); 337 WebFormControlElement& e = const_cast<WebFormControlElement&>(element);
332 WebSelectElement select_element = e.to<WebSelectElement>(); 338 WebSelectElement select_element = e.to<WebSelectElement>();
333 value = select_element.value(); 339 value = select_element.value();
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 WebVector<WebFormControlElement> control_elements; 416 WebVector<WebFormControlElement> control_elements;
411 element.getFormControlElements(control_elements); 417 element.getFormControlElements(control_elements);
412 418
413 // A vector of bools that indicate whether each field in the form meets the 419 // A vector of bools that indicate whether each field in the form meets the
414 // requirements and thus will be in the resulting |form|. 420 // requirements and thus will be in the resulting |form|.
415 std::vector<bool> fields_extracted(control_elements.size(), false); 421 std::vector<bool> fields_extracted(control_elements.size(), false);
416 422
417 for (size_t i = 0; i < control_elements.size(); ++i) { 423 for (size_t i = 0; i < control_elements.size(); ++i) {
418 const WebFormControlElement& control_element = control_elements[i]; 424 const WebFormControlElement& control_element = control_elements[i];
419 425
426 const WebInputElement& controll_input_element =
427 control_element.toConst<WebInputElement>();
Ilya Sherman 2011/01/10 20:08:48 nit: If this conversion is legal (see above), you
420 if (requirements & REQUIRE_AUTOCOMPLETE && 428 if (requirements & REQUIRE_AUTOCOMPLETE &&
421 control_element.formControlType() == WebString::fromUTF8("text")) { 429 IsTextInput(controll_input_element)) {
422 const WebInputElement& input_element = 430 const WebInputElement& input_element =
423 control_element.toConst<WebInputElement>(); 431 control_element.toConst<WebInputElement>();
424 if (!input_element.autoComplete()) 432 if (!input_element.autoComplete())
425 continue; 433 continue;
426 } 434 }
427 435
428 if (requirements & REQUIRE_ENABLED && !control_element.isEnabled()) 436 if (requirements & REQUIRE_ENABLED && !control_element.isEnabled())
429 continue; 437 continue;
430 438
431 // Create a new FormField, fill it out and map it to the field's name. 439 // 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; 632 return true;
625 } 633 }
626 634
627 bool FormManager::ClearFormWithNode(const WebNode& node) { 635 bool FormManager::ClearFormWithNode(const WebNode& node) {
628 FormElement* form_element = NULL; 636 FormElement* form_element = NULL;
629 if (!FindCachedFormElementWithNode(node, &form_element)) 637 if (!FindCachedFormElementWithNode(node, &form_element))
630 return false; 638 return false;
631 639
632 for (size_t i = 0; i < form_element->control_elements.size(); ++i) { 640 for (size_t i = 0; i < form_element->control_elements.size(); ++i) {
633 WebFormControlElement element = form_element->control_elements[i]; 641 WebFormControlElement element = form_element->control_elements[i];
634 if (element.formControlType() == WebString::fromUTF8("text")) { 642 WebInputElement input_element = element.to<WebInputElement>();
635 643 if (IsTextInput(input_element)) {
636 WebInputElement input_element = element.to<WebInputElement>();
637 644
638 // We don't modify the value of disabled fields. 645 // We don't modify the value of disabled fields.
639 if (!input_element.isEnabled()) 646 if (!input_element.isEnabled())
640 continue; 647 continue;
641 648
642 input_element.setValue(string16()); 649 input_element.setValue(string16());
643 input_element.setAutofilled(false); 650 input_element.setAutofilled(false);
644 651
645 // Clearing the value in the focused node (above) can cause selection 652 // Clearing the value in the focused node (above) can cause selection
646 // to be lost. We force selection range to restore the text cursor. 653 // to be lost. We force selection range to restore the text cursor.
(...skipping 11 matching lines...) Expand all
658 } 665 }
659 666
660 bool FormManager::ClearPreviewedFormWithNode(const WebNode& node, 667 bool FormManager::ClearPreviewedFormWithNode(const WebNode& node,
661 bool was_autofilled) { 668 bool was_autofilled) {
662 FormElement* form_element = NULL; 669 FormElement* form_element = NULL;
663 if (!FindCachedFormElementWithNode(node, &form_element)) 670 if (!FindCachedFormElementWithNode(node, &form_element))
664 return false; 671 return false;
665 672
666 for (size_t i = 0; i < form_element->control_elements.size(); ++i) { 673 for (size_t i = 0; i < form_element->control_elements.size(); ++i) {
667 WebFormControlElement* element = &form_element->control_elements[i]; 674 WebFormControlElement* element = &form_element->control_elements[i];
668 675 WebInputElement input_element = element->to<WebInputElement>();
669 // Only input elements can be previewed. 676 // Only input elements can be previewed.
670 if (element->formControlType() != WebString::fromUTF8("text")) 677 if (!IsTextInput(input_element))
671 continue; 678 continue;
672 679
673 // If the input element has not been auto-filled, FormManager has not 680 // If the input element has not been auto-filled, FormManager has not
674 // previewed this field, so we have nothing to reset. 681 // previewed this field, so we have nothing to reset.
675 WebInputElement input_element = element->to<WebInputElement>();
676 if (!input_element.isAutofilled()) 682 if (!input_element.isAutofilled())
677 continue; 683 continue;
678 684
679 // There might be unrelated elements in this form which have already been 685 // 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 686 // auto-filled. For example, the user might have already filled the address
681 // part of a form and now be dealing with the credit card section. We only 687 // part of a form and now be dealing with the credit card section. We only
682 // want to reset the auto-filled status for fields that were previewed. 688 // want to reset the auto-filled status for fields that were previewed.
683 if (input_element.suggestedValue().isEmpty()) 689 if (input_element.suggestedValue().isEmpty())
684 continue; 690 continue;
685 691
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 } 730 }
725 } 731 }
726 732
727 bool FormManager::FormWithNodeIsAutoFilled(const WebNode& node) { 733 bool FormManager::FormWithNodeIsAutoFilled(const WebNode& node) {
728 FormElement* form_element = NULL; 734 FormElement* form_element = NULL;
729 if (!FindCachedFormElementWithNode(node, &form_element)) 735 if (!FindCachedFormElementWithNode(node, &form_element))
730 return false; 736 return false;
731 737
732 for (size_t i = 0; i < form_element->control_elements.size(); ++i) { 738 for (size_t i = 0; i < form_element->control_elements.size(); ++i) {
733 WebFormControlElement element = form_element->control_elements[i]; 739 WebFormControlElement element = form_element->control_elements[i];
734 if (element.formControlType() != WebString::fromUTF8("text")) 740 WebInputElement input_element = element.to<WebInputElement>();
741 if (!IsTextInput(input_element))
735 continue; 742 continue;
736 743
737 const WebInputElement& input_element = element.to<WebInputElement>();
738 if (input_element.isAutofilled()) 744 if (input_element.isAutofilled())
739 return true; 745 return true;
740 } 746 }
741 747
742 return false; 748 return false;
743 } 749 }
744 750
745 // static 751 // static
746 string16 FormManager::InferLabelForElement( 752 string16 FormManager::InferLabelForElement(
747 const WebFormControlElement& element) { 753 const WebFormControlElement& element) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
837 if (k >= data.fields.size()) 843 if (k >= data.fields.size())
838 continue; 844 continue;
839 845
840 DCHECK_EQ(data.fields[k].name(), element_name); 846 DCHECK_EQ(data.fields[k].name(), element_name);
841 847
842 bool is_initiating_node = false; 848 bool is_initiating_node = false;
843 849
844 // More than likely |requirements| will contain REQUIRE_AUTOCOMPLETE and/or 850 // More than likely |requirements| will contain REQUIRE_AUTOCOMPLETE and/or
845 // REQUIRE_EMPTY, which both require text form control elements, so special- 851 // REQUIRE_EMPTY, which both require text form control elements, so special-
846 // case this type of element. 852 // case this type of element.
847 if (element->formControlType() == WebString::fromUTF8("text")) { 853 const WebInputElement& input_element =
848 const WebInputElement& input_element = 854 element->toConst<WebInputElement>();
849 element->toConst<WebInputElement>(); 855 if (IsTextInput(input_element)) {
850 856
851 // TODO(jhawkins): WebKit currently doesn't handle the autocomplete 857 // TODO(jhawkins): WebKit currently doesn't handle the autocomplete
852 // attribute for select control elements, but it probably should. 858 // attribute for select control elements, but it probably should.
853 if (requirements & REQUIRE_AUTOCOMPLETE && !input_element.autoComplete()) 859 if (requirements & REQUIRE_AUTOCOMPLETE && !input_element.autoComplete())
854 continue; 860 continue;
855 861
856 is_initiating_node = (input_element == node); 862 is_initiating_node = (input_element == node);
857 // Don't require the node that initiated the auto-fill process to be 863 // Don't require the node that initiated the auto-fill process to be
858 // empty. The user is typing in this field and we should complete the 864 // empty. The user is typing in this field and we should complete the
859 // value when the user selects a value to fill out. 865 // value when the user selects a value to fill out.
(...skipping 15 matching lines...) Expand all
875 delete callback; 881 delete callback;
876 } 882 }
877 883
878 void FormManager::FillFormField(WebFormControlElement* field, 884 void FormManager::FillFormField(WebFormControlElement* field,
879 const FormField* data, 885 const FormField* data,
880 bool is_initiating_node) { 886 bool is_initiating_node) {
881 // Nothing to fill. 887 // Nothing to fill.
882 if (data->value().empty()) 888 if (data->value().empty())
883 return; 889 return;
884 890
885 if (field->formControlType() == WebString::fromUTF8("text")) { 891 WebInputElement input_element = field->to<WebInputElement>();
886 WebInputElement input_element = field->to<WebInputElement>(); 892 if (IsTextInput(input_element)) {
887 893
888 // If the maxlength attribute contains a negative value, maxLength() 894 // If the maxlength attribute contains a negative value, maxLength()
889 // returns the default maxlength value. 895 // returns the default maxlength value.
890 input_element.setValue(data->value().substr(0, input_element.maxLength())); 896 input_element.setValue(data->value().substr(0, input_element.maxLength()));
891 input_element.setAutofilled(true); 897 input_element.setAutofilled(true);
892 if (is_initiating_node) { 898 if (is_initiating_node) {
893 int length = input_element.value().length(); 899 int length = input_element.value().length();
894 input_element.setSelectionRange(length, length); 900 input_element.setSelectionRange(length, length);
895 } 901 }
896 } else if (field->formControlType() == WebString::fromUTF8("select-one")) { 902 } else if (field->formControlType() == WebString::fromUTF8("select-one")) {
897 WebSelectElement select_element = field->to<WebSelectElement>(); 903 WebSelectElement select_element = field->to<WebSelectElement>();
898 select_element.setValue(data->value()); 904 select_element.setValue(data->value());
899 } 905 }
900 } 906 }
901 907
902 void FormManager::PreviewFormField(WebFormControlElement* field, 908 void FormManager::PreviewFormField(WebFormControlElement* field,
903 const FormField* data, 909 const FormField* data,
904 bool is_initiating_node) { 910 bool is_initiating_node) {
905 // Nothing to preview. 911 // Nothing to preview.
906 if (data->value().empty()) 912 if (data->value().empty())
907 return; 913 return;
908 914
909 // Only preview input fields. 915 // Only preview input fields.
910 if (field->formControlType() != WebString::fromUTF8("text")) 916 WebInputElement input_element = field->to<WebInputElement>();
917 if (!IsTextInput(input_element))
911 return; 918 return;
912 919
913 WebInputElement input_element = field->to<WebInputElement>();
914
915 // If the maxlength attribute contains a negative value, maxLength() 920 // If the maxlength attribute contains a negative value, maxLength()
916 // returns the default maxlength value. 921 // returns the default maxlength value.
917 input_element.setSuggestedValue( 922 input_element.setSuggestedValue(
918 data->value().substr(0, input_element.maxLength())); 923 data->value().substr(0, input_element.maxLength()));
919 input_element.setAutofilled(true); 924 input_element.setAutofilled(true);
920 if (is_initiating_node) 925 if (is_initiating_node)
921 input_element.setSelectionRange(0, input_element.suggestedValue().length()); 926 input_element.setSelectionRange(0, input_element.suggestedValue().length());
922 } 927 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698