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

Side by Side Diff: chrome/renderer/autofill/form_autofill_util.cc

Issue 11348273: [autofill] Fill in values on a successful run of interactive autocomplete. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: isherman@ review Created 8 years 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 | Annotate | Revision Log
OLDNEW
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 26 matching lines...) Expand all
37 using WebKit::WebOptionElement; 37 using WebKit::WebOptionElement;
38 using WebKit::WebSelectElement; 38 using WebKit::WebSelectElement;
39 using WebKit::WebString; 39 using WebKit::WebString;
40 using WebKit::WebVector; 40 using WebKit::WebVector;
41 41
42 namespace { 42 namespace {
43 43
44 using autofill::ExtractAutofillableElements; 44 using autofill::ExtractAutofillableElements;
45 using autofill::IsTextInput; 45 using autofill::IsTextInput;
46 using autofill::IsSelectElement; 46 using autofill::IsSelectElement;
47 using autofill::REQUIRE_AUTOCOMPLETE;
48 using autofill::REQUIRE_FOCUSABLE;
49 using autofill::RequirementsMask;
Ilya Sherman 2012/11/30 04:04:54 Do these lines actually compile? I didn't think t
Dan Beam 2012/11/30 04:13:33 Yes, at least with g++.
47 50
48 // The maximum length allowed for form data. 51 // The maximum length allowed for form data.
49 const size_t kMaxDataLength = 1024; 52 const size_t kMaxDataLength = 1024;
50 53
51 bool IsOptionElement(const WebElement& element) { 54 bool IsOptionElement(const WebElement& element) {
52 return element.hasTagName("option"); 55 return element.hasTagName("option");
53 } 56 }
54 57
55 bool IsScriptElement(const WebElement& element) { 58 bool IsScriptElement(const WebElement& element) {
56 return element.hasTagName("script"); 59 return element.hasTagName("script");
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 for (size_t i = 0; i < list_items.size(); ++i) { 409 for (size_t i = 0; i < list_items.size(); ++i) {
407 if (IsOptionElement(list_items[i])) { 410 if (IsOptionElement(list_items[i])) {
408 const WebOptionElement option = list_items[i].toConst<WebOptionElement>(); 411 const WebOptionElement option = list_items[i].toConst<WebOptionElement>();
409 option_values->push_back(option.value()); 412 option_values->push_back(option.value());
410 option_contents->push_back(option.text()); 413 option_contents->push_back(option.text());
411 } 414 }
412 } 415 }
413 } 416 }
414 417
415 // The callback type used by |ForEachMatchingFormField()|. 418 // The callback type used by |ForEachMatchingFormField()|.
416 typedef void (*Callback)(WebKit::WebFormControlElement*, 419 typedef void (*Callback)(const FormFieldData&,
417 const FormFieldData*, 420 bool, /* is_initiating_element */
418 bool); 421 WebKit::WebFormControlElement*);
419 422
420 // For each autofillable field in |data| that matches a field in the |form|, 423 // For each autofillable field in |data| that matches a field in the |form|,
421 // the |callback| is invoked with the corresponding |form| field data. 424 // the |callback| is invoked with the corresponding |form| field data.
422 void ForEachMatchingFormField(const WebFormElement& form_element, 425 void ForEachMatchingFormField(const WebFormElement& form_element,
423 const WebElement& initiating_element, 426 const WebElement& initiating_element,
424 const FormData& data, 427 const FormData& data,
428 RequirementsMask requirements,
425 Callback callback) { 429 Callback callback) {
426 std::vector<WebFormControlElement> control_elements; 430 std::vector<WebFormControlElement> control_elements;
427 ExtractAutofillableElements(form_element, autofill::REQUIRE_AUTOCOMPLETE, 431 ExtractAutofillableElements(form_element, requirements, &control_elements);
428 &control_elements);
429 432
430 if (control_elements.size() != data.fields.size()) { 433 if (control_elements.size() != data.fields.size()) {
431 // This case should be reachable only for pathological websites, which add 434 // This case should be reachable only for pathological websites, which add
432 // or remove form fields while the user is interacting with the Autofill 435 // or remove form fields while the user is interacting with the Autofill
433 // popup. I (isherman) am not aware of any such websites, and so am 436 // popup. I (isherman) am not aware of any such websites, and so am
434 // optimistically including a NOTREACHED(). If you ever trip this check, 437 // optimistically including a NOTREACHED(). If you ever trip this check,
435 // please file a bug against me. 438 // please file a bug against me.
436 NOTREACHED(); 439 NOTREACHED();
437 return; 440 return;
438 } 441 }
(...skipping 20 matching lines...) Expand all
459 462
460 const WebInputElement* input_element = toWebInputElement(element); 463 const WebInputElement* input_element = toWebInputElement(element);
461 if (IsTextInput(input_element)) { 464 if (IsTextInput(input_element)) {
462 // Only autofill empty fields and the field that initiated the filling, 465 // Only autofill empty fields and the field that initiated the filling,
463 // i.e. the field the user is currently editing and interacting with. 466 // i.e. the field the user is currently editing and interacting with.
464 if (!is_initiating_element && !input_element->value().isEmpty()) 467 if (!is_initiating_element && !input_element->value().isEmpty())
465 continue; 468 continue;
466 } 469 }
467 470
468 if (!element->isEnabled() || element->isReadOnly() || 471 if (!element->isEnabled() || element->isReadOnly() ||
469 !element->isFocusable()) 472 (requirements & REQUIRE_FOCUSABLE && !element->isFocusable()))
470 continue; 473 continue;
471 474
472 callback(element, &data.fields[i], is_initiating_element); 475 callback(data.fields[i], is_initiating_element, element);
473 } 476 }
474 } 477 }
475 478
476 // Sets the |field|'s value to the value in |data|. 479 // Sets the |field|'s value to the value in |data|.
477 // Also sets the "autofilled" attribute, causing the background to be yellow. 480 // Also sets the "autofilled" attribute, causing the background to be yellow.
478 void FillFormField(WebKit::WebFormControlElement* field, 481 void FillFormField(const FormFieldData& data,
479 const FormFieldData* data, 482 bool is_initiating_node,
480 bool is_initiating_node) { 483 WebKit::WebFormControlElement* field) {
481 // Nothing to fill. 484 // Nothing to fill.
482 if (data->value.empty()) 485 if (data.value.empty())
483 return; 486 return;
484 487
485 WebInputElement* input_element = toWebInputElement(field); 488 WebInputElement* input_element = toWebInputElement(field);
486 if (IsTextInput(input_element)) { 489 if (IsTextInput(input_element)) {
487 // If the maxlength attribute contains a negative value, maxLength() 490 // If the maxlength attribute contains a negative value, maxLength()
488 // returns the default maxlength value. 491 // returns the default maxlength value.
489 input_element->setValue( 492 input_element->setValue(
490 data->value.substr(0, input_element->maxLength()), true); 493 data.value.substr(0, input_element->maxLength()), true);
491 input_element->setAutofilled(true); 494 input_element->setAutofilled(true);
492 if (is_initiating_node) { 495 if (is_initiating_node) {
493 int length = input_element->value().length(); 496 int length = input_element->value().length();
494 input_element->setSelectionRange(length, length); 497 input_element->setSelectionRange(length, length);
495 // Clear the current IME composition (the underline), if there is one. 498 // Clear the current IME composition (the underline), if there is one.
496 input_element->document().frame()->unmarkText(); 499 input_element->document().frame()->unmarkText();
497 } 500 }
498 } else { 501 } else {
499 DCHECK(IsSelectElement(*field)); 502 DCHECK(IsSelectElement(*field));
500 WebSelectElement select_element = field->to<WebSelectElement>(); 503 WebSelectElement select_element = field->to<WebSelectElement>();
501 if (select_element.value() != data->value) { 504 if (select_element.value() != data.value) {
502 select_element.setValue(data->value); 505 select_element.setValue(data.value);
503 select_element.dispatchFormControlChangeEvent(); 506 select_element.dispatchFormControlChangeEvent();
504 } 507 }
505 } 508 }
506 } 509 }
507 510
508 // Sets the |field|'s "suggested" (non JS visible) value to the value in |data|. 511 // Sets the |field|'s "suggested" (non JS visible) value to the value in |data|.
509 // Also sets the "autofilled" attribute, causing the background to be yellow. 512 // Also sets the "autofilled" attribute, causing the background to be yellow.
510 void PreviewFormField(WebKit::WebFormControlElement* field, 513 void PreviewFormField(const FormFieldData& data,
511 const FormFieldData* data, 514 bool is_initiating_node,
512 bool is_initiating_node) { 515 WebKit::WebFormControlElement* field) {
513 // Nothing to preview. 516 // Nothing to preview.
514 if (data->value.empty()) 517 if (data.value.empty())
515 return; 518 return;
516 519
517 // Only preview input fields. 520 // Only preview input fields.
518 WebInputElement* input_element = toWebInputElement(field); 521 WebInputElement* input_element = toWebInputElement(field);
519 if (!IsTextInput(input_element)) 522 if (!IsTextInput(input_element))
520 return; 523 return;
521 524
522 // If the maxlength attribute contains a negative value, maxLength() 525 // If the maxlength attribute contains a negative value, maxLength()
523 // returns the default maxlength value. 526 // returns the default maxlength value.
524 input_element->setSuggestedValue( 527 input_element->setSuggestedValue(
525 data->value.substr(0, input_element->maxLength())); 528 data.value.substr(0, input_element->maxLength()));
526 input_element->setAutofilled(true); 529 input_element->setAutofilled(true);
527 if (is_initiating_node) { 530 if (is_initiating_node) {
528 // Select the part of the text that the user didn't type. 531 // Select the part of the text that the user didn't type.
529 input_element->setSelectionRange(input_element->value().length(), 532 input_element->setSelectionRange(input_element->value().length(),
530 input_element->suggestedValue().length()); 533 input_element->suggestedValue().length());
531 } 534 }
532 } 535 }
533 536
534 } // namespace 537 } // namespace
535 538
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
810 extract_mask, 813 extract_mask,
811 form, 814 form,
812 field); 815 field);
813 } 816 }
814 817
815 void FillForm(const FormData& form, const WebInputElement& element) { 818 void FillForm(const FormData& form, const WebInputElement& element) {
816 WebFormElement form_element = element.form(); 819 WebFormElement form_element = element.form();
817 if (form_element.isNull()) 820 if (form_element.isNull())
818 return; 821 return;
819 822
823 RequirementsMask requirements =
824 static_cast<RequirementsMask>(REQUIRE_AUTOCOMPLETE | REQUIRE_FOCUSABLE);
825 ForEachMatchingFormField(form_element,
826 element,
827 form,
828 requirements,
829 &FillFormField);
830 }
831
832 void FillFormAndNonFocusableElements(const FormData& form_data,
833 const WebFormElement& form_element) {
834 if (form_element.isNull())
835 return;
836
820 ForEachMatchingFormField(form_element, 837 ForEachMatchingFormField(form_element,
821 element, 838 WebInputElement(),
822 form, 839 form_data,
840 REQUIRE_AUTOCOMPLETE,
823 &FillFormField); 841 &FillFormField);
824 } 842 }
825 843
826 void PreviewForm(const FormData& form, const WebInputElement& element) { 844 void PreviewForm(const FormData& form, const WebInputElement& element) {
827 WebFormElement form_element = element.form(); 845 WebFormElement form_element = element.form();
828 if (form_element.isNull()) 846 if (form_element.isNull())
829 return; 847 return;
830 848
849 RequirementsMask requirements =
850 static_cast<RequirementsMask>(REQUIRE_AUTOCOMPLETE | REQUIRE_FOCUSABLE);
831 ForEachMatchingFormField(form_element, 851 ForEachMatchingFormField(form_element,
832 element, 852 element,
833 form, 853 form,
854 requirements,
834 &PreviewFormField); 855 &PreviewFormField);
835 } 856 }
836 857
837 bool ClearPreviewedFormWithElement(const WebInputElement& element, 858 bool ClearPreviewedFormWithElement(const WebInputElement& element,
838 bool was_autofilled) { 859 bool was_autofilled) {
839 WebFormElement form_element = element.form(); 860 WebFormElement form_element = element.form();
840 if (form_element.isNull()) 861 if (form_element.isNull())
841 return false; 862 return false;
842 863
843 std::vector<WebFormControlElement> control_elements; 864 std::vector<WebFormControlElement> control_elements;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
896 continue; 917 continue;
897 918
898 if (input_element->isAutofilled()) 919 if (input_element->isAutofilled())
899 return true; 920 return true;
900 } 921 }
901 922
902 return false; 923 return false;
903 } 924 }
904 925
905 } // namespace autofill 926 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698