OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "components/autofill/core/browser/autofill_manager.h" | 5 #include "components/autofill/core/browser/autofill_manager.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
601 | 601 |
602 void AutofillManager::FillOrPreviewCreditCardForm( | 602 void AutofillManager::FillOrPreviewCreditCardForm( |
603 AutofillDriver::RendererFormDataAction action, | 603 AutofillDriver::RendererFormDataAction action, |
604 int query_id, | 604 int query_id, |
605 const FormData& form, | 605 const FormData& form, |
606 const FormFieldData& field, | 606 const FormFieldData& field, |
607 const CreditCard& credit_card) { | 607 const CreditCard& credit_card) { |
608 if (action == AutofillDriver::FORM_DATA_ACTION_FILL) { | 608 if (action == AutofillDriver::FORM_DATA_ACTION_FILL) { |
609 if (credit_card.record_type() == CreditCard::MASKED_SERVER_CARD && | 609 if (credit_card.record_type() == CreditCard::MASKED_SERVER_CARD && |
610 WillFillCreditCardNumber(form, field)) { | 610 WillFillCreditCardNumber(form, field)) { |
611 unmask_request_.card = credit_card; | |
612 unmasking_query_id_ = query_id; | 611 unmasking_query_id_ = query_id; |
613 unmasking_form_ = form; | 612 unmasking_form_ = form; |
614 unmasking_field_ = field; | 613 unmasking_field_ = field; |
615 payments_client_->Prepare(); | 614 masked_card_ = credit_card; |
616 client_->ShowUnmaskPrompt(unmask_request_.card, | 615 full_card_request()->GetFullCard(masked_card_, |
617 AutofillClient::UNMASK_FOR_AUTOFILL, | 616 AutofillClient::UNMASK_FOR_AUTOFILL, |
618 weak_ptr_factory_.GetWeakPtr()); | 617 weak_ptr_factory_.GetWeakPtr()); |
619 client_->LoadRiskData(base::Bind(&AutofillManager::OnDidGetUnmaskRiskData, | |
620 weak_ptr_factory_.GetWeakPtr())); | |
621 credit_card_form_event_logger_->OnDidSelectMaskedServerCardSuggestion(); | 618 credit_card_form_event_logger_->OnDidSelectMaskedServerCardSuggestion(); |
622 return; | 619 return; |
623 } | 620 } |
624 credit_card_form_event_logger_->OnDidFillSuggestion(credit_card); | 621 credit_card_form_event_logger_->OnDidFillSuggestion(credit_card); |
625 } | 622 } |
626 | 623 |
627 FillOrPreviewDataModelForm(action, query_id, form, field, credit_card, | 624 FillOrPreviewDataModelForm(action, query_id, form, field, credit_card, |
628 true /* is_credit_card */); | 625 true /* is_credit_card */, base::string16()); |
Mathieu
2016/04/22 17:58:35
nit: I would add /* cvc */ here and below
please use gerrit instead
2016/04/22 20:50:18
Done.
| |
629 } | 626 } |
630 | 627 |
631 void AutofillManager::FillOrPreviewProfileForm( | 628 void AutofillManager::FillOrPreviewProfileForm( |
632 AutofillDriver::RendererFormDataAction action, | 629 AutofillDriver::RendererFormDataAction action, |
633 int query_id, | 630 int query_id, |
634 const FormData& form, | 631 const FormData& form, |
635 const FormFieldData& field, | 632 const FormFieldData& field, |
636 const AutofillProfile& profile) { | 633 const AutofillProfile& profile) { |
637 if (action == AutofillDriver::FORM_DATA_ACTION_FILL) | 634 if (action == AutofillDriver::FORM_DATA_ACTION_FILL) |
638 address_form_event_logger_->OnDidFillSuggestion(profile); | 635 address_form_event_logger_->OnDidFillSuggestion(profile); |
639 | 636 |
640 FillOrPreviewDataModelForm(action, query_id, form, field, profile, | 637 FillOrPreviewDataModelForm(action, query_id, form, field, profile, |
641 false /* is_credit_card */); | 638 false /* is_credit_card */, base::string16()); |
642 } | 639 } |
643 | 640 |
644 void AutofillManager::FillOrPreviewForm( | 641 void AutofillManager::FillOrPreviewForm( |
645 AutofillDriver::RendererFormDataAction action, | 642 AutofillDriver::RendererFormDataAction action, |
646 int query_id, | 643 int query_id, |
647 const FormData& form, | 644 const FormData& form, |
648 const FormFieldData& field, | 645 const FormFieldData& field, |
649 int unique_id) { | 646 int unique_id) { |
650 if (!IsValidFormData(form) || !IsValidFormFieldData(field)) | 647 if (!IsValidFormData(form) || !IsValidFormFieldData(field)) |
651 return; | 648 return; |
652 | 649 |
653 // NOTE: RefreshDataModels may invalidate |data_model| because it causes the | 650 // NOTE: RefreshDataModels may invalidate |data_model| because it causes the |
654 // PersonalDataManager to reload Mac address book entries. Thus it must come | 651 // PersonalDataManager to reload Mac address book entries. Thus it must come |
655 // before GetProfile or GetCreditCard. | 652 // before GetProfile or GetCreditCard. |
656 if (!RefreshDataModels() || !driver_->RendererIsAvailable()) | 653 if (!RefreshDataModels() || !driver_->RendererIsAvailable()) |
657 return; | 654 return; |
658 | 655 |
659 const CreditCard* credit_card = nullptr; | 656 const CreditCard* credit_card = nullptr; |
660 const AutofillProfile* profile = nullptr; | 657 const AutofillProfile* profile = nullptr; |
661 if (GetCreditCard(unique_id, &credit_card)) | 658 if (GetCreditCard(unique_id, &credit_card)) |
662 FillOrPreviewCreditCardForm(action, query_id, form, field, *credit_card); | 659 FillOrPreviewCreditCardForm(action, query_id, form, field, *credit_card); |
663 else if (GetProfile(unique_id, &profile)) | 660 else if (GetProfile(unique_id, &profile)) |
664 FillOrPreviewProfileForm(action, query_id, form, field, *profile); | 661 FillOrPreviewProfileForm(action, query_id, form, field, *profile); |
665 } | 662 } |
666 | 663 |
667 void AutofillManager::FillCreditCardForm(int query_id, | 664 void AutofillManager::FillCreditCardForm(int query_id, |
668 const FormData& form, | 665 const FormData& form, |
669 const FormFieldData& field, | 666 const FormFieldData& field, |
670 const CreditCard& credit_card) { | 667 const CreditCard& credit_card, |
668 const base::string16& cvc) { | |
671 if (!IsValidFormData(form) || !IsValidFormFieldData(field) || | 669 if (!IsValidFormData(form) || !IsValidFormFieldData(field) || |
672 !driver_->RendererIsAvailable()) { | 670 !driver_->RendererIsAvailable()) { |
673 return; | 671 return; |
674 } | 672 } |
675 | 673 |
676 FillOrPreviewDataModelForm(AutofillDriver::FORM_DATA_ACTION_FILL, query_id, | 674 FillOrPreviewDataModelForm(AutofillDriver::FORM_DATA_ACTION_FILL, query_id, |
677 form, field, credit_card, true); | 675 form, field, credit_card, true, cvc); |
678 } | 676 } |
679 | 677 |
680 void AutofillManager::OnFocusNoLongerOnForm() { | 678 void AutofillManager::OnFocusNoLongerOnForm() { |
681 ProcessPendingFormForUpload(); | 679 ProcessPendingFormForUpload(); |
682 } | 680 } |
683 | 681 |
684 void AutofillManager::OnDidPreviewAutofillFormData() { | 682 void AutofillManager::OnDidPreviewAutofillFormData() { |
685 if (test_delegate_) | 683 if (test_delegate_) |
686 test_delegate_->DidPreviewFormData(); | 684 test_delegate_->DidPreviewFormData(); |
687 } | 685 } |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
815 personal_data_->RemoveByGUID(guid); | 813 personal_data_->RemoveByGUID(guid); |
816 return true; | 814 return true; |
817 } | 815 } |
818 | 816 |
819 void AutofillManager::RemoveAutocompleteEntry(const base::string16& name, | 817 void AutofillManager::RemoveAutocompleteEntry(const base::string16& name, |
820 const base::string16& value) { | 818 const base::string16& value) { |
821 autocomplete_history_manager_->OnRemoveAutocompleteEntry(name, value); | 819 autocomplete_history_manager_->OnRemoveAutocompleteEntry(name, value); |
822 } | 820 } |
823 | 821 |
824 bool AutofillManager::IsShowingUnmaskPrompt() { | 822 bool AutofillManager::IsShowingUnmaskPrompt() { |
825 return unmask_request_.card.Compare(CreditCard()) != 0; | 823 return full_card_request_ && full_card_request_->IsGettingFullCard(); |
826 } | 824 } |
827 | 825 |
828 const std::vector<FormStructure*>& AutofillManager::GetFormStructures() { | 826 const std::vector<FormStructure*>& AutofillManager::GetFormStructures() { |
829 return form_structures_.get(); | 827 return form_structures_.get(); |
830 } | 828 } |
831 | 829 |
830 FullCardRequest* AutofillManager::full_card_request() { | |
Mathieu
2016/04/22 17:58:35
nit: A getter with non trivial logic should probab
please use gerrit instead
2016/04/22 20:50:18
Done.
| |
831 if (!full_card_request_) { | |
832 full_card_request_.reset(new FullCardRequest( | |
833 driver_->GetURLRequestContext(), client_, personal_data_)); | |
834 } | |
835 | |
836 return full_card_request_.get(); | |
837 } | |
838 | |
832 void AutofillManager::SetTestDelegate(AutofillManagerTestDelegate* delegate) { | 839 void AutofillManager::SetTestDelegate(AutofillManagerTestDelegate* delegate) { |
833 test_delegate_ = delegate; | 840 test_delegate_ = delegate; |
834 } | 841 } |
835 | 842 |
836 void AutofillManager::OnSetDataList(const std::vector<base::string16>& values, | 843 void AutofillManager::OnSetDataList(const std::vector<base::string16>& values, |
837 const std::vector<base::string16>& labels) { | 844 const std::vector<base::string16>& labels) { |
838 if (!IsValidString16Vector(values) || | 845 if (!IsValidString16Vector(values) || |
839 !IsValidString16Vector(labels) || | 846 !IsValidString16Vector(labels) || |
840 values.size() != labels.size()) | 847 values.size() != labels.size()) |
841 return; | 848 return; |
(...skipping 28 matching lines...) Expand all Loading... | |
870 client_->GetRapporService()); | 877 client_->GetRapporService()); |
871 | 878 |
872 // Forward form structures to the password generation manager to detect | 879 // Forward form structures to the password generation manager to detect |
873 // account creation forms. | 880 // account creation forms. |
874 driver_->PropagateAutofillPredictions(queried_forms); | 881 driver_->PropagateAutofillPredictions(queried_forms); |
875 | 882 |
876 // If the corresponding flag is set, annotate forms with the predicted types. | 883 // If the corresponding flag is set, annotate forms with the predicted types. |
877 driver_->SendAutofillTypePredictionsToRenderer(queried_forms); | 884 driver_->SendAutofillTypePredictionsToRenderer(queried_forms); |
878 } | 885 } |
879 | 886 |
880 void AutofillManager::OnUnmaskResponse(const UnmaskResponse& response) { | |
881 unmask_request_.user_response = response; | |
882 if (!unmask_request_.risk_data.empty()) { | |
883 real_pan_request_timestamp_ = base::Time::Now(); | |
884 payments_client_->UnmaskCard(unmask_request_); | |
885 } | |
886 } | |
887 | |
888 void AutofillManager::OnUnmaskPromptClosed() { | |
889 payments_client_->CancelRequest(); | |
890 driver_->RendererShouldClearPreviewedForm(); | |
891 unmask_request_ = payments::PaymentsClient::UnmaskRequestDetails(); | |
892 } | |
893 | |
894 IdentityProvider* AutofillManager::GetIdentityProvider() { | 887 IdentityProvider* AutofillManager::GetIdentityProvider() { |
895 return client_->GetIdentityProvider(); | 888 return client_->GetIdentityProvider(); |
896 } | 889 } |
897 | 890 |
898 void AutofillManager::OnDidGetRealPan(AutofillClient::PaymentsRpcResult result, | 891 void AutofillManager::OnDidGetRealPan(AutofillClient::PaymentsRpcResult result, |
899 const std::string& real_pan) { | 892 const std::string& real_pan) { |
900 AutofillMetrics::LogRealPanDuration( | 893 NOTREACHED(); |
901 base::Time::Now() - real_pan_request_timestamp_, result); | |
902 if (!real_pan.empty()) { | |
903 DCHECK_EQ(AutofillClient::SUCCESS, result); | |
904 credit_card_form_event_logger_->OnDidFillSuggestion(unmask_request_.card); | |
905 unmask_request_.card.set_record_type(CreditCard::FULL_SERVER_CARD); | |
906 unmask_request_.card.SetNumber(base::UTF8ToUTF16(real_pan)); | |
907 if (!unmask_request_.user_response.exp_month.empty()) { | |
908 unmask_request_.card.SetRawInfo(CREDIT_CARD_EXP_MONTH, | |
909 unmask_request_.user_response.exp_month); | |
910 } | |
911 if (!unmask_request_.user_response.exp_year.empty()) { | |
912 unmask_request_.card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, | |
913 unmask_request_.user_response.exp_year); | |
914 } | |
915 if (unmask_request_.user_response.should_store_pan) | |
916 personal_data_->UpdateServerCreditCard(unmask_request_.card); | |
917 | |
918 FillCreditCardForm(unmasking_query_id_, unmasking_form_, unmasking_field_, | |
919 unmask_request_.card); | |
920 } | |
921 | |
922 client_->OnUnmaskVerificationResult(result); | |
923 } | 894 } |
924 | 895 |
925 void AutofillManager::OnDidGetUploadDetails( | 896 void AutofillManager::OnDidGetUploadDetails( |
926 AutofillClient::PaymentsRpcResult result, | 897 AutofillClient::PaymentsRpcResult result, |
927 const base::string16& context_token, | 898 const base::string16& context_token, |
928 std::unique_ptr<base::DictionaryValue> legal_message) { | 899 std::unique_ptr<base::DictionaryValue> legal_message) { |
929 // TODO(jdonnelly): Log duration. | 900 // TODO(jdonnelly): Log duration. |
930 if (result == AutofillClient::SUCCESS) { | 901 if (result == AutofillClient::SUCCESS) { |
931 // Do *not* call payments_client_->Prepare() here. We shouldn't send | 902 // Do *not* call payments_client_->Prepare() here. We shouldn't send |
932 // credentials until the user has explicitly accepted a prompt to upload. | 903 // credentials until the user has explicitly accepted a prompt to upload. |
(...skipping 28 matching lines...) Expand all Loading... | |
961 AutofillMetrics::UPLOAD_NOT_OFFERED_GET_UPLOAD_DETAILS_FAILED); | 932 AutofillMetrics::UPLOAD_NOT_OFFERED_GET_UPLOAD_DETAILS_FAILED); |
962 } | 933 } |
963 } | 934 } |
964 | 935 |
965 void AutofillManager::OnDidUploadCard( | 936 void AutofillManager::OnDidUploadCard( |
966 AutofillClient::PaymentsRpcResult result) { | 937 AutofillClient::PaymentsRpcResult result) { |
967 // We don't do anything user-visible if the upload attempt fails. | 938 // We don't do anything user-visible if the upload attempt fails. |
968 // TODO(jdonnelly): Log duration. | 939 // TODO(jdonnelly): Log duration. |
969 } | 940 } |
970 | 941 |
971 void AutofillManager::OnDidGetUnmaskRiskData(const std::string& risk_data) { | 942 void AutofillManager::OnFullCardDetails(const CreditCard& card, |
972 unmask_request_.risk_data = risk_data; | 943 const base::string16& cvc) { |
973 if (!unmask_request_.user_response.cvc.empty()) { | 944 credit_card_form_event_logger_->OnDidFillSuggestion(masked_card_); |
974 real_pan_request_timestamp_ = base::Time::Now(); | 945 FillCreditCardForm(unmasking_query_id_, unmasking_form_, unmasking_field_, |
975 payments_client_->UnmaskCard(unmask_request_); | 946 card, cvc); |
976 } | 947 masked_card_ = CreditCard(); |
948 } | |
949 | |
950 void AutofillManager::OnFullCardError() { | |
951 driver_->RendererShouldClearPreviewedForm(); | |
977 } | 952 } |
978 | 953 |
979 void AutofillManager::OnUserDidAcceptUpload() { | 954 void AutofillManager::OnUserDidAcceptUpload() { |
980 user_did_accept_upload_prompt_ = true; | 955 user_did_accept_upload_prompt_ = true; |
981 if (!upload_request_.risk_data.empty()) { | 956 if (!upload_request_.risk_data.empty()) { |
982 upload_request_.app_locale = app_locale_; | 957 upload_request_.app_locale = app_locale_; |
983 payments_client_->UploadCard(upload_request_); | 958 payments_client_->UploadCard(upload_request_); |
984 } | 959 } |
985 } | 960 } |
986 | 961 |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1253 address_form_event_logger_.reset( | 1228 address_form_event_logger_.reset( |
1254 new AutofillMetrics::FormEventLogger(false /* is_for_credit_card */)); | 1229 new AutofillMetrics::FormEventLogger(false /* is_for_credit_card */)); |
1255 credit_card_form_event_logger_.reset( | 1230 credit_card_form_event_logger_.reset( |
1256 new AutofillMetrics::FormEventLogger(true /* is_for_credit_card */)); | 1231 new AutofillMetrics::FormEventLogger(true /* is_for_credit_card */)); |
1257 has_logged_autofill_enabled_ = false; | 1232 has_logged_autofill_enabled_ = false; |
1258 has_logged_address_suggestions_count_ = false; | 1233 has_logged_address_suggestions_count_ = false; |
1259 did_show_suggestions_ = false; | 1234 did_show_suggestions_ = false; |
1260 user_did_type_ = false; | 1235 user_did_type_ = false; |
1261 user_did_autofill_ = false; | 1236 user_did_autofill_ = false; |
1262 user_did_edit_autofilled_field_ = false; | 1237 user_did_edit_autofilled_field_ = false; |
1263 unmask_request_ = payments::PaymentsClient::UnmaskRequestDetails(); | 1238 masked_card_ = CreditCard(); |
1264 unmasking_query_id_ = -1; | 1239 unmasking_query_id_ = -1; |
1265 unmasking_form_ = FormData(); | 1240 unmasking_form_ = FormData(); |
1266 unmasking_field_ = FormFieldData(); | 1241 unmasking_field_ = FormFieldData(); |
1267 forms_loaded_timestamps_.clear(); | 1242 forms_loaded_timestamps_.clear(); |
1268 initial_interaction_timestamp_ = TimeTicks(); | 1243 initial_interaction_timestamp_ = TimeTicks(); |
1269 external_delegate_->Reset(); | 1244 external_delegate_->Reset(); |
1270 } | 1245 } |
1271 | 1246 |
1272 AutofillManager::AutofillManager(AutofillDriver* driver, | 1247 AutofillManager::AutofillManager(AutofillDriver* driver, |
1273 AutofillClient* client, | 1248 AutofillClient* client, |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1377 *credit_card = personal_data_->GetCreditCardByGUID(credit_card_id); | 1352 *credit_card = personal_data_->GetCreditCardByGUID(credit_card_id); |
1378 return !!*credit_card; | 1353 return !!*credit_card; |
1379 } | 1354 } |
1380 | 1355 |
1381 void AutofillManager::FillOrPreviewDataModelForm( | 1356 void AutofillManager::FillOrPreviewDataModelForm( |
1382 AutofillDriver::RendererFormDataAction action, | 1357 AutofillDriver::RendererFormDataAction action, |
1383 int query_id, | 1358 int query_id, |
1384 const FormData& form, | 1359 const FormData& form, |
1385 const FormFieldData& field, | 1360 const FormFieldData& field, |
1386 const AutofillDataModel& data_model, | 1361 const AutofillDataModel& data_model, |
1387 bool is_credit_card) { | 1362 bool is_credit_card, |
1363 const base::string16& cvc) { | |
1388 FormStructure* form_structure = NULL; | 1364 FormStructure* form_structure = NULL; |
1389 AutofillField* autofill_field = NULL; | 1365 AutofillField* autofill_field = NULL; |
1390 if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field)) | 1366 if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field)) |
1391 return; | 1367 return; |
1392 | 1368 |
1393 DCHECK(form_structure); | 1369 DCHECK(form_structure); |
1394 DCHECK(autofill_field); | 1370 DCHECK(autofill_field); |
1395 | 1371 |
1396 FormData result = form; | 1372 FormData result = form; |
1397 | 1373 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1452 FieldTypeGroup field_group_type = cached_field->Type().group(); | 1428 FieldTypeGroup field_group_type = cached_field->Type().group(); |
1453 | 1429 |
1454 if (field_group_type == NO_GROUP) | 1430 if (field_group_type == NO_GROUP) |
1455 continue; | 1431 continue; |
1456 | 1432 |
1457 base::string16 value = | 1433 base::string16 value = |
1458 data_model.GetInfo(cached_field->Type(), app_locale_); | 1434 data_model.GetInfo(cached_field->Type(), app_locale_); |
1459 if (is_credit_card && | 1435 if (is_credit_card && |
1460 cached_field->Type().GetStorableType() == | 1436 cached_field->Type().GetStorableType() == |
1461 CREDIT_CARD_VERIFICATION_CODE) { | 1437 CREDIT_CARD_VERIFICATION_CODE) { |
1462 // If this is |unmask_request_.card|, |unmask_request_.user_response.cvc| | 1438 value = cvc; |
1463 // should be non-empty and vice versa. | |
1464 value = unmask_request_.user_response.cvc; | |
1465 DCHECK_EQ(&unmask_request_.card == &data_model, !value.empty()); | |
1466 } else if (is_credit_card && IsCreditCardExpirationType( | 1439 } else if (is_credit_card && IsCreditCardExpirationType( |
1467 cached_field->Type().GetStorableType()) && | 1440 cached_field->Type().GetStorableType()) && |
1468 static_cast<const CreditCard*>(&data_model) | 1441 static_cast<const CreditCard*>(&data_model) |
1469 ->IsExpired(base::Time::Now())) { | 1442 ->IsExpired(base::Time::Now())) { |
1470 // Don't fill expired cards expiration date. | 1443 // Don't fill expired cards expiration date. |
1471 value = base::string16(); | 1444 value = base::string16(); |
1472 } | 1445 } |
1473 | 1446 |
1474 // Must match ForEachMatchingFormField() in form_autofill_util.cc. | 1447 // Must match ForEachMatchingFormField() in form_autofill_util.cc. |
1475 // Only notify autofilling of empty fields and the field that initiated | 1448 // Only notify autofilling of empty fields and the field that initiated |
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2021 if (i > 0) | 1994 if (i > 0) |
2022 fputs("Next oldest form:\n", file); | 1995 fputs("Next oldest form:\n", file); |
2023 } | 1996 } |
2024 fputs("\n", file); | 1997 fputs("\n", file); |
2025 | 1998 |
2026 fclose(file); | 1999 fclose(file); |
2027 } | 2000 } |
2028 #endif // ENABLE_FORM_DEBUG_DUMP | 2001 #endif // ENABLE_FORM_DEBUG_DUMP |
2029 | 2002 |
2030 } // namespace autofill | 2003 } // namespace autofill |
OLD | NEW |