Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(459)

Side by Side Diff: chrome/renderer/form_manager.cc

Issue 2138005: AutoFill: Preview form field values when the user changes the AutoFill dropdown (Closed)
Patch Set: Rebase. Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/renderer/form_manager.h ('k') | chrome/renderer/form_manager_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « chrome/renderer/form_manager.h ('k') | chrome/renderer/form_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698