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

Side by Side Diff: chrome/renderer/autofill/form_autofill_util.cc

Issue 11000016: Move forms/ out of webkit/. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Response to review Created 8 years, 2 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
« no previous file with comments | « chrome/renderer/autofill/form_autofill_util.h ('k') | chrome/renderer/autofill/form_cache.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/form_autofill_util.h" 5 #include "chrome/renderer/autofill/form_autofill_util.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/scoped_vector.h" 10 #include "base/memory/scoped_vector.h"
11 #include "base/string_util.h" 11 #include "base/string_util.h"
12 #include "base/utf_string_conversions.h" 12 #include "base/utf_string_conversions.h"
13 #include "chrome/common/form_data.h"
14 #include "chrome/common/form_field_data.h"
13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement .h" 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement .h"
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormElement.h" 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormElement.h"
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h" 20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebLabelElement.h" 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebLabelElement.h"
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" 22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h"
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeList.h" 23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeList.h"
22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebOptionElement.h" 24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebOptionElement.h"
23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSelectElement.h" 25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSelectElement.h"
24 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" 26 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
25 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h" 27 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h"
26 #include "webkit/forms/form_data.h"
27 #include "webkit/forms/form_field.h"
28 28
29 using WebKit::WebElement; 29 using WebKit::WebElement;
30 using WebKit::WebFormControlElement; 30 using WebKit::WebFormControlElement;
31 using WebKit::WebFormElement; 31 using WebKit::WebFormElement;
32 using WebKit::WebFrame; 32 using WebKit::WebFrame;
33 using WebKit::WebInputElement; 33 using WebKit::WebInputElement;
34 using WebKit::WebLabelElement; 34 using WebKit::WebLabelElement;
35 using WebKit::WebNode; 35 using WebKit::WebNode;
36 using WebKit::WebNodeList; 36 using WebKit::WebNodeList;
37 using WebKit::WebOptionElement; 37 using WebKit::WebOptionElement;
38 using WebKit::WebSelectElement; 38 using WebKit::WebSelectElement;
39 using WebKit::WebString; 39 using WebKit::WebString;
40 using WebKit::WebVector; 40 using WebKit::WebVector;
41 using webkit::forms::FormData;
42 using webkit::forms::FormField;
43 41
44 namespace { 42 namespace {
45 43
46 using autofill::ExtractAutofillableElements; 44 using autofill::ExtractAutofillableElements;
47 using autofill::IsTextInput; 45 using autofill::IsTextInput;
48 using autofill::IsSelectElement; 46 using autofill::IsSelectElement;
49 47
50 // The maximum length allowed for form data. 48 // The maximum length allowed for form data.
51 const size_t kMaxDataLength = 1024; 49 const size_t kMaxDataLength = 1024;
52 50
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 if (IsOptionElement(list_items[i])) { 407 if (IsOptionElement(list_items[i])) {
410 const WebOptionElement option = list_items[i].toConst<WebOptionElement>(); 408 const WebOptionElement option = list_items[i].toConst<WebOptionElement>();
411 option_values->push_back(option.value()); 409 option_values->push_back(option.value());
412 option_contents->push_back(option.text()); 410 option_contents->push_back(option.text());
413 } 411 }
414 } 412 }
415 } 413 }
416 414
417 // The callback type used by |ForEachMatchingFormField()|. 415 // The callback type used by |ForEachMatchingFormField()|.
418 typedef void (*Callback)(WebKit::WebFormControlElement*, 416 typedef void (*Callback)(WebKit::WebFormControlElement*,
419 const webkit::forms::FormField*, 417 const FormFieldData*,
420 bool); 418 bool);
421 419
422 // For each autofillable field in |data| that matches a field in the |form|, 420 // For each autofillable field in |data| that matches a field in the |form|,
423 // the |callback| is invoked with the corresponding |form| field data. 421 // the |callback| is invoked with the corresponding |form| field data.
424 void ForEachMatchingFormField(const WebFormElement& form_element, 422 void ForEachMatchingFormField(const WebFormElement& form_element,
425 const WebElement& initiating_element, 423 const WebElement& initiating_element,
426 const FormData& data, 424 const FormData& data,
427 Callback callback) { 425 Callback callback) {
428 std::vector<WebFormControlElement> control_elements; 426 std::vector<WebFormControlElement> control_elements;
429 ExtractAutofillableElements(form_element, autofill::REQUIRE_AUTOCOMPLETE, 427 ExtractAutofillableElements(form_element, autofill::REQUIRE_AUTOCOMPLETE,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 !element->isFocusable()) 469 !element->isFocusable())
472 continue; 470 continue;
473 471
474 callback(element, &data.fields[i], is_initiating_element); 472 callback(element, &data.fields[i], is_initiating_element);
475 } 473 }
476 } 474 }
477 475
478 // Sets the |field|'s value to the value in |data|. 476 // Sets the |field|'s value to the value in |data|.
479 // Also sets the "autofilled" attribute, causing the background to be yellow. 477 // Also sets the "autofilled" attribute, causing the background to be yellow.
480 void FillFormField(WebKit::WebFormControlElement* field, 478 void FillFormField(WebKit::WebFormControlElement* field,
481 const webkit::forms::FormField* data, 479 const FormFieldData* data,
482 bool is_initiating_node) { 480 bool is_initiating_node) {
483 // Nothing to fill. 481 // Nothing to fill.
484 if (data->value.empty()) 482 if (data->value.empty())
485 return; 483 return;
486 484
487 WebInputElement* input_element = toWebInputElement(field); 485 WebInputElement* input_element = toWebInputElement(field);
488 if (IsTextInput(input_element)) { 486 if (IsTextInput(input_element)) {
489 // If the maxlength attribute contains a negative value, maxLength() 487 // If the maxlength attribute contains a negative value, maxLength()
490 // returns the default maxlength value. 488 // returns the default maxlength value.
491 input_element->setValue( 489 input_element->setValue(
492 data->value.substr(0, input_element->maxLength()), true); 490 data->value.substr(0, input_element->maxLength()), true);
493 input_element->setAutofilled(true); 491 input_element->setAutofilled(true);
494 if (is_initiating_node) { 492 if (is_initiating_node) {
495 int length = input_element->value().length(); 493 int length = input_element->value().length();
496 input_element->setSelectionRange(length, length); 494 input_element->setSelectionRange(length, length);
497 } 495 }
498 } else { 496 } else {
499 DCHECK(IsSelectElement(*field)); 497 DCHECK(IsSelectElement(*field));
500 WebSelectElement select_element = field->to<WebSelectElement>(); 498 WebSelectElement select_element = field->to<WebSelectElement>();
501 if (select_element.value() != data->value) { 499 if (select_element.value() != data->value) {
502 select_element.setValue(data->value); 500 select_element.setValue(data->value);
503 select_element.dispatchFormControlChangeEvent(); 501 select_element.dispatchFormControlChangeEvent();
504 } 502 }
505 } 503 }
506 } 504 }
507 505
508 // Sets the |field|'s "suggested" (non JS visible) value to the value in |data|. 506 // Sets the |field|'s "suggested" (non JS visible) value to the value in |data|.
509 // Also sets the "autofilled" attribute, causing the background to be yellow. 507 // Also sets the "autofilled" attribute, causing the background to be yellow.
510 void PreviewFormField(WebKit::WebFormControlElement* field, 508 void PreviewFormField(WebKit::WebFormControlElement* field,
511 const webkit::forms::FormField* data, 509 const FormFieldData* data,
512 bool is_initiating_node) { 510 bool is_initiating_node) {
513 // Nothing to preview. 511 // Nothing to preview.
514 if (data->value.empty()) 512 if (data->value.empty())
515 return; 513 return;
516 514
517 // Only preview input fields. 515 // Only preview input fields.
518 WebInputElement* input_element = toWebInputElement(field); 516 WebInputElement* input_element = toWebInputElement(field);
519 if (!IsTextInput(input_element)) 517 if (!IsTextInput(input_element))
520 return; 518 return;
521 519
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 if (IsTextInput(input_element) && !input_element->autoComplete()) 578 if (IsTextInput(input_element) && !input_element->autoComplete())
581 continue; 579 continue;
582 } 580 }
583 581
584 autofillable_elements->push_back(element); 582 autofillable_elements->push_back(element);
585 } 583 }
586 } 584 }
587 585
588 void WebFormControlElementToFormField(const WebFormControlElement& element, 586 void WebFormControlElementToFormField(const WebFormControlElement& element,
589 ExtractMask extract_mask, 587 ExtractMask extract_mask,
590 FormField* field) { 588 FormFieldData* field) {
591 DCHECK(field); 589 DCHECK(field);
592 DCHECK(!element.isNull()); 590 DCHECK(!element.isNull());
593 591
594 // The label is not officially part of a WebFormControlElement; however, the 592 // The label is not officially part of a WebFormControlElement; however, the
595 // labels for all form control elements are scraped from the DOM and set in 593 // labels for all form control elements are scraped from the DOM and set in
596 // WebFormElementToFormData. 594 // WebFormElementToFormData.
597 field->name = element.nameForAutofill(); 595 field->name = element.nameForAutofill();
598 field->form_control_type = element.formControlType(); 596 field->form_control_type = element.formControlType();
599 field->autocomplete_type = element.getAttribute("x-autocompletetype"); 597 field->autocomplete_type = element.getAttribute("x-autocompletetype");
600 TrimWhitespace(field->autocomplete_type, TRIM_ALL, &field->autocomplete_type); 598 TrimWhitespace(field->autocomplete_type, TRIM_ALL, &field->autocomplete_type);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
656 value = value.substr(0, kMaxDataLength); 654 value = value.substr(0, kMaxDataLength);
657 655
658 field->value = value; 656 field->value = value;
659 } 657 }
660 658
661 bool WebFormElementToFormData( 659 bool WebFormElementToFormData(
662 const WebKit::WebFormElement& form_element, 660 const WebKit::WebFormElement& form_element,
663 const WebKit::WebFormControlElement& form_control_element, 661 const WebKit::WebFormControlElement& form_control_element,
664 RequirementsMask requirements, 662 RequirementsMask requirements,
665 ExtractMask extract_mask, 663 ExtractMask extract_mask,
666 webkit::forms::FormData* form, 664 FormData* form,
667 webkit::forms::FormField* field) { 665 FormFieldData* field) {
668 const WebFrame* frame = form_element.document().frame(); 666 const WebFrame* frame = form_element.document().frame();
669 if (!frame) 667 if (!frame)
670 return false; 668 return false;
671 669
672 if (requirements & REQUIRE_AUTOCOMPLETE && !form_element.autoComplete()) 670 if (requirements & REQUIRE_AUTOCOMPLETE && !form_element.autoComplete())
673 return false; 671 return false;
674 672
675 form->name = GetFormIdentifier(form_element); 673 form->name = GetFormIdentifier(form_element);
676 form->method = form_element.method(); 674 form->method = form_element.method();
677 form->origin = frame->document().url(); 675 form->origin = frame->document().url();
678 form->action = frame->document().completeURL(form_element.action()); 676 form->action = frame->document().completeURL(form_element.action());
679 form->user_submitted = form_element.wasUserSubmitted(); 677 form->user_submitted = form_element.wasUserSubmitted();
680 678
681 // If the completed URL is not valid, just use the action we get from 679 // If the completed URL is not valid, just use the action we get from
682 // WebKit. 680 // WebKit.
683 if (!form->action.is_valid()) 681 if (!form->action.is_valid())
684 form->action = GURL(form_element.action()); 682 form->action = GURL(form_element.action());
685 683
686 // A map from a FormField's name to the FormField itself. 684 // A map from a FormFieldData's name to the FormFieldData itself.
687 std::map<string16, FormField*> name_map; 685 std::map<string16, FormFieldData*> name_map;
688 686
689 // The extracted FormFields. We use pointers so we can store them in 687 // The extracted FormFields. We use pointers so we can store them in
690 // |name_map|. 688 // |name_map|.
691 ScopedVector<FormField> form_fields; 689 ScopedVector<FormFieldData> form_fields;
692 690
693 WebVector<WebFormControlElement> control_elements; 691 WebVector<WebFormControlElement> control_elements;
694 form_element.getFormControlElements(control_elements); 692 form_element.getFormControlElements(control_elements);
695 693
696 // A vector of bools that indicate whether each field in the form meets the 694 // A vector of bools that indicate whether each field in the form meets the
697 // requirements and thus will be in the resulting |form|. 695 // requirements and thus will be in the resulting |form|.
698 std::vector<bool> fields_extracted(control_elements.size(), false); 696 std::vector<bool> fields_extracted(control_elements.size(), false);
699 697
700 for (size_t i = 0; i < control_elements.size(); ++i) { 698 for (size_t i = 0; i < control_elements.size(); ++i) {
701 const WebFormControlElement& control_element = control_elements[i]; 699 const WebFormControlElement& control_element = control_elements[i];
702 700
703 if (!IsAutofillableElement(control_element)) 701 if (!IsAutofillableElement(control_element))
704 continue; 702 continue;
705 703
706 const WebInputElement* input_element = toWebInputElement(&control_element); 704 const WebInputElement* input_element = toWebInputElement(&control_element);
707 if (requirements & REQUIRE_AUTOCOMPLETE && IsTextInput(input_element) && 705 if (requirements & REQUIRE_AUTOCOMPLETE && IsTextInput(input_element) &&
708 !input_element->autoComplete()) 706 !input_element->autoComplete())
709 continue; 707 continue;
710 708
711 // Create a new FormField, fill it out and map it to the field's name. 709 // Create a new FormFieldData, fill it out and map it to the field's name.
712 FormField* form_field = new FormField; 710 FormFieldData* form_field = new FormFieldData;
713 WebFormControlElementToFormField(control_element, extract_mask, form_field); 711 WebFormControlElementToFormField(control_element, extract_mask, form_field);
714 form_fields.push_back(form_field); 712 form_fields.push_back(form_field);
715 // TODO(jhawkins): A label element is mapped to a form control element's id. 713 // TODO(jhawkins): A label element is mapped to a form control element's id.
716 // field->name() will contain the id only if the name does not exist. Add 714 // field->name() will contain the id only if the name does not exist. Add
717 // an id() method to WebFormControlElement and use that here. 715 // an id() method to WebFormControlElement and use that here.
718 name_map[form_field->name] = form_field; 716 name_map[form_field->name] = form_field;
719 fields_extracted[i] = true; 717 fields_extracted[i] = true;
720 } 718 }
721 719
722 // If we failed to extract any fields, give up. Also, to avoid overly 720 // If we failed to extract any fields, give up. Also, to avoid overly
723 // expensive computation, we impose a maximum number of allowable fields. 721 // expensive computation, we impose a maximum number of allowable fields.
724 if (form_fields.empty() || form_fields.size() > kMaxParseableFields) 722 if (form_fields.empty() || form_fields.size() > kMaxParseableFields)
725 return false; 723 return false;
726 724
727 // Loop through the label elements inside the form element. For each label 725 // Loop through the label elements inside the form element. For each label
728 // element, get the corresponding form control element, use the form control 726 // element, get the corresponding form control element, use the form control
729 // element's name as a key into the <name, FormField> map to find the 727 // element's name as a key into the <name, FormFieldData> map to find the
730 // previously created FormField and set the FormField's label to the 728 // previously created FormFieldData and set the FormFieldData's label to the
731 // label.firstChild().nodeValue() of the label element. 729 // label.firstChild().nodeValue() of the label element.
732 WebNodeList labels = form_element.getElementsByTagName("label"); 730 WebNodeList labels = form_element.getElementsByTagName("label");
733 for (unsigned i = 0; i < labels.length(); ++i) { 731 for (unsigned i = 0; i < labels.length(); ++i) {
734 WebLabelElement label = labels.item(i).to<WebLabelElement>(); 732 WebLabelElement label = labels.item(i).to<WebLabelElement>();
735 WebFormControlElement field_element = 733 WebFormControlElement field_element =
736 label.correspondingControl().to<WebFormControlElement>(); 734 label.correspondingControl().to<WebFormControlElement>();
737 735
738 string16 element_name; 736 string16 element_name;
739 if (field_element.isNull()) { 737 if (field_element.isNull()) {
740 // Sometimes site authors will incorrectly specify the corresponding 738 // Sometimes site authors will incorrectly specify the corresponding
741 // field element's name rather than its id, so we compensate here. 739 // field element's name rather than its id, so we compensate here.
742 element_name = label.getAttribute("for"); 740 element_name = label.getAttribute("for");
743 } else if ( 741 } else if (
744 !field_element.isFormControlElement() || 742 !field_element.isFormControlElement() ||
745 field_element.formControlType() == WebString::fromUTF8("hidden")) { 743 field_element.formControlType() == WebString::fromUTF8("hidden")) {
746 continue; 744 continue;
747 } else { 745 } else {
748 element_name = field_element.nameForAutofill(); 746 element_name = field_element.nameForAutofill();
749 } 747 }
750 748
751 std::map<string16, FormField*>::iterator iter = name_map.find(element_name); 749 std::map<string16, FormFieldData*>::iterator iter =
750 name_map.find(element_name);
752 if (iter != name_map.end()) { 751 if (iter != name_map.end()) {
753 string16 label_text = FindChildText(label); 752 string16 label_text = FindChildText(label);
754 753
755 // Concatenate labels because some sites might have multiple label 754 // Concatenate labels because some sites might have multiple label
756 // candidates. 755 // candidates.
757 if (!iter->second->label.empty() && !label_text.empty()) 756 if (!iter->second->label.empty() && !label_text.empty())
758 iter->second->label += ASCIIToUTF16(" "); 757 iter->second->label += ASCIIToUTF16(" ");
759 iter->second->label += label_text; 758 iter->second->label += label_text;
760 } 759 }
761 } 760 }
(...skipping 13 matching lines...) Expand all
775 if (form_fields[field_idx]->label.empty()) 774 if (form_fields[field_idx]->label.empty())
776 form_fields[field_idx]->label = InferLabelForElement(control_element); 775 form_fields[field_idx]->label = InferLabelForElement(control_element);
777 776
778 if (field && form_control_element == control_element) 777 if (field && form_control_element == control_element)
779 *field = *form_fields[field_idx]; 778 *field = *form_fields[field_idx];
780 779
781 ++field_idx; 780 ++field_idx;
782 } 781 }
783 782
784 // Copy the created FormFields into the resulting FormData object. 783 // Copy the created FormFields into the resulting FormData object.
785 for (ScopedVector<FormField>::const_iterator iter = form_fields.begin(); 784 for (ScopedVector<FormFieldData>::const_iterator iter = form_fields.begin();
786 iter != form_fields.end(); ++iter) { 785 iter != form_fields.end(); ++iter) {
787 form->fields.push_back(**iter); 786 form->fields.push_back(**iter);
788 } 787 }
789 788
790 return true; 789 return true;
791 } 790 }
792 791
793 bool FindFormAndFieldForInputElement(const WebInputElement& element, 792 bool FindFormAndFieldForInputElement(const WebInputElement& element,
794 FormData* form, 793 FormData* form,
795 webkit::forms::FormField* field, 794 FormFieldData* field,
796 RequirementsMask requirements) { 795 RequirementsMask requirements) {
797 if (!IsAutofillableElement(element)) 796 if (!IsAutofillableElement(element))
798 return false; 797 return false;
799 798
800 const WebFormElement form_element = element.form(); 799 const WebFormElement form_element = element.form();
801 if (form_element.isNull()) 800 if (form_element.isNull())
802 return false; 801 return false;
803 802
804 ExtractMask extract_mask = 803 ExtractMask extract_mask =
805 static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTIONS); 804 static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTIONS);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
895 continue; 894 continue;
896 895
897 if (input_element->isAutofilled()) 896 if (input_element->isAutofilled())
898 return true; 897 return true;
899 } 898 }
900 899
901 return false; 900 return false;
902 } 901 }
903 902
904 } // namespace autofill 903 } // namespace autofill
OLDNEW
« no previous file with comments | « chrome/renderer/autofill/form_autofill_util.h ('k') | chrome/renderer/autofill/form_cache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698