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 |