| 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 |