| OLD | NEW |
| 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/autofill/form_manager.h" | 5 #include "chrome/renderer/autofill/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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 | 45 |
| 46 // The number of fields required by AutoFill. Ideally we could send the forms | 46 // The number of fields required by AutoFill. Ideally we could send the forms |
| 47 // to AutoFill no matter how many fields are in the forms; however, finding the | 47 // to AutoFill no matter how many fields are in the forms; however, finding the |
| 48 // label for each field is a costly operation and we can't spare the cycles if | 48 // label for each field is a costly operation and we can't spare the cycles if |
| 49 // it's not necessary. | 49 // it's not necessary. |
| 50 const size_t kRequiredAutoFillFields = 3; | 50 const size_t kRequiredAutoFillFields = 3; |
| 51 | 51 |
| 52 // The maximum length allowed for form data. | 52 // The maximum length allowed for form data. |
| 53 const size_t kMaxDataLength = 1024; | 53 const size_t kMaxDataLength = 1024; |
| 54 | 54 |
| 55 // TODO(isherman): Replace calls to this with IsTextInput() once | 55 // In HTML5, all text fields except password are text input fields to |
| 56 // http://codereview.chromium.org/6033010/ lands. | 56 // autocomplete. |
| 57 bool IsTextElement(const WebFormControlElement& element) { | 57 bool IsTextInput(const WebInputElement* element) { |
| 58 return element.formControlType() == WebString::fromUTF8("text"); | 58 if (!element) |
| 59 return false; |
| 60 |
| 61 return element->isTextField() && !element->isPasswordField(); |
| 59 } | 62 } |
| 60 | 63 |
| 61 bool IsSelectElement(const WebFormControlElement& element) { | 64 bool IsSelectElement(const WebFormControlElement& element) { |
| 62 return element.formControlType() == ASCIIToUTF16("select-one"); | 65 return element.formControlType() == ASCIIToUTF16("select-one"); |
| 63 } | 66 } |
| 64 | 67 |
| 65 bool IsOptionElement(const WebElement& element) { | 68 bool IsOptionElement(const WebElement& element) { |
| 66 return element.hasTagName("option"); | 69 return element.hasTagName("option"); |
| 67 } | 70 } |
| 68 | 71 |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 ExtractMask extract_mask, | 331 ExtractMask extract_mask, |
| 329 FormField* field) { | 332 FormField* field) { |
| 330 DCHECK(field); | 333 DCHECK(field); |
| 331 | 334 |
| 332 // The label is not officially part of a WebFormControlElement; however, the | 335 // The label is not officially part of a WebFormControlElement; however, the |
| 333 // labels for all form control elements are scraped from the DOM and set in | 336 // labels for all form control elements are scraped from the DOM and set in |
| 334 // WebFormElementToFormData. | 337 // WebFormElementToFormData. |
| 335 field->set_name(element.nameForAutofill()); | 338 field->set_name(element.nameForAutofill()); |
| 336 field->set_form_control_type(element.formControlType()); | 339 field->set_form_control_type(element.formControlType()); |
| 337 | 340 |
| 338 if (IsTextElement(element)) { | 341 const WebInputElement* input_element = toWebInputElement(&element); |
| 342 if (IsTextInput(input_element)) { |
| 339 const WebInputElement& input_element = element.toConst<WebInputElement>(); | 343 const WebInputElement& input_element = element.toConst<WebInputElement>(); |
| 340 field->set_max_length(input_element.maxLength()); | 344 field->set_max_length(input_element.maxLength()); |
| 341 field->set_autofilled(input_element.isAutofilled()); | 345 field->set_autofilled(input_element.isAutofilled()); |
| 342 } else if (extract_mask & EXTRACT_OPTIONS) { | 346 } else if (extract_mask & EXTRACT_OPTIONS) { |
| 343 // Set option strings on the field if available. | 347 // Set option strings on the field if available. |
| 344 std::vector<string16> option_strings; | 348 std::vector<string16> option_strings; |
| 345 GetOptionStringsFromElement(element, &option_strings); | 349 GetOptionStringsFromElement(element, &option_strings); |
| 346 field->set_option_strings(option_strings); | 350 field->set_option_strings(option_strings); |
| 347 } | 351 } |
| 348 | 352 |
| 349 if (!(extract_mask & EXTRACT_VALUE)) | 353 if (!(extract_mask & EXTRACT_VALUE)) |
| 350 return; | 354 return; |
| 351 | 355 |
| 352 string16 value; | 356 string16 value; |
| 353 if (IsTextElement(element) || | 357 if (IsTextInput(input_element) || |
| 354 element.formControlType() == WebString::fromUTF8("hidden")) { | 358 element.formControlType() == WebString::fromUTF8("hidden")) { |
| 355 const WebInputElement& input_element = element.toConst<WebInputElement>(); | 359 value = input_element->value(); |
| 356 value = input_element.value(); | |
| 357 } else if (IsSelectElement(element)) { | 360 } else if (IsSelectElement(element)) { |
| 358 const WebSelectElement select_element = element.toConst<WebSelectElement>(); | 361 const WebSelectElement select_element = element.toConst<WebSelectElement>(); |
| 359 value = select_element.value(); | 362 value = select_element.value(); |
| 360 | 363 |
| 361 // Convert the |select_element| value to text if requested. | 364 // Convert the |select_element| value to text if requested. |
| 362 if (extract_mask & EXTRACT_OPTION_TEXT) { | 365 if (extract_mask & EXTRACT_OPTION_TEXT) { |
| 363 WebVector<WebElement> list_items = select_element.listItems(); | 366 WebVector<WebElement> list_items = select_element.listItems(); |
| 364 for (size_t i = 0; i < list_items.size(); ++i) { | 367 for (size_t i = 0; i < list_items.size(); ++i) { |
| 365 if (IsOptionElement(list_items[i])) { | 368 if (IsOptionElement(list_items[i])) { |
| 366 const WebOptionElement option_element = | 369 const WebOptionElement option_element = |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 WebVector<WebFormControlElement> control_elements; | 440 WebVector<WebFormControlElement> control_elements; |
| 438 element.getFormControlElements(control_elements); | 441 element.getFormControlElements(control_elements); |
| 439 | 442 |
| 440 // A vector of bools that indicate whether each field in the form meets the | 443 // A vector of bools that indicate whether each field in the form meets the |
| 441 // requirements and thus will be in the resulting |form|. | 444 // requirements and thus will be in the resulting |form|. |
| 442 std::vector<bool> fields_extracted(control_elements.size(), false); | 445 std::vector<bool> fields_extracted(control_elements.size(), false); |
| 443 | 446 |
| 444 for (size_t i = 0; i < control_elements.size(); ++i) { | 447 for (size_t i = 0; i < control_elements.size(); ++i) { |
| 445 const WebFormControlElement& control_element = control_elements[i]; | 448 const WebFormControlElement& control_element = control_elements[i]; |
| 446 | 449 |
| 447 if (requirements & REQUIRE_AUTOCOMPLETE && IsTextElement(control_element)) { | 450 const WebInputElement* input_element = toWebInputElement(&control_element); |
| 448 const WebInputElement& input_element = | 451 if (requirements & REQUIRE_AUTOCOMPLETE && IsTextInput(input_element) && |
| 449 control_element.toConst<WebInputElement>(); | 452 !input_element->autoComplete()) |
| 450 if (!input_element.autoComplete()) | 453 continue; |
| 451 continue; | |
| 452 } | |
| 453 | 454 |
| 454 if (requirements & REQUIRE_ENABLED && !control_element.isEnabled()) | 455 if (requirements & REQUIRE_ENABLED && !control_element.isEnabled()) |
| 455 continue; | 456 continue; |
| 456 | 457 |
| 457 // Create a new FormField, fill it out and map it to the field's name. | 458 // Create a new FormField, fill it out and map it to the field's name. |
| 458 FormField* field = new FormField; | 459 FormField* field = new FormField; |
| 459 WebFormControlElementToFormField(control_element, extract_mask, field); | 460 WebFormControlElementToFormField(control_element, extract_mask, field); |
| 460 form_fields.push_back(field); | 461 form_fields.push_back(field); |
| 461 // TODO(jhawkins): A label element is mapped to a form control element's id. | 462 // TODO(jhawkins): A label element is mapped to a form control element's id. |
| 462 // field->name() will contain the id only if the name does not exist. Add | 463 // field->name() will contain the id only if the name does not exist. Add |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 return true; | 648 return true; |
| 648 } | 649 } |
| 649 | 650 |
| 650 bool FormManager::ClearFormWithNode(const WebNode& node) { | 651 bool FormManager::ClearFormWithNode(const WebNode& node) { |
| 651 FormElement* form_element = NULL; | 652 FormElement* form_element = NULL; |
| 652 if (!FindCachedFormElementWithNode(node, &form_element)) | 653 if (!FindCachedFormElementWithNode(node, &form_element)) |
| 653 return false; | 654 return false; |
| 654 | 655 |
| 655 for (size_t i = 0; i < form_element->control_elements.size(); ++i) { | 656 for (size_t i = 0; i < form_element->control_elements.size(); ++i) { |
| 656 WebFormControlElement element = form_element->control_elements[i]; | 657 WebFormControlElement element = form_element->control_elements[i]; |
| 657 if (IsTextElement(element)) { | 658 WebInputElement* input_element = toWebInputElement(&element); |
| 658 WebInputElement input_element = element.to<WebInputElement>(); | 659 if (IsTextInput(input_element)) { |
| 659 | 660 |
| 660 // We don't modify the value of disabled fields. | 661 // We don't modify the value of disabled fields. |
| 661 if (!input_element.isEnabled()) | 662 if (!input_element->isEnabled()) |
| 662 continue; | 663 continue; |
| 663 | 664 |
| 664 input_element.setValue(string16()); | 665 input_element->setValue(string16()); |
| 665 input_element.setAutofilled(false); | 666 input_element->setAutofilled(false); |
| 666 | 667 |
| 667 // Clearing the value in the focused node (above) can cause selection | 668 // Clearing the value in the focused node (above) can cause selection |
| 668 // to be lost. We force selection range to restore the text cursor. | 669 // to be lost. We force selection range to restore the text cursor. |
| 669 if (node == input_element) { | 670 if (node == *input_element) { |
| 670 int length = input_element.value().length(); | 671 int length = input_element->value().length(); |
| 671 input_element.setSelectionRange(length, length); | 672 input_element->setSelectionRange(length, length); |
| 672 } | 673 } |
| 673 } else if (IsSelectElement(element)) { | 674 } else if (IsSelectElement(element)) { |
| 674 WebSelectElement select_element = element.to<WebSelectElement>(); | 675 WebSelectElement select_element = element.to<WebSelectElement>(); |
| 675 select_element.setValue(form_element->control_values[i]); | 676 select_element.setValue(form_element->control_values[i]); |
| 676 } | 677 } |
| 677 } | 678 } |
| 678 | 679 |
| 679 return true; | 680 return true; |
| 680 } | 681 } |
| 681 | 682 |
| 682 bool FormManager::ClearPreviewedFormWithNode(const WebNode& node, | 683 bool FormManager::ClearPreviewedFormWithNode(const WebNode& node, |
| 683 bool was_autofilled) { | 684 bool was_autofilled) { |
| 684 FormElement* form_element = NULL; | 685 FormElement* form_element = NULL; |
| 685 if (!FindCachedFormElementWithNode(node, &form_element)) | 686 if (!FindCachedFormElementWithNode(node, &form_element)) |
| 686 return false; | 687 return false; |
| 687 | 688 |
| 688 for (size_t i = 0; i < form_element->control_elements.size(); ++i) { | 689 for (size_t i = 0; i < form_element->control_elements.size(); ++i) { |
| 689 WebFormControlElement* element = &form_element->control_elements[i]; | 690 WebInputElement* input_element = |
| 690 | 691 toWebInputElement(&form_element->control_elements[i]); |
| 691 // Only text input elements can be previewed. | 692 // Only text input elements can be previewed. |
| 692 if (!IsTextElement(*element)) | 693 if (!IsTextInput(input_element)) |
| 693 continue; | 694 continue; |
| 694 | 695 |
| 695 // If the input element has not been auto-filled, FormManager has not | 696 // If the input element has not been auto-filled, FormManager has not |
| 696 // previewed this field, so we have nothing to reset. | 697 // previewed this field, so we have nothing to reset. |
| 697 WebInputElement input_element = element->to<WebInputElement>(); | 698 if (!input_element->isAutofilled()) |
| 698 if (!input_element.isAutofilled()) | |
| 699 continue; | 699 continue; |
| 700 | 700 |
| 701 // There might be unrelated elements in this form which have already been | 701 // There might be unrelated elements in this form which have already been |
| 702 // auto-filled. For example, the user might have already filled the address | 702 // auto-filled. For example, the user might have already filled the address |
| 703 // part of a form and now be dealing with the credit card section. We only | 703 // part of a form and now be dealing with the credit card section. We only |
| 704 // want to reset the auto-filled status for fields that were previewed. | 704 // want to reset the auto-filled status for fields that were previewed. |
| 705 if (input_element.suggestedValue().isEmpty()) | 705 if (input_element->suggestedValue().isEmpty()) |
| 706 continue; | 706 continue; |
| 707 | 707 |
| 708 // Clear the suggested value. For the initiating node, also restore the | 708 // Clear the suggested value. For the initiating node, also restore the |
| 709 // original value. | 709 // original value. |
| 710 input_element.setSuggestedValue(WebString()); | 710 input_element->setSuggestedValue(WebString()); |
| 711 bool is_initiating_node = (node == input_element); | 711 bool is_initiating_node = (node == *input_element); |
| 712 if (is_initiating_node) { | 712 if (is_initiating_node) { |
| 713 // Call |setValue()| to force the renderer to update the field's displayed | 713 // Call |setValue()| to force the renderer to update the field's displayed |
| 714 // value. | 714 // value. |
| 715 input_element.setValue(input_element.value()); | 715 input_element->setValue(input_element->value()); |
| 716 input_element.setAutofilled(was_autofilled); | 716 input_element->setAutofilled(was_autofilled); |
| 717 } else { | 717 } else { |
| 718 input_element.setAutofilled(false); | 718 input_element->setAutofilled(false); |
| 719 } | 719 } |
| 720 | 720 |
| 721 // Clearing the suggested value in the focused node (above) can cause | 721 // Clearing the suggested value in the focused node (above) can cause |
| 722 // selection to be lost. We force selection range to restore the text | 722 // selection to be lost. We force selection range to restore the text |
| 723 // cursor. | 723 // cursor. |
| 724 if (is_initiating_node) { | 724 if (is_initiating_node) { |
| 725 int length = input_element.value().length(); | 725 int length = input_element->value().length(); |
| 726 input_element.setSelectionRange(length, length); | 726 input_element->setSelectionRange(length, length); |
| 727 } | 727 } |
| 728 } | 728 } |
| 729 | 729 |
| 730 return true; | 730 return true; |
| 731 } | 731 } |
| 732 | 732 |
| 733 void FormManager::Reset() { | 733 void FormManager::Reset() { |
| 734 form_elements_.reset(); | 734 form_elements_.reset(); |
| 735 } | 735 } |
| 736 | 736 |
| 737 void FormManager::ResetFrame(const WebFrame* frame) { | 737 void FormManager::ResetFrame(const WebFrame* frame) { |
| 738 FormElementList::iterator iter = form_elements_.begin(); | 738 FormElementList::iterator iter = form_elements_.begin(); |
| 739 while (iter != form_elements_.end()) { | 739 while (iter != form_elements_.end()) { |
| 740 if ((*iter)->form_element.document().frame() == frame) | 740 if ((*iter)->form_element.document().frame() == frame) |
| 741 iter = form_elements_.erase(iter); | 741 iter = form_elements_.erase(iter); |
| 742 else | 742 else |
| 743 ++iter; | 743 ++iter; |
| 744 } | 744 } |
| 745 } | 745 } |
| 746 | 746 |
| 747 bool FormManager::FormWithNodeIsAutoFilled(const WebNode& node) { | 747 bool FormManager::FormWithNodeIsAutoFilled(const WebNode& node) { |
| 748 FormElement* form_element = NULL; | 748 FormElement* form_element = NULL; |
| 749 if (!FindCachedFormElementWithNode(node, &form_element)) | 749 if (!FindCachedFormElementWithNode(node, &form_element)) |
| 750 return false; | 750 return false; |
| 751 | 751 |
| 752 for (size_t i = 0; i < form_element->control_elements.size(); ++i) { | 752 for (size_t i = 0; i < form_element->control_elements.size(); ++i) { |
| 753 WebFormControlElement element = form_element->control_elements[i]; | 753 WebInputElement* input_element = |
| 754 if (!IsTextElement(element)) | 754 toWebInputElement(&form_element->control_elements[i]); |
| 755 if (!IsTextInput(input_element)) |
| 755 continue; | 756 continue; |
| 756 | 757 |
| 757 const WebInputElement& input_element = element.to<WebInputElement>(); | 758 if (input_element->isAutofilled()) |
| 758 if (input_element.isAutofilled()) | |
| 759 return true; | 759 return true; |
| 760 } | 760 } |
| 761 | 761 |
| 762 return false; | 762 return false; |
| 763 } | 763 } |
| 764 | 764 |
| 765 bool FormManager::FindCachedFormElementWithNode(const WebNode& node, | 765 bool FormManager::FindCachedFormElementWithNode(const WebNode& node, |
| 766 FormElement** form_element) { | 766 FormElement** form_element) { |
| 767 for (FormElementList::const_iterator form_iter = form_elements_.begin(); | 767 for (FormElementList::const_iterator form_iter = form_elements_.begin(); |
| 768 form_iter != form_elements_.end(); ++form_iter) { | 768 form_iter != form_elements_.end(); ++form_iter) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 829 if (k >= data.fields.size()) | 829 if (k >= data.fields.size()) |
| 830 continue; | 830 continue; |
| 831 | 831 |
| 832 DCHECK_EQ(data.fields[k].name(), element_name); | 832 DCHECK_EQ(data.fields[k].name(), element_name); |
| 833 | 833 |
| 834 bool is_initiating_node = false; | 834 bool is_initiating_node = false; |
| 835 | 835 |
| 836 // More than likely |requirements| will contain REQUIRE_AUTOCOMPLETE and/or | 836 // More than likely |requirements| will contain REQUIRE_AUTOCOMPLETE and/or |
| 837 // REQUIRE_EMPTY, which both require text form control elements, so special- | 837 // REQUIRE_EMPTY, which both require text form control elements, so special- |
| 838 // case this type of element. | 838 // case this type of element. |
| 839 if (IsTextElement(*element)) { | 839 const WebInputElement* input_element = toWebInputElement(element); |
| 840 const WebInputElement& input_element = | 840 if (IsTextInput(input_element)) { |
| 841 element->toConst<WebInputElement>(); | |
| 842 | 841 |
| 843 // TODO(jhawkins): WebKit currently doesn't handle the autocomplete | 842 // TODO(jhawkins): WebKit currently doesn't handle the autocomplete |
| 844 // attribute for select control elements, but it probably should. | 843 // attribute for select control elements, but it probably should. |
| 845 if (requirements & REQUIRE_AUTOCOMPLETE && !input_element.autoComplete()) | 844 if (requirements & REQUIRE_AUTOCOMPLETE && !input_element->autoComplete()) |
| 846 continue; | 845 continue; |
| 847 | 846 |
| 848 is_initiating_node = (input_element == node); | 847 is_initiating_node = (*input_element == node); |
| 849 // Don't require the node that initiated the auto-fill process to be | 848 // Don't require the node that initiated the auto-fill process to be |
| 850 // empty. The user is typing in this field and we should complete the | 849 // empty. The user is typing in this field and we should complete the |
| 851 // value when the user selects a value to fill out. | 850 // value when the user selects a value to fill out. |
| 852 if (requirements & REQUIRE_EMPTY && | 851 if (requirements & REQUIRE_EMPTY && |
| 853 !is_initiating_node && | 852 !is_initiating_node && |
| 854 !input_element.value().isEmpty()) | 853 !input_element->value().isEmpty()) |
| 855 continue; | 854 continue; |
| 856 } | 855 } |
| 857 | 856 |
| 858 if (requirements & REQUIRE_ENABLED && !element->isEnabled()) | 857 if (requirements & REQUIRE_ENABLED && !element->isEnabled()) |
| 859 continue; | 858 continue; |
| 860 | 859 |
| 861 callback->Run(element, &data.fields[k], is_initiating_node); | 860 callback->Run(element, &data.fields[k], is_initiating_node); |
| 862 | 861 |
| 863 // We found a matching form field so move on to the next. | 862 // We found a matching form field so move on to the next. |
| 864 ++j; | 863 ++j; |
| 865 } | 864 } |
| 866 | 865 |
| 867 delete callback; | 866 delete callback; |
| 868 } | 867 } |
| 869 | 868 |
| 870 void FormManager::FillFormField(WebFormControlElement* field, | 869 void FormManager::FillFormField(WebFormControlElement* field, |
| 871 const FormField* data, | 870 const FormField* data, |
| 872 bool is_initiating_node) { | 871 bool is_initiating_node) { |
| 873 // Nothing to fill. | 872 // Nothing to fill. |
| 874 if (data->value().empty()) | 873 if (data->value().empty()) |
| 875 return; | 874 return; |
| 876 | 875 |
| 877 if (IsTextElement(*field)) { | 876 WebInputElement* input_element = toWebInputElement(field); |
| 878 WebInputElement input_element = field->to<WebInputElement>(); | 877 if (IsTextInput(input_element)) { |
| 879 | 878 |
| 880 // If the maxlength attribute contains a negative value, maxLength() | 879 // If the maxlength attribute contains a negative value, maxLength() |
| 881 // returns the default maxlength value. | 880 // returns the default maxlength value. |
| 882 input_element.setValue(data->value().substr(0, input_element.maxLength())); | 881 input_element->setValue( |
| 883 input_element.setAutofilled(true); | 882 data->value().substr(0, input_element->maxLength())); |
| 883 input_element->setAutofilled(true); |
| 884 if (is_initiating_node) { | 884 if (is_initiating_node) { |
| 885 int length = input_element.value().length(); | 885 int length = input_element->value().length(); |
| 886 input_element.setSelectionRange(length, length); | 886 input_element->setSelectionRange(length, length); |
| 887 } | 887 } |
| 888 } else if (IsSelectElement(*field)) { | 888 } else if (IsSelectElement(*field)) { |
| 889 WebSelectElement select_element = field->to<WebSelectElement>(); | 889 WebSelectElement select_element = field->to<WebSelectElement>(); |
| 890 select_element.setValue(data->value()); | 890 select_element.setValue(data->value()); |
| 891 } | 891 } |
| 892 } | 892 } |
| 893 | 893 |
| 894 void FormManager::PreviewFormField(WebFormControlElement* field, | 894 void FormManager::PreviewFormField(WebFormControlElement* field, |
| 895 const FormField* data, | 895 const FormField* data, |
| 896 bool is_initiating_node) { | 896 bool is_initiating_node) { |
| 897 // Nothing to preview. | 897 // Nothing to preview. |
| 898 if (data->value().empty()) | 898 if (data->value().empty()) |
| 899 return; | 899 return; |
| 900 | 900 |
| 901 // Only preview input fields. | 901 // Only preview input fields. |
| 902 if (!IsTextElement(*field)) | 902 WebInputElement* input_element = toWebInputElement(field); |
| 903 if (!IsTextInput(input_element)) |
| 903 return; | 904 return; |
| 904 | 905 |
| 905 WebInputElement input_element = field->to<WebInputElement>(); | |
| 906 | |
| 907 // If the maxlength attribute contains a negative value, maxLength() | 906 // If the maxlength attribute contains a negative value, maxLength() |
| 908 // returns the default maxlength value. | 907 // returns the default maxlength value. |
| 909 input_element.setSuggestedValue( | 908 input_element->setSuggestedValue( |
| 910 data->value().substr(0, input_element.maxLength())); | 909 data->value().substr(0, input_element->maxLength())); |
| 911 input_element.setAutofilled(true); | 910 input_element->setAutofilled(true); |
| 912 if (is_initiating_node) | 911 if (is_initiating_node) |
| 913 input_element.setSelectionRange(0, input_element.suggestedValue().length()); | 912 input_element->setSelectionRange(0, |
| 913 input_element->suggestedValue().length()); |
| 914 } | 914 } |
| 915 | 915 |
| 916 } // namespace autofill | 916 } // namespace autofill |
| OLD | NEW |