OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "components/autofill/content/renderer/form_autofill_util.h" | 5 #include "components/autofill/content/renderer/form_autofill_util.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 #include "third_party/WebKit/public/web/WebFormElement.h" | 25 #include "third_party/WebKit/public/web/WebFormElement.h" |
26 #include "third_party/WebKit/public/web/WebFrame.h" | 26 #include "third_party/WebKit/public/web/WebFrame.h" |
27 #include "third_party/WebKit/public/web/WebInputElement.h" | 27 #include "third_party/WebKit/public/web/WebInputElement.h" |
28 #include "third_party/WebKit/public/web/WebLabelElement.h" | 28 #include "third_party/WebKit/public/web/WebLabelElement.h" |
29 #include "third_party/WebKit/public/web/WebNode.h" | 29 #include "third_party/WebKit/public/web/WebNode.h" |
30 #include "third_party/WebKit/public/web/WebNodeList.h" | 30 #include "third_party/WebKit/public/web/WebNodeList.h" |
31 #include "third_party/WebKit/public/web/WebOptionElement.h" | 31 #include "third_party/WebKit/public/web/WebOptionElement.h" |
32 #include "third_party/WebKit/public/web/WebSelectElement.h" | 32 #include "third_party/WebKit/public/web/WebSelectElement.h" |
33 #include "third_party/WebKit/public/web/WebTextAreaElement.h" | 33 #include "third_party/WebKit/public/web/WebTextAreaElement.h" |
34 | 34 |
35 using WebKit::WebDocument; | 35 using blink::WebDocument; |
36 using WebKit::WebElement; | 36 using blink::WebElement; |
37 using WebKit::WebExceptionCode; | 37 using blink::WebExceptionCode; |
38 using WebKit::WebFormControlElement; | 38 using blink::WebFormControlElement; |
39 using WebKit::WebFormElement; | 39 using blink::WebFormElement; |
40 using WebKit::WebFrame; | 40 using blink::WebFrame; |
41 using WebKit::WebInputElement; | 41 using blink::WebInputElement; |
42 using WebKit::WebLabelElement; | 42 using blink::WebLabelElement; |
43 using WebKit::WebNode; | 43 using blink::WebNode; |
44 using WebKit::WebNodeList; | 44 using blink::WebNodeList; |
45 using WebKit::WebOptionElement; | 45 using blink::WebOptionElement; |
46 using WebKit::WebSelectElement; | 46 using blink::WebSelectElement; |
47 using WebKit::WebTextAreaElement; | 47 using blink::WebTextAreaElement; |
48 using WebKit::WebString; | 48 using blink::WebString; |
49 using WebKit::WebVector; | 49 using blink::WebVector; |
50 | 50 |
51 namespace autofill { | 51 namespace autofill { |
52 namespace { | 52 namespace { |
53 | 53 |
54 // The maximum length allowed for form data. | 54 // The maximum length allowed for form data. |
55 const size_t kMaxDataLength = 1024; | 55 const size_t kMaxDataLength = 1024; |
56 | 56 |
57 // A bit field mask for FillForm functions to not fill some fields. | 57 // A bit field mask for FillForm functions to not fill some fields. |
58 enum FieldFilterMask { | 58 enum FieldFilterMask { |
59 FILTER_NONE = 0, | 59 FILTER_NONE = 0, |
(...skipping 13 matching lines...) Expand all Loading... |
73 bool IsScriptElement(const WebElement& element) { | 73 bool IsScriptElement(const WebElement& element) { |
74 CR_DEFINE_STATIC_LOCAL(WebString, kScript, ("script")); | 74 CR_DEFINE_STATIC_LOCAL(WebString, kScript, ("script")); |
75 return element.hasTagName(kScript); | 75 return element.hasTagName(kScript); |
76 } | 76 } |
77 | 77 |
78 bool IsNoScriptElement(const WebElement& element) { | 78 bool IsNoScriptElement(const WebElement& element) { |
79 CR_DEFINE_STATIC_LOCAL(WebString, kNoScript, ("noscript")); | 79 CR_DEFINE_STATIC_LOCAL(WebString, kNoScript, ("noscript")); |
80 return element.hasTagName(kNoScript); | 80 return element.hasTagName(kNoScript); |
81 } | 81 } |
82 | 82 |
83 bool HasTagName(const WebNode& node, const WebKit::WebString& tag) { | 83 bool HasTagName(const WebNode& node, const blink::WebString& tag) { |
84 return node.isElementNode() && node.toConst<WebElement>().hasHTMLTagName(tag); | 84 return node.isElementNode() && node.toConst<WebElement>().hasHTMLTagName(tag); |
85 } | 85 } |
86 | 86 |
87 bool IsAutofillableElement(const WebFormControlElement& element) { | 87 bool IsAutofillableElement(const WebFormControlElement& element) { |
88 const WebInputElement* input_element = toWebInputElement(&element); | 88 const WebInputElement* input_element = toWebInputElement(&element); |
89 return IsAutofillableInputElement(input_element) || | 89 return IsAutofillableInputElement(input_element) || |
90 IsSelectElement(element) || | 90 IsSelectElement(element) || |
91 IsTextAreaElement(element); | 91 IsTextAreaElement(element); |
92 } | 92 } |
93 | 93 |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 const WebOptionElement option = list_items[i].toConst<WebOptionElement>(); | 455 const WebOptionElement option = list_items[i].toConst<WebOptionElement>(); |
456 option_values->push_back(option.value()); | 456 option_values->push_back(option.value()); |
457 option_contents->push_back(option.text()); | 457 option_contents->push_back(option.text()); |
458 } | 458 } |
459 } | 459 } |
460 } | 460 } |
461 | 461 |
462 // The callback type used by |ForEachMatchingFormField()|. | 462 // The callback type used by |ForEachMatchingFormField()|. |
463 typedef void (*Callback)(const FormFieldData&, | 463 typedef void (*Callback)(const FormFieldData&, |
464 bool, /* is_initiating_element */ | 464 bool, /* is_initiating_element */ |
465 WebKit::WebFormControlElement*); | 465 blink::WebFormControlElement*); |
466 | 466 |
467 // For each autofillable field in |data| that matches a field in the |form|, | 467 // For each autofillable field in |data| that matches a field in the |form|, |
468 // the |callback| is invoked with the corresponding |form| field data. | 468 // the |callback| is invoked with the corresponding |form| field data. |
469 void ForEachMatchingFormField(const WebFormElement& form_element, | 469 void ForEachMatchingFormField(const WebFormElement& form_element, |
470 const WebElement& initiating_element, | 470 const WebElement& initiating_element, |
471 const FormData& data, | 471 const FormData& data, |
472 FieldFilterMask filters, | 472 FieldFilterMask filters, |
473 bool force_override, | 473 bool force_override, |
474 Callback callback) { | 474 Callback callback) { |
475 std::vector<WebFormControlElement> control_elements; | 475 std::vector<WebFormControlElement> control_elements; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 continue; | 519 continue; |
520 | 520 |
521 callback(data.fields[i], is_initiating_element, element); | 521 callback(data.fields[i], is_initiating_element, element); |
522 } | 522 } |
523 } | 523 } |
524 | 524 |
525 // Sets the |field|'s value to the value in |data|. | 525 // Sets the |field|'s value to the value in |data|. |
526 // Also sets the "autofilled" attribute, causing the background to be yellow. | 526 // Also sets the "autofilled" attribute, causing the background to be yellow. |
527 void FillFormField(const FormFieldData& data, | 527 void FillFormField(const FormFieldData& data, |
528 bool is_initiating_node, | 528 bool is_initiating_node, |
529 WebKit::WebFormControlElement* field) { | 529 blink::WebFormControlElement* field) { |
530 // Nothing to fill. | 530 // Nothing to fill. |
531 if (data.value.empty()) | 531 if (data.value.empty()) |
532 return; | 532 return; |
533 | 533 |
534 field->setAutofilled(true); | 534 field->setAutofilled(true); |
535 | 535 |
536 WebInputElement* input_element = toWebInputElement(field); | 536 WebInputElement* input_element = toWebInputElement(field); |
537 if (IsTextInput(input_element) || IsMonthInput(input_element)) { | 537 if (IsTextInput(input_element) || IsMonthInput(input_element)) { |
538 // If the maxlength attribute contains a negative value, maxLength() | 538 // If the maxlength attribute contains a negative value, maxLength() |
539 // returns the default maxlength value. | 539 // returns the default maxlength value. |
(...skipping 20 matching lines...) Expand all Loading... |
560 } else { | 560 } else { |
561 DCHECK(IsCheckableElement(input_element)); | 561 DCHECK(IsCheckableElement(input_element)); |
562 input_element->setChecked(data.is_checked, true); | 562 input_element->setChecked(data.is_checked, true); |
563 } | 563 } |
564 } | 564 } |
565 | 565 |
566 // Sets the |field|'s "suggested" (non JS visible) value to the value in |data|. | 566 // Sets the |field|'s "suggested" (non JS visible) value to the value in |data|. |
567 // Also sets the "autofilled" attribute, causing the background to be yellow. | 567 // Also sets the "autofilled" attribute, causing the background to be yellow. |
568 void PreviewFormField(const FormFieldData& data, | 568 void PreviewFormField(const FormFieldData& data, |
569 bool is_initiating_node, | 569 bool is_initiating_node, |
570 WebKit::WebFormControlElement* field) { | 570 blink::WebFormControlElement* field) { |
571 // Nothing to preview. | 571 // Nothing to preview. |
572 if (data.value.empty()) | 572 if (data.value.empty()) |
573 return; | 573 return; |
574 | 574 |
575 // Only preview input fields. Excludes checkboxes and radio buttons, as there | 575 // Only preview input fields. Excludes checkboxes and radio buttons, as there |
576 // is no provision for setSuggestedCheckedValue in WebInputElement. | 576 // is no provision for setSuggestedCheckedValue in WebInputElement. |
577 WebInputElement* input_element = toWebInputElement(field); | 577 WebInputElement* input_element = toWebInputElement(field); |
578 if (!IsTextInput(input_element)) | 578 if (!IsTextInput(input_element)) |
579 return; | 579 return; |
580 | 580 |
(...skipping 18 matching lines...) Expand all Loading... |
599 return "ID"; | 599 return "ID"; |
600 case WebElementDescriptor::NONE: | 600 case WebElementDescriptor::NONE: |
601 return "NONE"; | 601 return "NONE"; |
602 } | 602 } |
603 NOTREACHED(); | 603 NOTREACHED(); |
604 return "UNKNOWN"; | 604 return "UNKNOWN"; |
605 } | 605 } |
606 | 606 |
607 // Recursively checks whether |node| or any of its children have a non-empty | 607 // Recursively checks whether |node| or any of its children have a non-empty |
608 // bounding box. The recursion depth is bounded by |depth|. | 608 // bounding box. The recursion depth is bounded by |depth|. |
609 bool IsWebNodeVisibleImpl(const WebKit::WebNode& node, const int depth) { | 609 bool IsWebNodeVisibleImpl(const blink::WebNode& node, const int depth) { |
610 if (depth < 0) | 610 if (depth < 0) |
611 return false; | 611 return false; |
612 if (node.hasNonEmptyBoundingBox()) | 612 if (node.hasNonEmptyBoundingBox()) |
613 return true; | 613 return true; |
614 | 614 |
615 // The childNodes method is not a const method. Therefore it cannot be called | 615 // The childNodes method is not a const method. Therefore it cannot be called |
616 // on a const reference. Therefore we need a const cast. | 616 // on a const reference. Therefore we need a const cast. |
617 const WebKit::WebNodeList& children = | 617 const blink::WebNodeList& children = |
618 const_cast<WebKit::WebNode&>(node).childNodes(); | 618 const_cast<blink::WebNode&>(node).childNodes(); |
619 size_t length = children.length(); | 619 size_t length = children.length(); |
620 for (size_t i = 0; i < length; ++i) { | 620 for (size_t i = 0; i < length; ++i) { |
621 const WebKit::WebNode& item = children.item(i); | 621 const blink::WebNode& item = children.item(i); |
622 if (IsWebNodeVisibleImpl(item, depth - 1)) | 622 if (IsWebNodeVisibleImpl(item, depth - 1)) |
623 return true; | 623 return true; |
624 } | 624 } |
625 return false; | 625 return false; |
626 } | 626 } |
627 | 627 |
628 } // namespace | 628 } // namespace |
629 | 629 |
630 const size_t kMaxParseableFields = 200; | 630 const size_t kMaxParseableFields = 200; |
631 | 631 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
666 | 666 |
667 const base::string16 GetFormIdentifier(const WebFormElement& form) { | 667 const base::string16 GetFormIdentifier(const WebFormElement& form) { |
668 base::string16 identifier = form.name(); | 668 base::string16 identifier = form.name(); |
669 CR_DEFINE_STATIC_LOCAL(WebString, kId, ("id")); | 669 CR_DEFINE_STATIC_LOCAL(WebString, kId, ("id")); |
670 if (identifier.empty()) | 670 if (identifier.empty()) |
671 identifier = form.getAttribute(kId); | 671 identifier = form.getAttribute(kId); |
672 | 672 |
673 return identifier; | 673 return identifier; |
674 } | 674 } |
675 | 675 |
676 bool IsWebNodeVisible(const WebKit::WebNode& node) { | 676 bool IsWebNodeVisible(const blink::WebNode& node) { |
677 // In the bug http://crbug.com/237216 the form's bounding box is empty | 677 // In the bug http://crbug.com/237216 the form's bounding box is empty |
678 // however the form has non empty children. Thus we need to look at the | 678 // however the form has non empty children. Thus we need to look at the |
679 // form's children. | 679 // form's children. |
680 int kNodeSearchDepth = 2; | 680 int kNodeSearchDepth = 2; |
681 return IsWebNodeVisibleImpl(node, kNodeSearchDepth); | 681 return IsWebNodeVisibleImpl(node, kNodeSearchDepth); |
682 } | 682 } |
683 | 683 |
684 bool ClickElement(const WebDocument& document, | 684 bool ClickElement(const WebDocument& document, |
685 const WebElementDescriptor& element_descriptor) { | 685 const WebElementDescriptor& element_descriptor) { |
686 WebString web_descriptor = WebString::fromUTF8(element_descriptor.descriptor); | 686 WebString web_descriptor = WebString::fromUTF8(element_descriptor.descriptor); |
687 WebKit::WebElement element; | 687 blink::WebElement element; |
688 | 688 |
689 switch (element_descriptor.retrieval_method) { | 689 switch (element_descriptor.retrieval_method) { |
690 case WebElementDescriptor::CSS_SELECTOR: { | 690 case WebElementDescriptor::CSS_SELECTOR: { |
691 WebExceptionCode ec = 0; | 691 WebExceptionCode ec = 0; |
692 element = document.querySelector(web_descriptor, ec); | 692 element = document.querySelector(web_descriptor, ec); |
693 if (ec) | 693 if (ec) |
694 DVLOG(1) << "Query selector failed. Error code: " << ec << "."; | 694 DVLOG(1) << "Query selector failed. Error code: " << ec << "."; |
695 break; | 695 break; |
696 } | 696 } |
697 case WebElementDescriptor::ID: | 697 case WebElementDescriptor::ID: |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 | 820 |
821 // Constrain the maximum data length to prevent a malicious site from DOS'ing | 821 // Constrain the maximum data length to prevent a malicious site from DOS'ing |
822 // the browser: http://crbug.com/49332 | 822 // the browser: http://crbug.com/49332 |
823 if (value.size() > kMaxDataLength) | 823 if (value.size() > kMaxDataLength) |
824 value = value.substr(0, kMaxDataLength); | 824 value = value.substr(0, kMaxDataLength); |
825 | 825 |
826 field->value = value; | 826 field->value = value; |
827 } | 827 } |
828 | 828 |
829 bool WebFormElementToFormData( | 829 bool WebFormElementToFormData( |
830 const WebKit::WebFormElement& form_element, | 830 const blink::WebFormElement& form_element, |
831 const WebKit::WebFormControlElement& form_control_element, | 831 const blink::WebFormControlElement& form_control_element, |
832 RequirementsMask requirements, | 832 RequirementsMask requirements, |
833 ExtractMask extract_mask, | 833 ExtractMask extract_mask, |
834 FormData* form, | 834 FormData* form, |
835 FormFieldData* field) { | 835 FormFieldData* field) { |
836 CR_DEFINE_STATIC_LOCAL(WebString, kLabel, ("label")); | 836 CR_DEFINE_STATIC_LOCAL(WebString, kLabel, ("label")); |
837 CR_DEFINE_STATIC_LOCAL(WebString, kFor, ("for")); | 837 CR_DEFINE_STATIC_LOCAL(WebString, kFor, ("for")); |
838 CR_DEFINE_STATIC_LOCAL(WebString, kHidden, ("hidden")); | 838 CR_DEFINE_STATIC_LOCAL(WebString, kHidden, ("hidden")); |
839 | 839 |
840 const WebFrame* frame = form_element.document().frame(); | 840 const WebFrame* frame = form_element.document().frame(); |
841 if (!frame) | 841 if (!frame) |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1100 if (!IsAutofillableInputElement(input_element)) | 1100 if (!IsAutofillableInputElement(input_element)) |
1101 continue; | 1101 continue; |
1102 | 1102 |
1103 if (input_element->isAutofilled()) | 1103 if (input_element->isAutofilled()) |
1104 return true; | 1104 return true; |
1105 } | 1105 } |
1106 | 1106 |
1107 return false; | 1107 return false; |
1108 } | 1108 } |
1109 | 1109 |
1110 bool IsWebpageEmpty(const WebKit::WebFrame* frame) { | 1110 bool IsWebpageEmpty(const blink::WebFrame* frame) { |
1111 WebKit::WebDocument document = frame->document(); | 1111 blink::WebDocument document = frame->document(); |
1112 | 1112 |
1113 return IsWebElementEmpty(document.head()) && | 1113 return IsWebElementEmpty(document.head()) && |
1114 IsWebElementEmpty(document.body()); | 1114 IsWebElementEmpty(document.body()); |
1115 } | 1115 } |
1116 | 1116 |
1117 bool IsWebElementEmpty(const WebKit::WebElement& element) { | 1117 bool IsWebElementEmpty(const blink::WebElement& element) { |
1118 // This array contains all tags which can be present in an empty page. | 1118 // This array contains all tags which can be present in an empty page. |
1119 const char* const kAllowedValue[] = { | 1119 const char* const kAllowedValue[] = { |
1120 "script", | 1120 "script", |
1121 "meta", | 1121 "meta", |
1122 "title", | 1122 "title", |
1123 }; | 1123 }; |
1124 const size_t kAllowedValueLength = arraysize(kAllowedValue); | 1124 const size_t kAllowedValueLength = arraysize(kAllowedValue); |
1125 | 1125 |
1126 if (element.isNull()) | 1126 if (element.isNull()) |
1127 return true; | 1127 return true; |
1128 // The childNodes method is not a const method. Therefore it cannot be called | 1128 // The childNodes method is not a const method. Therefore it cannot be called |
1129 // on a const reference. Therefore we need a const cast. | 1129 // on a const reference. Therefore we need a const cast. |
1130 const WebKit::WebNodeList& children = | 1130 const blink::WebNodeList& children = |
1131 const_cast<WebKit::WebElement&>(element).childNodes(); | 1131 const_cast<blink::WebElement&>(element).childNodes(); |
1132 for (size_t i = 0; i < children.length(); ++i) { | 1132 for (size_t i = 0; i < children.length(); ++i) { |
1133 const WebKit::WebNode& item = children.item(i); | 1133 const blink::WebNode& item = children.item(i); |
1134 | 1134 |
1135 if (item.isTextNode() && | 1135 if (item.isTextNode() && |
1136 !ContainsOnlyWhitespaceASCII(item.nodeValue().utf8())) | 1136 !ContainsOnlyWhitespaceASCII(item.nodeValue().utf8())) |
1137 return false; | 1137 return false; |
1138 | 1138 |
1139 // We ignore all other items with names which begin with | 1139 // We ignore all other items with names which begin with |
1140 // the character # because they are not html tags. | 1140 // the character # because they are not html tags. |
1141 if (item.nodeName().utf8()[0] == '#') | 1141 if (item.nodeName().utf8()[0] == '#') |
1142 continue; | 1142 continue; |
1143 | 1143 |
1144 bool tag_is_allowed = false; | 1144 bool tag_is_allowed = false; |
1145 // Test if the item name is in the kAllowedValue array | 1145 // Test if the item name is in the kAllowedValue array |
1146 for (size_t allowed_value_index = 0; | 1146 for (size_t allowed_value_index = 0; |
1147 allowed_value_index < kAllowedValueLength; ++allowed_value_index) { | 1147 allowed_value_index < kAllowedValueLength; ++allowed_value_index) { |
1148 if (HasTagName(item, | 1148 if (HasTagName(item, |
1149 WebString::fromUTF8(kAllowedValue[allowed_value_index]))) { | 1149 WebString::fromUTF8(kAllowedValue[allowed_value_index]))) { |
1150 tag_is_allowed = true; | 1150 tag_is_allowed = true; |
1151 break; | 1151 break; |
1152 } | 1152 } |
1153 } | 1153 } |
1154 if (!tag_is_allowed) | 1154 if (!tag_is_allowed) |
1155 return false; | 1155 return false; |
1156 } | 1156 } |
1157 return true; | 1157 return true; |
1158 } | 1158 } |
1159 | 1159 |
1160 } // namespace autofill | 1160 } // namespace autofill |
OLD | NEW |