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 26 matching lines...) Expand all Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |