| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/renderer/form_manager.h" | 5 #include "chrome/renderer/form_manager.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/scoped_vector.h" | 8 #include "base/scoped_vector.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "base/stl_util-inl.h" | 10 #include "base/stl_util-inl.h" |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 const WebFormControlElement& control_element = control_elements[i]; | 309 const WebFormControlElement& control_element = control_elements[i]; |
| 310 | 310 |
| 311 if (requirements & REQUIRE_AUTOCOMPLETE && | 311 if (requirements & REQUIRE_AUTOCOMPLETE && |
| 312 control_element.formControlType() == WebString::fromUTF8("text")) { | 312 control_element.formControlType() == WebString::fromUTF8("text")) { |
| 313 const WebInputElement& input_element = | 313 const WebInputElement& input_element = |
| 314 control_element.toConst<WebInputElement>(); | 314 control_element.toConst<WebInputElement>(); |
| 315 if (!input_element.autoComplete()) | 315 if (!input_element.autoComplete()) |
| 316 continue; | 316 continue; |
| 317 } | 317 } |
| 318 | 318 |
| 319 if (requirements & REQUIRE_ELEMENTS_ENABLED && !control_element.isEnabled()) | 319 if (requirements & REQUIRE_ENABLED && !control_element.isEnabled()) |
| 320 continue; | 320 continue; |
| 321 | 321 |
| 322 // Create a new FormField, fill it out and map it to the field's name. | 322 // Create a new FormField, fill it out and map it to the field's name. |
| 323 FormField* field = new FormField; | 323 FormField* field = new FormField; |
| 324 WebFormControlElementToFormField(control_element, get_values, field); | 324 WebFormControlElementToFormField(control_element, get_values, field); |
| 325 form_fields.push_back(field); | 325 form_fields.push_back(field); |
| 326 // TODO(jhawkins): A label element is mapped to a form control element's id. | 326 // TODO(jhawkins): A label element is mapped to a form control element's id. |
| 327 // field->name() will contain the id only if the name does not exist. Add | 327 // field->name() will contain the id only if the name does not exist. Add |
| 328 // an id() method to WebFormControlElement and use that here. | 328 // an id() method to WebFormControlElement and use that here. |
| 329 name_map[field->name()] = field; | 329 name_map[field->name()] = field; |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 } | 512 } |
| 513 | 513 |
| 514 return false; | 514 return false; |
| 515 } | 515 } |
| 516 | 516 |
| 517 bool FormManager::FillForm(const FormData& form) { | 517 bool FormManager::FillForm(const FormData& form) { |
| 518 FormElement* form_element = NULL; | 518 FormElement* form_element = NULL; |
| 519 if (!FindCachedFormElement(form, &form_element)) | 519 if (!FindCachedFormElement(form, &form_element)) |
| 520 return false; | 520 return false; |
| 521 | 521 |
| 522 ForEachMatchingFormField( | 522 RequirementsMask requirements = static_cast<RequirementsMask>( |
| 523 form_element, form, NewCallback(this, &FormManager::FillFormField)); | 523 REQUIRE_AUTOCOMPLETE | REQUIRE_ENABLED | REQUIRE_EMPTY); |
| 524 ForEachMatchingFormField(form_element, |
| 525 requirements, |
| 526 form, |
| 527 NewCallback(this, &FormManager::FillFormField)); |
| 524 | 528 |
| 525 return true; | 529 return true; |
| 526 } | 530 } |
| 527 | 531 |
| 528 void FormManager::FillForms(const std::vector<webkit_glue::FormData>& forms) { | 532 bool FormManager::PreviewForm(const FormData& form) { |
| 529 for (std::vector<webkit_glue::FormData>::const_iterator iter = forms.begin(); | 533 FormElement* form_element = NULL; |
| 534 if (!FindCachedFormElement(form, &form_element)) |
| 535 return false; |
| 536 |
| 537 RequirementsMask requirements = static_cast<RequirementsMask>( |
| 538 REQUIRE_AUTOCOMPLETE | REQUIRE_ENABLED | REQUIRE_EMPTY); |
| 539 ForEachMatchingFormField(form_element, |
| 540 requirements, |
| 541 form, |
| 542 NewCallback(this, &FormManager::PreviewFormField)); |
| 543 |
| 544 return true; |
| 545 } |
| 546 |
| 547 void FormManager::ClearPreviewedForm(const FormData& form) { |
| 548 FormElement* form_element = NULL; |
| 549 if (!FindCachedFormElement(form, &form_element)) |
| 550 return; |
| 551 |
| 552 for (size_t i = 0; i < form_element->control_elements.size(); ++i) { |
| 553 WebFormControlElement* element = &form_element->control_elements[i]; |
| 554 |
| 555 // Only input elements can be previewed. |
| 556 if (element->formControlType() != WebString::fromUTF8("text")) |
| 557 continue; |
| 558 |
| 559 // If the input element has not been auto-filled, FormManager has not |
| 560 // previewed this field, so we have nothing to reset. |
| 561 WebInputElement input_element = element->to<WebInputElement>(); |
| 562 if (!input_element.isAutofilled()) |
| 563 continue; |
| 564 |
| 565 input_element.setPlaceholder(string16()); |
| 566 input_element.setAutofilled(false); |
| 567 } |
| 568 } |
| 569 |
| 570 void FormManager::FillForms(const std::vector<FormData>& forms) { |
| 571 for (std::vector<FormData>::const_iterator iter = forms.begin(); |
| 530 iter != forms.end(); ++iter) { | 572 iter != forms.end(); ++iter) { |
| 531 FillForm(*iter); | 573 FillForm(*iter); |
| 532 } | 574 } |
| 533 } | 575 } |
| 534 | 576 |
| 535 void FormManager::Reset() { | 577 void FormManager::Reset() { |
| 536 for (WebFrameFormElementMap::iterator iter = form_elements_map_.begin(); | 578 for (WebFrameFormElementMap::iterator iter = form_elements_map_.begin(); |
| 537 iter != form_elements_map_.end(); ++iter) { | 579 iter != form_elements_map_.end(); ++iter) { |
| 538 STLDeleteElements(&iter->second); | 580 STLDeleteElements(&iter->second); |
| 539 } | 581 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 575 const WebFormControlElement& control_element = *element_iter; | 617 const WebFormControlElement& control_element = *element_iter; |
| 576 | 618 |
| 577 if (requirements & REQUIRE_AUTOCOMPLETE && | 619 if (requirements & REQUIRE_AUTOCOMPLETE && |
| 578 control_element.formControlType() == WebString::fromUTF8("text")) { | 620 control_element.formControlType() == WebString::fromUTF8("text")) { |
| 579 const WebInputElement& input_element = | 621 const WebInputElement& input_element = |
| 580 control_element.toConst<WebInputElement>(); | 622 control_element.toConst<WebInputElement>(); |
| 581 if (!input_element.autoComplete()) | 623 if (!input_element.autoComplete()) |
| 582 continue; | 624 continue; |
| 583 } | 625 } |
| 584 | 626 |
| 585 if (requirements & REQUIRE_ELEMENTS_ENABLED && !control_element.isEnabled()) | 627 if (requirements & REQUIRE_ENABLED && !control_element.isEnabled()) |
| 586 continue; | 628 continue; |
| 587 | 629 |
| 588 FormField field; | 630 FormField field; |
| 589 WebFormControlElementToFormField(control_element, false, &field); | 631 WebFormControlElementToFormField(control_element, false, &field); |
| 590 form->fields.push_back(field); | 632 form->fields.push_back(field); |
| 591 } | 633 } |
| 592 | 634 |
| 593 return true; | 635 return true; |
| 594 } | 636 } |
| 595 | 637 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 632 if (element_name == form.name && action == form.action) { | 674 if (element_name == form.name && action == form.action) { |
| 633 *form_element = *form_iter; | 675 *form_element = *form_iter; |
| 634 return true; | 676 return true; |
| 635 } | 677 } |
| 636 } | 678 } |
| 637 } | 679 } |
| 638 | 680 |
| 639 return false; | 681 return false; |
| 640 } | 682 } |
| 641 | 683 |
| 642 void FormManager::ForEachMatchingFormField( | 684 void FormManager::ForEachMatchingFormField(FormElement* form, |
| 643 FormElement* form, const FormData& data, Callback* callback) { | 685 RequirementsMask requirements, |
| 686 const FormData& data, |
| 687 Callback* callback) { |
| 644 // It's possible that the site has injected fields into the form after the | 688 // It's possible that the site has injected fields into the form after the |
| 645 // page has loaded, so we can't assert that the size of the cached control | 689 // page has loaded, so we can't assert that the size of the cached control |
| 646 // elements is equal to the size of the fields in |form|. Fortunately, the | 690 // elements is equal to the size of the fields in |form|. Fortunately, the |
| 647 // one case in the wild where this happens, paypal.com signup form, the fields | 691 // one case in the wild where this happens, paypal.com signup form, the fields |
| 648 // are appended to the end of the form and are not visible. | 692 // are appended to the end of the form and are not visible. |
| 649 for (size_t i = 0, j = 0; | 693 for (size_t i = 0, j = 0; |
| 650 i < form->control_elements.size() && j < data.fields.size(); | 694 i < form->control_elements.size() && j < data.fields.size(); |
| 651 ++i) { | 695 ++i) { |
| 652 WebFormControlElement* element = &form->control_elements[i]; | 696 WebFormControlElement* element = &form->control_elements[i]; |
| 653 WebString element_name = element->nameForAutofill(); | 697 WebString element_name = element->nameForAutofill(); |
| 654 | 698 |
| 655 // Empty WebString != empty string16, so we have to explicitly | 699 // Empty WebString != empty string16, so we have to explicitly |
| 656 // check for this case. | 700 // check for this case. |
| 657 if (element_name.isEmpty() && data.fields[j].name().empty()) | 701 if (element_name.isEmpty() && data.fields[j].name().empty()) |
| 658 continue; | 702 continue; |
| 659 | 703 |
| 660 // Search forward in the |form| for a corresponding field. | 704 // Search forward in the |form| for a corresponding field. |
| 661 size_t k = j; | 705 size_t k = j; |
| 662 while (k < data.fields.size() && element_name != data.fields[k].name()) | 706 while (k < data.fields.size() && element_name != data.fields[k].name()) |
| 663 k++; | 707 k++; |
| 664 | 708 |
| 665 if (k >= data.fields.size()) | 709 if (k >= data.fields.size()) |
| 666 continue; | 710 continue; |
| 667 | 711 |
| 668 DCHECK_EQ(data.fields[k].name(), element_name); | 712 DCHECK_EQ(data.fields[k].name(), element_name); |
| 713 |
| 714 // More than likely |requirements| will contain REQUIRE_AUTOCOMPLETE and/or |
| 715 // REQUIRE_EMPTY, which both require text form control elements, so special- |
| 716 // case this type of element. |
| 717 if (element->formControlType() == WebString::fromUTF8("text")) { |
| 718 const WebInputElement& input_element = |
| 719 element->toConst<WebInputElement>(); |
| 720 |
| 721 // TODO(jhawkins): WebKit currently doesn't handle the autocomplete |
| 722 // attribute for select control elements, but it probably should. |
| 723 if (requirements & REQUIRE_AUTOCOMPLETE && !input_element.autoComplete()) |
| 724 continue; |
| 725 |
| 726 if (requirements & REQUIRE_EMPTY && !input_element.value().isEmpty()) |
| 727 continue; |
| 728 } |
| 729 |
| 730 if (requirements & REQUIRE_ENABLED && !element->isEnabled()) |
| 731 continue; |
| 732 |
| 669 callback->Run(element, &data.fields[k]); | 733 callback->Run(element, &data.fields[k]); |
| 670 | 734 |
| 671 // We found a matching form field so move on to the next. | 735 // We found a matching form field so move on to the next. |
| 672 ++j; | 736 ++j; |
| 673 } | 737 } |
| 674 | 738 |
| 675 delete callback; | 739 delete callback; |
| 676 } | 740 } |
| 677 | 741 |
| 678 void FormManager::FillFormField(WebKit::WebFormControlElement* field, | 742 void FormManager::FillFormField(WebKit::WebFormControlElement* field, |
| 679 const FormField* data) { | 743 const FormField* data) { |
| 680 // Nothing to fill. | 744 // Nothing to fill. |
| 681 if (data->value().empty()) | 745 if (data->value().empty()) |
| 682 return; | 746 return; |
| 683 | 747 |
| 684 if (field->formControlType() == WebString::fromUTF8("text")) { | 748 if (field->formControlType() == WebString::fromUTF8("text")) { |
| 685 WebInputElement input_element = field->to<WebInputElement>(); | 749 WebInputElement input_element = field->to<WebInputElement>(); |
| 686 | 750 |
| 687 // Don't auto-fill a disabled field. | |
| 688 if (!input_element.isEnabledFormControl()) | |
| 689 return; | |
| 690 | |
| 691 // Don't auto-fill a field with autocomplete=off. | |
| 692 if (!input_element.autoComplete()) | |
| 693 return; | |
| 694 | |
| 695 // Don't overwrite a pre-existing value in the field. | |
| 696 if (!input_element.value().isEmpty()) | |
| 697 return; | |
| 698 | |
| 699 // If the maxlength attribute contains a negative value, maxLength() | 751 // If the maxlength attribute contains a negative value, maxLength() |
| 700 // returns the default maxlength value. | 752 // returns the default maxlength value. |
| 701 input_element.setValue(data->value().substr(0, input_element.maxLength())); | 753 input_element.setValue(data->value().substr(0, input_element.maxLength())); |
| 702 input_element.setAutofilled(true); | 754 input_element.setAutofilled(true); |
| 703 } else if (field->formControlType() == WebString::fromUTF8("select-one")) { | 755 } else if (field->formControlType() == WebString::fromUTF8("select-one")) { |
| 704 WebSelectElement select_element = field->to<WebSelectElement>(); | 756 WebSelectElement select_element = field->to<WebSelectElement>(); |
| 705 select_element.setValue(data->value()); | 757 select_element.setValue(data->value()); |
| 706 } | 758 } |
| 707 } | 759 } |
| 760 |
| 761 void FormManager::PreviewFormField(WebKit::WebFormControlElement* field, |
| 762 const FormField* data) { |
| 763 // Nothing to preview. |
| 764 if (data->value().empty()) |
| 765 return; |
| 766 |
| 767 // Only preview input fields. |
| 768 if (field->formControlType() != WebString::fromUTF8("text")) |
| 769 return; |
| 770 |
| 771 WebInputElement input_element = field->to<WebInputElement>(); |
| 772 |
| 773 // If the maxlength attribute contains a negative value, maxLength() |
| 774 // returns the default maxlength value. |
| 775 input_element.setPlaceholder( |
| 776 data->value().substr(0, input_element.maxLength())); |
| 777 input_element.setAutofilled(true); |
| 778 } |
| OLD | NEW |