| OLD | NEW |
| 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" |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 using autofill::ExtractAutofillableElements; | 48 using autofill::ExtractAutofillableElements; |
| 49 using autofill::IsAutofillableInputElement; | 49 using autofill::IsAutofillableInputElement; |
| 50 using autofill::IsCheckableElement; | 50 using autofill::IsCheckableElement; |
| 51 using autofill::IsSelectElement; | 51 using autofill::IsSelectElement; |
| 52 using autofill::IsTextInput; | 52 using autofill::IsTextInput; |
| 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 bool IsOptionElement(const WebElement& element) { | 57 bool IsOptionElement(const WebElement& element) { |
| 58 return element.hasTagName("option"); | 58 CR_DEFINE_STATIC_LOCAL(WebString, kOption, ("option")); |
| 59 return element.hasTagName(kOption); |
| 59 } | 60 } |
| 60 | 61 |
| 61 bool IsScriptElement(const WebElement& element) { | 62 bool IsScriptElement(const WebElement& element) { |
| 62 return element.hasTagName("script"); | 63 CR_DEFINE_STATIC_LOCAL(WebString, kScript, ("script")); |
| 64 return element.hasTagName(kScript); |
| 63 } | 65 } |
| 64 | 66 |
| 65 bool IsNoScriptElement(const WebElement& element) { | 67 bool IsNoScriptElement(const WebElement& element) { |
| 66 return element.hasTagName("noscript"); | 68 CR_DEFINE_STATIC_LOCAL(WebString, kNoScript, ("noscript")); |
| 69 return element.hasTagName(kNoScript); |
| 67 } | 70 } |
| 68 | 71 |
| 69 bool HasTagName(const WebNode& node, const WebKit::WebString& tag) { | 72 bool HasTagName(const WebNode& node, const WebKit::WebString& tag) { |
| 70 return node.isElementNode() && node.toConst<WebElement>().hasTagName(tag); | 73 return node.isElementNode() && node.toConst<WebElement>().hasTagName(tag); |
| 71 } | 74 } |
| 72 | 75 |
| 73 bool IsAutofillableElement(const WebFormControlElement& element) { | 76 bool IsAutofillableElement(const WebFormControlElement& element) { |
| 74 const WebInputElement* input_element = toWebInputElement(&element); | 77 const WebInputElement* input_element = toWebInputElement(&element); |
| 75 return IsAutofillableInputElement(input_element) || IsSelectElement(element); | 78 return IsAutofillableInputElement(input_element) || IsSelectElement(element); |
| 76 } | 79 } |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 | 197 |
| 195 // Otherwise, only consider normal HTML elements and their contents. | 198 // Otherwise, only consider normal HTML elements and their contents. |
| 196 if (node_type != WebNode::TextNode && | 199 if (node_type != WebNode::TextNode && |
| 197 node_type != WebNode::ElementNode) | 200 node_type != WebNode::ElementNode) |
| 198 break; | 201 break; |
| 199 | 202 |
| 200 // A label might be split across multiple "lightweight" nodes. | 203 // A label might be split across multiple "lightweight" nodes. |
| 201 // Coalesce any text contained in multiple consecutive | 204 // Coalesce any text contained in multiple consecutive |
| 202 // (a) plain text nodes or | 205 // (a) plain text nodes or |
| 203 // (b) inline HTML elements that are essentially equivalent to text nodes. | 206 // (b) inline HTML elements that are essentially equivalent to text nodes. |
| 207 CR_DEFINE_STATIC_LOCAL(WebString, kBold, ("b")); |
| 208 CR_DEFINE_STATIC_LOCAL(WebString, kStrong, ("strong")); |
| 209 CR_DEFINE_STATIC_LOCAL(WebString, kSpan, ("span")); |
| 210 CR_DEFINE_STATIC_LOCAL(WebString, kFont, ("font")); |
| 204 if (previous.isTextNode() || | 211 if (previous.isTextNode() || |
| 205 HasTagName(previous, "b") || HasTagName(previous, "strong") || | 212 HasTagName(previous, kBold) || HasTagName(previous, kStrong) || |
| 206 HasTagName(previous, "span") || HasTagName(previous, "font")) { | 213 HasTagName(previous, kSpan) || HasTagName(previous, kFont)) { |
| 207 string16 value = FindChildText(previous); | 214 string16 value = FindChildText(previous); |
| 208 // A text node's value will be empty if it is for a line break. | 215 // A text node's value will be empty if it is for a line break. |
| 209 bool add_space = previous.isTextNode() && value.empty(); | 216 bool add_space = previous.isTextNode() && value.empty(); |
| 210 inferred_label = | 217 inferred_label = |
| 211 CombineAndCollapseWhitespace(value, inferred_label, add_space); | 218 CombineAndCollapseWhitespace(value, inferred_label, add_space); |
| 212 continue; | 219 continue; |
| 213 } | 220 } |
| 214 | 221 |
| 215 // If we have identified a partial label and have reached a non-lightweight | 222 // If we have identified a partial label and have reached a non-lightweight |
| 216 // element, consider the label to be complete. | 223 // element, consider the label to be complete. |
| 217 string16 trimmed_label; | 224 string16 trimmed_label; |
| 218 TrimWhitespace(inferred_label, TRIM_ALL, &trimmed_label); | 225 TrimWhitespace(inferred_label, TRIM_ALL, &trimmed_label); |
| 219 if (!trimmed_label.empty()) | 226 if (!trimmed_label.empty()) |
| 220 break; | 227 break; |
| 221 | 228 |
| 222 // <img> and <br> tags often appear between the input element and its | 229 // <img> and <br> tags often appear between the input element and its |
| 223 // label text, so skip over them. | 230 // label text, so skip over them. |
| 224 if (HasTagName(previous, "img") || HasTagName(previous, "br")) | 231 CR_DEFINE_STATIC_LOCAL(WebString, kImage, ("img")); |
| 232 CR_DEFINE_STATIC_LOCAL(WebString, kBreak, ("br")); |
| 233 if (HasTagName(previous, kImage) || HasTagName(previous, kBreak)) |
| 225 continue; | 234 continue; |
| 226 | 235 |
| 227 // We only expect <p> and <label> tags to contain the full label text. | 236 // We only expect <p> and <label> tags to contain the full label text. |
| 228 if (HasTagName(previous, "p") || HasTagName(previous, "label")) | 237 CR_DEFINE_STATIC_LOCAL(WebString, kPage, ("p")); |
| 238 CR_DEFINE_STATIC_LOCAL(WebString, kLabel, ("label")); |
| 239 if (HasTagName(previous, kPage) || HasTagName(previous, kLabel)) |
| 229 inferred_label = FindChildText(previous); | 240 inferred_label = FindChildText(previous); |
| 230 | 241 |
| 231 break; | 242 break; |
| 232 } | 243 } |
| 233 | 244 |
| 234 TrimWhitespace(inferred_label, TRIM_ALL, &inferred_label); | 245 TrimWhitespace(inferred_label, TRIM_ALL, &inferred_label); |
| 235 return inferred_label; | 246 return inferred_label; |
| 236 } | 247 } |
| 237 | 248 |
| 238 // Helper for |InferLabelForElement()| that infers a label, if possible, from | 249 // Helper for |InferLabelForElement()| that infers a label, if possible, from |
| 239 // enclosing list item, | 250 // enclosing list item, |
| 240 // e.g. <li>Some Text<input ...><input ...><input ...></tr> | 251 // e.g. <li>Some Text<input ...><input ...><input ...></tr> |
| 241 string16 InferLabelFromListItem(const WebFormControlElement& element) { | 252 string16 InferLabelFromListItem(const WebFormControlElement& element) { |
| 242 WebNode parent = element.parentNode(); | 253 WebNode parent = element.parentNode(); |
| 254 CR_DEFINE_STATIC_LOCAL(WebString, kListItem, ("li")); |
| 243 while (!parent.isNull() && parent.isElementNode() && | 255 while (!parent.isNull() && parent.isElementNode() && |
| 244 !parent.to<WebElement>().hasTagName("li")) { | 256 !parent.to<WebElement>().hasTagName(kListItem)) { |
| 245 parent = parent.parentNode(); | 257 parent = parent.parentNode(); |
| 246 } | 258 } |
| 247 | 259 |
| 248 if (!parent.isNull() && HasTagName(parent, "li")) | 260 if (!parent.isNull() && HasTagName(parent, kListItem)) |
| 249 return FindChildText(parent); | 261 return FindChildText(parent); |
| 250 | 262 |
| 251 return string16(); | 263 return string16(); |
| 252 } | 264 } |
| 253 | 265 |
| 254 // Helper for |InferLabelForElement()| that infers a label, if possible, from | 266 // Helper for |InferLabelForElement()| that infers a label, if possible, from |
| 255 // surrounding table structure, | 267 // surrounding table structure, |
| 256 // e.g. <tr><td>Some Text</td><td><input ...></td></tr> | 268 // e.g. <tr><td>Some Text</td><td><input ...></td></tr> |
| 257 // or <tr><th>Some Text</th><td><input ...></td></tr> | 269 // or <tr><th>Some Text</th><td><input ...></td></tr> |
| 258 // or <tr><td><b>Some Text</b></td><td><b><input ...></b></td></tr> | 270 // or <tr><td><b>Some Text</b></td><td><b><input ...></b></td></tr> |
| 259 // or <tr><th><b>Some Text</b></th><td><b><input ...></b></td></tr> | 271 // or <tr><th><b>Some Text</b></th><td><b><input ...></b></td></tr> |
| 260 string16 InferLabelFromTableColumn(const WebFormControlElement& element) { | 272 string16 InferLabelFromTableColumn(const WebFormControlElement& element) { |
| 273 CR_DEFINE_STATIC_LOCAL(WebString, kTableCell, ("td")); |
| 261 WebNode parent = element.parentNode(); | 274 WebNode parent = element.parentNode(); |
| 262 while (!parent.isNull() && parent.isElementNode() && | 275 while (!parent.isNull() && parent.isElementNode() && |
| 263 !parent.to<WebElement>().hasTagName("td")) { | 276 !parent.to<WebElement>().hasTagName(kTableCell)) { |
| 264 parent = parent.parentNode(); | 277 parent = parent.parentNode(); |
| 265 } | 278 } |
| 266 | 279 |
| 267 if (parent.isNull()) | 280 if (parent.isNull()) |
| 268 return string16(); | 281 return string16(); |
| 269 | 282 |
| 270 // Check all previous siblings, skipping non-element nodes, until we find a | 283 // Check all previous siblings, skipping non-element nodes, until we find a |
| 271 // non-empty text block. | 284 // non-empty text block. |
| 272 string16 inferred_label; | 285 string16 inferred_label; |
| 273 WebNode previous = parent.previousSibling(); | 286 WebNode previous = parent.previousSibling(); |
| 287 CR_DEFINE_STATIC_LOCAL(WebString, kTableHeader, ("th")); |
| 274 while (inferred_label.empty() && !previous.isNull()) { | 288 while (inferred_label.empty() && !previous.isNull()) { |
| 275 if (HasTagName(previous, "td") || HasTagName(previous, "th")) | 289 if (HasTagName(previous, kTableCell) || HasTagName(previous, kTableHeader)) |
| 276 inferred_label = FindChildText(previous); | 290 inferred_label = FindChildText(previous); |
| 277 | 291 |
| 278 previous = previous.previousSibling(); | 292 previous = previous.previousSibling(); |
| 279 } | 293 } |
| 280 | 294 |
| 281 return inferred_label; | 295 return inferred_label; |
| 282 } | 296 } |
| 283 | 297 |
| 284 // Helper for |InferLabelForElement()| that infers a label, if possible, from | 298 // Helper for |InferLabelForElement()| that infers a label, if possible, from |
| 285 // surrounding table structure, | 299 // surrounding table structure, |
| 286 // e.g. <tr><td>Some Text</td></tr><tr><td><input ...></td></tr> | 300 // e.g. <tr><td>Some Text</td></tr><tr><td><input ...></td></tr> |
| 287 string16 InferLabelFromTableRow(const WebFormControlElement& element) { | 301 string16 InferLabelFromTableRow(const WebFormControlElement& element) { |
| 302 CR_DEFINE_STATIC_LOCAL(WebString, kTableRow, ("tr")); |
| 288 WebNode parent = element.parentNode(); | 303 WebNode parent = element.parentNode(); |
| 289 while (!parent.isNull() && parent.isElementNode() && | 304 while (!parent.isNull() && parent.isElementNode() && |
| 290 !parent.to<WebElement>().hasTagName("tr")) { | 305 !parent.to<WebElement>().hasTagName(kTableRow)) { |
| 291 parent = parent.parentNode(); | 306 parent = parent.parentNode(); |
| 292 } | 307 } |
| 293 | 308 |
| 294 if (parent.isNull()) | 309 if (parent.isNull()) |
| 295 return string16(); | 310 return string16(); |
| 296 | 311 |
| 297 // Check all previous siblings, skipping non-element nodes, until we find a | 312 // Check all previous siblings, skipping non-element nodes, until we find a |
| 298 // non-empty text block. | 313 // non-empty text block. |
| 299 string16 inferred_label; | 314 string16 inferred_label; |
| 300 WebNode previous = parent.previousSibling(); | 315 WebNode previous = parent.previousSibling(); |
| 301 while (inferred_label.empty() && !previous.isNull()) { | 316 while (inferred_label.empty() && !previous.isNull()) { |
| 302 if (HasTagName(previous, "tr")) | 317 if (HasTagName(previous, kTableRow)) |
| 303 inferred_label = FindChildText(previous); | 318 inferred_label = FindChildText(previous); |
| 304 | 319 |
| 305 previous = previous.previousSibling(); | 320 previous = previous.previousSibling(); |
| 306 } | 321 } |
| 307 | 322 |
| 308 return inferred_label; | 323 return inferred_label; |
| 309 } | 324 } |
| 310 | 325 |
| 311 // Helper for |InferLabelForElement()| that infers a label, if possible, from | 326 // Helper for |InferLabelForElement()| that infers a label, if possible, from |
| 312 // a surrounding div table, | 327 // a surrounding div table, |
| 313 // e.g. <div>Some Text<span><input ...></span></div> | 328 // e.g. <div>Some Text<span><input ...></span></div> |
| 314 // e.g. <div>Some Text</div><div><input ...></div> | 329 // e.g. <div>Some Text</div><div><input ...></div> |
| 315 string16 InferLabelFromDivTable(const WebFormControlElement& element) { | 330 string16 InferLabelFromDivTable(const WebFormControlElement& element) { |
| 316 WebNode node = element.parentNode(); | 331 WebNode node = element.parentNode(); |
| 317 bool looking_for_parent = true; | 332 bool looking_for_parent = true; |
| 318 | 333 |
| 319 // Search the sibling and parent <div>s until we find a candidate label. | 334 // Search the sibling and parent <div>s until we find a candidate label. |
| 320 string16 inferred_label; | 335 string16 inferred_label; |
| 336 CR_DEFINE_STATIC_LOCAL(WebString, kDiv, ("div")); |
| 337 CR_DEFINE_STATIC_LOCAL(WebString, kTable, ("table")); |
| 338 CR_DEFINE_STATIC_LOCAL(WebString, kFieldSet, ("fieldset")); |
| 321 while (inferred_label.empty() && !node.isNull()) { | 339 while (inferred_label.empty() && !node.isNull()) { |
| 322 if (HasTagName(node, "div")) { | 340 if (HasTagName(node, kDiv)) { |
| 323 looking_for_parent = false; | 341 looking_for_parent = false; |
| 324 inferred_label = FindChildText(node); | 342 inferred_label = FindChildText(node); |
| 325 } else if (looking_for_parent && | 343 } else if (looking_for_parent && |
| 326 (HasTagName(node, "table") || HasTagName(node, "fieldset"))) { | 344 (HasTagName(node, kTable) || HasTagName(node, kFieldSet))) { |
| 327 // If the element is in a table or fieldset, its label most likely is too. | 345 // If the element is in a table or fieldset, its label most likely is too. |
| 328 break; | 346 break; |
| 329 } | 347 } |
| 330 | 348 |
| 331 if (node.previousSibling().isNull()) { | 349 if (node.previousSibling().isNull()) { |
| 332 // If there are no more siblings, continue walking up the tree. | 350 // If there are no more siblings, continue walking up the tree. |
| 333 looking_for_parent = true; | 351 looking_for_parent = true; |
| 334 } | 352 } |
| 335 | 353 |
| 336 if (looking_for_parent) | 354 if (looking_for_parent) |
| 337 node = node.parentNode(); | 355 node = node.parentNode(); |
| 338 else | 356 else |
| 339 node = node.previousSibling(); | 357 node = node.previousSibling(); |
| 340 } | 358 } |
| 341 | 359 |
| 342 return inferred_label; | 360 return inferred_label; |
| 343 } | 361 } |
| 344 | 362 |
| 345 // Helper for |InferLabelForElement()| that infers a label, if possible, from | 363 // Helper for |InferLabelForElement()| that infers a label, if possible, from |
| 346 // a surrounding definition list, | 364 // a surrounding definition list, |
| 347 // e.g. <dl><dt>Some Text</dt><dd><input ...></dd></dl> | 365 // e.g. <dl><dt>Some Text</dt><dd><input ...></dd></dl> |
| 348 // e.g. <dl><dt><b>Some Text</b></dt><dd><b><input ...></b></dd></dl> | 366 // e.g. <dl><dt><b>Some Text</b></dt><dd><b><input ...></b></dd></dl> |
| 349 string16 InferLabelFromDefinitionList(const WebFormControlElement& element) { | 367 string16 InferLabelFromDefinitionList(const WebFormControlElement& element) { |
| 368 CR_DEFINE_STATIC_LOCAL(WebString, kDefinitionData, ("dd")); |
| 350 WebNode parent = element.parentNode(); | 369 WebNode parent = element.parentNode(); |
| 351 while (!parent.isNull() && parent.isElementNode() && | 370 while (!parent.isNull() && parent.isElementNode() && |
| 352 !parent.to<WebElement>().hasTagName("dd")) | 371 !parent.to<WebElement>().hasTagName(kDefinitionData)) |
| 353 parent = parent.parentNode(); | 372 parent = parent.parentNode(); |
| 354 | 373 |
| 355 if (parent.isNull() || !HasTagName(parent, "dd")) | 374 if (parent.isNull() || !HasTagName(parent, kDefinitionData)) |
| 356 return string16(); | 375 return string16(); |
| 357 | 376 |
| 358 // Skip by any intervening text nodes. | 377 // Skip by any intervening text nodes. |
| 359 WebNode previous = parent.previousSibling(); | 378 WebNode previous = parent.previousSibling(); |
| 360 while (!previous.isNull() && previous.isTextNode()) | 379 while (!previous.isNull() && previous.isTextNode()) |
| 361 previous = previous.previousSibling(); | 380 previous = previous.previousSibling(); |
| 362 | 381 |
| 363 if (previous.isNull() || !HasTagName(previous, "dt")) | 382 CR_DEFINE_STATIC_LOCAL(WebString, kDefinitionTag, ("dt")); |
| 383 if (previous.isNull() || !HasTagName(previous, kDefinitionTag)) |
| 364 return string16(); | 384 return string16(); |
| 365 | 385 |
| 366 return FindChildText(previous); | 386 return FindChildText(previous); |
| 367 } | 387 } |
| 368 | 388 |
| 369 // Infers corresponding label for |element| from surrounding context in the DOM, | 389 // Infers corresponding label for |element| from surrounding context in the DOM, |
| 370 // e.g. the contents of the preceding <p> tag or text element. | 390 // e.g. the contents of the preceding <p> tag or text element. |
| 371 string16 InferLabelForElement(const WebFormControlElement& element) { | 391 string16 InferLabelForElement(const WebFormControlElement& element) { |
| 372 string16 inferred_label = InferLabelFromPrevious(element); | 392 string16 inferred_label = InferLabelFromPrevious(element); |
| 373 if (!inferred_label.empty()) | 393 if (!inferred_label.empty()) |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 } | 606 } |
| 587 | 607 |
| 588 bool IsAutofillableInputElement(const WebInputElement* element) { | 608 bool IsAutofillableInputElement(const WebInputElement* element) { |
| 589 // TODO(ramankk): Uncomment IsCheckableElement part once we have solution | 609 // TODO(ramankk): Uncomment IsCheckableElement part once we have solution |
| 590 // for the observed performance regression. | 610 // for the observed performance regression. |
| 591 return IsTextInput(element); // || IsCheckableElement(element); | 611 return IsTextInput(element); // || IsCheckableElement(element); |
| 592 } | 612 } |
| 593 | 613 |
| 594 const string16 GetFormIdentifier(const WebFormElement& form) { | 614 const string16 GetFormIdentifier(const WebFormElement& form) { |
| 595 string16 identifier = form.name(); | 615 string16 identifier = form.name(); |
| 616 CR_DEFINE_STATIC_LOCAL(WebString, kId, ("id")); |
| 596 if (identifier.empty()) | 617 if (identifier.empty()) |
| 597 identifier = form.getAttribute(WebString("id")); | 618 identifier = form.getAttribute(kId); |
| 598 | 619 |
| 599 return identifier; | 620 return identifier; |
| 600 } | 621 } |
| 601 | 622 |
| 602 bool ClickElement(const WebDocument& document, | 623 bool ClickElement(const WebDocument& document, |
| 603 const WebElementDescriptor& element_descriptor) { | 624 const WebElementDescriptor& element_descriptor) { |
| 604 WebString web_descriptor = WebString::fromUTF8(element_descriptor.descriptor); | 625 WebString web_descriptor = WebString::fromUTF8(element_descriptor.descriptor); |
| 605 WebKit::WebElement element; | 626 WebKit::WebElement element; |
| 606 | 627 |
| 607 switch (element_descriptor.retrieval_method) { | 628 switch (element_descriptor.retrieval_method) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 | 677 |
| 657 autofillable_elements->push_back(element); | 678 autofillable_elements->push_back(element); |
| 658 } | 679 } |
| 659 } | 680 } |
| 660 | 681 |
| 661 void WebFormControlElementToFormField(const WebFormControlElement& element, | 682 void WebFormControlElementToFormField(const WebFormControlElement& element, |
| 662 ExtractMask extract_mask, | 683 ExtractMask extract_mask, |
| 663 FormFieldData* field) { | 684 FormFieldData* field) { |
| 664 DCHECK(field); | 685 DCHECK(field); |
| 665 DCHECK(!element.isNull()); | 686 DCHECK(!element.isNull()); |
| 687 CR_DEFINE_STATIC_LOCAL(WebString, kAutocomplete, ("autocomplete")); |
| 666 | 688 |
| 667 // The label is not officially part of a WebFormControlElement; however, the | 689 // The label is not officially part of a WebFormControlElement; however, the |
| 668 // labels for all form control elements are scraped from the DOM and set in | 690 // labels for all form control elements are scraped from the DOM and set in |
| 669 // WebFormElementToFormData. | 691 // WebFormElementToFormData. |
| 670 field->name = element.nameForAutofill(); | 692 field->name = element.nameForAutofill(); |
| 671 field->form_control_type = UTF16ToUTF8(element.formControlType()); | 693 field->form_control_type = UTF16ToUTF8(element.formControlType()); |
| 672 field->autocomplete_attribute = | 694 field->autocomplete_attribute = |
| 673 UTF16ToUTF8(element.getAttribute("autocomplete")); | 695 UTF16ToUTF8(element.getAttribute(kAutocomplete)); |
| 674 if (field->autocomplete_attribute.size() > kMaxDataLength) { | 696 if (field->autocomplete_attribute.size() > kMaxDataLength) { |
| 675 // Discard overly long attribute values to avoid DOS-ing the browser | 697 // Discard overly long attribute values to avoid DOS-ing the browser |
| 676 // process. However, send over a default string to indicate that the | 698 // process. However, send over a default string to indicate that the |
| 677 // attribute was present. | 699 // attribute was present. |
| 678 field->autocomplete_attribute = "x-max-data-length-exceeded"; | 700 field->autocomplete_attribute = "x-max-data-length-exceeded"; |
| 679 } | 701 } |
| 680 | 702 |
| 681 if (!IsAutofillableElement(element)) | 703 if (!IsAutofillableElement(element)) |
| 682 return; | 704 return; |
| 683 | 705 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 field->value = value; | 756 field->value = value; |
| 735 } | 757 } |
| 736 | 758 |
| 737 bool WebFormElementToFormData( | 759 bool WebFormElementToFormData( |
| 738 const WebKit::WebFormElement& form_element, | 760 const WebKit::WebFormElement& form_element, |
| 739 const WebKit::WebFormControlElement& form_control_element, | 761 const WebKit::WebFormControlElement& form_control_element, |
| 740 RequirementsMask requirements, | 762 RequirementsMask requirements, |
| 741 ExtractMask extract_mask, | 763 ExtractMask extract_mask, |
| 742 FormData* form, | 764 FormData* form, |
| 743 FormFieldData* field) { | 765 FormFieldData* field) { |
| 766 CR_DEFINE_STATIC_LOCAL(WebString, kLabel, ("label")); |
| 767 CR_DEFINE_STATIC_LOCAL(WebString, kFor, ("for")); |
| 768 CR_DEFINE_STATIC_LOCAL(WebString, kHidden, ("hidden")); |
| 769 |
| 744 const WebFrame* frame = form_element.document().frame(); | 770 const WebFrame* frame = form_element.document().frame(); |
| 745 if (!frame) | 771 if (!frame) |
| 746 return false; | 772 return false; |
| 747 | 773 |
| 748 if (requirements & REQUIRE_AUTOCOMPLETE && !form_element.autoComplete()) | 774 if (requirements & REQUIRE_AUTOCOMPLETE && !form_element.autoComplete()) |
| 749 return false; | 775 return false; |
| 750 | 776 |
| 751 form->name = GetFormIdentifier(form_element); | 777 form->name = GetFormIdentifier(form_element); |
| 752 form->method = form_element.method(); | 778 form->method = form_element.method(); |
| 753 form->origin = frame->document().url(); | 779 form->origin = frame->document().url(); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 799 // If we failed to extract any fields, give up. Also, to avoid overly | 825 // If we failed to extract any fields, give up. Also, to avoid overly |
| 800 // expensive computation, we impose a maximum number of allowable fields. | 826 // expensive computation, we impose a maximum number of allowable fields. |
| 801 if (form_fields.empty() || form_fields.size() > kMaxParseableFields) | 827 if (form_fields.empty() || form_fields.size() > kMaxParseableFields) |
| 802 return false; | 828 return false; |
| 803 | 829 |
| 804 // Loop through the label elements inside the form element. For each label | 830 // Loop through the label elements inside the form element. For each label |
| 805 // element, get the corresponding form control element, use the form control | 831 // element, get the corresponding form control element, use the form control |
| 806 // element's name as a key into the <name, FormFieldData> map to find the | 832 // element's name as a key into the <name, FormFieldData> map to find the |
| 807 // previously created FormFieldData and set the FormFieldData's label to the | 833 // previously created FormFieldData and set the FormFieldData's label to the |
| 808 // label.firstChild().nodeValue() of the label element. | 834 // label.firstChild().nodeValue() of the label element. |
| 809 WebNodeList labels = form_element.getElementsByTagName("label"); | 835 WebNodeList labels = form_element.getElementsByTagName(kLabel); |
| 810 for (unsigned i = 0; i < labels.length(); ++i) { | 836 for (unsigned i = 0; i < labels.length(); ++i) { |
| 811 WebLabelElement label = labels.item(i).to<WebLabelElement>(); | 837 WebLabelElement label = labels.item(i).to<WebLabelElement>(); |
| 812 WebFormControlElement field_element = | 838 WebFormControlElement field_element = |
| 813 label.correspondingControl().to<WebFormControlElement>(); | 839 label.correspondingControl().to<WebFormControlElement>(); |
| 814 | 840 |
| 815 string16 element_name; | 841 string16 element_name; |
| 816 if (field_element.isNull()) { | 842 if (field_element.isNull()) { |
| 817 // Sometimes site authors will incorrectly specify the corresponding | 843 // Sometimes site authors will incorrectly specify the corresponding |
| 818 // field element's name rather than its id, so we compensate here. | 844 // field element's name rather than its id, so we compensate here. |
| 819 element_name = label.getAttribute("for"); | 845 element_name = label.getAttribute(kFor); |
| 820 } else if ( | 846 } else if ( |
| 821 !field_element.isFormControlElement() || | 847 !field_element.isFormControlElement() || |
| 822 field_element.formControlType() == WebString::fromUTF8("hidden")) { | 848 field_element.formControlType() == kHidden) { |
| 823 continue; | 849 continue; |
| 824 } else { | 850 } else { |
| 825 element_name = field_element.nameForAutofill(); | 851 element_name = field_element.nameForAutofill(); |
| 826 } | 852 } |
| 827 | 853 |
| 828 std::map<string16, FormFieldData*>::iterator iter = | 854 std::map<string16, FormFieldData*>::iterator iter = |
| 829 name_map.find(element_name); | 855 name_map.find(element_name); |
| 830 if (iter != name_map.end()) { | 856 if (iter != name_map.end()) { |
| 831 string16 label_text = FindChildText(label); | 857 string16 label_text = FindChildText(label); |
| 832 | 858 |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 987 continue; | 1013 continue; |
| 988 | 1014 |
| 989 if (input_element->isAutofilled()) | 1015 if (input_element->isAutofilled()) |
| 990 return true; | 1016 return true; |
| 991 } | 1017 } |
| 992 | 1018 |
| 993 return false; | 1019 return false; |
| 994 } | 1020 } |
| 995 | 1021 |
| 996 } // namespace autofill | 1022 } // namespace autofill |
| OLD | NEW |