summaryrefslogtreecommitdiff
path: root/chromium/components/autofill
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-01-23 17:21:03 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-01-23 16:25:15 +0000
commitc551f43206405019121bd2b2c93714319a0a3300 (patch)
tree1f48c30631c421fd4bbb3c36da20183c8a2ed7d7 /chromium/components/autofill
parent7961cea6d1041e3e454dae6a1da660b453efd238 (diff)
downloadqtwebengine-chromium-c551f43206405019121bd2b2c93714319a0a3300.tar.gz
BASELINE: Update Chromium to 79.0.3945.139
Change-Id: I336b7182fab9bca80b709682489c07db112eaca5 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/components/autofill')
-rw-r--r--chromium/components/autofill/android/BUILD.gn4
-rw-r--r--chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java11
-rw-r--r--chromium/components/autofill/android/java/src/org/chromium/components/autofill/FormData.java11
-rw-r--r--chromium/components/autofill/android/java/src/org/chromium/components/autofill/FormFieldData.java2
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver.cc4
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver.h10
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver_factory.cc34
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver_factory.h1
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc10
-rw-r--r--chromium/components/autofill/content/browser/risk/fingerprint.cc24
-rw-r--r--chromium/components/autofill/content/browser/risk/fingerprint_browsertest.cc3
-rw-r--r--chromium/components/autofill/content/common/mojom/autofill_agent.mojom19
-rw-r--r--chromium/components/autofill/content/common/mojom/autofill_driver.mojom9
-rw-r--r--chromium/components/autofill/content/renderer/BUILD.gn2
-rw-r--r--chromium/components/autofill/content/renderer/PRESUBMIT.py6
-rw-r--r--chromium/components/autofill/content/renderer/autofill_agent.cc96
-rw-r--r--chromium/components/autofill/content/renderer/autofill_agent.h27
-rw-r--r--chromium/components/autofill/content/renderer/form_autofill_util.cc84
-rw-r--r--chromium/components/autofill/content/renderer/form_autofill_util.h28
-rw-r--r--chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc157
-rw-r--r--chromium/components/autofill/content/renderer/form_cache.cc146
-rw-r--r--chromium/components/autofill/content/renderer/form_cache.h25
-rw-r--r--chromium/components/autofill/content/renderer/form_cache_browsertest.cc194
-rw-r--r--chromium/components/autofill/content/renderer/password_autofill_agent.cc683
-rw-r--r--chromium/components/autofill/content/renderer/password_autofill_agent.h70
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils.cc799
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils.h52
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc2217
-rw-r--r--chromium/components/autofill/content/renderer/password_generation_agent.cc23
-rw-r--r--chromium/components/autofill/content/renderer/provisionally_saved_password_form.cc47
-rw-r--r--chromium/components/autofill/content/renderer/provisionally_saved_password_form.h62
-rw-r--r--chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc26
-rw-r--r--chromium/components/autofill/core/browser/BUILD.gn21
-rw-r--r--chromium/components/autofill/core/browser/autocomplete_history_manager_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/autofill_address_util.cc34
-rw-r--r--chromium/components/autofill/core/browser/autofill_address_util.h5
-rw-r--r--chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.css4
-rw-r--r--chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals_ios.html51
-rw-r--r--chromium/components/autofill/core/browser/autofill_assistant_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/autofill_client.cc4
-rw-r--r--chromium/components/autofill/core/browser/autofill_client.h43
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_util.cc64
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_util.h5
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_util_unittest.cc27
-rw-r--r--chromium/components/autofill/core/browser/autofill_download_manager.cc16
-rw-r--r--chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc56
-rw-r--r--chromium/components/autofill/core/browser/autofill_driver.h4
-rw-r--r--chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments.cc1
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate.cc16
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate.h6
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc51
-rw-r--r--chromium/components/autofill/core/browser/autofill_field.cc49
-rw-r--r--chromium/components/autofill/core/browser/autofill_field.h39
-rw-r--r--chromium/components/autofill/core/browser/autofill_handler.cc38
-rw-r--r--chromium/components/autofill/core/browser/autofill_internals_service.cc23
-rw-r--r--chromium/components/autofill/core/browser/autofill_internals_service.h24
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager.cc45
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager.h5
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager_unittest.cc71
-rw-r--r--chromium/components/autofill/core/browser/autofill_merge_unittest.cc22
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.cc141
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.h144
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics_unittest.cc357
-rw-r--r--chromium/components/autofill/core/browser/autofill_test_utils.cc72
-rw-r--r--chromium/components/autofill/core/browser/autofill_test_utils.h19
-rw-r--r--chromium/components/autofill/core/browser/autofill_type.cc84
-rw-r--r--chromium/components/autofill/core/browser/autofill_type.h7
-rw-r--r--chromium/components/autofill/core/browser/data_driven_test.cc21
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_data_model_unittest.cc3
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_profile.cc8
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_profile.h4
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.cc66
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.h10
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_profile_comparator_unittest.cc18
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_profile_unittest.cc30
-rw-r--r--chromium/components/autofill/core/browser/data_model/contact_info.cc52
-rw-r--r--chromium/components/autofill/core/browser/data_model/contact_info.h12
-rw-r--r--chromium/components/autofill/core/browser/data_model/contact_info_unittest.cc397
-rw-r--r--chromium/components/autofill/core/browser/data_model/credit_card.cc6
-rw-r--r--chromium/components/autofill/core/browser/data_model/credit_card.h14
-rw-r--r--chromium/components/autofill/core/browser/data_model/credit_card_unittest.cc6
-rw-r--r--chromium/components/autofill/core/browser/field_types.h19
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer.cc27
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer.h23
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer_unittest.cc188
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/autofill_scanner.h3
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/field_candidates.cc4
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/field_candidates.h5
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/form_field.cc1
-rw-r--r--chromium/components/autofill/core/browser/form_structure.cc84
-rw-r--r--chromium/components/autofill/core/browser/form_structure.h50
-rw-r--r--chromium/components/autofill/core/browser/form_structure_unittest.cc35
-rw-r--r--chromium/components/autofill/core/browser/logging/log_buffer_submitter.h2
-rw-r--r--chromium/components/autofill/core/browser/logging/log_protobufs.h31
-rw-r--r--chromium/components/autofill/core/browser/logging/log_router.cc2
-rw-r--r--chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc35
-rw-r--r--chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.h18
-rw-r--r--chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc15
-rw-r--r--chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h9
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_access_manager.cc201
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_access_manager.h35
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc703
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.cc8
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h11
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc20
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc343
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.h54
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc151
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_save_manager.cc44
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_save_manager.h33
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc501
-rw-r--r--chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.cc42
-rw-r--r--chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.h38
-rw-r--r--chromium/components/autofill/core/browser/payments/full_card_request.cc36
-rw-r--r--chromium/components/autofill/core/browser/payments/full_card_request.h14
-rw-r--r--chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc137
-rw-r--r--chromium/components/autofill/core/browser/payments/legal_message_line.cc2
-rw-r--r--chromium/components/autofill/core/browser/payments/local_card_migration_manager.cc23
-rw-r--r--chromium/components/autofill/core/browser/payments/local_card_migration_manager.h5
-rw-r--r--chromium/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc15
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client.cc174
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client.h67
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client_unittest.cc86
-rw-r--r--chromium/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.cc6
-rw-r--r--chromium/components/autofill/core/browser/payments/test_payments_client.cc49
-rw-r--r--chromium/components/autofill/core/browser/payments/test_payments_client.h12
-rw-r--r--chromium/components/autofill/core/browser/payments/test_strike_database.cc3
-rw-r--r--chromium/components/autofill/core/browser/payments/upi_vpa_save_manager.cc21
-rw-r--r--chromium/components/autofill/core/browser/payments/upi_vpa_save_manager.h29
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager.cc157
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager.h45
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager_observer.h7
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager_unittest.cc132
-rw-r--r--chromium/components/autofill/core/browser/proto/server.proto8
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_client.cc19
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_client.h16
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_clock.h2
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_driver.cc2
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_driver.h3
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_external_delegate.cc7
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_external_delegate.h2
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_tick_clock.cc31
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_tick_clock.h42
-rw-r--r--chromium/components/autofill/core/browser/test_personal_data_manager.cc7
-rw-r--r--chromium/components/autofill/core/browser/test_personal_data_manager.h4
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller.h36
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl.cc127
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl.h62
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl_unittest.cc147
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view.h26
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view_delegate_mobile.cc82
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view_delegate_mobile.h55
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller.h1
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.cc15
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.h1
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl_unittest.cc88
-rw-r--r--chromium/components/autofill/core/browser/ui/popup_item_ids.h5
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc6
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.cc5
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.h3
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc6
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util_unittest.cc6
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table.cc69
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table.h22
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc404
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc6
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc6
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc78
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h5
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc5
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h3
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_service_observer.h7
-rw-r--r--chromium/components/autofill/core/browser/webdata/web_data_service_unittest.cc29
-rw-r--r--chromium/components/autofill/core/common/BUILD.gn8
-rw-r--r--chromium/components/autofill/core/common/autofill_clock.cc4
-rw-r--r--chromium/components/autofill/core/common/autofill_clock.h4
-rw-r--r--chromium/components/autofill/core/common/autofill_features.cc21
-rw-r--r--chromium/components/autofill/core/common/autofill_features.h6
-rw-r--r--chromium/components/autofill/core/common/autofill_internals/log_message.cc8
-rw-r--r--chromium/components/autofill/core/common/autofill_internals/log_message.h23
-rw-r--r--chromium/components/autofill/core/common/autofill_internals/log_message_unittest.cc (renamed from chromium/components/autofill/core/browser/autofill_internals_service_unittest.cc)17
-rw-r--r--chromium/components/autofill/core/common/autofill_internals/logging_scope.cc8
-rw-r--r--chromium/components/autofill/core/common/autofill_internals/logging_scope.h6
-rw-r--r--chromium/components/autofill/core/common/autofill_internals/logging_scope_unittest.cc23
-rw-r--r--chromium/components/autofill/core/common/autofill_payments_features.cc27
-rw-r--r--chromium/components/autofill/core/common/autofill_payments_features.h4
-rw-r--r--chromium/components/autofill/core/common/autofill_prefs.cc34
-rw-r--r--chromium/components/autofill/core/common/autofill_prefs.h5
-rw-r--r--chromium/components/autofill/core/common/autofill_regex_constants.cc15
-rw-r--r--chromium/components/autofill/core/common/autofill_tick_clock.cc33
-rw-r--r--chromium/components/autofill/core/common/autofill_tick_clock.h37
-rw-r--r--chromium/components/autofill/core/common/autofill_util.cc2
-rw-r--r--chromium/components/autofill/core/common/form_data.cc98
-rw-r--r--chromium/components/autofill/core/common/form_data.h26
-rw-r--r--chromium/components/autofill/core/common/form_data_predictions.cc23
-rw-r--r--chromium/components/autofill/core/common/form_data_predictions.h5
-rw-r--r--chromium/components/autofill/core/common/form_data_unittest.cc16
-rw-r--r--chromium/components/autofill/core/common/form_field_data.cc49
-rw-r--r--chromium/components/autofill/core/common/form_field_data.h20
-rw-r--r--chromium/components/autofill/core/common/form_field_data_predictions.cc26
-rw-r--r--chromium/components/autofill/core/common/form_field_data_predictions.h5
-rw-r--r--chromium/components/autofill/core/common/logging/log_buffer.cc (renamed from chromium/components/autofill/core/browser/logging/log_buffer.cc)4
-rw-r--r--chromium/components/autofill/core/common/logging/log_buffer.h (renamed from chromium/components/autofill/core/browser/logging/log_buffer.h)20
-rw-r--r--chromium/components/autofill/core/common/logging/log_buffer_unittest.cc (renamed from chromium/components/autofill/core/browser/logging/log_buffer_unittest.cc)2
-rw-r--r--chromium/components/autofill/core/common/mojom/autofill_types.mojom29
-rw-r--r--chromium/components/autofill/core/common/mojom/autofill_types.typemap2
-rw-r--r--chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc101
-rw-r--r--chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits.h60
-rw-r--r--chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc113
-rw-r--r--chromium/components/autofill/core/common/mojom/test_autofill_types.mojom2
-rw-r--r--chromium/components/autofill/core/common/password_form.cc47
-rw-r--r--chromium/components/autofill/core/common/password_form.h23
-rw-r--r--chromium/components/autofill/core/common/password_form_field_prediction_map.h22
-rw-r--r--chromium/components/autofill/core/common/password_form_fill_data.cc26
-rw-r--r--chromium/components/autofill/core/common/password_form_fill_data.h27
-rw-r--r--chromium/components/autofill/core/common/password_form_fill_data_unittest.cc17
-rw-r--r--chromium/components/autofill/core/common/password_generation_util.cc2
-rw-r--r--chromium/components/autofill/core/common/password_generation_util.h8
-rw-r--r--chromium/components/autofill/core/common/save_password_progress_logger.cc65
-rw-r--r--chromium/components/autofill/core/common/save_password_progress_logger.h31
-rw-r--r--chromium/components/autofill/ios/browser/autofill_agent.mm16
-rw-r--r--chromium/components/autofill/ios/browser/autofill_agent_unittests.mm15
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios.h3
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios.mm2
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.h2
-rw-r--r--chromium/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.h2
-rw-r--r--chromium/components/autofill/ios/browser/js_autofill_manager.mm2
-rw-r--r--chromium/components/autofill/ios/browser/js_suggestion_manager.mm2
-rw-r--r--chromium/components/autofill/ios/form_util/form_activity_tab_helper.h4
230 files changed, 6296 insertions, 7196 deletions
diff --git a/chromium/components/autofill/android/BUILD.gn b/chromium/components/autofill/android/BUILD.gn
index 88c3ffd4b58..3313c23417b 100644
--- a/chromium/components/autofill/android/BUILD.gn
+++ b/chromium/components/autofill/android/BUILD.gn
@@ -100,10 +100,12 @@ android_library("autofill_java") {
android_library("provider_java") {
deps = [
"//base:base_java",
+ "//base:jni_java",
"//components/autofill/core/common/mojom:mojo_types_java",
"//content/public/android:content_java",
- "//third_party/android_deps:com_android_support_support_annotations_java",
+ "//third_party/android_deps:androidx_annotation_annotation_java",
]
+ annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
java_files = [
"java/src/org/chromium/components/autofill/AutofillProvider.java",
"java/src/org/chromium/components/autofill/FormData.java",
diff --git a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java b/chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java
index 0937a500970..a7d05d359a4 100644
--- a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java
+++ b/chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java
@@ -11,6 +11,7 @@ import android.view.autofill.AutofillValue;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
import org.chromium.content_public.browser.WebContents;
/**
@@ -132,7 +133,8 @@ public abstract class AutofillProvider {
* @param formData the form to fill.
*/
protected void autofill(long nativeAutofillProvider, FormData formData) {
- nativeOnAutofillAvailable(nativeAutofillProvider, formData);
+ AutofillProviderJni.get().onAutofillAvailable(
+ nativeAutofillProvider, AutofillProvider.this, formData);
}
/**
@@ -147,6 +149,9 @@ public abstract class AutofillProvider {
@CalledByNative
protected abstract void onDidFillAutofillFormData();
- private native void nativeOnAutofillAvailable(
- long nativeAutofillProviderAndroid, FormData formData);
+ @NativeMethods
+ interface Natives {
+ void onAutofillAvailable(
+ long nativeAutofillProviderAndroid, AutofillProvider caller, FormData formData);
+ }
}
diff --git a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/FormData.java b/chromium/components/autofill/android/java/src/org/chromium/components/autofill/FormData.java
index ca1362a286a..5c4db2d1bdb 100644
--- a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/FormData.java
+++ b/chromium/components/autofill/android/java/src/org/chromium/components/autofill/FormData.java
@@ -6,6 +6,7 @@ package org.chromium.components.autofill;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
import java.util.ArrayList;
@@ -35,10 +36,11 @@ public class FormData {
}
private void popupFormFields(int fieldCount) {
- FormFieldData formFieldData = nativeGetNextFormFieldData(mNativeObj);
+ FormFieldData formFieldData =
+ FormDataJni.get().getNextFormFieldData(mNativeObj, FormData.this);
while (formFieldData != null) {
mFields.add(formFieldData);
- formFieldData = nativeGetNextFormFieldData(mNativeObj);
+ formFieldData = FormDataJni.get().getNextFormFieldData(mNativeObj, FormData.this);
}
assert mFields.size() == fieldCount;
}
@@ -48,5 +50,8 @@ public class FormData {
mNativeObj = 0;
}
- private native FormFieldData nativeGetNextFormFieldData(long nativeFormDataAndroid);
+ @NativeMethods
+ interface Natives {
+ FormFieldData getNextFormFieldData(long nativeFormDataAndroid, FormData caller);
+ }
}
diff --git a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/FormFieldData.java b/chromium/components/autofill/android/java/src/org/chromium/components/autofill/FormFieldData.java
index aa4a395dbda..9a95d0a775a 100644
--- a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/FormFieldData.java
+++ b/chromium/components/autofill/android/java/src/org/chromium/components/autofill/FormFieldData.java
@@ -4,7 +4,7 @@
package org.chromium.components.autofill;
-import android.support.annotation.IntDef;
+import androidx.annotation.IntDef;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver.cc b/chromium/components/autofill/content/browser/content_autofill_driver.cc
index 68239ae09f5..9d2e0b76391 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver.cc
@@ -176,10 +176,10 @@ void ContentAutofillDriver::RendererShouldPreviewFieldWithValue(
}
void ContentAutofillDriver::RendererShouldSetSuggestionAvailability(
- bool available) {
+ const mojom::AutofillState state) {
if (!RendererIsAvailable())
return;
- GetAutofillAgent()->SetSuggestionAvailability(available);
+ GetAutofillAgent()->SetSuggestionAvailability(state);
}
void ContentAutofillDriver::PopupHidden() {
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver.h b/chromium/components/autofill/content/browser/content_autofill_driver.h
index c2496dc87b0..abe86a99845 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver.h
+++ b/chromium/components/autofill/content/browser/content_autofill_driver.h
@@ -7,6 +7,7 @@
#include <memory>
#include <string>
+#include <vector>
#include "base/supports_user_data.h"
#include "build/build_config.h"
@@ -24,7 +25,7 @@
namespace content {
class NavigationHandle;
class RenderFrameHost;
-}
+} // namespace content
namespace autofill {
@@ -77,7 +78,8 @@ class ContentAutofillDriver : public AutofillDriver,
void RendererShouldFillFieldWithValue(const base::string16& value) override;
void RendererShouldPreviewFieldWithValue(
const base::string16& value) override;
- void RendererShouldSetSuggestionAvailability(bool available) override;
+ void RendererShouldSetSuggestionAvailability(
+ const mojom::AutofillState state) override;
void PopupHidden() override;
gfx::RectF TransformBoundingBoxToViewportCoordinates(
const gfx::RectF& bounding_box) override;
@@ -120,10 +122,6 @@ class ContentAutofillDriver : public AutofillDriver,
// subframe navigations. See navigation_handle.h for details.
void DidNavigateMainFrame(content::NavigationHandle* navigation_handle);
- AutofillExternalDelegate* autofill_external_delegate() {
- return autofill_external_delegate_.get();
- }
-
AutofillManager* autofill_manager() { return autofill_manager_; }
AutofillHandler* autofill_handler() { return autofill_handler_.get(); }
content::RenderFrameHost* render_frame_host() { return render_frame_host_; }
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver_factory.cc b/chromium/components/autofill/content/browser/content_autofill_driver_factory.cc
index e4dece7c37d..a34b85e8edc 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver_factory.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver_factory.cc
@@ -57,17 +57,10 @@ void ContentAutofillDriverFactory::CreateForWebContentsAndDelegate(
if (FromWebContents(contents))
return;
- auto new_factory = std::make_unique<ContentAutofillDriverFactory>(
- contents, client, app_locale, enable_download_manager, provider);
- const std::vector<content::RenderFrameHost*> frames =
- contents->GetAllFrames();
- for (content::RenderFrameHost* frame : frames) {
- if (frame->IsRenderFrameLive())
- new_factory->RenderFrameCreated(frame);
- }
-
- contents->SetUserData(kContentAutofillDriverFactoryWebContentsUserDataKey,
- std::move(new_factory));
+ contents->SetUserData(
+ kContentAutofillDriverFactoryWebContentsUserDataKey,
+ std::make_unique<ContentAutofillDriverFactory>(
+ contents, client, app_locale, enable_download_manager, provider));
}
// static
@@ -115,17 +108,20 @@ ContentAutofillDriverFactory::ContentAutofillDriverFactory(
ContentAutofillDriver* ContentAutofillDriverFactory::DriverForFrame(
content::RenderFrameHost* render_frame_host) {
+ AutofillDriver* driver = DriverForKey(render_frame_host);
+
+ // ContentAutofillDriver are created on demand here.
+ if (!driver) {
+ AddForKey(render_frame_host,
+ base::Bind(CreateDriver, render_frame_host, client(), app_locale_,
+ enable_download_manager_, provider_));
+ driver = DriverForKey(render_frame_host);
+ }
+
// This cast is safe because AutofillDriverFactory::AddForKey is protected
// and always called with ContentAutofillDriver instances within
// ContentAutofillDriverFactory.
- return static_cast<ContentAutofillDriver*>(DriverForKey(render_frame_host));
-}
-
-void ContentAutofillDriverFactory::RenderFrameCreated(
- content::RenderFrameHost* render_frame_host) {
- AddForKey(render_frame_host,
- base::Bind(CreateDriver, render_frame_host, client(), app_locale_,
- enable_download_manager_, provider_));
+ return static_cast<ContentAutofillDriver*>(driver);
}
void ContentAutofillDriverFactory::RenderFrameDeleted(
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver_factory.h b/chromium/components/autofill/content/browser/content_autofill_driver_factory.h
index a530737bd8c..ddd66b77b69 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver_factory.h
+++ b/chromium/components/autofill/content/browser/content_autofill_driver_factory.h
@@ -63,7 +63,6 @@ class ContentAutofillDriverFactory : public AutofillDriverFactory,
content::RenderFrameHost* render_frame_host);
// content::WebContentsObserver:
- void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc b/chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc
index 547fbd9d9c1..9815b85401a 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc
@@ -188,8 +188,11 @@ class FakeAutofillAgent : public mojom::AutofillAgent {
CallDone();
}
- void SetSuggestionAvailability(bool value) override {
- suggestions_available_ = value;
+ void SetSuggestionAvailability(const mojom::AutofillState state) override {
+ if (state == mojom::AutofillState::kAutofillAvailable)
+ suggestions_available_ = true;
+ else if (state == mojom::AutofillState::kNoSuggestions)
+ suggestions_available_ = false;
CallDone();
}
@@ -204,9 +207,6 @@ class FakeAutofillAgent : public mojom::AutofillAgent {
void PreviewPasswordSuggestion(const base::string16& username,
const base::string16& password) override {}
- void ShowInitialPasswordAccountSuggestions(
- const PasswordFormFillData& form_data) override {}
-
void SetUserGestureRequired(bool required) override {}
void SetSecureContextRequired(bool required) override {}
diff --git a/chromium/components/autofill/content/browser/risk/fingerprint.cc b/chromium/components/autofill/content/browser/risk/fingerprint.cc
index e640bf8c7bd..fd6b9ab2765 100644
--- a/chromium/components/autofill/content/browser/risk/fingerprint.cc
+++ b/chromium/components/autofill/content/browser/risk/fingerprint.cc
@@ -28,6 +28,7 @@
#include "base/timer/timer.h"
#include "base/values.h"
#include "components/autofill/content/browser/risk/proto/fingerprint.pb.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/font_list_async.h"
#include "content/public/browser/gpu_data_manager.h"
@@ -40,6 +41,7 @@
#include "content/public/common/webplugininfo.h"
#include "gpu/config/gpu_info.h"
#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "ppapi/buildflags/buildflags.h"
#include "services/device/public/cpp/geolocation/geoposition.h"
#include "services/device/public/mojom/constants.mojom.h"
@@ -65,7 +67,7 @@ const int kTimeoutSeconds = 4;
// Returns the delta between the local timezone and UTC.
base::TimeDelta GetTimezoneOffset() {
- const base::Time utc = base::Time::Now();
+ const base::Time utc = AutofillClock::Now();
base::Time::Exploded local;
utc.LocalExplode(&local);
@@ -81,7 +83,7 @@ base::TimeDelta GetTimezoneOffset() {
// "Mac OS X 10.6.8".
std::string GetOperatingSystemVersion() {
return base::SysInfo::OperatingSystemName() + " " +
- base::SysInfo::OperatingSystemVersion();
+ base::SysInfo::OperatingSystemVersion();
}
// Adds the list of |fonts| to the |machine|.
@@ -106,8 +108,7 @@ void AddFontsToFingerprint(const base::ListValue& fonts,
void AddPluginsToFingerprint(const std::vector<content::WebPluginInfo>& plugins,
Fingerprint::MachineCharacteristics* machine) {
for (const content::WebPluginInfo& it : plugins) {
- Fingerprint::MachineCharacteristics::Plugin* plugin =
- machine->add_plugin();
+ Fingerprint::MachineCharacteristics::Plugin* plugin = machine->add_plugin();
plugin->set_name(base::UTF16ToUTF8(it.name));
plugin->set_description(base::UTF16ToUTF8(it.desc));
for (const content::WebPluginMimeType& mime_type : it.mime_types)
@@ -241,8 +242,8 @@ class FingerprintDataLoader : public content::GpuDataManagerObserver {
std::vector<content::WebPluginInfo> plugins_;
bool waiting_on_plugins_;
device::mojom::Geoposition geoposition_;
- device::mojom::GeolocationPtr geolocation_;
- device::mojom::GeolocationContextPtr geolocation_context_;
+ mojo::Remote<device::mojom::Geolocation> geolocation_;
+ mojo::Remote<device::mojom::GeolocationContext> geolocation_context_;
// Timer to enforce a maximum timeout before the |callback_| is called, even
// if not all asynchronous data has been loaded.
@@ -296,7 +297,7 @@ FingerprintDataLoader::FingerprintDataLoader(
if (gpu_data_manager_->GpuAccessAllowed(nullptr) &&
!gpu_data_manager_->IsEssentialGpuInfoAvailable()) {
gpu_observer_.Add(gpu_data_manager_);
- gpu_data_manager_->RequestCompleteGpuInfoIfNeeded();
+ OnGpuInfoUpdate();
}
#if BUILDFLAG(ENABLE_PLUGINS)
@@ -313,9 +314,10 @@ FingerprintDataLoader::FingerprintDataLoader(
// Load geolocation data.
DCHECK(connector);
- connector->BindInterface(device::mojom::kServiceName,
- mojo::MakeRequest(&geolocation_context_));
- geolocation_context_->BindGeolocation(mojo::MakeRequest(&geolocation_));
+ connector->Connect(device::mojom::kServiceName,
+ geolocation_context_.BindNewPipeAndPassReceiver());
+ geolocation_context_->BindGeolocation(
+ geolocation_.BindNewPipeAndPassReceiver());
geolocation_->SetHighAccuracy(false);
geolocation_->QueryNextPosition(
base::BindOnce(&FingerprintDataLoader::OnGotGeoposition,
@@ -431,7 +433,7 @@ void FingerprintDataLoader::FillFingerprint() {
Fingerprint::Metadata* metadata = fingerprint->mutable_metadata();
metadata->set_timestamp_ms(
- (base::Time::Now() - base::Time::UnixEpoch()).InMilliseconds());
+ (AutofillClock::Now() - base::Time::UnixEpoch()).InMilliseconds());
metadata->set_obfuscated_gaia_id(obfuscated_gaia_id_);
metadata->set_fingerprinter_version(kFingerprinterVersion);
diff --git a/chromium/components/autofill/content/browser/risk/fingerprint_browsertest.cc b/chromium/components/autofill/content/browser/risk/fingerprint_browsertest.cc
index 8cff02245f7..5ce5460c35e 100644
--- a/chromium/components/autofill/content/browser/risk/fingerprint_browsertest.cc
+++ b/chromium/components/autofill/content/browser/risk/fingerprint_browsertest.cc
@@ -13,6 +13,7 @@
#include "base/run_loop.h"
#include "build/build_config.h"
#include "components/autofill/content/browser/risk/proto/fingerprint.pb.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/browser/system_connector.h"
#include "content/public/common/screen_info.h"
@@ -211,7 +212,7 @@ IN_PROC_BROWSER_TEST_F(AutofillRiskFingerprintTest, GetFingerprint) {
base::RunLoop run_loop;
internal::GetFingerprintInternal(
kObfuscatedGaiaId, window_bounds_, content_bounds_, screen_info,
- "25.0.0.123", kCharset, kAcceptLanguages, base::Time::Now(), kLocale,
+ "25.0.0.123", kCharset, kAcceptLanguages, AutofillClock::Now(), kLocale,
kUserAgent,
base::TimeDelta::FromDays(1), // Ought to be longer than any test run.
base::Bind(&AutofillRiskFingerprintTest::GetFingerprintTestCallback,
diff --git a/chromium/components/autofill/content/common/mojom/autofill_agent.mojom b/chromium/components/autofill/content/common/mojom/autofill_agent.mojom
index 2a80baca5cc..a1d4dc65d85 100644
--- a/chromium/components/autofill/content/common/mojom/autofill_agent.mojom
+++ b/chromium/components/autofill/content/common/mojom/autofill_agent.mojom
@@ -36,8 +36,8 @@ interface AutofillAgent {
PreviewFieldWithValue(mojo_base.mojom.String16 value);
// Sets the currently selected node's corresponding accessibility node's
- // suggestion availability.
- SetSuggestionAvailability(bool available);
+ // autofill/autocomplete suggestion availability.
+ SetSuggestionAvailability(AutofillState type);
// Sets the currently selected node's value to be the given data list value.
AcceptDataListSuggestion(mojo_base.mojom.String16 value);
@@ -52,10 +52,6 @@ interface AutofillAgent {
PreviewPasswordSuggestion(mojo_base.mojom.String16 username,
mojo_base.mojom.String16 password);
- // Sent when a password form is initially detected and suggestions should be
- // shown. Used by the fill-on-select experiment.
- ShowInitialPasswordAccountSuggestions(PasswordFormFillData form_data);
-
// Configures the render to require, or not, a user gesture before notifying
// the autofill agent of a field change. The default is true. Bypassing the
// user gesture check should only used for Android Webview, which needs to
@@ -96,10 +92,13 @@ interface PasswordAutofillAgent {
// logging the decisions made about saving the password.
SetLoggingState(bool active);
- // Sent when Autofill manager gets the query response from the Autofill server
- // which contains information about username and password for some forms.
- // |predictions| maps forms to their username fields.
- AutofillUsernameAndPasswordDataReceived(FormsPredictionsMap predictions);
+ // Informs the renderer that the Touch To Fill sheet has been closed.
+ // Indicates whether the virtual keyboard should be shown instead.
+ TouchToFillClosed(bool show_virtual_keyboard);
+
+ // Annotate password related (username, password) DOM input elements with
+ // corresponding HTML attributes. It is used only for debugging.
+ AnnotateFieldsWithParsingResult(ParsingResult parsing_result);
};
// There is one instance of this interface per render frame in the render
diff --git a/chromium/components/autofill/content/common/mojom/autofill_driver.mojom b/chromium/components/autofill/content/common/mojom/autofill_driver.mojom
index b7fa28ae376..73e2536ca52 100644
--- a/chromium/components/autofill/content/common/mojom/autofill_driver.mojom
+++ b/chromium/components/autofill/content/common/mojom/autofill_driver.mojom
@@ -102,9 +102,12 @@ interface PasswordManagerDriver {
// save/update prompt anchored to the omnibox icon should be removed.
HideManualFallbackForSaving();
- // Notification that same-document navigation happened and at this moment we
- // have filled password form. We use this as a signal for successful login.
- SameDocumentNavigation(PasswordForm password_form);
+ // Notification that same-document navigation happened. We use this as a
+ // signal for successful login.
+ // TODO(crbug.com/949519): Rename this method to a more generic name since
+ // it's called in many scenarios other than SameDocumentNavigation such as
+ // FRAME_DETACHED.
+ SameDocumentNavigation(SubmissionIndicatorEvent submission_indication_event);
// Sends |log| to browser for displaying to the user. Only strings passed as
// an argument to methods overriding SavePasswordProgressLogger::SendLog may
diff --git a/chromium/components/autofill/content/renderer/BUILD.gn b/chromium/components/autofill/content/renderer/BUILD.gn
index 95d49af5ae5..f36cc9d156e 100644
--- a/chromium/components/autofill/content/renderer/BUILD.gn
+++ b/chromium/components/autofill/content/renderer/BUILD.gn
@@ -32,8 +32,6 @@ jumbo_static_library("renderer") {
"password_generation_agent.h",
"prefilled_values_detector.cc",
"prefilled_values_detector.h",
- "provisionally_saved_password_form.cc",
- "provisionally_saved_password_form.h",
"renderer_save_password_progress_logger.cc",
"renderer_save_password_progress_logger.h",
]
diff --git a/chromium/components/autofill/content/renderer/PRESUBMIT.py b/chromium/components/autofill/content/renderer/PRESUBMIT.py
index 30f2ba54021..f17ca91e903 100644
--- a/chromium/components/autofill/content/renderer/PRESUBMIT.py
+++ b/chromium/components/autofill/content/renderer/PRESUBMIT.py
@@ -22,9 +22,9 @@ def _CheckNoDirectPasswordCalls(input_api, output_api):
files.append(f)
if len(files):
- return [ output_api.PresubmitError(
- 'Do not call IsPasswordField() or FormControlType() directly but ' +
- 'use IsPasswordFieldForAutofill() and FormControlTypeForAutofill() ' +
+ return [ output_api.PresubmitPromptWarning(
+ 'Consider to not call IsPasswordField() or FormControlType() directly ' +
+ 'but use IsPasswordFieldForAutofill() and FormControlTypeForAutofill() ' +
'respectively. These declare text input fields as password fields ' +
'if they have been password fields in the past. This is relevant ' +
'for websites that allow to reveal passwords with a button that ' +
diff --git a/chromium/components/autofill/content/renderer/autofill_agent.cc b/chromium/components/autofill/content/renderer/autofill_agent.cc
index 5c479361950..e372068d96b 100644
--- a/chromium/components/autofill/content/renderer/autofill_agent.cc
+++ b/chromium/components/autofill/content/renderer/autofill_agent.cc
@@ -31,6 +31,7 @@
#include "components/autofill/core/common/autofill_data_validation.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_switches.h"
+#include "components/autofill/core/common/autofill_tick_clock.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_data_predictions.h"
@@ -48,6 +49,7 @@
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/platform/web_keyboard_event.h"
#include "third_party/blink/public/platform/web_url_request.h"
+#include "third_party/blink/public/web/web_ax_enums.h"
#include "third_party/blink/public/web/web_ax_object.h"
#include "third_party/blink/public/web/web_console_message.h"
#include "third_party/blink/public/web/web_document.h"
@@ -219,8 +221,7 @@ void AutofillAgent::DidChangeScrollOffsetImpl(
if (form_util::FindFormAndFieldForFormControlElement(element_, &form,
&field)) {
GetAutofillDriver()->TextFieldDidScroll(
- form, field,
- render_frame()->GetRenderView()->ElementBoundsInWindow(element_));
+ form, field, render_frame()->ElementBoundsInWindow(element_));
}
// Ignore subsequent scroll offset changes.
@@ -269,8 +270,7 @@ void AutofillAgent::FocusedElementChanged(const WebElement& element) {
if (form_util::FindFormAndFieldForFormControlElement(element_, &form,
&field)) {
GetAutofillDriver()->FocusOnFormField(
- form, field,
- render_frame()->GetRenderView()->ElementBoundsInWindow(element_));
+ form, field, render_frame()->ElementBoundsInWindow(element_));
}
}
@@ -351,9 +351,8 @@ void AutofillAgent::OnTextFieldDidChange(const WebInputElement& element) {
if (form_util::FindFormAndFieldForFormControlElement(element, &form,
&field)) {
GetAutofillDriver()->TextFieldDidChange(
- form, field,
- render_frame()->GetRenderView()->ElementBoundsInWindow(element),
- base::TimeTicks::Now());
+ form, field, render_frame()->ElementBoundsInWindow(element),
+ AutofillTickClock::NowTicks());
}
}
@@ -430,7 +429,7 @@ void AutofillAgent::TriggerRefillIfNeeded(const FormData& form) {
if (form_util::FindFormAndFieldForFormControlElement(element_, &updated_form,
&field) &&
(!element_.IsAutofilled() || !form.DynamicallySameFormAs(updated_form))) {
- base::TimeTicks forms_seen_timestamp = base::TimeTicks::Now();
+ base::TimeTicks forms_seen_timestamp = AutofillTickClock::NowTicks();
WebLocalFrame* frame = render_frame()->GetWebFrame();
std::vector<FormData> forms;
forms.push_back(updated_form);
@@ -460,7 +459,8 @@ void AutofillAgent::FillForm(int32_t id, const FormData& form) {
if (!element_.Form().IsNull())
UpdateLastInteractedForm(element_.Form());
- GetAutofillDriver()->DidFillAutofillFormData(form, base::TimeTicks::Now());
+ GetAutofillDriver()->DidFillAutofillFormData(form,
+ AutofillTickClock::NowTicks());
TriggerRefillIfNeeded(form);
}
@@ -528,14 +528,32 @@ void AutofillAgent::PreviewFieldWithValue(const base::string16& value) {
DoPreviewFieldWithValue(value, input_element);
}
-void AutofillAgent::SetSuggestionAvailability(bool available) {
+void AutofillAgent::SetSuggestionAvailability(
+ const mojom::AutofillState state) {
if (element_.IsNull())
return;
WebInputElement* input_element = ToWebInputElement(&element_);
- if (input_element)
- WebAXObject::FromWebNode(*input_element)
- .HandleAutofillStateChanged(available);
+ if (input_element) {
+ switch (state) {
+ case autofill::mojom::AutofillState::kAutofillAvailable:
+ WebAXObject::FromWebNode(*input_element)
+ .HandleAutofillStateChanged(
+ blink::WebAXAutofillState::kAutofillAvailable);
+ return;
+ case autofill::mojom::AutofillState::kAutocompleteAvailable:
+ WebAXObject::FromWebNode(*input_element)
+ .HandleAutofillStateChanged(
+ blink::WebAXAutofillState::kAutocompleteAvailable);
+ return;
+ case autofill::mojom::AutofillState::kNoSuggestions:
+ WebAXObject::FromWebNode(*input_element)
+ .HandleAutofillStateChanged(
+ blink::WebAXAutofillState::kNoSuggestions);
+ return;
+ }
+ NOTREACHED();
+ }
}
void AutofillAgent::AcceptDataListSuggestion(const base::string16& value) {
@@ -563,31 +581,6 @@ void AutofillAgent::PreviewPasswordSuggestion(const base::string16& username,
DCHECK(handled);
}
-void AutofillAgent::ShowInitialPasswordAccountSuggestions(
- const PasswordFormFillData& form_data) {
- std::vector<blink::WebInputElement> elements;
- std::unique_ptr<RendererSavePasswordProgressLogger> logger;
- if (password_autofill_agent_->logging_state_active()) {
- logger.reset(new RendererSavePasswordProgressLogger(
- GetPasswordManagerDriver().get()));
- logger->LogMessage(SavePasswordProgressLogger::
- STRING_ON_SHOW_INITIAL_PASSWORD_ACCOUNT_SUGGESTIONS);
- }
- password_autofill_agent_->GetFillableElementFromFormData(
- form_data, logger.get(), &elements);
-
- // If wait_for_username is true, we don't want to initially show form options
- // until the user types in a valid username.
- if (form_data.wait_for_username)
- return;
-
- ShowSuggestionsOptions options;
- options.autofill_on_empty_values = true;
- options.show_full_suggestion_list = true;
- for (auto element : elements)
- ShowSuggestions(element, options);
-}
-
bool AutofillAgent::CollectFormlessElements(FormData* output) {
if (render_frame() == nullptr || render_frame()->GetWebFrame() == nullptr)
return false;
@@ -785,8 +778,7 @@ void AutofillAgent::QueryAutofillSuggestions(
const WebInputElement* input_element = ToWebInputElement(&element);
if (input_element) {
// Find the datalist values and send them to the browser process.
- GetDataListSuggestions(*input_element,
- &data_list_values,
+ GetDataListSuggestions(*input_element, &data_list_values,
&data_list_labels);
TrimStringVectorForIPC(&data_list_values);
TrimStringVectorForIPC(&data_list_labels);
@@ -797,7 +789,7 @@ void AutofillAgent::QueryAutofillSuggestions(
GetAutofillDriver()->SetDataList(data_list_values, data_list_labels);
GetAutofillDriver()->QueryFormFieldAutofill(
autofill_query_id_, form, field,
- render_frame()->GetRenderView()->ElementBoundsInWindow(element_),
+ render_frame()->ElementBoundsInWindow(element_),
autoselect_first_suggestion);
}
@@ -821,7 +813,7 @@ void AutofillAgent::DoPreviewFieldWithValue(const base::string16& value,
void AutofillAgent::ProcessForms() {
// Record timestamp of when the forms are first seen. This is used to
// measure the overhead of the Autofill feature.
- base::TimeTicks forms_seen_timestamp = base::TimeTicks::Now();
+ base::TimeTicks forms_seen_timestamp = AutofillTickClock::NowTicks();
WebLocalFrame* frame = render_frame()->GetWebFrame();
std::vector<FormData> forms = form_cache_.ExtractNewForms();
@@ -845,11 +837,6 @@ void AutofillAgent::HidePopup() {
GetAutofillDriver()->HidePopup();
}
-bool AutofillAgent::IsUserGesture() const {
- return WebUserGestureIndicator::IsProcessingUserGesture(
- render_frame()->GetWebFrame());
-}
-
void AutofillAgent::DidAssociateFormControlsDynamically() {
// If the control flow is here than the document was at least loaded. The
// whole page doesn't have to be loaded.
@@ -883,8 +870,10 @@ void AutofillAgent::DidReceiveLeftMouseDownOrGestureTapInNode(
DCHECK(!node.IsNull());
focused_node_was_last_clicked_ = node.Focused();
- if (IsKeyboardAccessoryEnabled() || !focus_requires_scroll_)
+ if (IsTouchToFillEnabled() || IsKeyboardAccessoryEnabled() ||
+ !focus_requires_scroll_) {
HandleFocusChangeComplete();
+ }
}
void AutofillAgent::SelectControlDidChange(
@@ -914,12 +903,9 @@ void AutofillAgent::SelectFieldOptionsChanged(
bool AutofillAgent::ShouldSuppressKeyboard(
const WebFormControlElement& element) {
- // The keyboard should be suppressed if we can show the Touch To Fill UI.
- //
// Note: This is currently only implemented for passwords. Consider supporting
// other autofill types in the future as well.
- return IsTouchToFillEnabled() &&
- password_autofill_agent_->TryToShowTouchToFill(element);
+ return password_autofill_agent_->ShouldSuppressKeyboard();
}
void AutofillAgent::SelectWasUpdated(
@@ -946,6 +932,9 @@ void AutofillAgent::FormControlElementClicked(
if (!input_element && !form_util::IsTextAreaElement(element))
return;
+ if (IsTouchToFillEnabled())
+ password_autofill_agent_->TryToShowTouchToFill(element);
+
ShowSuggestionsOptions options;
options.autofill_on_empty_values = true;
// Show full suggestions when clicking on an already-focused form field.
@@ -1023,8 +1012,7 @@ void AutofillAgent::OnProvisionallySaveForm(
if (form_util::FindFormAndFieldForFormControlElement(element, &form,
&field)) {
GetAutofillDriver()->SelectControlDidChange(
- form, field,
- render_frame()->GetRenderView()->ElementBoundsInWindow(element));
+ form, field, render_frame()->ElementBoundsInWindow(element));
}
}
}
diff --git a/chromium/components/autofill/content/renderer/autofill_agent.h b/chromium/components/autofill/content/renderer/autofill_agent.h
index e552ea1c5a6..0ea12f07a06 100644
--- a/chromium/components/autofill/content/renderer/autofill_agent.h
+++ b/chromium/components/autofill/content/renderer/autofill_agent.h
@@ -40,8 +40,6 @@ class WebVector;
namespace autofill {
struct FormData;
-struct FormFieldData;
-struct PasswordFormFillData;
class PasswordAutofillAgent;
class PasswordGenerationAgent;
@@ -83,14 +81,12 @@ class AutofillAgent : public content::RenderFrameObserver,
void ClearPreviewedForm() override;
void FillFieldWithValue(const base::string16& value) override;
void PreviewFieldWithValue(const base::string16& value) override;
- void SetSuggestionAvailability(bool available) override;
+ void SetSuggestionAvailability(const mojom::AutofillState state) override;
void AcceptDataListSuggestion(const base::string16& value) override;
void FillPasswordSuggestion(const base::string16& username,
const base::string16& password) override;
void PreviewPasswordSuggestion(const base::string16& username,
const base::string16& password) override;
- void ShowInitialPasswordAccountSuggestions(
- const PasswordFormFillData& form_data) override;
void SetUserGestureRequired(bool required) override;
void SetSecureContextRequired(bool required) override;
void SetFocusRequiresScroll(bool require) override;
@@ -232,12 +228,6 @@ class AutofillAgent : public content::RenderFrameObserver,
// Sets the element value to reflect the selected |suggested_value|.
void DoAcceptDataListSuggestion(const base::string16& suggested_value);
- // Fills |form| and |field| with the FormData and FormField corresponding to
- // |node|. Returns true if the data was found; and false otherwise.
- bool FindFormAndFieldForNode(const blink::WebNode& node,
- FormData* form,
- FormFieldData* field) WARN_UNUSED_RESULT;
-
// Set |node| to display the given |value|.
void DoFillFieldWithValue(const base::string16& value,
blink::WebInputElement* node);
@@ -251,24 +241,9 @@ class AutofillAgent : public content::RenderFrameObserver,
// Notifies browser of new fillable forms in |render_frame|.
void ProcessForms();
- // Sends a message to the browser that the form is about to be submitted,
- // only if the particular message has not been previously submitted for the
- // form in the current frame.
- // Additionally, depending on |send_submitted_event| a message is sent to the
- // browser that the form was submitted.
- void SendFormEvents(const blink::WebFormElement& form,
- bool send_submitted_event);
-
// Hides any currently showing Autofill popup.
void HidePopup();
- // TODO(crbug.com/785524): Investigate why this method need to be mocked in
- // chrome_render_view_test.cc, this isn't called now, but this is no test
- // failed.
- // Returns true if the text field change is due to a user gesture. Can be
- // overriden in tests.
- virtual bool IsUserGesture() const;
-
// Attempt to get submitted FormData from last_interacted_form_ or
// provisionally_saved_form_, return true if |form| is set.
bool GetSubmittedForm(FormData* form);
diff --git a/chromium/components/autofill/content/renderer/form_autofill_util.cc b/chromium/components/autofill/content/renderer/form_autofill_util.cc
index c33dba2fb0d..3ded21383a4 100644
--- a/chromium/components/autofill/content/renderer/form_autofill_util.cc
+++ b/chromium/components/autofill/content/renderer/form_autofill_util.cc
@@ -1486,57 +1486,22 @@ bool ExtractFormData(const WebFormElement& form_element, FormData* data) {
data, nullptr);
}
-bool IsFormVisible(blink::WebLocalFrame* frame,
- const blink::WebFormElement& form_element,
- const GURL& canonical_action,
- const GURL& canonical_origin,
- const FormData& form_data) {
- const GURL frame_origin = GetCanonicalOriginForDocument(frame->GetDocument());
- blink::WebVector<WebFormElement> forms;
- frame->GetDocument().Forms(forms);
-
- // Omitting the action attribute would result in |canonical_origin| for
- // hierarchical schemes like http:, and in an empty URL for non-hierarchical
- // schemes like about: or data: etc.
- const bool action_is_empty = canonical_action.is_empty()
- || canonical_action == canonical_origin;
-
- // Since empty or unspecified action fields are automatically set to page URL,
- // action field for forms cannot be used for comparing (all forms with
- // empty/unspecified actions have the same value). If an action field is set
- // to the page URL, this method checks ALL fields of the form instead (using
- // FormData.SameFormAs). This is also true if the action was set to the page
- // URL on purpose.
- for (const WebFormElement& form : forms) {
- if (!AreFormContentsVisible(form))
- continue;
-
- // Try to match the WebFormElement reference first.
- if (!form_element.IsNull() && form == form_element) {
- return true; // Form still exists.
- }
-
- GURL iter_canonical_action = GetCanonicalActionForForm(form);
- bool form_action_is_empty = iter_canonical_action.is_empty() ||
- iter_canonical_action == frame_origin;
- if (action_is_empty != form_action_is_empty)
- continue;
-
- if (action_is_empty) { // Both actions are empty, compare all fields.
- FormData extracted_form_data;
- WebFormElementToFormData(form, WebFormControlElement(), nullptr,
- EXTRACT_NONE, &extracted_form_data, nullptr);
- if (form_data.SameFormAs(extracted_form_data)) {
- return true; // Form still exists.
- }
- } else { // Both actions are non-empty, compare actions only.
- if (canonical_action == iter_canonical_action) {
- return true; // Form still exists.
- }
- }
- }
+bool IsFormVisible(blink::WebLocalFrame* frame, uint32_t form_renderer_id) {
+ WebDocument doc = frame->GetDocument();
+ if (doc.IsNull())
+ return false;
+ WebFormElement form = FindFormByUniqueRendererId(doc, form_renderer_id);
+ return form.IsNull() ? false : AreFormContentsVisible(form);
+}
- return false;
+bool IsFormControlVisible(blink::WebLocalFrame* frame,
+ uint32_t field_renderer_id) {
+ WebDocument doc = frame->GetDocument();
+ if (doc.IsNull())
+ return false;
+ WebFormControlElement field =
+ FindFormControlElementsByUniqueRendererId(doc, field_renderer_id);
+ return field.IsNull() ? false : IsWebElementVisible(field);
}
bool IsSomeControlElementVisible(
@@ -1803,6 +1768,8 @@ bool WebFormElementToFormData(
form->unique_renderer_id = form_element.UniqueRendererFormId();
form->url = GetCanonicalOriginForDocument(frame->GetDocument());
form->action = GetCanonicalActionForForm(form_element);
+ form->is_action_empty =
+ form_element.Action().IsNull() || form_element.Action().IsEmpty();
if (IsAutofillFieldMetadataEnabled()) {
SCOPED_UMA_HISTOGRAM_TIMER(
"PasswordManager.ButtonTitlePerformance.HasFormTag");
@@ -2015,23 +1982,6 @@ void FillForm(const FormData& form, const WebFormControlElement& element) {
&FillFormField);
}
-void FillFormIncludingNonFocusableElements(const FormData& form_data,
- const WebFormElement& form_element) {
- if (form_element.IsNull()) {
- NOTREACHED();
- return;
- }
-
- FieldFilterMask filter_mask = static_cast<FieldFilterMask>(
- FILTER_DISABLED_ELEMENTS | FILTER_READONLY_ELEMENTS);
- ForEachMatchingFormField(form_element,
- WebInputElement(),
- form_data,
- filter_mask,
- true, /* force override */
- &FillFormField);
-}
-
void PreviewForm(const FormData& form, const WebFormControlElement& element) {
WebFormElement form_element = element.Form();
if (form_element.IsNull()) {
diff --git a/chromium/components/autofill/content/renderer/form_autofill_util.h b/chromium/components/autofill/content/renderer/form_autofill_util.h
index bb64fb7fe73..ac542f3d570 100644
--- a/chromium/components/autofill/content/renderer/form_autofill_util.h
+++ b/chromium/components/autofill/content/renderer/form_autofill_util.h
@@ -10,10 +10,13 @@
#include <set>
#include <vector>
+#include "base/i18n/rtl.h"
#include "base/macros.h"
#include "base/strings/string16.h"
#include "components/autofill/core/common/autofill_constants.h"
-#include "components/autofill/core/common/password_form_field_prediction_map.h"
+#include "components/autofill/core/common/form_data.h"
+#include "components/autofill/core/common/form_field_data.h"
+#include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/web_element_collection.h"
#include "ui/gfx/geometry/rect_f.h"
@@ -71,15 +74,14 @@ GURL StripAuthAndParams(const GURL& gurl);
// successful.
bool ExtractFormData(const blink::WebFormElement& form_element, FormData* data);
-// Helper function to check if there exist any visible form on |frame| which
-// equals |form_element|. If |form_element| is null, checks if forms action
-// equals |action|. Returns true if so. For forms with empty or unspecified
-// actions, all form data are used for comparison.
-bool IsFormVisible(blink::WebLocalFrame* frame,
- const blink::WebFormElement& form_element,
- const GURL& action,
- const GURL& origin,
- const FormData& form_data);
+// Helper function to check if a form with renderer id |form_renderer_id| exists
+// in |frame| and is visible.
+bool IsFormVisible(blink::WebLocalFrame* frame, uint32_t form_renderer_id);
+
+// Helper function to check if a field with renderer id |field_renderer_id|
+// exists in |frame| and is visible.
+bool IsFormControlVisible(blink::WebLocalFrame* frame,
+ uint32_t field_renderer_id);
// Returns true if at least one element from |control_elements| is visible.
bool IsSomeControlElementVisible(
@@ -220,12 +222,6 @@ bool FindFormAndFieldForFormControlElement(
void FillForm(const FormData& form,
const blink::WebFormControlElement& element);
-// Fills focusable and non-focusable form control elements within |form_element|
-// with field data from |form_data|.
-void FillFormIncludingNonFocusableElements(
- const FormData& form_data,
- const blink::WebFormElement& form_element);
-
// Previews the form represented by |form|. |element| is the input element that
// initiated the preview process.
void PreviewForm(const FormData& form,
diff --git a/chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc b/chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc
index 18df8232567..433bfc80b0a 100644
--- a/chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc
+++ b/chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc
@@ -7,6 +7,7 @@
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h"
#include "content/public/test/render_view_test.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_string.h"
@@ -20,18 +21,23 @@
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_select_element.h"
-using autofill::FormFieldData;
using autofill::mojom::ButtonTitleType;
using blink::WebDocument;
using blink::WebElement;
+using blink::WebElementCollection;
using blink::WebFormControlElement;
using blink::WebFormElement;
using blink::WebInputElement;
using blink::WebLocalFrame;
+using blink::WebNode;
using blink::WebSelectElement;
using blink::WebString;
using blink::WebVector;
+namespace autofill {
+namespace form_util {
+namespace {
+
struct AutofillFieldLabelSourceCase {
const char* html;
const FormFieldData::LabelSource label_source;
@@ -159,7 +165,7 @@ TEST_F(FormAutofillUtilsTest, FindChildTextTest) {
WebElement target = web_frame->GetDocument().GetElementById("target");
ASSERT_FALSE(target.IsNull());
EXPECT_EQ(base::UTF8ToUTF16(test_case.expected_label),
- autofill::form_util::FindChildText(target));
+ FindChildText(target));
}
}
@@ -176,14 +182,13 @@ TEST_F(FormAutofillUtilsTest, FindChildTextSkipElementTest) {
ASSERT_FALSE(target.IsNull());
WebVector<WebElement> web_to_skip =
web_frame->GetDocument().QuerySelectorAll("div[class='skip']");
- std::set<blink::WebNode> to_skip;
+ std::set<WebNode> to_skip;
for (size_t i = 0; i < web_to_skip.size(); ++i) {
to_skip.insert(web_to_skip[i]);
}
EXPECT_EQ(base::UTF8ToUTF16(test_case.expected_label),
- autofill::form_util::FindChildTextWithIgnoreListForTesting(
- target, to_skip));
+ FindChildTextWithIgnoreListForTesting(target, to_skip));
}
}
@@ -212,8 +217,8 @@ TEST_F(FormAutofillUtilsTest, InferLabelForElementTest) {
FormFieldData::LabelSource label_source =
FormFieldData::LabelSource::kUnknown;
base::string16 label;
- autofill::form_util::InferLabelForElementForTesting(form_target, stop_words,
- &label, &label_source);
+ InferLabelForElementForTesting(form_target, stop_words, &label,
+ &label_source);
EXPECT_EQ(base::UTF8ToUTF16(test_case.expected_label), label);
}
}
@@ -289,8 +294,7 @@ TEST_F(FormAutofillUtilsTest, InferButtonTitleForFormTest) {
const WebFormElement& form_target = target.ToConst<WebFormElement>();
ASSERT_FALSE(form_target.IsNull());
- autofill::ButtonTitleList actual =
- autofill::form_util::InferButtonTitlesForTesting(form_target);
+ autofill::ButtonTitleList actual = InferButtonTitlesForTesting(form_target);
autofill::ButtonTitleList expected = {
{base::UTF8ToUTF16("Clear field"),
ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE},
@@ -326,8 +330,7 @@ TEST_F(FormAutofillUtilsTest, InferButtonTitleForFormTest_TooLongTitle) {
const WebFormElement& form_target = target.ToConst<WebFormElement>();
ASSERT_FALSE(form_target.IsNull());
- autofill::ButtonTitleList actual =
- autofill::form_util::InferButtonTitlesForTesting(form_target);
+ autofill::ButtonTitleList actual = InferButtonTitlesForTesting(form_target);
int total_length = 0;
for (auto title : actual) {
@@ -357,8 +360,7 @@ TEST_F(FormAutofillUtilsTest, InferButtonTitle_Formless) {
const WebElement& body = web_frame->GetDocument().Body();
ASSERT_FALSE(body.IsNull());
- autofill::ButtonTitleList actual =
- autofill::form_util::InferButtonTitlesForTesting(body);
+ autofill::ButtonTitleList actual = InferButtonTitlesForTesting(body);
autofill::ButtonTitleList expected = {
{base::UTF8ToUTF16("Show password"),
ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE},
@@ -376,23 +378,22 @@ TEST_F(FormAutofillUtilsTest, IsEnabled) {
"<input type='password' id='name3'>"
"<input type='text' id='name4' disabled>");
- const std::vector<blink::WebElement> dummy_fieldsets;
+ const std::vector<WebElement> dummy_fieldsets;
WebLocalFrame* web_frame = GetMainFrame();
ASSERT_TRUE(web_frame);
- std::vector<blink::WebFormControlElement> control_elements;
- blink::WebElementCollection inputs =
+ std::vector<WebFormControlElement> control_elements;
+ WebElementCollection inputs =
web_frame->GetDocument().GetElementsByHTMLTagName("input");
- for (blink::WebElement element = inputs.FirstItem(); !element.IsNull();
+ for (WebElement element = inputs.FirstItem(); !element.IsNull();
element = inputs.NextItem()) {
- control_elements.push_back(element.To<blink::WebFormControlElement>());
+ control_elements.push_back(element.To<WebFormControlElement>());
}
autofill::FormData target;
- EXPECT_TRUE(
- autofill::form_util::UnownedPasswordFormElementsAndFieldSetsToFormData(
- dummy_fieldsets, control_elements, nullptr, web_frame->GetDocument(),
- nullptr, autofill::form_util::EXTRACT_NONE, &target, nullptr));
+ EXPECT_TRUE(UnownedPasswordFormElementsAndFieldSetsToFormData(
+ dummy_fieldsets, control_elements, nullptr, web_frame->GetDocument(),
+ nullptr, EXTRACT_NONE, &target, nullptr));
const struct {
const char* const name;
bool enabled;
@@ -415,23 +416,22 @@ TEST_F(FormAutofillUtilsTest, IsReadonly) {
"<input type='password' id='name3'>"
"<input type='text' id='name4' readonly>");
- const std::vector<blink::WebElement> dummy_fieldsets;
+ const std::vector<WebElement> dummy_fieldsets;
WebLocalFrame* web_frame = GetMainFrame();
ASSERT_TRUE(web_frame);
- std::vector<blink::WebFormControlElement> control_elements;
- blink::WebElementCollection inputs =
+ std::vector<WebFormControlElement> control_elements;
+ WebElementCollection inputs =
web_frame->GetDocument().GetElementsByHTMLTagName("input");
- for (blink::WebElement element = inputs.FirstItem(); !element.IsNull();
+ for (WebElement element = inputs.FirstItem(); !element.IsNull();
element = inputs.NextItem()) {
- control_elements.push_back(element.To<blink::WebFormControlElement>());
+ control_elements.push_back(element.To<WebFormControlElement>());
}
autofill::FormData target;
- EXPECT_TRUE(
- autofill::form_util::UnownedPasswordFormElementsAndFieldSetsToFormData(
- dummy_fieldsets, control_elements, nullptr, web_frame->GetDocument(),
- nullptr, autofill::form_util::EXTRACT_NONE, &target, nullptr));
+ EXPECT_TRUE(UnownedPasswordFormElementsAndFieldSetsToFormData(
+ dummy_fieldsets, control_elements, nullptr, web_frame->GetDocument(),
+ nullptr, EXTRACT_NONE, &target, nullptr));
const struct {
const char* const name;
bool readonly;
@@ -452,27 +452,26 @@ TEST_F(FormAutofillUtilsTest, IsFocusable) {
"<input type='text' id='name1' value='123'>"
"<input type='text' id='name2' style='display:none'>");
- const std::vector<blink::WebElement> dummy_fieldsets;
+ const std::vector<WebElement> dummy_fieldsets;
WebLocalFrame* web_frame = GetMainFrame();
ASSERT_TRUE(web_frame);
- std::vector<blink::WebFormControlElement> control_elements;
+ std::vector<WebFormControlElement> control_elements;
control_elements.push_back(web_frame->GetDocument()
.GetElementById("name1")
- .To<blink::WebFormControlElement>());
+ .To<WebFormControlElement>());
control_elements.push_back(web_frame->GetDocument()
.GetElementById("name2")
- .To<blink::WebFormControlElement>());
+ .To<WebFormControlElement>());
EXPECT_TRUE(autofill::form_util::IsWebElementVisible(control_elements[0]));
EXPECT_FALSE(autofill::form_util::IsWebElementVisible(control_elements[1]));
autofill::FormData target;
- EXPECT_TRUE(
- autofill::form_util::UnownedPasswordFormElementsAndFieldSetsToFormData(
- dummy_fieldsets, control_elements, nullptr, web_frame->GetDocument(),
- nullptr, autofill::form_util::EXTRACT_NONE, &target, nullptr));
+ EXPECT_TRUE(UnownedPasswordFormElementsAndFieldSetsToFormData(
+ dummy_fieldsets, control_elements, nullptr, web_frame->GetDocument(),
+ nullptr, EXTRACT_NONE, &target, nullptr));
ASSERT_EQ(2u, target.fields.size());
EXPECT_EQ(base::UTF8ToUTF16("name1"), target.fields[0].name);
EXPECT_TRUE(target.fields[0].is_focusable);
@@ -483,19 +482,17 @@ TEST_F(FormAutofillUtilsTest, IsFocusable) {
TEST_F(FormAutofillUtilsTest, FindFormByUniqueId) {
LoadHTML("<body><form id='form1'></form><form id='form2'></form></body>");
WebDocument doc = GetMainFrame()->GetDocument();
- blink::WebVector<WebFormElement> forms;
+ WebVector<WebFormElement> forms;
doc.Forms(forms);
for (const auto& form : forms) {
- EXPECT_EQ(form, autofill::form_util::FindFormByUniqueRendererId(
- doc, form.UniqueRendererFormId()));
+ EXPECT_EQ(form,
+ FindFormByUniqueRendererId(doc, form.UniqueRendererFormId()));
}
// Expect null form element for non-existing form id.
uint32_t non_existing_id = forms[0].UniqueRendererFormId() + 1000;
- EXPECT_TRUE(
- autofill::form_util::FindFormByUniqueRendererId(doc, non_existing_id)
- .IsNull());
+ EXPECT_TRUE(FindFormByUniqueRendererId(doc, non_existing_id).IsNull());
}
TEST_F(FormAutofillUtilsTest, FindFormControlByUniqueId) {
@@ -505,7 +502,6 @@ TEST_F(FormAutofillUtilsTest, FindFormControlByUniqueId) {
auto input1 = doc.GetElementById("i1").To<WebInputElement>();
auto input2 = doc.GetElementById("i2").To<WebInputElement>();
uint32_t non_existing_id = input2.UniqueRendererFormControlId() + 1000;
- using autofill::form_util::FindFormControlElementsByUniqueRendererId;
EXPECT_EQ(input1, FindFormControlElementsByUniqueRendererId(
doc, input1.UniqueRendererFormControlId()));
@@ -526,9 +522,7 @@ TEST_F(FormAutofillUtilsTest, FindFormControlElementsByUniqueIdNoForm) {
non_existing_id,
input1.UniqueRendererFormControlId()};
- auto elements =
- autofill::form_util::FindFormControlElementsByUniqueRendererId(
- doc, renderer_ids);
+ auto elements = FindFormControlElementsByUniqueRendererId(doc, renderer_ids);
ASSERT_EQ(3u, elements.size());
EXPECT_EQ(input3, elements[0]);
@@ -550,9 +544,8 @@ TEST_F(FormAutofillUtilsTest, FindFormControlElementsByUniqueIdWithForm) {
non_existing_id,
input1.UniqueRendererFormControlId()};
- auto elements =
- autofill::form_util::FindFormControlElementsByUniqueRendererId(
- doc, form.UniqueRendererFormId(), renderer_ids);
+ auto elements = FindFormControlElementsByUniqueRendererId(
+ doc, form.UniqueRendererFormId(), renderer_ids);
// |input3| is not in the form, so it shouldn't be returned.
ASSERT_EQ(3u, elements.size());
@@ -562,7 +555,7 @@ TEST_F(FormAutofillUtilsTest, FindFormControlElementsByUniqueIdWithForm) {
// Expect that no elements are retured for non existing form id.
uint32_t non_existing_form_id = form.UniqueRendererFormId() + 1000;
- elements = autofill::form_util::FindFormControlElementsByUniqueRendererId(
+ elements = FindFormControlElementsByUniqueRendererId(
doc, non_existing_form_id, renderer_ids);
ASSERT_EQ(3u, elements.size());
EXPECT_TRUE(elements[0].IsNull());
@@ -692,3 +685,61 @@ TEST_F(FormAutofillUtilsTest, GetAriaDescribedByInvalid) {
EXPECT_EQ(autofill::form_util::GetAriaDescription(doc, element),
base::UTF8ToUTF16(""));
}
+
+TEST_F(FormAutofillUtilsTest, IsFormVisible) {
+ LoadHTML("<body><form id='form1'><input id='i1'></form></body>");
+ WebDocument doc = GetMainFrame()->GetDocument();
+ auto form = doc.GetElementById("form1").To<WebFormElement>();
+ uint32_t form_id = form.UniqueRendererFormId();
+
+ EXPECT_TRUE(autofill::form_util::IsFormVisible(GetMainFrame(), form_id));
+
+ // Hide a form.
+ form.SetAttribute("style", "display:none");
+ EXPECT_FALSE(autofill::form_util::IsFormVisible(GetMainFrame(), form_id));
+}
+
+TEST_F(FormAutofillUtilsTest, IsFormControlVisible) {
+ LoadHTML("<body><input id='input1'></body>");
+ WebDocument doc = GetMainFrame()->GetDocument();
+ auto input = doc.GetElementById("input1").To<WebFormControlElement>();
+ uint32_t input_id = input.UniqueRendererFormControlId();
+
+ EXPECT_TRUE(IsFormControlVisible(GetMainFrame(), input_id));
+
+ // Hide a field.
+ input.SetAttribute("style", "display:none");
+ EXPECT_FALSE(autofill::form_util::IsFormVisible(GetMainFrame(), input_id));
+}
+
+TEST_F(FormAutofillUtilsTest, IsActionEmptyFalse) {
+ LoadHTML(
+ "<body><form id='form1' action='done.html'><input "
+ "id='i1'></form></body>");
+ WebDocument doc = GetMainFrame()->GetDocument();
+ auto web_form = doc.GetElementById("form1").To<WebFormElement>();
+
+ FormData form_data;
+ ASSERT_TRUE(WebFormElementToFormData(
+ web_form, WebFormControlElement(), nullptr /*field_data_manager*/,
+ EXTRACT_VALUE, &form_data, nullptr /* FormFieldData */));
+
+ EXPECT_FALSE(form_data.is_action_empty);
+}
+
+TEST_F(FormAutofillUtilsTest, IsActionEmptyTrue) {
+ LoadHTML("<body><form id='form1'><input id='i1'></form></body>");
+ WebDocument doc = GetMainFrame()->GetDocument();
+ auto web_form = doc.GetElementById("form1").To<WebFormElement>();
+
+ FormData form_data;
+ ASSERT_TRUE(WebFormElementToFormData(
+ web_form, WebFormControlElement(), nullptr /*field_data_manager*/,
+ EXTRACT_VALUE, &form_data, nullptr /* FormFieldData */));
+
+ EXPECT_TRUE(form_data.is_action_empty);
+}
+
+} // namespace
+} // namespace form_util
+} // namespace autofill
diff --git a/chromium/components/autofill/content/renderer/form_cache.cc b/chromium/components/autofill/content/renderer/form_cache.cc
index 0e67646e8b7..cb6edb14c4a 100644
--- a/chromium/components/autofill/content/renderer/form_cache.cc
+++ b/chromium/components/autofill/content/renderer/form_cache.cc
@@ -5,6 +5,7 @@
#include "components/autofill/content/renderer/form_cache.h"
#include <algorithm>
+#include <set>
#include <string>
#include <utility>
@@ -12,6 +13,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/stl_util.h"
+#include "base/strings/strcat.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
@@ -161,15 +163,16 @@ void LogDeprecationMessages(const WebFormControlElement& element) {
for (const char* str : deprecated) {
if (autocomplete_attribute.find(str) == std::string::npos)
continue;
- std::string msg = std::string("autocomplete='") + str +
- "' is deprecated and will soon be ignored. See http://goo.gl/YjeSsW";
+ std::string msg = base::StrCat(
+ {"autocomplete='", str,
+ "' is deprecated and will soon be ignored. See http://goo.gl/YjeSsW"});
WebConsoleMessage console_message = WebConsoleMessage(
blink::mojom::ConsoleMessageLevel::kWarning, WebString::FromASCII(msg));
element.GetDocument().GetFrame()->AddMessageToConsole(console_message);
}
}
-// Determines whether the form is interesting enough to send to the browser
+// Determines whether the form is interesting enough to be sent to the browser
// for further operations.
bool IsFormInteresting(const FormData& form, size_t num_editable_elements) {
if (form.fields.empty())
@@ -199,9 +202,7 @@ bool IsFormInteresting(const FormData& form, size_t num_editable_elements) {
} // namespace
FormCache::FormCache(WebLocalFrame* frame) : frame_(frame) {}
-
-FormCache::~FormCache() {
-}
+FormCache::~FormCache() = default;
std::vector<FormData> FormCache::ExtractNewForms() {
std::vector<FormData> forms;
@@ -214,6 +215,8 @@ std::vector<FormData> FormCache::ExtractNewForms() {
WebVector<WebFormElement> web_forms;
document.Forms(web_forms);
+ std::set<uint32_t> observed_unique_renderer_ids;
+
// Log an error message for deprecated attributes, but only the first time
// the form is parsed.
bool log_deprecation_messages = parsed_forms_.empty();
@@ -223,14 +226,12 @@ std::vector<FormData> FormCache::ExtractNewForms() {
form_util::EXTRACT_OPTIONS);
size_t num_fields_seen = 0;
- for (size_t i = 0; i < web_forms.size(); ++i) {
- const WebFormElement& form_element = web_forms[i];
-
+ for (const WebFormElement& form_element : web_forms) {
std::vector<WebFormControlElement> control_elements =
form_util::ExtractAutofillableElementsInForm(form_element);
+
size_t num_editable_elements =
ScanFormControlElements(control_elements, log_deprecation_messages);
-
if (num_editable_elements == 0)
continue;
@@ -240,9 +241,14 @@ std::vector<FormData> FormCache::ExtractNewForms() {
continue;
}
+ for (const auto& field : form.fields)
+ observed_unique_renderer_ids.insert(field.unique_renderer_id);
+
num_fields_seen += form.fields.size();
- if (num_fields_seen > form_util::kMaxParseableFields)
+ if (num_fields_seen > form_util::kMaxParseableFields) {
+ PruneInitialValueCaches(observed_unique_renderer_ids);
return forms;
+ }
if (!base::Contains(parsed_forms_, form) &&
IsFormInteresting(form, num_editable_elements)) {
@@ -267,22 +273,29 @@ std::vector<FormData> FormCache::ExtractNewForms() {
size_t num_editable_elements =
ScanFormControlElements(control_elements, log_deprecation_messages);
-
- if (num_editable_elements == 0)
+ if (num_editable_elements == 0) {
+ PruneInitialValueCaches(observed_unique_renderer_ids);
return forms;
+ }
FormData synthetic_form;
if (!UnownedCheckoutFormElementsAndFieldSetsToFormData(
fieldsets, control_elements, nullptr, document, extract_mask,
&synthetic_form, nullptr)) {
+ PruneInitialValueCaches(observed_unique_renderer_ids);
return forms;
}
+ for (const auto& field : synthetic_form.fields)
+ observed_unique_renderer_ids.insert(field.unique_renderer_id);
+
num_fields_seen += synthetic_form.fields.size();
- if (num_fields_seen > form_util::kMaxParseableFields)
+ if (num_fields_seen > form_util::kMaxParseableFields) {
+ PruneInitialValueCaches(observed_unique_renderer_ids);
return forms;
+ }
- if (!parsed_forms_.count(synthetic_form) &&
+ if (!base::Contains(parsed_forms_, synthetic_form) &&
IsFormInteresting(synthetic_form, num_editable_elements)) {
SaveInitialValues(control_elements);
forms.push_back(synthetic_form);
@@ -290,6 +303,8 @@ std::vector<FormData> FormCache::ExtractNewForms() {
parsed_forms_.erase(synthetic_form_);
synthetic_form_ = synthetic_form;
}
+
+ PruneInitialValueCaches(observed_unique_renderer_ids);
return forms;
}
@@ -302,16 +317,13 @@ void FormCache::Reset() {
bool FormCache::ClearSectionWithElement(const WebFormControlElement& element) {
WebFormElement form_element = element.Form();
- std::vector<WebFormControlElement> control_elements;
- if (form_element.IsNull()) {
- control_elements = form_util::GetUnownedAutofillableFormFieldElements(
- element.GetDocument().All(), nullptr);
- } else {
- control_elements =
- form_util::ExtractAutofillableElementsInForm(form_element);
- }
- for (size_t i = 0; i < control_elements.size(); ++i) {
- WebFormControlElement control_element = control_elements[i];
+ std::vector<WebFormControlElement> control_elements =
+ form_element.IsNull()
+ ? form_util::GetUnownedAutofillableFormFieldElements(
+ element.GetDocument().All(), nullptr)
+ : form_util::ExtractAutofillableElementsInForm(form_element);
+
+ for (WebFormControlElement& control_element : control_elements) {
// Don't modify the value of disabled fields.
if (!control_element.IsEnabled())
continue;
@@ -341,8 +353,8 @@ bool FormCache::ClearSectionWithElement(const WebFormControlElement& element) {
} else if (form_util::IsSelectElement(control_element)) {
WebSelectElement select_element = control_element.To<WebSelectElement>();
- std::map<const WebSelectElement, base::string16>::const_iterator
- initial_value_iter = initial_select_values_.find(select_element);
+ auto initial_value_iter = initial_select_values_.find(
+ select_element.UniqueRendererFormControlId());
if (initial_value_iter != initial_select_values_.end() &&
select_element.Value().Utf16() != initial_value_iter->second) {
select_element.SetAutofillValue(
@@ -351,11 +363,11 @@ bool FormCache::ClearSectionWithElement(const WebFormControlElement& element) {
} else {
WebInputElement input_element = control_element.To<WebInputElement>();
DCHECK(form_util::IsCheckableElement(&input_element));
- std::map<const WebInputElement, bool>::const_iterator it =
- initial_checked_state_.find(input_element);
- if (it != initial_checked_state_.end() &&
- input_element.IsChecked() != it->second) {
- input_element.SetChecked(it->second, true);
+ auto checkable_element_it = initial_checked_state_.find(
+ input_element.UniqueRendererFormControlId());
+ if (checkable_element_it != initial_checked_state_.end() &&
+ input_element.IsChecked() != checkable_element_it->second) {
+ input_element.SetChecked(checkable_element_it->second, true);
}
}
}
@@ -381,12 +393,10 @@ bool FormCache::ShowPredictions(const FormDataPredictions& form,
if (!found_synthetic_form) {
// Find the real form by searching through the WebDocuments.
bool found_form = false;
- WebFormElement form_element;
WebVector<WebFormElement> web_forms;
frame_->GetDocument().Forms(web_forms);
- for (size_t i = 0; i < web_forms.size(); ++i) {
- form_element = web_forms[i];
+ for (const WebFormElement& form_element : web_forms) {
// To match two forms, we look for the form's name and the number of
// fields on that form. (Form names may not be unique.)
// Note: WebString() == WebString(string16()) does not evaluate to |true|
@@ -445,32 +455,15 @@ bool FormCache::ShowPredictions(const FormDataPredictions& form,
const base::string16 truncated_label = field_data.label.substr(
0, std::min(field_data.label.length(), kMaxLabelSize));
- // A rough estimate of the maximum title size is:
- // 8 field titles at <17 chars each
- // + 7 values at <40 chars each
- // + 1 truncated label at <kMaxLabelSize;
- // = 516 chars, rounded up to the next multiple of 64 = 576
- // A particularly large parseable name could blow through this and cause
- // another allocation, but that's OK.
- constexpr size_t kMaxTitleSize = 576;
- std::string title;
- title.reserve(kMaxTitleSize);
- title += "overall type: ";
- title += field.overall_type;
- title += "\nserver type: ";
- title += field.server_type;
- title += "\nheuristic type: ";
- title += field.heuristic_type;
- title += "\nlabel: ";
- title += base::UTF16ToUTF8(truncated_label);
- title += "\nparseable name: ";
- title += field.parseable_name;
- title += "\nsection: ";
- title += field.section;
- title += "\nfield signature: ";
- title += field.signature;
- title += "\nform signature: ";
- title += form.signature;
+ std::string title =
+ base::StrCat({"overall type: ", field.overall_type, //
+ "\nserver type: ", field.server_type, //
+ "\nheuristic type: ", field.heuristic_type, //
+ "\nlabel: ", base::UTF16ToUTF8(truncated_label), //
+ "\nparseable name: ", field.parseable_name, //
+ "\nsection: ", field.section, //
+ "\nfield signature: ", field.signature, //
+ "\nform signature: ", form.signature});
// Set this debug string to the title so that a developer can easily debug
// by hovering the mouse over the input field.
@@ -494,9 +487,7 @@ size_t FormCache::ScanFormControlElements(
const std::vector<WebFormControlElement>& control_elements,
bool log_deprecation_messages) {
size_t num_editable_elements = 0;
- for (size_t i = 0; i < control_elements.size(); ++i) {
- const WebFormControlElement& element = control_elements[i];
-
+ for (const WebFormControlElement& element : control_elements) {
if (log_deprecation_messages)
LogDeprecationMessages(element);
@@ -521,12 +512,14 @@ void FormCache::SaveInitialValues(
const WebSelectElement select_element =
element.ToConst<WebSelectElement>();
initial_select_values_.insert(
- std::make_pair(select_element, select_element.Value().Utf16()));
+ std::make_pair(select_element.UniqueRendererFormControlId(),
+ select_element.Value().Utf16()));
} else {
const WebInputElement* input_element = ToWebInputElement(&element);
if (form_util::IsCheckableElement(input_element)) {
initial_checked_state_.insert(
- std::make_pair(*input_element, input_element->IsChecked()));
+ std::make_pair(input_element->UniqueRendererFormControlId(),
+ input_element->IsChecked()));
}
}
}
@@ -564,4 +557,25 @@ bool FormCache::ShouldShowAutocompleteConsoleWarnings(
return false;
}
+void FormCache::PruneInitialValueCaches(
+ const std::set<uint32_t> ids_to_retain) {
+ // Prune initial_select_values_.
+ for (auto iter = initial_select_values_.begin();
+ iter != initial_select_values_.end();) {
+ if (!base::Contains(ids_to_retain, iter->first))
+ iter = initial_select_values_.erase(iter);
+ else
+ ++iter;
+ }
+
+ // Prune initial_checked_state_.
+ for (auto iter = initial_checked_state_.begin();
+ iter != initial_checked_state_.end();) {
+ if (!base::Contains(ids_to_retain, iter->first))
+ iter = initial_checked_state_.erase(iter);
+ else
+ ++iter;
+ }
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/content/renderer/form_cache.h b/chromium/components/autofill/content/renderer/form_cache.h
index c4db022d8cb..9cc7da62142 100644
--- a/chromium/components/autofill/content/renderer/form_cache.h
+++ b/chromium/components/autofill/content/renderer/form_cache.h
@@ -18,13 +18,12 @@
namespace blink {
class WebFormControlElement;
-class WebInputElement;
class WebLocalFrame;
-class WebSelectElement;
}
namespace autofill {
+struct FormData;
struct FormDataPredictions;
// Manages the forms in a single RenderFrame.
@@ -34,7 +33,8 @@ class FormCache {
~FormCache();
// Scans the DOM in |frame_| extracting and storing forms that have not been
- // seen before. Returns the extracted forms.
+ // seen before. Returns the extracted forms. Note that modified forms are
+ // considered new forms.
std::vector<FormData> ExtractNewForms();
// Resets the forms.
@@ -57,10 +57,10 @@ class FormCache {
ShouldShowAutocompleteConsoleWarnings_Enabled);
FRIEND_TEST_ALL_PREFIXES(FormCacheTest,
ShouldShowAutocompleteConsoleWarnings_Disabled);
+ FRIEND_TEST_ALL_PREFIXES(FormCacheBrowserTest, FreeDataOnElementRemoval);
// Scans |control_elements| and returns the number of editable elements.
- // Also remembers the initial <select> and <input> element states, and
- // logs warning messages for deprecated attribute if
+ // Also logs warning messages for deprecated attribute if
// |log_deprecation_messages| is set.
size_t ScanFormControlElements(
const std::vector<blink::WebFormControlElement>& control_elements,
@@ -78,6 +78,10 @@ class FormCache {
const std::string& predicted_autocomplete,
const std::string& actual_autocomplete);
+ // Clears all entries from |initial_select_values_| and
+ // |initial_checked_state_| whose keys not contained in |ids_to_retain|.
+ void PruneInitialValueCaches(const std::set<uint32_t> ids_to_retain);
+
// The frame this FormCache is associated with. Weak reference.
blink::WebLocalFrame* frame_;
@@ -88,12 +92,13 @@ class FormCache {
// form owner.
FormData synthetic_form_;
- // The cached initial values for <select> elements.
- std::map<const blink::WebSelectElement, base::string16>
- initial_select_values_;
+ // The cached initial values for <select> elements. Entries are keyed by
+ // unique_renderer_form_control_id of the WebSelectElements.
+ std::map<uint32_t, base::string16> initial_select_values_;
- // The cached initial values for checkable <input> elements.
- std::map<const blink::WebInputElement, bool> initial_checked_state_;
+ // The cached initial values for checkable <input> elements. Entries are
+ // keyed by the unique_renderer_form_control_id of the WebInputElements.
+ std::map<uint32_t, bool> initial_checked_state_;
DISALLOW_COPY_AND_ASSIGN(FormCache);
};
diff --git a/chromium/components/autofill/content/renderer/form_cache_browsertest.cc b/chromium/components/autofill/content/renderer/form_cache_browsertest.cc
new file mode 100644
index 00000000000..f55fadb394e
--- /dev/null
+++ b/chromium/components/autofill/content/renderer/form_cache_browsertest.cc
@@ -0,0 +1,194 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/content/renderer/form_cache.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/content/renderer/form_autofill_util.h"
+#include "components/autofill/core/common/form_field_data.h"
+#include "content/public/test/render_view_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/web/web_document.h"
+#include "third_party/blink/public/web/web_input_element.h"
+#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_select_element.h"
+
+using base::ASCIIToUTF16;
+using blink::WebDocument;
+using blink::WebElement;
+using blink::WebInputElement;
+using blink::WebSelectElement;
+using blink::WebString;
+
+namespace autofill {
+
+const FormData* GetFormByName(const std::vector<FormData>& forms,
+ base::StringPiece name) {
+ for (const FormData& form : forms) {
+ if (form.name == ASCIIToUTF16(name))
+ return &form;
+ }
+ return nullptr;
+}
+
+class FormCacheBrowserTest : public content::RenderViewTest {
+ public:
+ FormCacheBrowserTest() = default;
+ ~FormCacheBrowserTest() override = default;
+};
+
+TEST_F(FormCacheBrowserTest, ExtractForms) {
+ LoadHTML(R"(
+ <form id="form1">
+ <input type="text" name="foo1">
+ <input type="text" name="foo2">
+ <input type="text" name="foo3">
+ </form>
+ <input type="text" name="unowned_element">
+ )");
+
+ FormCache form_cache(GetMainFrame());
+ std::vector<FormData> forms = form_cache.ExtractNewForms();
+
+ const FormData* form1 = GetFormByName(forms, "form1");
+ ASSERT_TRUE(form1);
+ EXPECT_EQ(3u, form1->fields.size());
+
+ const FormData* unowned_form = GetFormByName(forms, "");
+ ASSERT_TRUE(unowned_form);
+ EXPECT_EQ(1u, unowned_form->fields.size());
+}
+
+TEST_F(FormCacheBrowserTest, ExtractFormsTwice) {
+ LoadHTML(R"(
+ <form id="form1">
+ <input type="text" name="foo1">
+ <input type="text" name="foo2">
+ <input type="text" name="foo3">
+ </form>
+ <input type="text" name="unowned_element">
+ )");
+
+ FormCache form_cache(GetMainFrame());
+ std::vector<FormData> forms = form_cache.ExtractNewForms();
+
+ forms = form_cache.ExtractNewForms();
+ // As nothing has changed, there are no new forms and |forms| should be empty.
+ EXPECT_TRUE(forms.empty());
+}
+
+TEST_F(FormCacheBrowserTest, ExtractFormsAfterModification) {
+ LoadHTML(R"(
+ <form id="form1">
+ <input type="text" name="foo1">
+ <input type="text" name="foo2">
+ <input type="text" name="foo3">
+ </form>
+ <input type="text" name="unowned_element">
+ )");
+
+ FormCache form_cache(GetMainFrame());
+ std::vector<FormData> forms = form_cache.ExtractNewForms();
+
+ // Append an input element to the form and to the list of unowned inputs.
+ ExecuteJavaScriptForTests(R"(
+ var new_input_1 = document.createElement("input");
+ new_input_1.setAttribute("type", "text");
+ new_input_1.setAttribute("name", "foo4");
+
+ var form1 = document.getElementById("form1");
+ form1.appendChild(new_input_1);
+
+ var new_input_2 = document.createElement("input");
+ new_input_2.setAttribute("type", "text");
+ new_input_2.setAttribute("name", "unowned_element_2");
+ document.body.appendChild(new_input_2);
+ )");
+
+ forms = form_cache.ExtractNewForms();
+
+ const FormData* form1 = GetFormByName(forms, "form1");
+ ASSERT_TRUE(form1);
+ EXPECT_EQ(4u, form1->fields.size());
+
+ const FormData* unowned_form = GetFormByName(forms, "");
+ ASSERT_TRUE(unowned_form);
+ EXPECT_EQ(2u, unowned_form->fields.size());
+}
+
+TEST_F(FormCacheBrowserTest, FillAndClear) {
+ LoadHTML(R"(
+ <input type="text" name="text" id="text">
+ <input type="checkbox" checked name="checkbox" id="checkbox">
+ <select name="select" id="select">
+ <option value="first">first</option>
+ <option value="second" selected>second</option>
+ </select>
+ )");
+
+ FormCache form_cache(GetMainFrame());
+ std::vector<FormData> forms = form_cache.ExtractNewForms();
+
+ ASSERT_EQ(1u, forms.size());
+ FormData values_to_fill = forms[0];
+ values_to_fill.fields[0].value = ASCIIToUTF16("test");
+ values_to_fill.fields[0].is_autofilled = true;
+ values_to_fill.fields[1].check_status =
+ FormFieldData::CheckStatus::kCheckableButUnchecked;
+ values_to_fill.fields[1].is_autofilled = true;
+ values_to_fill.fields[2].value = ASCIIToUTF16("first");
+ values_to_fill.fields[2].is_autofilled = true;
+
+ WebDocument doc = GetMainFrame()->GetDocument();
+ auto text = doc.GetElementById("text").To<WebInputElement>();
+ auto checkbox = doc.GetElementById("checkbox").To<WebInputElement>();
+ auto select_element = doc.GetElementById("select").To<WebSelectElement>();
+
+ form_util::FillForm(values_to_fill, text);
+
+ EXPECT_EQ("test", text.Value().Ascii());
+ EXPECT_FALSE(checkbox.IsChecked());
+ EXPECT_EQ("first", select_element.Value().Ascii());
+
+ // Validate that clearing works, in particular that the previous values
+ // were saved correctly.
+ form_cache.ClearSectionWithElement(text);
+
+ EXPECT_EQ("", text.Value().Ascii());
+ EXPECT_TRUE(checkbox.IsChecked());
+ EXPECT_EQ("second", select_element.Value().Ascii());
+}
+
+TEST_F(FormCacheBrowserTest, FreeDataOnElementRemoval) {
+ LoadHTML(R"(
+ <div id="container">
+ <input type="text" name="text" id="text">
+ <input type="checkbox" checked name="checkbox" id="checkbox">
+ <select name="select" id="select">
+ <option value="first">first</option>
+ <option value="second" selected>second</option>
+ </select>
+ </div>
+ )");
+
+ FormCache form_cache(GetMainFrame());
+ form_cache.ExtractNewForms();
+
+ EXPECT_EQ(1u, form_cache.initial_select_values_.size());
+ EXPECT_EQ(1u, form_cache.initial_checked_state_.size());
+
+ ExecuteJavaScriptForTests(R"(
+ const container = document.getElementById('container');
+ while (container.childElementCount > 0) {
+ container.removeChild(container.children.item(0));
+ }
+ )");
+
+ std::vector<FormData> forms = form_cache.ExtractNewForms();
+ EXPECT_EQ(0u, forms.size());
+ EXPECT_EQ(0u, form_cache.initial_select_values_.size());
+ EXPECT_EQ(0u, form_cache.initial_checked_state_.size());
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/content/renderer/password_autofill_agent.cc b/chromium/components/autofill/content/renderer/password_autofill_agent.cc
index 2a5bc31ad6a..030c74d3ddb 100644
--- a/chromium/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/chromium/components/autofill/content/renderer/password_autofill_agent.cc
@@ -14,6 +14,7 @@
#include "base/bind.h"
#include "base/i18n/case_conversion.h"
+#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/numerics/safe_conversions.h"
@@ -29,6 +30,7 @@
#include "components/autofill/content/renderer/prefilled_values_detector.h"
#include "components/autofill/content/renderer/renderer_save_password_progress_logger.h"
#include "components/autofill/core/common/autofill_constants.h"
+#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/mojom/autofill_types.mojom.h"
@@ -72,6 +74,10 @@ using blink::WebView;
namespace autofill {
+using form_util::FindFormControlElementsByUniqueRendererId;
+using form_util::IsFormControlVisible;
+using form_util::IsFormVisible;
+
using mojom::FocusedFieldType;
using mojom::SubmissionIndicatorEvent;
using mojom::SubmissionSource;
@@ -81,9 +87,6 @@ namespace {
// The size above which we stop triggering autocomplete.
const size_t kMaximumTextSizeForAutocomplete = 1000;
-const char kDummyUsernameField[] = "anonymous_username";
-const char kDummyPasswordField[] = "anonymous_password";
-
// Names of HTML attributes to show form and field signatures for debugging.
const char kDebugAttributeForFormSignature[] = "form_signature";
const char kDebugAttributeForFieldSignature[] = "field_signature";
@@ -99,198 +102,6 @@ typedef SavePasswordProgressLogger Logger;
typedef std::vector<FormInputElementMap> FormElementsList;
-bool FillDataContainsFillableUsername(const PasswordFormFillData& fill_data) {
- return !fill_data.username_field.name.empty() &&
- (!fill_data.additional_logins.empty() ||
- !fill_data.username_field.value.empty());
-}
-
-// Returns true if password form has username and password fields with either
-// same or no name and id attributes supplied.
-bool DoesFormContainAmbiguousOrEmptyNames(
- const PasswordFormFillData& fill_data) {
- return (fill_data.username_field.name == fill_data.password_field.name) ||
- (fill_data.password_field.name ==
- base::ASCIIToUTF16(kDummyPasswordField) &&
- (!FillDataContainsFillableUsername(fill_data) ||
- fill_data.username_field.name ==
- base::ASCIIToUTF16(kDummyUsernameField)));
-}
-
-bool IsFieldPasswordField(const FormFieldData& field) {
- return (field.form_control_type == "password");
-}
-
-// Returns true if any password field within |control_elements| is supplied with
-// either |autocomplete='current-password'| or |autocomplete='new-password'|
-// attribute.
-bool HasPasswordWithAutocompleteAttribute(
- const std::vector<WebFormControlElement>& control_elements) {
- for (const WebFormControlElement& control_element : control_elements) {
- if (!control_element.HasHTMLTagName("input"))
- continue;
-
- const WebInputElement input_element =
- control_element.ToConst<WebInputElement>();
- const AutocompleteFlag flag = AutocompleteFlagForElement(input_element);
- if (input_element.IsPasswordFieldForAutofill() &&
- (flag == AutocompleteFlag::CURRENT_PASSWORD ||
- flag == AutocompleteFlag::NEW_PASSWORD)) {
- return true;
- }
- }
-
- return false;
-}
-
-// Returns the |field|'s autofillable name. If |ambiguous_or_empty_names| is set
-// to true returns a dummy name instead.
-base::string16 FieldName(const FormFieldData& field,
- bool ambiguous_or_empty_names) {
- return ambiguous_or_empty_names
- ? (IsFieldPasswordField(field)
- ? base::ASCIIToUTF16(kDummyPasswordField)
- : base::ASCIIToUTF16(kDummyUsernameField))
- : field.name;
-}
-
-bool IsUnownedPasswordFormVisible(const WebInputElement& input_element) {
- return !input_element.IsNull() &&
- form_util::IsWebElementVisible(input_element);
-}
-
-// Utility function to find the unique entry of |control_elements| for the
-// specified input |field|. On successful find, adds it to |result| and returns
-// |true|. Otherwise clears the references from each |HTMLInputElement| from
-// |result| and returns |false|.
-bool FindFormInputElement(
- const std::vector<WebFormControlElement>& control_elements,
- const FormFieldData& field,
- bool ambiguous_or_empty_names,
- FormInputElementMap* result) {
- // Match the first input element, if any.
- bool found_input = false;
- bool is_password_field = IsFieldPasswordField(field);
- bool does_password_field_has_ambigous_or_empty_name =
- ambiguous_or_empty_names && is_password_field;
- bool ambiguous_and_multiple_password_fields_with_autocomplete =
- does_password_field_has_ambigous_or_empty_name &&
- HasPasswordWithAutocompleteAttribute(control_elements);
- base::string16 field_name = FieldName(field, ambiguous_or_empty_names);
- for (const WebFormControlElement& control_element : control_elements) {
- if (!ambiguous_or_empty_names &&
- control_element.NameForAutofill().Utf16() != field_name) {
- continue;
- }
-
- if (!control_element.HasHTMLTagName("input"))
- continue;
-
- // Only fill saved passwords into password fields and usernames into text
- // fields.
- const WebInputElement input_element =
- control_element.ToConst<WebInputElement>();
- if (!input_element.IsTextField() ||
- input_element.IsPasswordFieldForAutofill() != is_password_field)
- continue;
-
- // For change password form with ambiguous or empty names keep only the
- // first password field having |autocomplete='current-password'| attribute
- // set. Also make sure we avoid keeping password fields having
- // |autocomplete='new-password'| attribute set.
- if (ambiguous_and_multiple_password_fields_with_autocomplete &&
- AutocompleteFlagForElement(input_element) !=
- AutocompleteFlag::CURRENT_PASSWORD) {
- continue;
- }
-
- // Check for a non-unique match.
- if (found_input) {
- // For change password form keep only the first password field entry.
- if (does_password_field_has_ambigous_or_empty_name) {
- if (!form_util::IsWebElementVisible((*result)[field_name])) {
- // If a previously chosen field was invisible then take the current
- // one.
- (*result)[field_name] = input_element;
- }
- continue;
- }
-
- found_input = false;
- break;
- }
-
- (*result)[field_name] = input_element;
- found_input = true;
- }
-
- // A required element was not found. This is not the right form.
- // Make sure no input elements from a partially matched form in this
- // iteration remain in the result set.
- // Note: clear will remove a reference from each InputElement.
- if (!found_input) {
- result->clear();
- return false;
- }
-
- return true;
-}
-
-// Helper to search through |control_elements| for the specified input elements
-// in |data|, and add results to |result|.
-bool FindFormInputElements(
- const std::vector<WebFormControlElement>& control_elements,
- const PasswordFormFillData& data,
- bool ambiguous_or_empty_names,
- FormInputElementMap* result) {
- return FindFormInputElement(control_elements, data.password_field,
- ambiguous_or_empty_names, result) &&
- (!FillDataContainsFillableUsername(data) ||
- FindFormInputElement(control_elements, data.username_field,
- ambiguous_or_empty_names, result));
-}
-
-// Helper to locate form elements identified by |data|.
-void FindFormElements(content::RenderFrame* render_frame,
- const PasswordFormFillData& data,
- bool ambiguous_or_empty_names,
- FormElementsList* results) {
- DCHECK(results);
-
- WebDocument doc = render_frame->GetWebFrame()->GetDocument();
-
- if (GetSignOnRealm(data.origin) !=
- GetSignOnRealm(form_util::GetCanonicalOriginForDocument(doc)))
- return;
-
- WebVector<WebFormElement> forms;
- doc.Forms(forms);
-
- for (const WebFormElement& form : forms) {
- // Action URL must match.
- if (data.action != form_util::GetCanonicalActionForForm(form))
- continue;
-
- std::vector<WebFormControlElement> control_elements =
- form_util::ExtractAutofillableElementsInForm(form);
- FormInputElementMap cur_map;
- if (FindFormInputElements(control_elements, data, ambiguous_or_empty_names,
- &cur_map))
- results->push_back(cur_map);
- }
- // If the element to be filled are not in a <form> element, the "action" and
- // origin should be the same.
- if (data.action != data.origin)
- return;
-
- std::vector<WebFormControlElement> control_elements =
- form_util::GetUnownedAutofillableFormFieldElements(doc.All(), nullptr);
- FormInputElementMap unowned_elements_map;
- if (FindFormInputElements(control_elements, data, ambiguous_or_empty_names,
- &unowned_elements_map))
- results->push_back(unowned_elements_map);
-}
-
bool IsElementEditable(const WebInputElement& element) {
return element.IsEnabled() && !element.IsReadOnly();
}
@@ -434,32 +245,11 @@ WebString GetFormSignatureAsWebString(const PasswordForm& password_form) {
base::NumberToString(CalculateFormSignature(password_form.form_data)));
}
-// Add parser annotations saved in |password_form| to |element|.
-void AddParserAnnotations(PasswordForm* password_form,
- blink::WebFormControlElement* element) {
- base::string16 element_name = element->NameForAutofill().Utf16();
- std::string attribute_value;
- if (password_form->username_element == element_name) {
- attribute_value = "username_element";
- } else if (password_form->password_element == element_name) {
- attribute_value = "password_element";
- } else if (password_form->new_password_element == element_name) {
- attribute_value = "new_password_element";
- } else if (password_form->confirmation_password_element == element_name) {
- attribute_value = "confirmation_password_element";
- }
- element->SetAttribute(
- blink::WebString::FromASCII(kDebugAttributeForParserAnnotations),
- attribute_value.empty() ? blink::WebString()
- : blink::WebString::FromASCII(attribute_value));
-}
-
// Annotate |fields| with field signatures and form signature as HTML
// attributes.
void AnnotateFieldsWithSignatures(
std::vector<blink::WebFormControlElement>* fields,
- const blink::WebString& form_signature,
- PasswordForm* password_form) {
+ const blink::WebString& form_signature) {
for (blink::WebFormControlElement& control_element : *fields) {
FieldSignature field_signature = CalculateFieldSignatureByNameAndType(
control_element.NameForAutofill().Utf16(),
@@ -470,8 +260,6 @@ void AnnotateFieldsWithSignatures(
control_element.SetAttribute(
blink::WebString::FromASCII(kDebugAttributeForFormSignature),
form_signature);
- if (password_form)
- AddParserAnnotations(password_form, &control_element);
}
}
@@ -481,7 +269,9 @@ void AnnotateFormsAndFieldsWithSignatures(WebLocalFrame* frame,
WebVector<WebFormElement>* forms) {
for (WebFormElement& form : *forms) {
std::unique_ptr<PasswordForm> password_form(
- CreatePasswordFormFromWebForm(form, nullptr, nullptr, nullptr));
+ CreateSimplifiedPasswordFormFromWebForm(
+ form, /*field_data_manager=*/nullptr,
+ /*username_detector_cache=*/nullptr));
WebString form_signature;
if (password_form) {
form_signature = GetFormSignatureAsWebString(*password_form);
@@ -490,21 +280,20 @@ void AnnotateFormsAndFieldsWithSignatures(WebLocalFrame* frame,
}
std::vector<WebFormControlElement> form_fields =
form_util::ExtractAutofillableElementsInForm(form);
- AnnotateFieldsWithSignatures(&form_fields, form_signature,
- password_form ? password_form.get() : nullptr);
+ AnnotateFieldsWithSignatures(&form_fields, form_signature);
}
std::vector<WebFormControlElement> unowned_elements =
form_util::GetUnownedAutofillableFormFieldElements(
frame->GetDocument().All(), nullptr);
std::unique_ptr<PasswordForm> password_form(
- CreatePasswordFormFromUnownedInputElements(*frame, nullptr, nullptr,
- nullptr));
+ CreateSimplifiedPasswordFormFromUnownedInputElements(
+ *frame, /*field_data_manager=*/nullptr,
+ /*username_detector_cache=*/nullptr));
WebString form_signature;
if (password_form)
form_signature = GetFormSignatureAsWebString(*password_form);
- AnnotateFieldsWithSignatures(&unowned_elements, form_signature,
- password_form ? password_form.get() : nullptr);
+ AnnotateFieldsWithSignatures(&unowned_elements, form_signature);
}
// Returns true iff there is a password field in |frame|.
@@ -584,6 +373,30 @@ bool IsInCrossOriginIframe(const WebInputElement& element) {
return false;
}
+// Whether any of the fields in |form) is a non-empty password field.
+bool FormHasNonEmptyPasswordField(const FormData& form) {
+ for (const auto& field : form.fields) {
+ if (field.IsPasswordInputElement()) {
+ if (!field.value.empty() || !field.typed_value.empty())
+ return true;
+ }
+ }
+ return false;
+}
+
+void AnnotateFieldWithParsingResult(WebDocument doc,
+ uint32_t renderer_id,
+ const std::string& text) {
+ if (renderer_id == FormData::kNotSetFormRendererId)
+ return;
+ auto element = FindFormControlElementsByUniqueRendererId(doc, renderer_id);
+ if (element.IsNull())
+ return;
+ element.SetAttribute(
+ WebString::FromASCII(kDebugAttributeForParserAnnotations),
+ WebString::FromASCII(text));
+}
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -940,44 +753,81 @@ bool PasswordAutofillAgent::FindPasswordInfoForElement(
return true;
}
-bool PasswordAutofillAgent::IsUsernameOrPasswordField(
+void PasswordAutofillAgent::MaybeCheckSafeBrowsingReputation(
const WebInputElement& element) {
+ // Enabled on desktop and Android
+#if BUILDFLAG(FULL_SAFE_BROWSING) || BUILDFLAG(SAFE_BROWSING_DB_REMOTE)
// Note: A site may use a Password field to collect a CVV or a Credit Card
// number, but showing a slightly misleading warning here is better than
// showing no warning at all.
- if (element.IsPasswordFieldForAutofill())
- return true;
-
- // If a field declares itself a username input, show the warning.
- if (AutocompleteFlagForElement(element) == AutocompleteFlag::USERNAME)
- return true;
+ if (!element.IsPasswordFieldForAutofill())
+ return;
+ if (checked_safe_browsing_reputation_)
+ return;
- // Otherwise, analyze the form and return true if this input element seems
- // to be the username field.
- std::unique_ptr<PasswordForm> password_form;
- if (element.Form().IsNull()) {
- // To double check that element's frame and |render_frame()->GetWebFrame()|
- // which is used in |GetPasswordFormFromUnownedInputElements| are identical.
- DCHECK_EQ(element.GetDocument().GetFrame(), render_frame()->GetWebFrame());
- password_form = GetPasswordFormFromUnownedInputElements();
- } else {
- password_form = GetPasswordFormFromWebForm(element.Form());
- }
+ checked_safe_browsing_reputation_ = true;
+ WebLocalFrame* frame = render_frame()->GetWebFrame();
+ GURL frame_url = GURL(frame->GetDocument().Url());
+ GURL action_url = element.Form().IsNull()
+ ? GURL()
+ : form_util::GetCanonicalActionForForm(element.Form());
+ GetPasswordManagerDriver()->CheckSafeBrowsingReputation(action_url,
+ frame_url);
+#endif
+}
- if (!password_form)
- return false;
- return (password_form->username_element == element.NameForAutofill().Utf16());
+bool PasswordAutofillAgent::ShouldSuppressKeyboard() {
+ // The keyboard should be suppressed if we are showing the Touch To Fill UI.
+ return touch_to_fill_state_ == TouchToFillState::kIsShowing;
}
bool PasswordAutofillAgent::TryToShowTouchToFill(
const WebFormControlElement& control_element) {
- const WebInputElement* element = ToWebInputElement(&control_element);
- if (!element || (!base::Contains(web_input_to_password_info_, *element) &&
- !base::Contains(password_to_username_, *element))) {
+ // Don't show Touch To Fill if it should only be enabled for insecure origins
+ // and we are currently on a potentially trustworthy origin.
+ if (base::GetFieldTrialParamByFeatureAsBool(features::kAutofillTouchToFill,
+ "insecure-origins-only",
+ /*default_value=*/false) &&
+ render_frame()
+ ->GetWebFrame()
+ ->GetDocument()
+ .GetSecurityOrigin()
+ .IsPotentiallyTrustworthy()) {
+ return false;
+ }
+
+ if (touch_to_fill_state_ != TouchToFillState::kShouldShow)
+ return false;
+
+ const WebInputElement* input_element = ToWebInputElement(&control_element);
+ WebInputElement username_element;
+ WebInputElement password_element;
+ PasswordInfo* password_info = nullptr;
+ if (!input_element ||
+ !FindPasswordInfoForElement(*input_element, &username_element,
+ &password_element, &password_info)) {
return false;
}
+ // Don't trigger Touch To Fill when there is no password element or it is not
+ // editable.
+ if (password_element.IsNull() || !IsElementEditable(password_element))
+ return false;
+
+ // Highlight the fields that are about to be filled by the user and remember
+ // the old autofill state of |username_element| and |password_element|.
+ if (IsUsernameAmendable(username_element,
+ input_element->IsPasswordFieldForAutofill())) {
+ username_autofill_state_ = username_element.GetAutofillState();
+ username_element.SetAutofillState(WebAutofillState::kPreviewed);
+ }
+
+ password_autofill_state_ = password_element.GetAutofillState();
+ password_element.SetAutofillState(WebAutofillState::kPreviewed);
+
+ focused_input_element_ = *input_element;
GetPasswordManagerDriver()->ShowTouchToFill();
+ touch_to_fill_state_ = TouchToFillState::kIsShowing;
return true;
}
@@ -990,22 +840,7 @@ bool PasswordAutofillAgent::ShowSuggestions(const WebInputElement& element,
if (!FindPasswordInfoForElement(element, &username_element, &password_element,
&password_info)) {
- if (IsUsernameOrPasswordField(element)) {
- WebLocalFrame* frame = render_frame()->GetWebFrame();
- GURL frame_url = GURL(frame->GetDocument().Url());
-// Enabled on desktop and Android
-#if BUILDFLAG(FULL_SAFE_BROWSING) || BUILDFLAG(SAFE_BROWSING_DB_REMOTE)
- if (!checked_safe_browsing_reputation_) {
- checked_safe_browsing_reputation_ = true;
- GURL action_url =
- element.Form().IsNull()
- ? GURL()
- : form_util::GetCanonicalActionForForm(element.Form());
- GetPasswordManagerDriver()->CheckSafeBrowsingReputation(action_url,
- frame_url);
- }
-#endif
- }
+ MaybeCheckSafeBrowsingReputation(element);
return false;
}
@@ -1015,11 +850,6 @@ bool PasswordAutofillAgent::ShowSuggestions(const WebInputElement& element,
return true;
}
- if (element.NameForAutofill().IsEmpty() &&
- !DoesFormContainAmbiguousOrEmptyNames(password_info->fill_data)) {
- return false; // If the field has no name, then we won't have values.
- }
-
// Don't attempt to autofill with values that are too large.
if (element.Value().length() > kMaximumTextSizeForAutocomplete)
return false;
@@ -1034,6 +864,13 @@ bool PasswordAutofillAgent::ShowSuggestions(const WebInputElement& element,
if (generation_popup_showing)
return false;
+ // Don't call ShowSuggestionPopup if Touch To Fill is currently showing. Since
+ // Touch To Fill in spirit is very similar to a suggestion pop-up, return true
+ // so that the AutofillAgent does not try to show other autofill suggestions
+ // instead.
+ if (touch_to_fill_state_ == TouchToFillState::kIsShowing)
+ return true;
+
// Chrome should never show more than one account for a password element since
// this implies that the username element cannot be modified. Thus even if
// |show_all| is true, check if the element in question is a password element
@@ -1059,32 +896,33 @@ void PasswordAutofillAgent::OnDynamicFormsSeen() {
void PasswordAutofillAgent::FireSubmissionIfFormDisappear(
SubmissionIndicatorEvent event) {
- if (!provisionally_saved_form_.IsPasswordValid())
+ if (!browser_has_form_to_process_)
return;
-
DCHECK(FrameCanAccessPasswordManager());
// Prompt to save only if the form is now gone, either invisible or
// removed from the DOM.
WebLocalFrame* frame = render_frame()->GetWebFrame();
- const auto& password_form = provisionally_saved_form_.password_form();
// TODO(crbug.com/720347): This method could be called often and checking form
- // visibility could be expesive. Add performance metrics for this.
+ // visibility could be expensive. Add performance metrics for this.
if (event != SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR) {
- if (form_util::IsFormVisible(frame,
- provisionally_saved_form_.form_element(),
- password_form.action, password_form.origin,
- password_form.form_data) ||
- (provisionally_saved_form_.form_element().IsNull() &&
- IsUnownedPasswordFormVisible(
- provisionally_saved_form_.input_element()))) {
- return;
+ bool is_last_updated_field_in_form =
+ last_updated_form_renderer_id_ != FormData::kNotSetFormRendererId;
+ // Check whether the form which is the candidate for submission disappeared.
+ // If yes this form is considered to be successfully submitted.
+ if (is_last_updated_field_in_form) {
+ // A form is inside <form> tag. Check the visibility of the whole form.
+ if (IsFormVisible(frame, last_updated_form_renderer_id_))
+ return;
+ } else {
+ // A form is without <form> tag. Check the visibility of the last updated
+ // field.
+ if (IsFormControlVisible(frame, last_updated_field_renderer_id_))
+ return;
}
}
-
- provisionally_saved_form_.SetSubmissionIndicatorEvent(event);
- GetPasswordManagerDriver()->SameDocumentNavigation(password_form);
- provisionally_saved_form_.Reset();
+ GetPasswordManagerDriver()->SameDocumentNavigation(event);
+ browser_has_form_to_process_ = false;
}
void PasswordAutofillAgent::UserGestureObserved() {
@@ -1268,13 +1106,10 @@ void PasswordAutofillAgent::OnFrameDetached() {
// If a sub frame has been destroyed while the user was entering information
// into a password form, try to save the data. See https://crbug.com/450806
// for examples of sites that perform login using this technique.
- if (render_frame()->GetWebFrame()->Parent() &&
- provisionally_saved_form_.IsPasswordValid()) {
+ if (render_frame()->GetWebFrame()->Parent() && browser_has_form_to_process_) {
DCHECK(FrameCanAccessPasswordManager());
- provisionally_saved_form_.SetSubmissionIndicatorEvent(
- SubmissionIndicatorEvent::FRAME_DETACHED);
GetPasswordManagerDriver()->SameDocumentNavigation(
- provisionally_saved_form_.password_form());
+ SubmissionIndicatorEvent::FRAME_DETACHED);
}
CleanupOnDocumentShutdown();
}
@@ -1291,18 +1126,6 @@ void PasswordAutofillAgent::OnWillSubmitForm(const WebFormElement& form) {
std::unique_ptr<PasswordForm> submitted_form =
GetPasswordFormFromWebForm(form);
- // As a site may clear field values, use a provisionally saved form as
- // the submitted form.
- if (provisionally_saved_form_.IsSet() &&
- (!submitted_form ||
- submitted_form->action ==
- provisionally_saved_form_.password_form().action)) {
- submitted_form.reset(
- new PasswordForm(provisionally_saved_form_.password_form()));
- if (logger)
- logger->LogMessage(Logger::STRING_SUBMITTED_PASSWORD_REPLACED);
- }
-
// If there is a provisionally saved password, copy over the previous
// password value so we get the user's typed password, not the value that
// may have been transformed for submit.
@@ -1328,8 +1151,7 @@ void PasswordAutofillAgent::OnWillSubmitForm(const WebFormElement& form) {
if (logger)
logger->LogMessage(Logger::STRING_SECURITY_ORIGIN_FAILURE);
}
-
- provisionally_saved_form_.Reset();
+ browser_has_form_to_process_ = false;
} else if (logger) {
logger->LogMessage(Logger::STRING_FORM_IS_NOT_PASSWORD);
}
@@ -1362,37 +1184,12 @@ void PasswordAutofillAgent::ReadyToCommitNavigation(
CleanupOnDocumentShutdown();
}
-void PasswordAutofillAgent::OnProbablyFormSubmitted() {
- std::unique_ptr<RendererSavePasswordProgressLogger> logger;
- if (logging_state_active_) {
- logger.reset(new RendererSavePasswordProgressLogger(
- GetPasswordManagerDriver().get()));
- logger->LogMessage(Logger::STRING_DID_START_PROVISIONAL_LOAD_METHOD);
- }
-
- if (!FrameCanAccessPasswordManager()) {
- if (logger)
- logger->LogMessage(Logger::STRING_SECURITY_ORIGIN_FAILURE);
- return;
- }
-
- // If onsubmit has been called, try and save that form.
- if (provisionally_saved_form_.IsSet()) {
- if (logger) {
- logger->LogPasswordForm(Logger::STRING_PROVISIONALLY_SAVED_FORM_FOR_FRAME,
- provisionally_saved_form_.password_form());
- }
- provisionally_saved_form_.SetSubmissionIndicatorEvent(
- SubmissionIndicatorEvent::
- PROVISIONALLY_SAVED_FORM_ON_START_PROVISIONAL_LOAD);
- GetPasswordManagerDriver()->PasswordFormSubmitted(
- provisionally_saved_form_.password_form());
- provisionally_saved_form_.Reset();
- }
-}
+void PasswordAutofillAgent::OnProbablyFormSubmitted() {}
-void PasswordAutofillAgent::FillUsingRendererIDs(
+// mojom::PasswordAutofillAgent:
+void PasswordAutofillAgent::FillPasswordForm(
const PasswordFormFillData& form_data) {
+ DCHECK(form_data.has_renderer_ids);
std::unique_ptr<RendererSavePasswordProgressLogger> logger;
if (logging_state_active_) {
logger.reset(new RendererSavePasswordProgressLogger(
@@ -1440,114 +1237,57 @@ void PasswordAutofillAgent::FillUsingRendererIDs(
logger.get());
}
-// mojom::PasswordAutofillAgent:
-void PasswordAutofillAgent::FillPasswordForm(
- const PasswordFormFillData& form_data) {
- if (form_data.has_renderer_ids) {
- FillUsingRendererIDs(form_data);
- return;
- }
+void PasswordAutofillAgent::SetLoggingState(bool active) {
+ logging_state_active_ = active;
+}
- std::vector<WebInputElement> elements;
- std::unique_ptr<RendererSavePasswordProgressLogger> logger;
- if (logging_state_active_) {
- logger.reset(new RendererSavePasswordProgressLogger(
- GetPasswordManagerDriver().get()));
- logger->LogMessage(Logger::STRING_ON_FILL_PASSWORD_FORM_METHOD);
- }
- GetFillableElementFromFormData(form_data, logger.get(), &elements);
+void PasswordAutofillAgent::TouchToFillClosed(bool show_virtual_keyboard) {
+ touch_to_fill_state_ = TouchToFillState::kWasShown;
- // If wait_for_username is true, we don't want to initially fill the form
- // until the user types in a valid username.
- if (form_data.wait_for_username) {
- LogFirstFillingResult(form_data, FillingResult::kWaitForUsername);
+ // Clear the autofill state from the username and password element. Note that
+ // we don't make use of ClearPreview() here, since this is considering the
+ // elements' SuggestedValue(), which Touch To Fill does not set.
+ DCHECK(!focused_input_element_.IsNull());
+ WebInputElement username_element;
+ WebInputElement password_element;
+ PasswordInfo* password_info = nullptr;
+ if (!FindPasswordInfoForElement(focused_input_element_, &username_element,
+ &password_element, &password_info)) {
return;
}
- if (elements.empty())
- LogFirstFillingResult(form_data, FillingResult::kNoFillableElementsFound);
-
- for (auto element : elements) {
- WebInputElement username_element = !element.IsPasswordFieldForAutofill()
- ? element
- : password_to_username_[element];
- WebInputElement password_element =
- element.IsPasswordFieldForAutofill()
- ? element
- : web_input_to_password_info_[element].password_field;
- FillUserNameAndPassword(username_element, password_element, form_data,
- logger.get());
- }
-}
-
-void PasswordAutofillAgent::GetFillableElementFromFormData(
- const PasswordFormFillData& form_data,
- RendererSavePasswordProgressLogger* logger,
- std::vector<WebInputElement>* elements) {
- DCHECK(elements);
- bool ambiguous_or_empty_names =
- DoesFormContainAmbiguousOrEmptyNames(form_data);
- FormElementsList forms;
- FindFormElements(render_frame(), form_data, ambiguous_or_empty_names, &forms);
- if (logger) {
- logger->LogBoolean(Logger::STRING_AMBIGUOUS_OR_EMPTY_NAMES,
- ambiguous_or_empty_names);
- logger->LogNumber(Logger::STRING_NUMBER_OF_POTENTIAL_FORMS_TO_FILL,
- forms.size());
- logger->LogBoolean(Logger::STRING_FORM_DATA_WAIT,
- form_data.wait_for_username);
- }
- for (const auto& form : forms) {
- base::string16 username_field_name;
- base::string16 password_field_name =
- FieldName(form_data.password_field, ambiguous_or_empty_names);
- bool form_contains_fillable_username_field =
- FillDataContainsFillableUsername(form_data);
- if (form_contains_fillable_username_field) {
- username_field_name =
- FieldName(form_data.username_field, ambiguous_or_empty_names);
- }
- if (logger) {
- logger->LogBoolean(Logger::STRING_CONTAINS_FILLABLE_USERNAME_FIELD,
- form_contains_fillable_username_field);
- logger->LogBoolean(Logger::STRING_USERNAME_FIELD_NAME_EMPTY,
- username_field_name.empty());
- logger->LogBoolean(Logger::STRING_PASSWORD_FIELD_NAME_EMPTY,
- password_field_name.empty());
- }
-
- // Attach autocomplete listener to enable selecting alternate logins.
- WebInputElement username_element;
- WebInputElement password_element;
-
- // Check whether the password form has a username input field.
- if (!username_field_name.empty()) {
- const auto it = form.find(username_field_name);
- DCHECK(it != form.end());
- username_element = it->second;
- }
-
- // No password field, bail out.
- if (password_field_name.empty())
- break;
+ if (!username_element.IsNull())
+ username_element.SetAutofillState(username_autofill_state_);
- // Get pointer to password element. (We currently only support single
- // password forms).
- {
- const auto it = form.find(password_field_name);
- DCHECK(it != form.end());
- password_element = it->second;
+ if (!password_element.IsNull())
+ password_element.SetAutofillState(password_autofill_state_);
+
+ if (show_virtual_keyboard) {
+ render_frame()->ShowVirtualKeyboard();
+
+ // Since Touch To Fill suppresses the Autofill popup, re-trigger the
+ // suggestions in case the virtual keyboard should be shown. This is limited
+ // to the keyboard accessory, as otherwise it would result in a flickering
+ // of the popup, due to showing the keyboard at the same time.
+ if (IsKeyboardAccessoryEnabled()) {
+ ShowSuggestions(focused_input_element_, /*show_all=*/false,
+ /*generation_popup_showing=*/false);
}
-
- WebInputElement main_element =
- username_element.IsNull() ? password_element : username_element;
- if (elements)
- elements->push_back(main_element);
- StoreDataForFillOnAccountSelect(form_data, username_element,
- password_element);
}
+}
- MaybeStoreFallbackData(form_data);
+void PasswordAutofillAgent::AnnotateFieldsWithParsingResult(
+ const ParsingResult& parsing_result) {
+ WebDocument doc = render_frame()->GetWebFrame()->GetDocument();
+ AnnotateFieldWithParsingResult(doc, parsing_result.username_renderer_id,
+ "username_element");
+ AnnotateFieldWithParsingResult(doc, parsing_result.password_renderer_id,
+ "password_element");
+ AnnotateFieldWithParsingResult(doc, parsing_result.new_password_renderer_id,
+ "new_password_element");
+ AnnotateFieldWithParsingResult(doc,
+ parsing_result.confirm_password_renderer_id,
+ "confirmation_password_element");
}
void PasswordAutofillAgent::FocusedNodeHasChanged(const blink::WebNode& node) {
@@ -1595,16 +1335,15 @@ void PasswordAutofillAgent::FocusedNodeHasChanged(const blink::WebNode& node) {
std::unique_ptr<PasswordForm> PasswordAutofillAgent::GetPasswordFormFromWebForm(
const WebFormElement& web_form) {
- return CreatePasswordFormFromWebForm(web_form, &field_data_manager_,
- &form_predictions_,
- &username_detector_cache_);
+ return CreateSimplifiedPasswordFormFromWebForm(web_form, &field_data_manager_,
+ &username_detector_cache_);
}
std::unique_ptr<PasswordForm>
PasswordAutofillAgent::GetSimplifiedPasswordFormFromWebForm(
const WebFormElement& web_form) {
- return CreateSimplifiedPasswordFormFromWebForm(web_form,
- &field_data_manager_);
+ return CreateSimplifiedPasswordFormFromWebForm(web_form, &field_data_manager_,
+ &username_detector_cache_);
}
std::unique_ptr<PasswordForm>
@@ -1619,9 +1358,8 @@ PasswordAutofillAgent::GetPasswordFormFromUnownedInputElements() {
WebLocalFrame* web_frame = frame->GetWebFrame();
if (!web_frame)
return nullptr;
- return CreatePasswordFormFromUnownedInputElements(
- *web_frame, &field_data_manager_, &form_predictions_,
- &username_detector_cache_);
+ return CreateSimplifiedPasswordFormFromUnownedInputElements(
+ *web_frame, &field_data_manager_, &username_detector_cache_);
}
std::unique_ptr<PasswordForm>
@@ -1633,17 +1371,7 @@ PasswordAutofillAgent::GetSimplifiedPasswordFormFromUnownedInputElements() {
if (!web_frame)
return nullptr;
return CreateSimplifiedPasswordFormFromUnownedInputElements(
- *web_frame, &field_data_manager_);
-}
-
-// mojom::PasswordAutofillAgent:
-void PasswordAutofillAgent::SetLoggingState(bool active) {
- logging_state_active_ = active;
-}
-
-void PasswordAutofillAgent::AutofillUsernameAndPasswordDataReceived(
- const FormsPredictionsMap& predictions) {
- form_predictions_.insert(predictions.begin(), predictions.end());
+ *web_frame, &field_data_manager_, &username_detector_cache_);
}
////////////////////////////////////////////////////////////////////////////////
@@ -1685,7 +1413,7 @@ bool PasswordAutofillAgent::ShowSuggestionPopup(
GetPasswordManagerDriver()->ShowPasswordSuggestions(
field.text_direction, username_string, options,
- render_frame()->GetRenderView()->ElementBoundsInWindow(user_input));
+ render_frame()->ElementBoundsInWindow(user_input));
username_query_prefix_ = username_string;
return CanShowSuggestion(password_info.fill_data, username_string, show_all);
}
@@ -1694,17 +1422,19 @@ void PasswordAutofillAgent::CleanupOnDocumentShutdown() {
web_input_to_password_info_.clear();
password_to_username_.clear();
last_supplied_password_info_iter_ = web_input_to_password_info_.end();
- provisionally_saved_form_.Reset();
+ browser_has_form_to_process_ = false;
field_data_manager_.ClearData();
username_autofill_state_ = WebAutofillState::kNotFilled;
password_autofill_state_ = WebAutofillState::kNotFilled;
sent_request_to_store_ = false;
checked_safe_browsing_reputation_ = false;
username_query_prefix_.clear();
- form_predictions_.clear();
username_detector_cache_.clear();
forms_structure_cache_.clear();
autofilled_elements_cache_.clear();
+ last_updated_field_renderer_id_ = FormData::kNotSetFormRendererId;
+ last_updated_form_renderer_id_ = FormData::kNotSetFormRendererId;
+ touch_to_fill_state_ = TouchToFillState::kShouldShow;
#if !defined(OS_ANDROID) && !defined(OS_IOS)
page_passwords_analyser_.Reset();
#endif
@@ -1729,6 +1459,7 @@ void PasswordAutofillAgent::ProvisionallySavePassword(
ProvisionallySaveRestriction restriction) {
DCHECK(!form.IsNull() || !element.IsNull());
+ SetLastUpdatedFormAndField(form, element);
std::unique_ptr<PasswordForm> password_form;
if (form.IsNull()) {
password_form = GetPasswordFormFromUnownedInputElements();
@@ -1738,22 +1469,19 @@ void PasswordAutofillAgent::ProvisionallySavePassword(
if (!password_form)
return;
- bool has_password = !password_form->password_value.empty() ||
- !password_form->new_password_value.empty();
+ bool has_password = FormHasNonEmptyPasswordField(password_form->form_data);
if (restriction == RESTRICTION_NON_EMPTY_PASSWORD && !has_password)
return;
if (!FrameCanAccessPasswordManager())
return;
- provisionally_saved_form_.Set(std::move(password_form), form, element);
-
if (has_password) {
- GetPasswordManagerDriver()->ShowManualFallbackForSaving(
- provisionally_saved_form_.password_form());
+ GetPasswordManagerDriver()->ShowManualFallbackForSaving(*password_form);
} else {
GetPasswordManagerDriver()->HideManualFallbackForSaving();
}
+ browser_has_form_to_process_ = true;
}
bool PasswordAutofillAgent::FillUserNameAndPassword(
@@ -1914,19 +1642,6 @@ void PasswordAutofillAgent::OnProvisionallySaveForm(
}
DCHECK_EQ(ElementChangeSource::WILL_SEND_SUBMIT_EVENT, source);
- // Forms submitted via XHR are not seen by WillSubmitForm if the default
- // onsubmit handler is overridden. Such submission first gets detected in
- // DidStartProvisionalLoad, which no longer knows about the particular form,
- // and uses the candidate stored in |provisionally_saved_form_|.
- //
- // User-typed password will get stored to |provisionally_saved_form_| in
- // TextDidChangeInTextField. Autofilled or JavaScript-copied passwords need to
- // be saved here.
- //
- // Only non-empty passwords are saved here. Empty passwords were likely
- // cleared by some scripts (http://crbug.com/28910, http://crbug.com/391693).
- // Had the user cleared the password, |provisionally_saved_form_| would
- // already have been updated in TextDidChangeInTextField.
ProvisionallySavePassword(form, input_element,
RESTRICTION_NON_EMPTY_PASSWORD);
}
@@ -2042,10 +1757,9 @@ void PasswordAutofillAgent::LogFirstFillingResult(
return;
UMA_HISTOGRAM_ENUMERATION("PasswordManager.FirstRendererFillingResult",
result);
- if (form_data.has_renderer_ids) {
- GetPasswordManagerDriver()->LogFirstFillingResult(
- form_data.form_renderer_id, base::strict_cast<int32_t>(result));
- }
+ DCHECK(form_data.has_renderer_ids);
+ GetPasswordManagerDriver()->LogFirstFillingResult(
+ form_data.form_renderer_id, base::strict_cast<int32_t>(result));
recorded_first_filling_result_ = true;
}
@@ -2132,4 +1846,15 @@ void PasswordAutofillAgent::AutofillField(const base::string16& value,
WebString::FromUTF16(value));
}
+void PasswordAutofillAgent::SetLastUpdatedFormAndField(
+ const WebFormElement& form,
+ const WebFormControlElement& input) {
+ last_updated_form_renderer_id_ = form.IsNull()
+ ? FormData::kNotSetFormRendererId
+ : form.UniqueRendererFormId();
+ last_updated_field_renderer_id_ = input.IsNull()
+ ? FormData::kNotSetFormRendererId
+ : input.UniqueRendererFormControlId();
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/content/renderer/password_autofill_agent.h b/chromium/components/autofill/content/renderer/password_autofill_agent.h
index 6346b5f2d92..81b0e38fb0e 100644
--- a/chromium/components/autofill/content/renderer/password_autofill_agent.h
+++ b/chromium/components/autofill/content/renderer/password_autofill_agent.h
@@ -20,11 +20,8 @@
#include "components/autofill/content/renderer/field_data_manager.h"
#include "components/autofill/content/renderer/form_tracker.h"
#include "components/autofill/content/renderer/html_based_username_detector.h"
-#include "components/autofill/content/renderer/provisionally_saved_password_form.h"
-#include "components/autofill/core/common/form_data_predictions.h"
#include "components/autofill/core/common/mojom/autofill_types.mojom.h"
#include "components/autofill/core/common/password_form.h"
-#include "components/autofill/core/common/password_form_field_prediction_map.h"
#include "components/autofill/core/common/password_form_fill_data.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/public/renderer/render_view_observer.h"
@@ -132,8 +129,9 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
void FillIntoFocusedField(bool is_password,
const base::string16& credential) override;
void SetLoggingState(bool active) override;
- void AutofillUsernameAndPasswordDataReceived(
- const FormsPredictionsMap& predictions) override;
+ void TouchToFillClosed(bool show_virtual_keyboard) override;
+ void AnnotateFieldsWithParsingResult(
+ const ParsingResult& parsing_result) override;
// FormTracker::Observer
void OnProvisionallySaveForm(const blink::WebFormElement& form,
@@ -177,8 +175,12 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
bool DidClearAutofillSelection(
const blink::WebFormControlElement& control_element);
- // Returns whether the element is a username or password textfield.
- bool IsUsernameOrPasswordField(const blink::WebInputElement& element);
+ // Sends a reputation check request in case if |element| has type password and
+ // no check request were sent from this frame load.
+ void MaybeCheckSafeBrowsingReputation(const blink::WebInputElement& element);
+
+ // Returns whether the soft keyboard should be suppressed.
+ bool ShouldSuppressKeyboard();
// Asks the agent to show the touch to fill UI for |control_element|. Returns
// whether the agent was able to do so.
@@ -196,11 +198,6 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
bool show_all,
bool generation_popup_showing);
- // Shows an Autofill-style popup with a warning that the form is not secure.
- // This UI is shown when a username or password field is autofilled or edited
- // on a non-secure page.
- void ShowNotSecureWarning(const blink::WebInputElement& element);
-
// Called when new form controls are inserted.
void OnDynamicFormsSeen();
@@ -209,15 +206,6 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
// JavaScript.
void UserGestureObserved();
- // Given password form data |form_data| returns a set of WebInputElements in
- // |elements|, which must be non-null, that the password manager has values
- // for filling. Also takes an optional logger |logger| for logging password
- // autofill behavior.
- void GetFillableElementFromFormData(
- const PasswordFormFillData& form_data,
- RendererSavePasswordProgressLogger* logger,
- std::vector<blink::WebInputElement>* elements);
-
// Called when the focused node has changed. This is not called if the focus
// moves outside the frame.
void FocusedNodeHasChanged(const blink::WebNode& node);
@@ -262,6 +250,16 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
RESTRICTION_NON_EMPTY_PASSWORD
};
+ // Enumeration representing possible Touch To Fill states. This is used to
+ // make sure that Touch To Fill will only be shown in response to the first
+ // password form focus during a frame's life time and to suppress the soft
+ // keyboard when Touch To Fill is shown.
+ enum class TouchToFillState {
+ kShouldShow,
+ kIsShowing,
+ kWasShown,
+ };
+
struct PasswordInfo {
blink::WebInputElement password_field;
PasswordFormFillData fill_data;
@@ -422,10 +420,6 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
void HidePopup();
- // TODO(https://crbug.com/831123): Rename to FillPasswordForm when browser
- // form parsing is launched.
- void FillUsingRendererIDs(const PasswordFormFillData& form_data);
-
// Returns pair(username_element, password_element) based on renderer ids from
// |username_field| and |password_field| from |form_data|.
std::pair<blink::WebInputElement, blink::WebInputElement>
@@ -466,6 +460,9 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
// non-null.
void AutofillField(const base::string16& value, blink::WebInputElement field);
+ void SetLastUpdatedFormAndField(const blink::WebFormElement& form,
+ const blink::WebFormControlElement& input);
+
// The logins we have filled so far with their associated info.
WebInputToPasswordInfoMap web_input_to_password_info_;
// A (sort-of) reverse map to |web_input_to_password_info_|.
@@ -473,10 +470,6 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
// The chronologically last insertion into |web_input_to_password_info_|.
WebInputToPasswordInfoMap::iterator last_supplied_password_info_iter_;
- // Set if the user might be submitting a password form on the current page,
- // but the submit may still fail (i.e. doesn't pass JavaScript validation).
- ProvisionallySavedPasswordForm provisionally_saved_form_;
-
// Map WebFormControlElement to the pair of:
// 1) The most recent text that user typed or PasswordManager autofilled in
// input elements. Used for storing username/password before JavaScript
@@ -504,16 +497,18 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
// True indicates that a request for credentials has been sent to the store.
bool sent_request_to_store_;
+ // True indicates that a form data has been sent to the browser process. Gets
+ // cleared when the form is submitted to indicate that the browser has already
+ // processed the form.
+ // TODO(crbug.com/949519): double check if we need this variable.
+ bool browser_has_form_to_process_ = false;
+
// True indicates that a safe browsing reputation check has been triggered.
bool checked_safe_browsing_reputation_;
// Records the username typed before suggestions preview.
base::string16 username_query_prefix_;
- // Contains server predictions for username, password and/or new password
- // fields for individual forms.
- FormsPredictionsMap form_predictions_;
-
// The HTML based username detector's cache which maps form elements to
// username predictions.
UsernameDetectorCache username_detector_cache_;
@@ -550,6 +545,15 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
// DidCommitProvisionalLoad() but only for non-same-document-navigations.
bool recorded_first_filling_result_ = false;
+ // Contains renderer id of last updated input element.
+ uint32_t last_updated_field_renderer_id_ = FormData::kNotSetFormRendererId;
+ // Contains renderer id of the form of the last updated input element.
+ uint32_t last_updated_form_renderer_id_ = FormData::kNotSetFormRendererId;
+
+ // Current state of Touch To Fill. This is reset during
+ // CleanupOnDocumentShutdown.
+ TouchToFillState touch_to_fill_state_ = TouchToFillState::kShouldShow;
+
DISALLOW_COPY_AND_ASSIGN(PasswordAutofillAgent);
};
diff --git a/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc b/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc
index 9e6c94e1581..c60a5360fb6 100644
--- a/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc
+++ b/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc
@@ -4,34 +4,17 @@
#include "components/autofill/content/renderer/password_form_conversion_utils.h"
-#include <stddef.h>
-
-#include <algorithm>
-#include <set>
-#include <string>
-
-#include "base/i18n/case_conversion.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
-#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
-#include "base/stl_util.h"
-#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
#include "components/autofill/content/renderer/form_autofill_util.h"
#include "components/autofill/content/renderer/html_based_username_detector.h"
-#include "components/autofill/core/common/autofill_regex_constants.h"
-#include "components/autofill/core/common/autofill_regexes.h"
-#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/password_form.h"
-#include "components/autofill/core/common/password_form_field_prediction_map.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/base/url_util.h"
#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_form_control_element.h"
#include "third_party/blink/public/web/web_input_element.h"
@@ -48,217 +31,8 @@ using blink::WebString;
namespace autofill {
-using mojom::PasswordFormFieldPredictionType;
-
namespace {
-constexpr char kAutocompleteUsername[] = "username";
-constexpr char kAutocompleteCurrentPassword[] = "current-password";
-constexpr char kAutocompleteNewPassword[] = "new-password";
-constexpr char kAutocompleteCreditCardPrefix[] = "cc-";
-
-// Parses the string with the value of an autocomplete attribute. If any of the
-// tokens "username", "current-password" or "new-password" are present, returns
-// an appropriate enum value, picking an arbitrary one if more are applicable.
-// Otherwise, it returns CREDIT_CARD if a token with a "cc-" prefix is found.
-// Otherwise, returns NONE.
-AutocompleteFlag ExtractAutocompleteFlag(const std::string& attribute) {
- std::vector<base::StringPiece> tokens =
- base::SplitStringPiece(attribute, base::kWhitespaceASCII,
- base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- bool cc_seen = false;
- for (base::StringPiece token : tokens) {
- if (base::LowerCaseEqualsASCII(token, kAutocompleteUsername))
- return AutocompleteFlag::USERNAME;
- if (base::LowerCaseEqualsASCII(token, kAutocompleteCurrentPassword))
- return AutocompleteFlag::CURRENT_PASSWORD;
- if (base::LowerCaseEqualsASCII(token, kAutocompleteNewPassword))
- return AutocompleteFlag::NEW_PASSWORD;
-
- if (!cc_seen) {
- cc_seen = base::StartsWith(token, kAutocompleteCreditCardPrefix,
- base::CompareCase::SENSITIVE);
- }
- }
- return cc_seen ? AutocompleteFlag::CREDIT_CARD : AutocompleteFlag::NONE;
-}
-
-// Helper to spare map::find boilerplate when caching field's autocomplete
-// attributes.
-class AutocompleteCache {
- public:
- AutocompleteCache();
-
- ~AutocompleteCache();
-
- // Computes and stores the AutocompleteFlag for |field| based on its
- // autocomplete attribute. Note that this cannot be done on-demand during
- // RetrieveFor, because the cache spares space and look-up time by not storing
- // AutocompleteFlag::NONE values, hence for all elements without an
- // autocomplete attribute, every retrieval would result in a new computation.
- void Store(const FormFieldData* field);
-
- // Retrieves the value previously stored for |field|.
- AutocompleteFlag RetrieveFor(const FormFieldData* field) const;
-
- private:
- std::map<const FormFieldData*, AutocompleteFlag> cache_;
-
- DISALLOW_COPY_AND_ASSIGN(AutocompleteCache);
-};
-
-AutocompleteCache::AutocompleteCache() = default;
-
-AutocompleteCache::~AutocompleteCache() = default;
-
-void AutocompleteCache::Store(const FormFieldData* field) {
- const AutocompleteFlag flag =
- ExtractAutocompleteFlag(field->autocomplete_attribute);
- // Only store non-trivial flags. Most of the elements will have the NONE
- // value, so spare storage and lookup time by assuming anything not stored in
- // |cache_| has the NONE flag.
- if (flag != AutocompleteFlag::NONE)
- cache_[field] = flag;
-}
-
-AutocompleteFlag AutocompleteCache::RetrieveFor(
- const FormFieldData* field) const {
- auto it = cache_.find(field);
- if (it == cache_.end())
- return AutocompleteFlag::NONE;
- return it->second;
-}
-
-// Describes fields filtering criteria. More priority criteria has higher value
-// in the enum. The fields with the maximal criteria are considered in a form,
-// others are ignored. Criteria for password and username fields are calculated
-// separately. For example, if there is a password field with user input, the
-// password fields without user input are ignored (independently whether the
-// fields are visible or not).
-enum class FieldFilteringLevel {
- NO_FILTER = 0,
- VISIBILITY = 1,
- USER_INPUT = 2
-};
-
-// Helper to determine which password is the main (current) one, and which is
-// the new password (e.g., on a sign-up or change password form), if any. If the
-// new password is found and there is another password field with the same user
-// input, the function also sets |confirmation_password| to this field.
-void LocateSpecificPasswords(std::vector<const FormFieldData*> passwords,
- const FormFieldData** current_password,
- const FormFieldData** new_password,
- const FormFieldData** confirmation_password,
- const AutocompleteCache& autocomplete_cache) {
- DCHECK(!passwords.empty());
- DCHECK(current_password && !*current_password);
- DCHECK(new_password && !*new_password);
- DCHECK(confirmation_password && !*confirmation_password);
-
- // First, look for elements marked with either autocomplete='current-password'
- // or 'new-password' -- if we find any, take the hint, and treat the first of
- // each kind as the element we are looking for.
- for (const FormFieldData* password : passwords) {
- const AutocompleteFlag flag = autocomplete_cache.RetrieveFor(password);
- if (flag == AutocompleteFlag::CURRENT_PASSWORD && !*current_password) {
- *current_password = password;
- } else if (flag == AutocompleteFlag::NEW_PASSWORD && !*new_password) {
- *new_password = password;
- } else if (*new_password && ((*new_password)->value == password->value)) {
- *confirmation_password = password;
- }
- }
-
- // If we have seen an element with either of autocomplete attributes above,
- // take that as a signal that the page author must have intentionally left the
- // rest of the password fields unmarked. Perhaps they are used for other
- // purposes, e.g., PINs, OTPs, and the like. So we skip all the heuristics we
- // normally do, and ignore the rest of the password fields.
- if (*current_password || *new_password)
- return;
-
- switch (passwords.size()) {
- case 1:
- // Single password, easy.
- *current_password = passwords[0];
- break;
- case 2:
- if (!passwords[0]->value.empty() &&
- passwords[0]->value == passwords[1]->value) {
- // Two identical non-empty passwords: assume we are seeing a new
- // password with a confirmation. This can be either a sign-up form or a
- // password change form that does not ask for the old password.
- *new_password = passwords[0];
- *confirmation_password = passwords[1];
- } else {
- // Assume first is old password, second is new (no choice but to guess).
- // This case also includes empty passwords in order to allow filling of
- // password change forms (that also could autofill for sign up form, but
- // we can't do anything with this using only client side information).
- *current_password = passwords[0];
- *new_password = passwords[1];
- }
- break;
- default:
- if (!passwords[0]->value.empty() &&
- passwords[0]->value == passwords[1]->value &&
- passwords[0]->value == passwords[2]->value) {
- // All three passwords are the same and non-empty? It may be a change
- // password form where old and new passwords are the same. It doesn't
- // matter what field is correct, let's save the value.
- *current_password = passwords[0];
- } else if (passwords[1]->value == passwords[2]->value) {
- // New password is the duplicated one, and comes second; or empty form
- // with 3 password fields, in which case we will assume this layout.
- *current_password = passwords[0];
- *new_password = passwords[1];
- *confirmation_password = passwords[2];
- } else if (passwords[0]->value == passwords[1]->value) {
- // It is strange that the new password comes first, but trust more which
- // fields are duplicated than the ordering of fields. Assume that
- // any password fields after the new password contain sensitive
- // information that isn't actually a password (security hint, SSN, etc.)
- *new_password = passwords[0];
- *confirmation_password = passwords[1];
- } else {
- // Three different passwords, or first and last match with middle
- // different. No idea which is which. Let's save the first password.
- // Password selection in a prompt will allow to correct the choice.
- *current_password = passwords[0];
- }
- }
-}
-
-void FindPredictedElements(
- const FormData& form_data,
- const FormsPredictionsMap& form_predictions,
- std::map<const FormFieldData*, PasswordFormFieldPredictionType>*
- predicted_fields) {
- // Matching only requires that action and name of the form match to allow
- // the username to be updated even if the form is changed after page load.
- // See https://crbug.com/476092 for more details.
- auto field_predictions = std::find_if(
- form_predictions.begin(), form_predictions.end(),
- [&form_data](const auto& form_predictions_pair) {
- return form_predictions_pair.first.action == form_data.action &&
- form_predictions_pair.first.name == form_data.name;
- });
-
- if (field_predictions == form_predictions.end())
- return;
-
- for (const auto& prediction : field_predictions->second) {
- const FormFieldData& target_field = prediction.first;
- const PasswordFormFieldPredictionType& type = prediction.second;
- for (const FormFieldData& field : form_data.fields) {
- if (field.name == target_field.name) {
- (*predicted_fields)[&field] = type;
- break;
- }
- }
- }
-}
-
const char kPasswordSiteUrlRegex[] =
"passwords(?:-[a-z-]+\\.corp)?\\.google\\.com";
@@ -272,116 +46,6 @@ struct PasswordSiteUrlLazyInstanceTraits
base::LazyInstance<re2::RE2, PasswordSiteUrlLazyInstanceTraits>
g_password_site_matcher = LAZY_INSTANCE_INITIALIZER;
-// Returns the |input_field| name if its non-empty; otherwise a |dummy_name|.
-base::string16 FieldName(const FormFieldData* input_field,
- const char* dummy_name) {
- return input_field->name.empty() ? base::ASCIIToUTF16(dummy_name)
- : input_field->name;
-}
-
-// Return the maximal filtering criteria that |field| passes.
-// If |ignore_autofilled_values|, autofilled value isn't considered user input.
-FieldFilteringLevel GetFiltertingLevelForField(const FormFieldData& field,
- bool ignore_autofilled_values) {
- FieldPropertiesMask user_input_mask =
- ignore_autofilled_values
- ? FieldPropertiesFlags::USER_TYPED
- : FieldPropertiesFlags::USER_TYPED | FieldPropertiesFlags::AUTOFILLED;
- if (field.properties_mask & user_input_mask)
- return FieldFilteringLevel::USER_INPUT;
- return field.is_focusable ? FieldFilteringLevel::VISIBILITY
- : FieldFilteringLevel::NO_FILTER;
-}
-
-// Calculates the maximal filtering levels for password and username fields and
-// saves them to |username_fields_level| and |password_fields_level|. The
-// criteria for username fields considers only the fields before the first
-// password field that has the maximal filtering level.
-void GetFieldFilteringLevels(const std::vector<FormFieldData>& fields,
- FieldFilteringLevel* username_fields_level,
- FieldFilteringLevel* password_fields_level) {
- DCHECK(password_fields_level);
- DCHECK(username_fields_level);
- *username_fields_level = FieldFilteringLevel::NO_FILTER;
- *password_fields_level = FieldFilteringLevel::NO_FILTER;
-
- FieldFilteringLevel max_level_found_for_username_fields =
- FieldFilteringLevel::NO_FILTER;
- for (const FormFieldData& field : fields) {
- if (!field.is_enabled || !field.IsTextInputElement())
- continue;
-
- // TODO(crbug.com/789917): Ignore autofilled values here because if there
- // are only autofilled values then a form may not be filled completely (i.e.
- // some user input is still expected). So, user input shouldn't be used for
- // fields filtering. Once the bug is resolved, autofilled values will not be
- // ignored.
- FieldFilteringLevel current_field_filtering_level =
- GetFiltertingLevelForField(field, true /* ignore_autofilled_values */);
-
- if (field.form_control_type == "password") {
- if (*password_fields_level < current_field_filtering_level) {
- *password_fields_level = current_field_filtering_level;
- *username_fields_level = max_level_found_for_username_fields;
- }
- } else {
- max_level_found_for_username_fields = std::max(
- max_level_found_for_username_fields, current_field_filtering_level);
- }
- }
-}
-
-ValueElementPair MakePossibleUsernamePair(const FormFieldData* input) {
- base::string16 trimmed_input_value;
- base::TrimString(input->value, base::ASCIIToUTF16(" "), &trimmed_input_value);
- return {trimmed_input_value, input->name};
-}
-
-bool StringMatchesCVC(const base::string16& str) {
- static const base::NoDestructor<base::string16> kCardCvcReCached(
- base::UTF8ToUTF16(kCardCvcRe));
-
- return MatchesPattern(str, *kCardCvcReCached);
-}
-
-// Which types of password fields are present in a form?
-enum class PasswordContents {
- kEnabled, // At least one enabled password field.
- kOnlyDisabled, // At least one password field, but not enabled.
- kNone // No password fields present.
-};
-
-// Returns the PasswordContents reflecting the contents of |fields|.
-PasswordContents GetPasswordContents(const std::vector<FormFieldData>& fields) {
- PasswordContents result = PasswordContents::kNone;
- for (const FormFieldData& field : fields) {
- if (field.form_control_type != "password")
- continue;
- result = PasswordContents::kOnlyDisabled;
- if (field.is_enabled)
- return PasswordContents::kEnabled;
- }
- return result;
-}
-
-// Find the first element in |username_predictions| (i.e. the most reliable
-// prediction) that occurs in |possible_usernames|.
-const FormFieldData* FindUsernameInPredictions(
- const std::vector<uint32_t>& username_predictions,
- const std::vector<const FormFieldData*>& possible_usernames) {
- for (uint32_t predicted_id : username_predictions) {
- auto iter =
- std::find_if(possible_usernames.begin(), possible_usernames.end(),
- [predicted_id](const FormFieldData* field) {
- return field->unique_renderer_id == predicted_id;
- });
- if (iter != possible_usernames.end()) {
- return *iter;
- }
- }
- return nullptr;
-}
-
// Extracts the username predictions. |control_elements| should be all the DOM
// elements of the form, |form_data| should be the already extracted FormData
// representation of that form. |username_detector_cache| is optional, and can
@@ -401,387 +65,6 @@ std::vector<uint32_t> GetUsernamePredictions(
username_detector_cache);
}
-// Get information about a login form encapsulated in a PasswordForm struct.
-// If an element of |form| has an entry in |nonscript_modified_values|, the
-// associated string is used instead of the element's value to create
-// the PasswordForm.
-bool GetPasswordForm(const GURL& form_origin,
- const std::vector<WebFormControlElement>& control_elements,
- PasswordForm* password_form,
- const FormsPredictionsMap* form_predictions,
- UsernameDetectorCache* username_detector_cache) {
- DCHECK(!control_elements.empty());
-
- const FormData& form_data = password_form->form_data;
- PasswordContents password_contents = GetPasswordContents(form_data.fields);
- switch (password_contents) {
- case PasswordContents::kEnabled:
- // All well, continue parsing.
- break;
- case PasswordContents::kOnlyDisabled:
- // The current parser gives up, but returns a fallback form so that the
- // newer parser can try parsing as well.
- password_form->scheme = PasswordForm::Scheme::kHtml;
- password_form->origin = form_origin;
- password_form->signon_realm = GetSignOnRealm(password_form->origin);
- return true;
- case PasswordContents::kNone:
- return false;
- }
- // Evaluate the context of the fields.
- password_form->form_data.username_predictions = GetUsernamePredictions(
- control_elements, form_data, username_detector_cache);
-
- // Narrow the scope to enabled text inputs.
- std::vector<const FormFieldData*> enabled_fields;
- enabled_fields.reserve(form_data.fields.size());
- for (const FormFieldData& field : form_data.fields) {
- if (field.is_enabled && field.IsTextInputElement())
- enabled_fields.push_back(&field);
- }
-
- // Remember the list of password fields without any heuristics applied in case
- // the heuristics fail and a fall-back is needed:
- // All password fields.
- std::vector<const FormFieldData*> passwords_without_heuristics;
- // Map from all password fields to the most recent non-password text input.
- std::map<const FormFieldData*, const FormFieldData*>
- preceding_text_input_for_password_without_heuristics;
- const FormFieldData* most_recent_text_input = nullptr; // Just a temporary.
- for (const FormFieldData* input : enabled_fields) {
- if (input->form_control_type == "password") {
- passwords_without_heuristics.push_back(input);
- preceding_text_input_for_password_without_heuristics[input] =
- most_recent_text_input;
- } else {
- most_recent_text_input = input;
- }
- }
-
- // Fill the cache with autocomplete flags.
- AutocompleteCache autocomplete_cache;
- for (const FormFieldData* input : enabled_fields) {
- autocomplete_cache.Store(input);
- }
-
- // Narrow the scope further: drop credit-card fields.
- std::vector<const FormFieldData*> plausible_inputs;
- plausible_inputs.reserve(enabled_fields.size());
- for (const FormFieldData* input : enabled_fields) {
- const AutocompleteFlag flag = autocomplete_cache.RetrieveFor(input);
- if (flag == AutocompleteFlag::CURRENT_PASSWORD ||
- flag == AutocompleteFlag::NEW_PASSWORD) {
- // A field marked as a password is considered not a credit-card field, no
- // matter what.
- plausible_inputs.push_back(input);
- } else if (flag != AutocompleteFlag::CREDIT_CARD) {
- const bool is_credit_card_verification =
- input->form_control_type == "password" &&
- (StringMatchesCVC(input->name_attribute) ||
- StringMatchesCVC(input->id_attribute));
- if (!is_credit_card_verification) {
- // Otherwise ensure that nothing hints that |input| is a credit-card
- // field.
- plausible_inputs.push_back(input);
- }
- }
- }
-
- // Further narrow to interesting fields (e.g., with user input, visible), if
- // present.
- // Compute the best filtering levels for usernames and for passwords.
- FieldFilteringLevel username_fields_level = FieldFilteringLevel::NO_FILTER;
- FieldFilteringLevel password_fields_level = FieldFilteringLevel::NO_FILTER;
- GetFieldFilteringLevels(form_data.fields, &username_fields_level,
- &password_fields_level);
- // Remove all fields with filtering level below the best.
- base::EraseIf(
- plausible_inputs, [password_fields_level,
- username_fields_level](const FormFieldData* input) {
- FieldFilteringLevel current_field_level = GetFiltertingLevelForField(
- *input, false /* ignore_autofilled_values */);
- if (input->form_control_type == "password")
- return current_field_level < password_fields_level;
- return current_field_level < username_fields_level;
- });
-
- // Further, remove all readonly passwords. If the password field is readonly,
- // the page is likely using a virtual keyboard and bypassing the password
- // field value (see http://crbug.com/475488). There is nothing Chrome can do
- // to fill passwords for now. Notable exceptions: if the password field was
- // made readonly by JavaScript before submission, it remains interesting. If
- // the password was marked via the autocomplete attribute, it also remains
- // interesting.
- base::EraseIf(plausible_inputs, [&autocomplete_cache](
- const FormFieldData* input) {
- if (!input->is_readonly)
- return false;
- if (input->form_control_type != "password")
- return false;
- // Check if the field was only made readonly before submission.
- if (input->properties_mask &
- (FieldPropertiesFlags::USER_TYPED | FieldPropertiesFlags::AUTOFILLED)) {
- return false;
- }
- // Check whether the field was explicitly marked as password.
- const AutocompleteFlag flag = autocomplete_cache.RetrieveFor(input);
- if (flag == AutocompleteFlag::CURRENT_PASSWORD ||
- flag == AutocompleteFlag::NEW_PASSWORD) {
- return false;
- }
- return true;
- });
-
- // Evaluate available server-side predictions.
- std::map<const FormFieldData*, PasswordFormFieldPredictionType>
- predicted_fields;
- const FormFieldData* predicted_username_field = nullptr;
- if (form_predictions) {
- FindPredictedElements(password_form->form_data, *form_predictions,
- &predicted_fields);
-
- for (const auto& predicted_pair : predicted_fields) {
- if (predicted_pair.second == PasswordFormFieldPredictionType::kUsername) {
- predicted_username_field = predicted_pair.first;
- break;
- }
- }
- }
-
- // Finally, remove all password fields for which we have a negative
- // prediction, unless they are explicitly marked by the autocomplete attribute
- // as a password.
- base::EraseIf(plausible_inputs, [&predicted_fields, &autocomplete_cache](
- const FormFieldData* input) {
- if (input->form_control_type != "password")
- return false;
- const AutocompleteFlag flag = autocomplete_cache.RetrieveFor(input);
- if (flag == AutocompleteFlag::CURRENT_PASSWORD ||
- flag == AutocompleteFlag::NEW_PASSWORD) {
- return false;
- }
- auto possible_password_field_iterator = predicted_fields.find(input);
- return possible_password_field_iterator != predicted_fields.end() &&
- possible_password_field_iterator->second ==
- PasswordFormFieldPredictionType::kNotPassword;
- });
-
- // Derive the list of all plausible passwords, usernames and the non-password
- // inputs preceding the plausible passwords.
- std::vector<const FormFieldData*> plausible_passwords;
- std::vector<const FormFieldData*> plausible_usernames;
- std::map<const FormFieldData*, const FormFieldData*>
- preceding_text_input_for_plausible_password;
- most_recent_text_input = nullptr;
- plausible_usernames.reserve(plausible_inputs.size());
- for (const FormFieldData* input : plausible_inputs) {
- if (input->form_control_type == "password") {
- plausible_passwords.push_back(input);
- preceding_text_input_for_plausible_password[input] =
- most_recent_text_input;
- } else {
- plausible_usernames.push_back(input);
- most_recent_text_input = input;
- }
- }
-
- // Evaluate autocomplete attributes for username.
- const FormFieldData* username_by_attribute = nullptr;
- for (const FormFieldData* input : plausible_inputs) {
- if (input->form_control_type != "password") {
- if (autocomplete_cache.RetrieveFor(input) == AutocompleteFlag::USERNAME) {
- // Only consider the first occurrence of autocomplete='username'.
- // Multiple occurences hint at the attribute being used incorrectly, in
- // which case sticking to the first one is just a bet.
- if (!username_by_attribute) {
- username_by_attribute = input;
- break;
- }
- }
- }
- }
-
- // Evaluate the context of the fields.
- const FormFieldData* username_field_by_context = nullptr;
- // Use HTML based username detector only if neither server predictions nor
- // autocomplete attributes were useful to detect the username.
- if (!predicted_username_field && !username_by_attribute) {
- username_field_by_context = FindUsernameInPredictions(
- form_data.username_predictions, plausible_usernames);
- }
-
- // Populate all_possible_passwords and form_has_autofilled_value in
- // |password_form|.
- // Contains the first password element for each non-empty password value.
- std::vector<ValueElementPair> all_possible_passwords;
- // Reserve enough space to prevent re-allocation. A re-allocation would
- // invalidate the contents of |seen_values|.
- all_possible_passwords.reserve(passwords_without_heuristics.size());
- std::set<base::StringPiece16> seen_values;
- // Pretend that an empty value has been already seen, so that empty-valued
- // password elements won't get added to |all_possible_passwords|.
- seen_values.insert(base::StringPiece16());
- for (const FormFieldData* password_field : passwords_without_heuristics) {
- if (seen_values.count(password_field->value) > 0)
- continue;
- all_possible_passwords.push_back(
- {password_field->value, password_field->name});
- seen_values.insert(
- base::StringPiece16(all_possible_passwords.back().first));
- }
-
- bool form_has_autofilled_value = false;
- for (const FormFieldData* password_field : passwords_without_heuristics) {
- bool field_has_autofilled_value =
- password_field->properties_mask & FieldPropertiesFlags::AUTOFILLED;
- form_has_autofilled_value |= field_has_autofilled_value;
- }
-
- if (!all_possible_passwords.empty()) {
- password_form->all_possible_passwords = std::move(all_possible_passwords);
- password_form->form_has_autofilled_value = form_has_autofilled_value;
- }
-
- // If for some reason (e.g. only credit card fields, confusing autocomplete
- // attributes) the passwords list is empty, build list based on user input (if
- // there is any non-empty password field) and the type of a field. Also mark
- // that the form should be available only for fallback saving (automatic
- // bubble will not pop up) and filling.
- password_form->only_for_fallback = plausible_passwords.empty();
- if (plausible_passwords.empty()) {
- plausible_passwords = std::move(passwords_without_heuristics);
- preceding_text_input_for_plausible_password =
- std::move(preceding_text_input_for_password_without_heuristics);
- }
-
- // Find the password fields.
- const FormFieldData* password = nullptr;
- const FormFieldData* new_password = nullptr;
- const FormFieldData* confirmation_password = nullptr;
- LocateSpecificPasswords(std::move(plausible_passwords), &password,
- &new_password, &confirmation_password,
- autocomplete_cache);
-
- // Choose the username element.
- const FormFieldData* username_field = nullptr;
- UsernameDetectionMethod username_detection_method =
- UsernameDetectionMethod::NO_USERNAME_DETECTED;
- password_form->username_marked_by_site = false;
-
- if (predicted_username_field) {
- // Server predictions are most trusted, so try them first. Only if the form
- // already has user input and the predicted username field has an empty
- // value, then don't trust the prediction (can be caused by, e.g., a <form>
- // actually contains several forms).
- if (password_fields_level < FieldFilteringLevel::USER_INPUT ||
- !predicted_username_field->value.empty()) {
- username_field = predicted_username_field;
- password_form->was_parsed_using_autofill_predictions = true;
- username_detection_method =
- UsernameDetectionMethod::SERVER_SIDE_PREDICTION;
- }
- }
-
- if (!username_field && username_by_attribute) {
- // Next in the trusted queue: autocomplete attributes.
- username_field = username_by_attribute;
- username_detection_method = UsernameDetectionMethod::AUTOCOMPLETE_ATTRIBUTE;
- }
-
- if (!username_field && username_field_by_context) {
- // Last step before base heuristics: HTML-based classifier.
- username_field = username_field_by_context;
- username_detection_method = UsernameDetectionMethod::HTML_BASED_CLASSIFIER;
- }
-
- // Compute base heuristic for username detection.
- const FormFieldData* base_heuristic_username = nullptr;
- if (password) {
- base_heuristic_username =
- preceding_text_input_for_plausible_password[password];
- }
- if (!base_heuristic_username && new_password) {
- base_heuristic_username =
- preceding_text_input_for_plausible_password[new_password];
- }
-
- // Apply base heuristic for username detection.
- if (!username_field) {
- username_field = base_heuristic_username;
- if (username_field)
- username_detection_method = UsernameDetectionMethod::BASE_HEURISTIC;
- } else if (base_heuristic_username == username_field &&
- username_detection_method !=
- UsernameDetectionMethod::AUTOCOMPLETE_ATTRIBUTE) {
- // TODO(crbug.com/786404): when the bug is fixed, remove this block and
- // calculate |base_heuristic_username| only if |username_field| is null.
- // This block was added to measure the impact of server-side predictions and
- // HTML based classifier compared to "old classifiers" (the based heuristic
- // and 'autocomplete' attribute).
- username_detection_method = UsernameDetectionMethod::BASE_HEURISTIC;
- }
- UMA_HISTOGRAM_ENUMERATION(
- "PasswordManager.UsernameDetectionMethod", username_detection_method,
- UsernameDetectionMethod::USERNAME_DETECTION_METHOD_COUNT);
-
- // Populate the username fields in |password_form|.
- if (username_field) {
- password_form->username_element =
- FieldName(username_field, "anonymous_username");
- password_form->username_value = username_field->value;
- if ((username_field->properties_mask &
- (FieldPropertiesFlags::USER_TYPED |
- FieldPropertiesFlags::AUTOFILLED)) &&
- !username_field->typed_value.empty()) {
- password_form->username_value = username_field->typed_value;
- }
- }
-
- // Populate the password fields in |password_form|.
- if (password) {
- password_form->password_element = FieldName(password, "anonymous_password");
- password_form->password_value = password->value;
- if ((password->properties_mask & (FieldPropertiesFlags::USER_TYPED |
- FieldPropertiesFlags::AUTOFILLED)) &&
- !password->typed_value.empty()) {
- password_form->password_value = password->typed_value;
- }
- }
- if (new_password) {
- password_form->new_password_element =
- FieldName(new_password, "anonymous_new_password");
- password_form->new_password_value = new_password->value;
- if (autocomplete_cache.RetrieveFor(new_password) ==
- AutocompleteFlag::NEW_PASSWORD) {
- password_form->new_password_marked_by_site = true;
- }
- if (confirmation_password) {
- password_form->confirmation_password_element =
- FieldName(confirmation_password, "anonymous_confirmation_password");
- }
- }
-
- // Populate |all_possible_usernames| in |password_form|.
- ValueElementVector all_possible_usernames;
- for (const FormFieldData* plausible_username : plausible_usernames) {
- if (plausible_username == username_field)
- continue;
- auto pair = MakePossibleUsernamePair(plausible_username);
- if (!pair.first.empty())
- all_possible_usernames.push_back(std::move(pair));
- }
- password_form->all_possible_usernames = std::move(all_possible_usernames);
-
- password_form->origin = std::move(form_origin);
- password_form->signon_realm = GetSignOnRealm(password_form->origin);
- password_form->scheme = PasswordForm::Scheme::kHtml;
- password_form->preferred = false;
- password_form->blacklisted_by_user = false;
- password_form->type = PasswordForm::Type::kManual;
-
- return true;
-}
-
bool HasGaiaSchemeAndHost(const WebFormElement& form) {
GURL form_url = form.GetDocument().Url();
GURL gaia_url = GaiaUrls::GetInstance()->gaia_url();
@@ -791,13 +74,6 @@ bool HasGaiaSchemeAndHost(const WebFormElement& form) {
} // namespace
-AutocompleteFlag AutocompleteFlagForElement(const WebInputElement& element) {
- static const base::NoDestructor<WebString> kAutocomplete(("autocomplete"));
- return ExtractAutocompleteFlag(
- element.GetAttribute(*kAutocomplete)
- .Utf8(WebString::UTF8ConversionMode::kStrictReplacingErrorsWithFFFD));
-}
-
re2::RE2* CreateMatcher(void* instance, const char* pattern) {
re2::RE2::Options options;
options.set_case_sensitive(false);
@@ -854,7 +130,8 @@ bool IsGaiaWithSkipSavePasswordForm(const blink::WebFormElement& form) {
std::unique_ptr<PasswordForm> CreateSimplifiedPasswordFormFromWebForm(
const WebFormElement& web_form,
- const FieldDataManager* field_data_manager) {
+ const FieldDataManager* field_data_manager,
+ UsernameDetectorCache* username_detector_cache) {
if (web_form.IsNull())
return nullptr;
@@ -867,32 +144,6 @@ std::unique_ptr<PasswordForm> CreateSimplifiedPasswordFormFromWebForm(
IsGaiaWithSkipSavePasswordForm(web_form) ||
IsGaiaReauthenticationForm(web_form);
- if (!WebFormElementToFormData(web_form, WebFormControlElement(),
- field_data_manager, form_util::EXTRACT_VALUE,
- &password_form->form_data,
- nullptr /* FormFieldData */)) {
- return nullptr;
- }
-
- return password_form;
-}
-
-std::unique_ptr<PasswordForm> CreatePasswordFormFromWebForm(
- const WebFormElement& web_form,
- const FieldDataManager* field_data_manager,
- const FormsPredictionsMap* form_predictions,
- UsernameDetectorCache* username_detector_cache) {
- if (web_form.IsNull())
- return nullptr;
-
- auto password_form = std::make_unique<PasswordForm>();
- password_form->action = form_util::GetCanonicalActionForForm(web_form);
- if (!password_form->action.is_valid())
- return nullptr;
- password_form->form_data.is_gaia_with_skip_save_password_form =
- IsGaiaWithSkipSavePasswordForm(web_form) ||
- IsGaiaReauthenticationForm(web_form);
-
blink::WebVector<WebFormControlElement> control_elements;
web_form.GetFormControlElements(control_elements);
if (control_elements.empty())
@@ -904,20 +155,18 @@ std::unique_ptr<PasswordForm> CreatePasswordFormFromWebForm(
nullptr /* FormFieldData */)) {
return nullptr;
}
+ password_form->form_data.username_predictions =
+ GetUsernamePredictions(control_elements.ReleaseVector(),
+ password_form->form_data, username_detector_cache);
- if (!GetPasswordForm(
- form_util::GetCanonicalOriginForDocument(web_form.GetDocument()),
- control_elements.ReleaseVector(), password_form.get(),
- form_predictions, username_detector_cache)) {
- return nullptr;
- }
return password_form;
}
std::unique_ptr<PasswordForm>
CreateSimplifiedPasswordFormFromUnownedInputElements(
const WebLocalFrame& frame,
- const FieldDataManager* field_data_manager) {
+ const FieldDataManager* field_data_manager,
+ UsernameDetectorCache* username_detector_cache) {
std::vector<WebElement> fieldsets;
std::vector<WebFormControlElement> control_elements =
form_util::GetUnownedFormFieldElements(frame.GetDocument().All(),
@@ -936,38 +185,8 @@ CreateSimplifiedPasswordFormFromUnownedInputElements(
password_form->origin =
form_util::GetCanonicalOriginForDocument(frame.GetDocument());
password_form->signon_realm = GetSignOnRealm(password_form->origin);
- return password_form;
-}
-
-std::unique_ptr<PasswordForm> CreatePasswordFormFromUnownedInputElements(
- const WebLocalFrame& frame,
- const FieldDataManager* field_data_manager,
- const FormsPredictionsMap* form_predictions,
- UsernameDetectorCache* username_detector_cache) {
- std::vector<WebElement> fieldsets;
- std::vector<WebFormControlElement> control_elements =
- form_util::GetUnownedFormFieldElements(frame.GetDocument().All(),
- &fieldsets);
- if (control_elements.empty())
- return nullptr;
-
- auto password_form = std::make_unique<PasswordForm>();
- if (!UnownedPasswordFormElementsAndFieldSetsToFormData(
- fieldsets, control_elements, nullptr, frame.GetDocument(),
- field_data_manager, form_util::EXTRACT_VALUE,
- &password_form->form_data, nullptr /* FormFieldData */)) {
- return nullptr;
- }
-
- if (!GetPasswordForm(
- form_util::GetCanonicalOriginForDocument(frame.GetDocument()),
- control_elements, password_form.get(), form_predictions,
- username_detector_cache)) {
- return nullptr;
- }
-
- // No actual action on the form, so use the the origin as the action.
- password_form->action = password_form->origin;
+ password_form->form_data.username_predictions = GetUsernamePredictions(
+ control_elements, password_form->form_data, username_detector_cache);
return password_form;
}
diff --git a/chromium/components/autofill/content/renderer/password_form_conversion_utils.h b/chromium/components/autofill/content/renderer/password_form_conversion_utils.h
index e02034c893b..3674d438d72 100644
--- a/chromium/components/autofill/content/renderer/password_form_conversion_utils.h
+++ b/chromium/components/autofill/content/renderer/password_form_conversion_utils.h
@@ -14,13 +14,11 @@
#include "base/strings/string_piece.h"
#include "components/autofill/content/renderer/html_based_username_detector.h"
#include "components/autofill/core/common/password_form.h"
-#include "components/autofill/core/common/password_form_field_prediction_map.h"
#include "third_party/blink/public/platform/web_string.h"
#include "url/gurl.h"
namespace blink {
class WebFormElement;
-class WebInputElement;
class WebLocalFrame;
}
@@ -31,32 +29,8 @@ class RE2;
namespace autofill {
struct PasswordForm;
-
class FieldDataManager;
-enum UsernameDetectionMethod {
- NO_USERNAME_DETECTED,
- BASE_HEURISTIC,
- HTML_BASED_CLASSIFIER,
- AUTOCOMPLETE_ATTRIBUTE,
- SERVER_SIDE_PREDICTION,
- USERNAME_DETECTION_METHOD_COUNT
-};
-
-// The susbset of autocomplete flags related to passwords.
-enum class AutocompleteFlag {
- NONE,
- USERNAME,
- CURRENT_PASSWORD,
- NEW_PASSWORD,
- // Represents the whole family of cc-* flags.
- CREDIT_CARD
-};
-
-// Returns the AutocompleteFlag derived from |element|'s autocomplete attribute.
-AutocompleteFlag AutocompleteFlagForElement(
- const blink::WebInputElement& element);
-
// The caller of this function is responsible for deleting the returned object.
re2::RE2* CreateMatcher(void* instance, const char* pattern);
@@ -66,34 +40,11 @@ bool IsGaiaReauthenticationForm(const blink::WebFormElement& form);
// Tests whether the given form is a GAIA form with a skip password argument.
bool IsGaiaWithSkipSavePasswordForm(const blink::WebFormElement& form);
-// Create a PasswordForm from DOM form. Webkit doesn't allow storing
-// custom metadata to DOM nodes, so we have to do this every time an event
-// happens with a given form and compare against previously Create'd forms
-// to identify..which sucks.
-// If an element of |form| has an entry in |field_data_manager|, the associated
-// string is used instead of the element's value to create the PasswordForm.
-// |form_predictions| is Autofill server response, if present it's used for
-// overwriting default username element selection.
-// |username_detector_cache| is used by the built-in HTML based username
-// detector to cache results. Can be null.
-std::unique_ptr<PasswordForm> CreatePasswordFormFromWebForm(
- const blink::WebFormElement& form,
- const FieldDataManager* field_data_manager,
- const FormsPredictionsMap* form_predictions,
- UsernameDetectorCache* username_detector_cache);
-
// Creates a |PasswordForm| from DOM which only contains the |form_data| as well
// as origin, action and gaia flags.
std::unique_ptr<PasswordForm> CreateSimplifiedPasswordFormFromWebForm(
const blink::WebFormElement& form,
- const FieldDataManager* field_data_manager);
-
-// Same as CreatePasswordFormFromWebForm() but for input elements that are not
-// enclosed in <form> element.
-std::unique_ptr<PasswordForm> CreatePasswordFormFromUnownedInputElements(
- const blink::WebLocalFrame& frame,
const FieldDataManager* field_data_manager,
- const FormsPredictionsMap* form_predictions,
UsernameDetectorCache* username_detector_cache);
// Same as CreateSimlePasswordFormFromWebForm() but for input elements that are
@@ -101,7 +52,8 @@ std::unique_ptr<PasswordForm> CreatePasswordFormFromUnownedInputElements(
std::unique_ptr<PasswordForm>
CreateSimplifiedPasswordFormFromUnownedInputElements(
const blink::WebLocalFrame& frame,
- const FieldDataManager* field_data_manager);
+ const FieldDataManager* field_data_manager,
+ UsernameDetectorCache* username_detector_cache);
// The "Realm" for the sign-on. This is scheme, host, port.
std::string GetSignOnRealm(const GURL& origin);
diff --git a/chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc b/chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
index 02b36b862d4..7b67bc51d62 100644
--- a/chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
+++ b/chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
@@ -5,47 +5,24 @@
#include <stddef.h>
#include <memory>
-#include "base/stl_util.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_feature_list.h"
-#include "build/build_config.h"
-#include "components/autofill/content/renderer/field_data_manager.h"
-#include "components/autofill/content/renderer/form_autofill_util.h"
#include "components/autofill/content/renderer/password_form_conversion_utils.h"
-#include "components/autofill/core/browser/form_structure.h"
-#include "components/autofill/core/common/form_field_data.h"
-#include "components/autofill/core/common/password_form.h"
#include "content/public/test/render_view_test.h"
#include "google_apis/gaia/gaia_urls.h"
-#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/web_document.h"
-#include "third_party/blink/public/web/web_form_control_element.h"
#include "third_party/blink/public/web/web_form_element.h"
-#include "third_party/blink/public/web/web_input_element.h"
#include "third_party/blink/public/web/web_local_frame.h"
-using blink::WebElement;
-using blink::WebFormControlElement;
using blink::WebFormElement;
-using blink::WebInputElement;
using blink::WebLocalFrame;
-using blink::WebString;
using blink::WebVector;
namespace autofill {
-using mojom::PasswordFormFieldPredictionType;
-
namespace {
-const char kTestFormActionURL[] = "http://cnn.com";
-
// A builder to produce HTML code for a password form composed of the desired
// number and kinds of username and password fields.
class PasswordFormBuilder {
@@ -73,20 +50,6 @@ class PasswordFormBuilder {
name_and_id, name_and_id, value, autocomplete_attribute.c_str());
}
- // Add a text field with name, id, value, label and placeholder,
- // without autocomplete.
- void AddTextFieldWithoutAutocomplete(const char* name,
- const char* id,
- const char* value,
- const char* label,
- const char* placeholder) {
- base::StringAppendF(&html_,
- "<LABEL for=\"%s\">%s</LABEL>"
- "<INPUT type=\"text\" name=\"%s\" id=\"%s\" "
- "value=\"%s\" placeholder=\"%s\"/>",
- id, label, name, id, value, placeholder);
- }
-
// Appends a new password-type field at the end of the form, having the
// specified |name_and_id|, |value|, and |autocomplete| attributes. Special
// values for |autocomplete| are the same as in AddTextField.
@@ -102,19 +65,6 @@ class PasswordFormBuilder {
name_and_id, name_and_id, value, autocomplete_attribute.c_str());
}
- // Appends a disabled text-type field at the end of the form.
- void AddDisabledUsernameField() {
- html_ += "<INPUT name=\"disabled field\" type=\"text\" disabled/>";
- }
-
- // Appends a disabled password-type field at the end of the form.
- void AddDisabledPasswordField() {
- html_ += "<INPUT name=\"disabled field\" type=\"password\" disabled/>";
- }
-
- // Appends a hidden field at the end of the form.
- void AddHiddenField() { html_ += "<INPUT type=\"hidden\"/>"; }
-
// Appends a new hidden-type field at the end of the form, having the
// specified |name_and_id| and |value| attributes.
void AddHiddenField(const char* name_and_id, const char* value) {
@@ -123,68 +73,10 @@ class PasswordFormBuilder {
name_and_id, name_and_id, value);
}
- // Append a text field with "display: none".
- void AddNonDisplayedTextField(const char* name_and_id, const char* value) {
- base::StringAppendF(
- &html_,
- "<INPUT type=\"text\" name=\"%s\" id=\"%s\" value=\"%s\""
- "style=\"display: none;\"/>",
- name_and_id, name_and_id, value);
- }
-
- // Append a password field with "display: none".
- void AddNonDisplayedPasswordField(const char* name_and_id,
- const char* value) {
- base::StringAppendF(
- &html_,
- "<INPUT type=\"password\" name=\"%s\" id=\"%s\" value=\"%s\""
- "style=\"display: none;\"/>",
- name_and_id, name_and_id, value);
- }
-
- // Append a text field with "visibility: hidden".
- void AddNonVisibleTextField(const char* name_and_id, const char* value) {
- base::StringAppendF(
- &html_,
- "<INPUT type=\"text\" name=\"%s\" id=\"%s\" value=\"%s\""
- "style=\"visibility: hidden;\"/>",
- name_and_id, name_and_id, value);
- }
-
- // Append a password field with "visibility: hidden".
- void AddNonVisiblePasswordField(const char* name_and_id, const char* value) {
- base::StringAppendF(
- &html_,
- "<INPUT type=\"password\" name=\"%s\" id=\"%s\" value=\"%s\""
- "style=\"visibility: hidden;\"/>",
- name_and_id, name_and_id, value);
- }
-
- // Add a field with a given type. Useful to add non-text fields.
- void AddFieldWithType(const char* name_and_id, const char* type) {
- base::StringAppendF(&html_, "<INPUT type=\"%s\" name=\"%s\" id=\"%s\"/>",
- type, name_and_id, name_and_id);
- }
-
- // Appends a new submit-type field at the end of the form with the specified
- // |name|.
- void AddSubmitButton(const char* name) {
- base::StringAppendF(
- &html_, "<INPUT type=\"submit\" name=\"%s\" value=\"Submit\"/>", name);
- }
-
// Returns the HTML code for the form containing the fields that have been
// added so far.
std::string ProduceHTML() const { return html_ + "</FORM>"; }
- // Appends a field of |type| without name or id attribute at the end of the
- // form.
- void AddAnonymousInputField(const char* type) {
- std::string type_attribute(type ? base::StringPrintf("type=\"%s\"", type)
- : "");
- base::StringAppendF(&html_, "<INPUT %s/>", type_attribute.c_str());
- }
-
private:
std::string html_;
@@ -197,74 +89,6 @@ class PasswordFormConversionUtilsTest : public content::RenderViewTest {
~PasswordFormConversionUtilsTest() override = default;
protected:
- // Loads the given |html|, retrieves the sole WebFormElement from it, and then
- // calls CreatePasswordForm(), passing it the |predictions| to convert it to
- // a PasswordForm. If |with_user_input| == true it's considered that all
- // values in the form elements came from the user input.
- std::unique_ptr<PasswordForm> LoadHTMLAndConvertForm(
- const std::string& html,
- FormsPredictionsMap* predictions,
- bool with_user_input) {
- WebFormElement form;
- LoadWebFormFromHTML(html, &form, nullptr);
-
- WebVector<WebFormControlElement> control_elements;
- form.GetFormControlElements(control_elements);
- FieldDataManager field_data_manager;
- for (size_t i = 0; i < control_elements.size(); ++i) {
- WebInputElement* input_element = ToWebInputElement(&control_elements[i]);
- if (input_element->HasAttribute("set-activated-submit"))
- input_element->SetActivatedSubmit(true);
- if (with_user_input) {
- field_data_manager.UpdateFieldDataMap(control_elements[i],
- input_element->Value().Utf16(),
- FieldPropertiesFlags::USER_TYPED);
- }
- }
-
- return CreatePasswordFormFromWebForm(
- form, with_user_input ? &field_data_manager : nullptr, predictions,
- &username_detector_cache_);
- }
-
- // Iterates on the form generated by the |html| and adds the fields and type
- // predictions corresponding to |predictions_positions| to |predictions|.
- void SetPredictions(const std::string& html,
- FormsPredictionsMap* predictions,
- const std::map<int, PasswordFormFieldPredictionType>&
- predictions_positions) {
- WebFormElement form;
- LoadWebFormFromHTML(html, &form, nullptr);
-
- FormData form_data;
- ASSERT_TRUE(form_util::WebFormElementToFormData(
- form, WebFormControlElement(), nullptr, form_util::EXTRACT_NONE,
- &form_data, nullptr));
-
- FormStructure form_structure(form_data);
-
- int field_index = 0;
- for (auto field = form_structure.begin(); field != form_structure.end();
- ++field, ++field_index) {
- if (predictions_positions.find(field_index) !=
- predictions_positions.end()) {
- (*predictions)[form_data][*(*field)] =
- predictions_positions.find(field_index)->second;
- }
- }
- }
-
- void GetFirstForm(WebFormElement* form) {
- WebLocalFrame* frame = GetMainFrame();
- ASSERT_TRUE(frame);
-
- WebVector<WebFormElement> forms;
- frame->GetDocument().Forms(forms);
- ASSERT_LE(1U, forms.size());
-
- *form = forms[0];
- }
-
// Loads the given |html| and retrieves the sole WebFormElement from it.
void LoadWebFormFromHTML(const std::string& html,
WebFormElement* form,
@@ -277,1799 +101,27 @@ class PasswordFormConversionUtilsTest : public content::RenderViewTest {
GetFirstForm(form);
}
- bool ExtractFormDataForFirstForm(FormData* data) {
- WebFormElement form;
- GetFirstForm(&form);
- return form_util::ExtractFormData(form, data);
- }
-
void TearDown() override {
- username_detector_cache_.clear();
content::RenderViewTest::TearDown();
}
- uint32_t GetRendererIdFromWebElementId(WebString id) {
+ private:
+ void GetFirstForm(WebFormElement* form) {
WebLocalFrame* frame = GetMainFrame();
- if (!frame || frame->GetDocument().IsNull())
- return FormData::kNotSetFormRendererId;
- WebElement element = frame->GetDocument().GetElementById(id);
- if (element.IsNull())
- return FormData::kNotSetFormRendererId;
- return element.To<WebInputElement>().UniqueRendererFormControlId();
- }
+ ASSERT_TRUE(frame);
- UsernameDetectorCache username_detector_cache_;
+ WebVector<WebFormElement> forms;
+ frame->GetDocument().Forms(forms);
+ ASSERT_LE(1U, forms.size());
+
+ *form = forms[0];
+ }
- private:
DISALLOW_COPY_AND_ASSIGN(PasswordFormConversionUtilsTest);
};
} // namespace
-TEST_F(PasswordFormConversionUtilsTest, BasicFormAttributes) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("username", "johnsmith", nullptr);
- builder.AddSubmitButton("inactive_submit");
- builder.AddSubmitButton("active_submit");
- builder.AddSubmitButton("inactive_submit2");
- builder.AddPasswordField("password", "secret", nullptr);
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
-
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ("data:", password_form->signon_realm);
- EXPECT_EQ(GURL(kTestFormActionURL), password_form->action);
- EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("johnsmith"), password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value);
- EXPECT_EQ(PasswordForm::Scheme::kHtml, password_form->scheme);
- EXPECT_FALSE(password_form->preferred);
- EXPECT_FALSE(password_form->blacklisted_by_user);
- EXPECT_EQ(PasswordForm::Type::kManual, password_form->type);
-}
-
-TEST_F(PasswordFormConversionUtilsTest, DisabledFieldsAreIgnored) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("username", "johnsmith", nullptr);
- builder.AddDisabledUsernameField();
- builder.AddDisabledPasswordField();
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("johnsmith"), password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value);
-}
-
-// When not enough fields are enabled to parse the form, the result should still
-// be not null. It must contain only minimal information, so that it is not used
-// for fill on load, for example. It must contain the full FormData, so that the
-// new parser can be run as well.
-TEST_F(PasswordFormConversionUtilsTest, OnlyDisabledFields) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddDisabledUsernameField();
- builder.AddDisabledPasswordField();
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
- EXPECT_TRUE(password_form->username_element.empty());
- EXPECT_TRUE(password_form->password_element.empty());
- EXPECT_TRUE(password_form->new_password_element.empty());
- EXPECT_EQ(2u, password_form->form_data.fields.size());
-}
-
-TEST_F(PasswordFormConversionUtilsTest, HTMLDetector_DeveloperGroupAttributes) {
- // Each test case consists of a set of parameters to be plugged into the
- // PasswordFormBuilder below, plus the corresponding expectations.
- // The test data contains cases that are identified by HTML detector, and not
- // by base heuristic. Thus, username field does not necessarely have to be
- // right before password field.
- // These tests basically check searching in developer group (i.e. name and id
- // attribute, concatenated, with "$" guard in between).
- struct TestCase {
- // Field parameters represent, in order of appearance, field name, field id
- // and field value.
- const char* first_text_field_parameters[3];
- const char* second_text_field_parameters[3];
- const char* expected_username_element;
- const WebString expected_username_id;
- const char* expected_username_value;
- } cases[] = {
- // There are both field name and id.
- {{"username", "x1d", "johnsmith"},
- {"email", "y1d", "js@google.com"},
- "username",
- "x1d",
- "johnsmith"},
- // there is no field id.
- {{"username", "x1d", "johnsmith"},
- {"email", "y1d", "js@google.com"},
- "username",
- "x1d",
- "johnsmith"},
- // Upper or mixed case shouldn't matter.
- {{"uSeRnAmE", "x1d", "johnsmith"},
- {"email", "y1d", "js@google.com"},
- "uSeRnAmE",
- "x1d",
- "johnsmith"},
- // Check removal of special characters.
- {{"u1_s2-e3~r4/n5(a)6m#e", "x1d", "johnsmith"},
- {"email", "y1d", "js@google.com"},
- "u1_s2-e3~r4/n5(a)6m#e",
- "x1d",
- "johnsmith"},
- // Check guard between field name and field id.
- {{"us", "ername", "johnsmith"},
- {"email", "id", "js@google.com"},
- "email",
- "id",
- "js@google.com"},
- // Check removal of fields with latin negative words in developer group.
- {{"email", "x", "js@google.com"},
- {"fake_username", "y", "johnsmith"},
- "email",
- "x",
- "js@google.com"},
- {{"email", "mail", "js@google.com"},
- {"user_name", "fullname", "johnsmith"},
- "email",
- "mail",
- "js@google.com"},
- // Identify latin translations of "username".
- {{"benutzername", "x", "johnsmith"},
- {"email", "y", "js@google.com"},
- "benutzername",
- "x",
- "johnsmith"},
- // Identify latin translations of "user".
- {{"utilizator", "x1d", "johnsmith"},
- {"email", "y1d", "js@google.com"},
- "utilizator",
- "x1d",
- "johnsmith"},
- // Identify technical words.
- {{"loginid", "x1d", "johnsmith"},
- {"email", "y1d", "js@google.com"},
- "loginid",
- "x1d",
- "johnsmith"},
- // Identify weak words.
- {{"usrname", "x1d", "johnsmith"},
- {"email", "y1d", "js@google.com"},
- "email",
- "y1d",
- "js@google.com"},
- // If a word matches in maximum 2 fields, it is accepted.
- // First encounter is selected as username.
- {{"username", "x1d", "johnsmith"},
- {"repeat_username", "y1d", "johnsmith"},
- "username",
- "x1d",
- "johnsmith"},
- // A short word should be enclosed between delimiters. Otherwise, an
- // Occurrence doesn't count.
- {{"identity_name", "idn", "johnsmith"},
- {"id", "xid", "123"},
- "id",
- "xid",
- "123"}};
-
- for (size_t i = 0; i < base::size(cases); ++i) {
- SCOPED_TRACE(testing::Message() << "Iteration " << i);
-
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextFieldWithoutAutocomplete(
- cases[i].first_text_field_parameters[0],
- cases[i].first_text_field_parameters[1],
- cases[i].first_text_field_parameters[2], "", "");
- builder.AddTextFieldWithoutAutocomplete(
- cases[i].second_text_field_parameters[0],
- cases[i].second_text_field_parameters[1],
- cases[i].second_text_field_parameters[2], "", "");
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- username_detector_cache_.clear();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
-
- uint32_t username_renderer_id =
- GetRendererIdFromWebElementId(cases[i].expected_username_id);
-
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_element),
- password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_value),
- password_form->username_value);
- // Check that the username field was found by HTML detector.
- ASSERT_EQ(1u, username_detector_cache_.size());
- ASSERT_FALSE(username_detector_cache_.begin()->second.empty());
- EXPECT_EQ(username_renderer_id,
- username_detector_cache_.begin()->second[0]);
- }
-}
-
-TEST_F(PasswordFormConversionUtilsTest, HTMLDetector_SeveralDetections) {
- // If word matches in more than 2 fields, we don't match on it.
- // We search for match with another word.
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextFieldWithoutAutocomplete("address", "xuser", "someaddress", "",
- "");
- builder.AddTextFieldWithoutAutocomplete("loginid", "yuser", "johnsmith", "",
- "");
- builder.AddTextFieldWithoutAutocomplete("tel", "zuser", "sometel", "", "");
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- DCHECK(username_detector_cache_.empty());
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
-
- uint32_t username_renderer_id = GetRendererIdFromWebElementId("yuser");
-
- ASSERT_TRUE(password_form);
-
- EXPECT_EQ(base::UTF8ToUTF16("loginid"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("johnsmith"), password_form->username_value);
- // Check that the username field was found by HTML detector.
- ASSERT_EQ(1u, username_detector_cache_.size());
- ASSERT_EQ(1u, username_detector_cache_.begin()->second.size());
- EXPECT_EQ(username_renderer_id, username_detector_cache_.begin()->second[0]);
-}
-
-TEST_F(PasswordFormConversionUtilsTest, HTMLDetector_UserGroupAttributes) {
- // Each test case consists of a set of parameters to be plugged into the
- // PasswordFormBuilder below, plus the corresponding expectations.
- // The test data contains cases that are identified by HTML detector, and not
- // by base heuristic. Thus, username field does not necessarely have to be
- // right before password field.
- // These tests basically check searching in user group.
- struct TestCase {
- // Field parameters represent, in order of appearance, field name, field
- // id, field value and field label or placeholder.
- // Field name and field id don't contain any significant information.
- const char* first_text_field_parameters[4];
- const char* second_text_field_parameters[4];
- const char* expected_username_element;
- const WebString expected_username_id;
- const char* expected_username_value;
- } cases[] = {
- // Label information will decide username.
- {{"name1", "id1", "johnsmith", "Username:"},
- {"name2", "id2", "js@google.com", "Email:"},
- "name1",
- "id1",
- "johnsmith"},
- // Placeholder information will decide username.
- {{"name1", "id1", "js@google.com", "Email:"},
- {"name2", "id2", "johnsmith", "Username:"},
- "name2",
- "id2",
- "johnsmith"},
- // Check removal of special characters.
- {{"name1", "id1", "johnsmith", "U s er n a m e:"},
- {"name2", "id2", "js@google.com", "Email:"},
- "name1",
- "id1",
- "johnsmith"},
- // Check removal of fields with latin negative words in user group.
- {{"name1", "id1", "johnsmith", "Username password:"},
- {"name2", "id2", "js@google.com", "Email:"},
- "name2",
- "id2",
- "js@google.com"},
- // Check removal of fields with non-latin negative words in user group.
- {{"name1", "id1", "js@google.com", "Email:"},
- {"name2", "id2", "johnsmith", "የይለፍቃልየይለፍቃል:"},
- "name1",
- "id1",
- "js@google.com"},
- // Identify latin translations of "username".
- {{"name1", "id1", "johnsmith", "Username:"},
- {"name2", "id2", "js@google.com", "Email:"},
- "name1",
- "id1",
- "johnsmith"},
- // Identify non-latin translations of "username".
- {{"name1", "id1", "johnsmith", "用户名:"},
- {"name2", "id2", "js@google.com", "Email:"},
- "name1",
- "id1",
- "johnsmith"},
- // Identify latin translations of "user".
- {{"name1", "id1", "johnsmith", "Wosuta:"},
- {"name2", "id2", "js@google.com", "Email:"},
- "name1",
- "id1",
- "johnsmith"},
- // Identify non-latin translations of "user".
- {{"name1", "id1", "johnsmith", "истифода:"},
- {"name2", "id2", "js@google.com", "Email:"},
- "name1",
- "id1",
- "johnsmith"},
- // Identify weak words.
- {{"name1", "id1", "johnsmith", "Insert your login details:"},
- {"name2", "id2", "js@google.com", "Insert your email:"},
- "name1",
- "id1",
- "johnsmith"},
- // Check user group priority, compared to developer group.
- // User group should have higher priority than developer group.
- {{"email", "id1", "js@google.com", "Username:"},
- {"username", "id2", "johnsmith", "Email:"},
- "email",
- "id1",
- "js@google.com"},
- // Check treatment for short dictionary words. "uid" has higher priority,
- // but its occurrence is ignored because it is a part of another word.
- {{"name1", "noword", "johnsmith", "Insert your id:"},
- {"name2", "uidentical", "js@google.com", "Insert something:"},
- "name1",
- "noword",
- "johnsmith"}};
-
- for (size_t i = 0; i < base::size(cases); ++i) {
- SCOPED_TRACE(testing::Message() << "Iteration " << i);
-
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextFieldWithoutAutocomplete(
- cases[i].first_text_field_parameters[0],
- cases[i].first_text_field_parameters[1],
- cases[i].first_text_field_parameters[2],
- cases[i].first_text_field_parameters[3], "");
- builder.AddTextFieldWithoutAutocomplete(
- cases[i].second_text_field_parameters[0],
- cases[i].second_text_field_parameters[1],
- cases[i].second_text_field_parameters[2], "",
- cases[i].second_text_field_parameters[3]);
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- username_detector_cache_.clear();
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
-
- uint32_t username_renderer_id =
- GetRendererIdFromWebElementId(cases[i].expected_username_id);
-
- ASSERT_TRUE(password_form);
-
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_element),
- password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_value),
- password_form->username_value);
- // Check that the username field was found by HTML detector.
- ASSERT_EQ(1u, username_detector_cache_.size());
- ASSERT_FALSE(username_detector_cache_.begin()->second.empty());
- EXPECT_EQ(username_renderer_id,
- username_detector_cache_.begin()->second[0]);
- }
-}
-
-TEST_F(PasswordFormConversionUtilsTest, HTMLDetectorCache) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("unknown", "12345", nullptr);
- builder.AddTextField("something", "smith", nullptr);
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
- WebFormElement form;
- LoadWebFormFromHTML(html, &form, nullptr);
- UsernameDetectorCache detector_cache;
-
- // No signals from HTML attributes. The classifier found nothing and cached
- // it.
- base::HistogramTester histogram_tester;
- std::unique_ptr<PasswordForm> password_form =
- CreatePasswordFormFromWebForm(form, nullptr, nullptr, &detector_cache);
-
- EXPECT_TRUE(password_form);
- ASSERT_EQ(1u, detector_cache.size());
- EXPECT_EQ(form.UniqueRendererFormId(), detector_cache.begin()->first);
- EXPECT_TRUE(detector_cache.begin()->second.empty());
- histogram_tester.ExpectUniqueSample("PasswordManager.UsernameDetectionMethod",
- UsernameDetectionMethod::BASE_HEURISTIC,
- 1);
-
- // Changing attributes would change the classifier's output. But the output
- // will be the same because it was cached in |username_detector_cache|.
- WebVector<WebFormControlElement> control_elements;
- form.GetFormControlElements(control_elements);
- control_elements[0].SetAttribute("name", "id");
- password_form =
- CreatePasswordFormFromWebForm(form, nullptr, nullptr, &detector_cache);
- EXPECT_TRUE(password_form);
- ASSERT_EQ(1u, detector_cache.size());
- EXPECT_EQ(form.UniqueRendererFormId(), detector_cache.begin()->first);
- EXPECT_TRUE(detector_cache.begin()->second.empty());
- histogram_tester.ExpectUniqueSample("PasswordManager.UsernameDetectionMethod",
- UsernameDetectionMethod::BASE_HEURISTIC,
- 2);
-
- // Clear the cache. The classifier will find username field and cache it.
- detector_cache.clear();
- ASSERT_EQ(4u, control_elements.size());
- password_form =
- CreatePasswordFormFromWebForm(form, nullptr, nullptr, &detector_cache);
- EXPECT_TRUE(password_form);
- ASSERT_EQ(1u, detector_cache.size());
- EXPECT_EQ(form.UniqueRendererFormId(), detector_cache.begin()->first);
- ASSERT_EQ(1u, detector_cache.begin()->second.size());
- EXPECT_EQ(control_elements[0].UniqueRendererFormControlId(),
- detector_cache.begin()->second[0]);
- EXPECT_THAT(
- histogram_tester.GetAllSamples("PasswordManager.UsernameDetectionMethod"),
- testing::UnorderedElementsAre(
- base::Bucket(UsernameDetectionMethod::BASE_HEURISTIC, 2),
- base::Bucket(UsernameDetectionMethod::HTML_BASED_CLASSIFIER, 1)));
-
- // Change the attributes again ("username" is stronger signal than "login"),
- // but keep the cache. The classifier's output should be the same.
- control_elements[1].SetAttribute("name", "username");
- password_form =
- CreatePasswordFormFromWebForm(form, nullptr, nullptr, &detector_cache);
- EXPECT_TRUE(password_form);
- ASSERT_EQ(1u, detector_cache.size());
- EXPECT_EQ(form.UniqueRendererFormId(), detector_cache.begin()->first);
- ASSERT_EQ(1u, detector_cache.begin()->second.size());
- EXPECT_EQ(control_elements[0].UniqueRendererFormControlId(),
- detector_cache.begin()->second[0]);
- EXPECT_THAT(
- histogram_tester.GetAllSamples("PasswordManager.UsernameDetectionMethod"),
- testing::UnorderedElementsAre(
- base::Bucket(UsernameDetectionMethod::BASE_HEURISTIC, 2),
- base::Bucket(UsernameDetectionMethod::HTML_BASED_CLASSIFIER, 2)));
-}
-
-TEST_F(PasswordFormConversionUtilsTest, HTMLDetectorCache_SkipSomePredictions) {
- // The cache of HTML based username detector may contain several predictions
- // (in the order of decreasing reliability) for the given form, but the
- // detector should consider only |possible_usernames| passed to
- // GetUsernameFieldBasedOnHtmlAttributes. For example, if a field has no user
- // input while others has, the field cannot be an username field.
-
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("username", "12345", nullptr);
- builder.AddTextField("email", "smith@google.com", nullptr);
- builder.AddTextField("id", "12345", nullptr);
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
- WebFormElement form;
- LoadWebFormFromHTML(html, &form, nullptr);
- WebVector<WebFormControlElement> control_elements;
- form.GetFormControlElements(control_elements);
- ASSERT_FALSE(control_elements.empty());
-
- // Add predictions for "email" and "id" fields to the cache.
- UsernameDetectorCache username_detector_cache;
- username_detector_cache[control_elements[0].Form().UniqueRendererFormId()] = {
- ToWebInputElement(&control_elements[1])
- ->UniqueRendererFormControlId(), // email
- ToWebInputElement(&control_elements[2])
- ->UniqueRendererFormControlId()}; // id
-
- // A user typed only into "id" and "password" fields. So, the prediction for
- // "email" field should be ignored despite it is more reliable than prediction
- // for "id" field.
- FieldDataManager field_data_manager;
- field_data_manager.UpdateFieldDataMap(
- control_elements[2], control_elements[2].Value().Utf16(),
- FieldPropertiesFlags::USER_TYPED); // id
- field_data_manager.UpdateFieldDataMap(
- control_elements[3], control_elements[3].Value().Utf16(),
- FieldPropertiesFlags::USER_TYPED); // password
-
- std::unique_ptr<PasswordForm> password_form = CreatePasswordFormFromWebForm(
- form, &field_data_manager, nullptr, &username_detector_cache);
-
- ASSERT_TRUE(password_form);
- EXPECT_EQ(base::UTF8ToUTF16("id"), password_form->username_element);
-}
-
-TEST_F(PasswordFormConversionUtilsTest,
- IdentifyingUsernameFieldsWithBaseHeuristic) {
- // Each test case consists of a set of parameters to be plugged into the
- // PasswordFormBuilder below, plus the corresponding expectations.
- // The test data should not contain field names that are identified by the
- // HTML based username detector, because with these tests only the base
- // heuristic (i.e. select as username the field before the password field)
- // is tested.
- struct TestCase {
- const char* autocomplete[3];
- const char* expected_username_element;
- const char* expected_username_value;
- const char* expected_all_possible_usernames;
- } cases[] = {
- // When no elements are marked with autocomplete='username', the text-type
- // input field before the first password element should get selected as
- // the username, and the rest should be marked as alternatives.
- {{nullptr, nullptr, nullptr},
- "usrname2",
- "William",
- "John+usrname1, Smith+usrname3"},
- // When a sole element is marked with autocomplete='username', it should
- // be treated as the username, but other text fields should be added to
- // |all_possible_usernames|.
- {{"username", nullptr, nullptr},
- "usrname1",
- "John",
- "William+usrname2, Smith+usrname3"},
- {{nullptr, "username", nullptr},
- "usrname2",
- "William",
- "John+usrname1, Smith+usrname3"},
- {{nullptr, nullptr, "username"},
- "usrname3",
- "Smith",
- "John+usrname1, William+usrname2"},
- // When >=2 elements have the attribute, the first should be selected as
- // the username, and the rest should go to |all_possible_usernames|.
- {{"username", "username", nullptr},
- "usrname1",
- "John",
- "William+usrname2, Smith+usrname3"},
- {{nullptr, "username", "username"},
- "usrname2",
- "William",
- "John+usrname1, Smith+usrname3"},
- {{"username", nullptr, "username"},
- "usrname1",
- "John",
- "William+usrname2, Smith+usrname3"},
- {{"username", "username", "username"},
- "usrname1",
- "John",
- "William+usrname2, Smith+usrname3"},
- // When there is an empty autocomplete attribute (i.e. autocomplete=""),
- // it should have the same effect as having no attribute whatsoever.
- {{"", "", ""}, "usrname2", "William", "John+usrname1, Smith+usrname3"},
- {{"", "", "username"},
- "usrname3",
- "Smith",
- "John+usrname1, William+usrname2"},
- {{"username", "", "username"},
- "usrname1",
- "John",
- "William+usrname2, Smith+usrname3"},
- // It should not matter if attribute values are upper or mixed case.
- {{"USERNAME", nullptr, "uSeRNaMe"},
- "usrname1",
- "John",
- "William+usrname2, Smith+usrname3"},
- {{"uSeRNaMe", nullptr, "USERNAME"},
- "usrname1",
- "John",
- "William+usrname2, Smith+usrname3"}};
-
- for (size_t i = 0; i < base::size(cases); ++i) {
- for (size_t nonempty_username_fields = 0; nonempty_username_fields < 2;
- ++nonempty_username_fields) {
- SCOPED_TRACE(testing::Message()
- << "Iteration " << i << " "
- << (nonempty_username_fields ? "nonempty" : "empty"));
-
- // Repeat each test once with empty, and once with non-empty usernames.
- // In the former case, no empty all_possible_usernames should be saved.
- const char* names[3];
- if (nonempty_username_fields) {
- names[0] = "John";
- names[1] = "William";
- names[2] = "Smith";
- } else {
- names[0] = names[1] = names[2] = "";
- }
-
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("usrname1", names[0], cases[i].autocomplete[0]);
- builder.AddTextField("usrname2", names[1], cases[i].autocomplete[1]);
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddTextField("usrname3", names[2], cases[i].autocomplete[2]);
- builder.AddPasswordField("password2", "othersecret", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
-
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_element),
- password_form->username_element);
-
- if (nonempty_username_fields) {
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_value),
- password_form->username_value);
- EXPECT_EQ(
- base::UTF8ToUTF16(cases[i].expected_all_possible_usernames),
- ValueElementVectorToString(password_form->all_possible_usernames));
- } else {
- EXPECT_TRUE(password_form->username_value.empty());
- EXPECT_TRUE(password_form->all_possible_usernames.empty());
- }
-
- // Do a basic sanity check that we are still having a password field.
- EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value);
- }
- }
-}
-
-TEST_F(PasswordFormConversionUtilsTest, IdentifyingTwoPasswordFields) {
- // Each test case consists of a set of parameters to be plugged into the
- // PasswordFormBuilder below, plus the corresponding expectations.
- struct TestCase {
- const char* password_values[2];
- const char* expected_password_element;
- const char* expected_password_value;
- const char* expected_new_password_element;
- const char* expected_new_password_value;
- const char* expected_confirmation_element;
- } cases[] = {
- // Two non-empty fields with the same value should be treated as a new
- // password field plus a confirmation field for the new password.
- {{"alpha", "alpha"}, "", "", "password1", "alpha", "password2"},
- // The same goes if the fields are yet empty: we speculate that we will
- // identify them as new password fields once they are filled out, and we
- // want to keep our abstract interpretation of the form less flaky.
- {{"", ""}, "password1", "", "password2", "", ""},
- // Two different values should be treated as a password change form, one
- // that also asks for the current password, but only once for the new.
- {{"alpha", ""}, "password1", "alpha", "password2", "", ""},
- {{"", "beta"}, "password1", "", "password2", "beta", ""},
- {{"alpha", "beta"}, "password1", "alpha", "password2", "beta", ""}};
-
- for (size_t i = 0; i < base::size(cases); ++i) {
- SCOPED_TRACE(testing::Message() << "Iteration " << i);
-
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("usrname1", "William", nullptr);
- builder.AddPasswordField("password1", cases[i].password_values[0], nullptr);
- builder.AddTextField("usrname2", "Smith", nullptr);
- builder.AddPasswordField("password2", cases[i].password_values[1], nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
-
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_element),
- password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_value),
- password_form->password_value);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_element),
- password_form->new_password_element);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_value),
- password_form->new_password_value);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_confirmation_element),
- password_form->confirmation_password_element);
-
- // Do a basic sanity check that we are still selecting the right username.
- EXPECT_EQ(base::UTF8ToUTF16("usrname1"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("William"), password_form->username_value);
- EXPECT_THAT(
- password_form->all_possible_usernames,
- testing::ElementsAre(ValueElementPair(base::UTF8ToUTF16("Smith"),
- base::UTF8ToUTF16("usrname2"))));
- }
-}
-
-TEST_F(PasswordFormConversionUtilsTest, IdentifyingThreePasswordFields) {
- // Each test case consists of a set of parameters to be plugged into the
- // PasswordFormBuilder below, plus the corresponding expectations.
- struct TestCase {
- const char* password_values[3];
- const char* expected_password_element;
- const char* expected_password_value;
- const char* expected_new_password_element;
- const char* expected_new_password_value;
- const char* expected_confirmation_element;
- } cases[] = {
- // Two fields with the same value, and one different: we should treat this
- // as a password change form with confirmation for the new password. Note
- // that we only recognize (current + new + new) and (new + new + current)
- // without autocomplete attributes.
- {{"alpha", "", ""}, "password1", "alpha", "password2", "", "password3"},
- {{"", "beta", "beta"}, "password1", "", "password2", "beta", "password3"},
- {{"alpha", "beta", "beta"},
- "password1",
- "alpha",
- "password2",
- "beta",
- "password3"},
- // If confirmed password comes first, assume that the third password
- // field is related to security question, SSN, or credit card and ignore
- // it.
- {{"beta", "beta", "alpha"}, "", "", "password1", "beta", "password2"},
- // If the fields are yet empty, we speculate that we will identify them as
- // (current + new + new) once they are filled out, so we should classify
- // them the same for now to keep our abstract interpretation less flaky.
- {{"", "", ""}, "password1", "", "password2", "", "password3"}};
-
- for (size_t i = 0; i < base::size(cases); ++i) {
- SCOPED_TRACE(testing::Message() << "Iteration " << i);
-
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("usrname1", "William", nullptr);
- builder.AddPasswordField("password1", cases[i].password_values[0], nullptr);
- builder.AddPasswordField("password2", cases[i].password_values[1], nullptr);
- builder.AddTextField("usrname2", "Smith", nullptr);
- builder.AddPasswordField("password3", cases[i].password_values[2], nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
-
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_element),
- password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_value),
- password_form->password_value);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_element),
- password_form->new_password_element);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_value),
- password_form->new_password_value);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_confirmation_element),
- password_form->confirmation_password_element);
-
- // Do a basic sanity check that we are still selecting the right username.
- EXPECT_EQ(base::UTF8ToUTF16("usrname1"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("William"), password_form->username_value);
- EXPECT_THAT(
- password_form->all_possible_usernames,
- testing::ElementsAre(ValueElementPair(base::UTF8ToUTF16("Smith"),
- base::UTF8ToUTF16("usrname2"))));
- }
-}
-
-TEST_F(PasswordFormConversionUtilsTest,
- IdentifyingPasswordFieldsWithAutocompleteAttributes) {
- // Each test case consists of a set of parameters to be plugged into the
- // PasswordFormBuilder below, plus the corresponding expectations.
- // The test data should not contain field names that are identified by the
- // HTML based username detector, because with these tests only the base
- // heuristic (i.e. select as username the field before the password field)
- // is tested.
- struct TestCase {
- const char* autocomplete[3];
- const char* expected_password_element;
- const char* expected_password_value;
- const char* expected_new_password_element;
- const char* expected_new_password_value;
- bool expected_new_password_marked_by_site;
- const char* expected_username_element;
- const char* expected_username_value;
- } cases[] = {
- // When there are elements marked with autocomplete='current-password',
- // but no elements with 'new-password', we should treat the first of the
- // former kind as the current password, and ignore all other password
- // fields, assuming they are not intentionally not marked. They might be
- // for other purposes, such as PINs, OTPs, and the like. Actual values in
- // the password fields should be ignored in all cases below.
- // Username is the element just before the first 'current-password' (even
- // if 'new-password' comes earlier). If no 'current-password', then the
- // element just before the first 'new-passwords'.
- {{"current-password", nullptr, nullptr},
- "password1",
- "alpha",
- "",
- "",
- false,
- "usrname1",
- "William"},
- {{nullptr, "current-password", nullptr},
- "password2",
- "beta",
- "",
- "",
- false,
- "usrname2",
- "Smith"},
- {{nullptr, nullptr, "current-password"},
- "password3",
- "gamma",
- "",
- "",
- false,
- "usrname2",
- "Smith"},
- {{nullptr, "current-password", "current-password"},
- "password2",
- "beta",
- "",
- "",
- false,
- "usrname2",
- "Smith"},
- {{"current-password", nullptr, "current-password"},
- "password1",
- "alpha",
- "",
- "",
- false,
- "usrname1",
- "William"},
- {{"current-password", "current-password", nullptr},
- "password1",
- "alpha",
- "",
- "",
- false,
- "usrname1",
- "William"},
- {{"current-password", "current-password", "current-password"},
- "password1",
- "alpha",
- "",
- "",
- false,
- "usrname1",
- "William"},
- // The same goes vice versa for autocomplete='new-password'.
- {{"new-password", nullptr, nullptr},
- "",
- "",
- "password1",
- "alpha",
- true,
- "usrname1",
- "William"},
- {{nullptr, "new-password", nullptr},
- "",
- "",
- "password2",
- "beta",
- true,
- "usrname2",
- "Smith"},
- {{nullptr, nullptr, "new-password"},
- "",
- "",
- "password3",
- "gamma",
- true,
- "usrname2",
- "Smith"},
- {{nullptr, "new-password", "new-password"},
- "",
- "",
- "password2",
- "beta",
- true,
- "usrname2",
- "Smith"},
- {{"new-password", nullptr, "new-password"},
- "",
- "",
- "password1",
- "alpha",
- true,
- "usrname1",
- "William"},
- {{"new-password", "new-password", nullptr},
- "",
- "",
- "password1",
- "alpha",
- true,
- "usrname1",
- "William"},
- {{"new-password", "new-password", "new-password"},
- "",
- "",
- "password1",
- "alpha",
- true,
- "usrname1",
- "William"},
- // When there is one element marked with autocomplete='current-password',
- // and one with 'new-password', just comply. Ignore the unmarked password
- // field(s) for the same reason as above.
- {{"current-password", "new-password", nullptr},
- "password1",
- "alpha",
- "password2",
- "beta",
- true,
- "usrname1",
- "William"},
- {{"current-password", nullptr, "new-password"},
- "password1",
- "alpha",
- "password3",
- "gamma",
- true,
- "usrname1",
- "William"},
- {{nullptr, "current-password", "new-password"},
- "password2",
- "beta",
- "password3",
- "gamma",
- true,
- "usrname2",
- "Smith"},
- {{"new-password", "current-password", nullptr},
- "password2",
- "beta",
- "password1",
- "alpha",
- true,
- "usrname2",
- "Smith"},
- {{"new-password", nullptr, "current-password"},
- "password3",
- "gamma",
- "password1",
- "alpha",
- true,
- "usrname2",
- "Smith"},
- {{nullptr, "new-password", "current-password"},
- "password3",
- "gamma",
- "password2",
- "beta",
- true,
- "usrname2",
- "Smith"},
- // In case of duplicated elements of either kind, go with the first one of
- // its kind.
- {{"current-password", "current-password", "new-password"},
- "password1",
- "alpha",
- "password3",
- "gamma",
- true,
- "usrname1",
- "William"},
- {{"current-password", "new-password", "current-password"},
- "password1",
- "alpha",
- "password2",
- "beta",
- true,
- "usrname1",
- "William"},
- {{"new-password", "current-password", "current-password"},
- "password2",
- "beta",
- "password1",
- "alpha",
- true,
- "usrname2",
- "Smith"},
- {{"current-password", "new-password", "new-password"},
- "password1",
- "alpha",
- "password2",
- "beta",
- true,
- "usrname1",
- "William"},
- {{"new-password", "current-password", "new-password"},
- "password2",
- "beta",
- "password1",
- "alpha",
- true,
- "usrname2",
- "Smith"},
- {{"new-password", "new-password", "current-password"},
- "password3",
- "gamma",
- "password1",
- "alpha",
- true,
- "usrname2",
- "Smith"},
- // When there is an empty autocomplete attribute (i.e. autocomplete=""),
- // it should have the same effect as having no attribute whatsoever.
- {{"current-password", "", ""},
- "password1",
- "alpha",
- "",
- "",
- false,
- "usrname1",
- "William"},
- {{"", "", "new-password"},
- "",
- "",
- "password3",
- "gamma",
- true,
- "usrname2",
- "Smith"},
- {{"", "new-password", ""},
- "",
- "",
- "password2",
- "beta",
- true,
- "usrname2",
- "Smith"},
- {{"", "current-password", "current-password"},
- "password2",
- "beta",
- "",
- "",
- false,
- "usrname2",
- "Smith"},
- {{"new-password", "", "new-password"},
- "",
- "",
- "password1",
- "alpha",
- true,
- "usrname1",
- "William"},
- {{"new-password", "", "current-password"},
- "password3",
- "gamma",
- "password1",
- "alpha",
- true,
- "usrname2",
- "Smith"},
- // It should not matter if attribute values are upper or mixed case.
- {{nullptr, "current-password", nullptr},
- "password2",
- "beta",
- "",
- "",
- false,
- "usrname2",
- "Smith"},
- {{nullptr, "CURRENT-PASSWORD", nullptr},
- "password2",
- "beta",
- "",
- "",
- false,
- "usrname2",
- "Smith"},
- {{nullptr, "new-password", nullptr},
- "",
- "",
- "password2",
- "beta",
- true,
- "usrname2",
- "Smith"},
- {{nullptr, "nEw-PaSsWoRd", nullptr},
- "",
- "",
- "password2",
- "beta",
- true,
- "usrname2",
- "Smith"}};
-
- for (size_t i = 0; i < base::size(cases); ++i) {
- SCOPED_TRACE(testing::Message() << "Iteration " << i);
-
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddPasswordField("pin1", "123456", nullptr);
- builder.AddPasswordField("pin2", "789101", nullptr);
- builder.AddTextField("usrname1", "William", nullptr);
- builder.AddPasswordField("password1", "alpha", cases[i].autocomplete[0]);
- builder.AddTextField("usrname2", "Smith", nullptr);
- builder.AddPasswordField("password2", "beta", cases[i].autocomplete[1]);
- builder.AddPasswordField("password3", "gamma", cases[i].autocomplete[2]);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
-
- EXPECT_FALSE(password_form->only_for_fallback);
- // In the absence of username autocomplete attributes, the username should
- // be the text input field just before 'current-password' or before
- // 'new-password', if there is no 'current-password'.
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_element),
- password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_value),
- password_form->username_value);
- if (strcmp(cases[i].expected_username_value, "William") == 0) {
- EXPECT_THAT(
- password_form->all_possible_usernames,
- testing::ElementsAre(ValueElementPair(
- base::UTF8ToUTF16("Smith"), base::UTF8ToUTF16("usrname2"))));
- } else {
- EXPECT_THAT(
- password_form->all_possible_usernames,
- testing::ElementsAre(ValueElementPair(
- base::UTF8ToUTF16("William"), base::UTF8ToUTF16("usrname1"))));
- }
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_element),
- password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_value),
- password_form->password_value);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_element),
- password_form->new_password_element);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_value),
- password_form->new_password_value);
- EXPECT_EQ(cases[i].expected_new_password_marked_by_site,
- password_form->new_password_marked_by_site);
- }
-}
-
-TEST_F(PasswordFormConversionUtilsTest,
- UsernameDetection_AutocompleteAttribute) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("username", "JohnSmith", "username");
- builder.AddTextField("Full name", "John A. Smith", nullptr);
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- base::HistogramTester histogram_tester;
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
- EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("JohnSmith"), password_form->username_value);
- histogram_tester.ExpectUniqueSample(
- "PasswordManager.UsernameDetectionMethod",
- UsernameDetectionMethod::AUTOCOMPLETE_ATTRIBUTE, 1);
-}
-
-TEST_F(PasswordFormConversionUtilsTest, IgnoreInvisibledTextFields) {
- PasswordFormBuilder builder(kTestFormActionURL);
-
- builder.AddNonDisplayedTextField("nondisplayed1", "nodispalyed_value1");
- builder.AddNonVisibleTextField("nonvisible1", "nonvisible_value1");
- builder.AddTextField("username", "johnsmith", nullptr);
- builder.AddNonDisplayedTextField("nondisplayed2", "nodispalyed_value2");
- builder.AddNonVisiblePasswordField("nonvisible2", "nonvisible_value2");
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("johnsmith"), password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16(""), password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->new_password_element);
- EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->new_password_value);
-}
-
-TEST_F(PasswordFormConversionUtilsTest, IgnoreInvisiblLoginPairs) {
- PasswordFormBuilder builder(kTestFormActionURL);
-
- builder.AddNonDisplayedTextField("nondisplayed1", "nodispalyed_value1");
- builder.AddNonDisplayedPasswordField("nondisplayed2", "nodispalyed_value2");
- builder.AddNonVisibleTextField("nonvisible1", "nonvisible_value1");
- builder.AddNonVisiblePasswordField("nonvisible2", "nonvisible_value2");
- builder.AddTextField("username", "johnsmith", nullptr);
- builder.AddNonVisibleTextField("nonvisible3", "nonvisible_value3");
- builder.AddNonVisiblePasswordField("nonvisible4", "nonvisible_value4");
- builder.AddNonDisplayedTextField("nondisplayed3", "nodispalyed_value3");
- builder.AddNonDisplayedPasswordField("nondisplayed4", "nodispalyed_value4");
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("johnsmith"), password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16(""), password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->new_password_element);
- EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->new_password_value);
-}
-
-TEST_F(PasswordFormConversionUtilsTest, OnlyNonDisplayedLoginPair) {
- PasswordFormBuilder builder(kTestFormActionURL);
-
- builder.AddNonDisplayedTextField("username", "William");
- builder.AddNonDisplayedPasswordField("password", "secret");
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16("username"),
- password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("William"),
- password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16("password"),
- password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("secret"),
- password_form->password_value);
-}
-
-TEST_F(PasswordFormConversionUtilsTest, OnlyNonVisibleLoginPair) {
- PasswordFormBuilder builder(kTestFormActionURL);
-
- builder.AddNonVisibleTextField("username", "William");
- builder.AddNonVisiblePasswordField("password", "secret");
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("William"), password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value);
-}
-
-TEST_F(PasswordFormConversionUtilsTest, VisiblePasswordAndInvisibleUsername) {
- PasswordFormBuilder builder(kTestFormActionURL);
-
- builder.AddNonDisplayedTextField("username", "William");
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("William"), password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value);
-}
-
-TEST_F(PasswordFormConversionUtilsTest,
- InvisiblePassword_LatestUsernameIsVisible) {
- PasswordFormBuilder builder(kTestFormActionURL);
-
- builder.AddNonDisplayedTextField("search", "query");
- builder.AddTextField("username", "William", nullptr);
- builder.AddNonDisplayedPasswordField("password", "secret");
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("William"), password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value);
-}
-
-TEST_F(PasswordFormConversionUtilsTest,
- InvisiblePassword_LatestUsernameIsInvisible) {
- PasswordFormBuilder builder(kTestFormActionURL);
-
- builder.AddTextField("search", "query", nullptr);
- builder.AddNonDisplayedTextField("username", "William");
- builder.AddNonDisplayedPasswordField("password", "secret");
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("William"), password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value);
-}
-
-// Checks that username/password fields are detected based on user input even if
-// visibility heuristics disagree.
-TEST_F(PasswordFormConversionUtilsTest, UserInput) {
- PasswordFormBuilder builder(kTestFormActionURL);
-
- builder.AddNonVisibleTextField("nonvisible_text", "actual_username");
- builder.AddTextField("visible_text", "fake_username", nullptr);
-
- builder.AddNonVisiblePasswordField("nonvisible_password", "actual_password");
- builder.AddPasswordField("visible_password", "fake_password", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- WebFormElement form;
- LoadWebFormFromHTML(html, &form, nullptr);
-
- FieldDataManager field_data_manager;
- WebVector<WebFormControlElement> control_elements;
- form.GetFormControlElements(control_elements);
- ASSERT_EQ("nonvisible_text", control_elements[0].NameForAutofill().Utf8());
- field_data_manager.UpdateFieldDataMap(control_elements[0],
- control_elements[0].Value().Utf16(),
- FieldPropertiesFlags::USER_TYPED);
- ASSERT_EQ("nonvisible_password",
- control_elements[2].NameForAutofill().Utf8());
- field_data_manager.UpdateFieldDataMap(control_elements[2],
- control_elements[2].Value().Utf16(),
- FieldPropertiesFlags::USER_TYPED);
-
- std::unique_ptr<PasswordForm> password_form = CreatePasswordFormFromWebForm(
- form, &field_data_manager, nullptr, nullptr);
-
- ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16("nonvisible_text"),
- password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("actual_username"),
- password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16("nonvisible_password"),
- password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("actual_password"),
- password_form->password_value);
- EXPECT_EQ(base::UTF8ToUTF16(""), password_form->new_password_element);
- EXPECT_EQ(base::UTF8ToUTF16(""), password_form->new_password_value);
-}
-
-TEST_F(PasswordFormConversionUtilsTest, TypedPasswordAndUsernameCachedOnPage) {
- PasswordFormBuilder builder(kTestFormActionURL);
- // The heuristics should consider only password field with user input (i.e.
- // password_with_user_input?) and visible username fields (i.e. nickname,
- // visible_text, captcha) since there is no username field with user input.
- builder.AddNonDisplayedPasswordField("nondisplayed1", "fake_password");
- builder.AddNonDisplayedTextField("nondisplayed1", "fake_username1");
- builder.AddTextField("nickname", "bob", nullptr);
- builder.AddTextField("visible_text", "cached_username",
- nullptr); // Username.
- builder.AddNonVisibleTextField("nonvisible_text", "fake_username2");
- builder.AddNonVisiblePasswordField("nonvisible_password", "not_password");
- builder.AddNonVisibleTextField("nonvisible_text", "fake_username2");
- builder.AddPasswordField("password_wo_user_input", "", nullptr);
- builder.AddNonVisibleTextField("nonvisible_text", "");
- builder.AddPasswordField("password_with_user_input1", "actual_password",
- nullptr); // Password to save.
- builder.AddPasswordField("password_with_user_input2", "actual_password",
- nullptr);
- builder.AddTextField("captcha", "12345", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- WebFormElement form;
- LoadWebFormFromHTML(html, &form, nullptr);
-
- FieldDataManager field_data_manager;
- WebVector<WebFormControlElement> control_elements;
- form.GetFormControlElements(control_elements);
- ASSERT_EQ("password_with_user_input1",
- control_elements[9].NameForAutofill().Utf8());
- field_data_manager.UpdateFieldDataMap(control_elements[9],
- control_elements[9].Value().Utf16(),
- FieldPropertiesFlags::USER_TYPED);
- ASSERT_EQ("password_with_user_input2",
- control_elements[10].NameForAutofill().Utf8());
- field_data_manager.UpdateFieldDataMap(control_elements[10],
- control_elements[10].Value().Utf16(),
- FieldPropertiesFlags::USER_TYPED);
-
- std::unique_ptr<PasswordForm> password_form = CreatePasswordFormFromWebForm(
- form, &field_data_manager, nullptr, nullptr);
-
- ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback);
-
- EXPECT_EQ(base::UTF8ToUTF16("visible_text"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("cached_username"),
- password_form->username_value);
-
- EXPECT_EQ(base::string16(), password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16(""), password_form->password_value);
-
- EXPECT_EQ(base::UTF8ToUTF16("password_with_user_input1"),
- password_form->new_password_element);
- EXPECT_EQ(base::UTF8ToUTF16("actual_password"),
- password_form->new_password_value);
-}
-
-TEST_F(PasswordFormConversionUtilsTest, TypedPasswordAndInvisibleUsername) {
- PasswordFormBuilder builder(kTestFormActionURL);
- // The heuristics should consider only password field with user input (i.e.
- // password_with_user_input?) and invisible username fields since all username
- // fields have no user input and are invisible.
- builder.AddNonDisplayedPasswordField("nondisplayed1", "fake_password");
- builder.AddNonDisplayedTextField("nondisplayed1", "fake_username1");
- builder.AddNonVisibleTextField("nickname", "bob");
- builder.AddNonVisibleTextField("this_is_username", "invisible_username");
- builder.AddNonVisiblePasswordField("nonvisible_password", "not_password");
- builder.AddPasswordField("password_wo_user_input", "", nullptr);
- builder.AddNonVisiblePasswordField("nonvisible_password2", "");
- builder.AddPasswordField("password_with_user_input1", "actual_password",
- nullptr); // Password to save.
- builder.AddNonVisibleTextField("nonvisible_text3", "---H09-$%");
- builder.AddPasswordField("password_with_user_input2", "actual_password",
- nullptr);
- builder.AddNonVisibleTextField("nonvisible_text3", "debug_info");
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- WebFormElement form;
- LoadWebFormFromHTML(html, &form, nullptr);
-
- FieldDataManager field_data_manager;
- WebVector<WebFormControlElement> control_elements;
- form.GetFormControlElements(control_elements);
- ASSERT_EQ("password_with_user_input1",
- control_elements[7].NameForAutofill().Utf8());
- field_data_manager.UpdateFieldDataMap(control_elements[7],
- control_elements[7].Value().Utf16(),
- FieldPropertiesFlags::USER_TYPED);
- ASSERT_EQ("password_with_user_input2",
- control_elements[9].NameForAutofill().Utf8());
- field_data_manager.UpdateFieldDataMap(control_elements[9],
- control_elements[9].Value().Utf16(),
- FieldPropertiesFlags::USER_TYPED);
-
- std::unique_ptr<PasswordForm> password_form = CreatePasswordFormFromWebForm(
- form, &field_data_manager, nullptr, nullptr);
-
- ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback);
-
- EXPECT_EQ(base::UTF8ToUTF16("this_is_username"),
- password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("invisible_username"),
- password_form->username_value);
-
- EXPECT_EQ(base::string16(), password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16(""), password_form->password_value);
-
- EXPECT_EQ(base::UTF8ToUTF16("password_with_user_input1"),
- password_form->new_password_element);
- EXPECT_EQ(base::UTF8ToUTF16("actual_password"),
- password_form->new_password_value);
-}
-
-TEST_F(PasswordFormConversionUtilsTest, InvalidFormDueToBadActionURL) {
- PasswordFormBuilder builder("invalid_target");
- builder.AddTextField("username", "JohnSmith", nullptr);
- builder.AddSubmitButton("submit");
- builder.AddPasswordField("password", "secret", nullptr);
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- EXPECT_FALSE(password_form);
-}
-
-TEST_F(PasswordFormConversionUtilsTest, InvalidFormDueToNoPasswordFields) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("username1", "John", nullptr);
- builder.AddTextField("username2", "Smith", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- EXPECT_FALSE(password_form);
-}
-
-TEST_F(PasswordFormConversionUtilsTest, ConfusingPasswordFields) {
- // Each test case consists of a set of parameters to be plugged into the
- // PasswordFormBuilder below.
- const char* cases[][3] = {
- // No autocomplete attributes to guide us, and we see:
- // * three password values that are all different,
- // * three password values that are all the same;
- // * three password values with the first and last matching.
- // In any case, we should just give up on this form.
- {"alpha", "beta", "gamma"},
- {"alpha", "alpha", "alpha"},
- {"alpha", "beta", "alpha"}};
-
- for (size_t i = 0; i < base::size(cases); ++i) {
- SCOPED_TRACE(testing::Message() << "Iteration " << i);
-
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("username1", "John", nullptr);
- builder.AddPasswordField("password1", cases[i][0], nullptr);
- builder.AddPasswordField("password2", cases[i][1], nullptr);
- builder.AddPasswordField("password3", cases[i][2], nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16("username1"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("John"), password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16("password1"), password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16(cases[i][0]), password_form->password_value);
- }
-}
-
-TEST_F(PasswordFormConversionUtilsTest,
- ManyPasswordFieldsWithoutAutocompleteAttributes) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("username1", "John", nullptr);
- builder.AddPasswordField("password1", "alpha", nullptr);
- builder.AddPasswordField("password2", "alpha", nullptr);
- builder.AddPasswordField("password3", "alpha", nullptr);
- builder.AddPasswordField("password4", "alpha", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16("username1"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("John"), password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16("password1"), password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("alpha"), password_form->password_value);
-}
-
-TEST_F(PasswordFormConversionUtilsTest, SetOtherPossiblePasswords) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("username1", "John", nullptr);
- builder.AddPasswordField("password1", "alpha1", nullptr);
- builder.AddPasswordField("password2", "alpha2", nullptr);
- builder.AddPasswordField("password3", "alpha3", nullptr);
- builder.AddPasswordField("password4", "alpha4", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->form_has_autofilled_value);
-
- // Make sure we have all possible passwords along with the username info.
- EXPECT_EQ(base::ASCIIToUTF16("username1"), password_form->username_element);
- EXPECT_EQ(base::ASCIIToUTF16("John"), password_form->username_value);
- EXPECT_EQ(base::ASCIIToUTF16("alpha1"), password_form->password_value);
- EXPECT_THAT(
- password_form->all_possible_passwords,
- testing::ElementsAre(ValueElementPair(base::ASCIIToUTF16("alpha1"),
- base::ASCIIToUTF16("password1")),
- ValueElementPair(base::ASCIIToUTF16("alpha2"),
- base::ASCIIToUTF16("password2")),
- ValueElementPair(base::ASCIIToUTF16("alpha3"),
- base::ASCIIToUTF16("password3")),
- ValueElementPair(base::ASCIIToUTF16("alpha4"),
- base::ASCIIToUTF16("password4"))));
- EXPECT_EQ(base::ASCIIToUTF16("alpha1+password1, alpha2+password2, "
- "alpha3+password3, alpha4+password4"),
- ValueElementVectorToString(password_form->all_possible_passwords));
-}
-
-TEST_F(PasswordFormConversionUtilsTest,
- AllPossiblePasswordsIncludeAutofilledValue) {
- for (bool autofilled_value_was_modified_by_user : {false, true}) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("username1", "John", nullptr);
- builder.AddPasswordField("old-password", "autofilled_value", nullptr);
- builder.AddPasswordField("new-password", "user_value", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- WebFormElement form;
- LoadWebFormFromHTML(html, &form, nullptr);
- WebVector<WebFormControlElement> control_elements;
- form.GetFormControlElements(control_elements);
-
- FieldDataManager field_data_manager;
- FieldPropertiesMask mask = FieldPropertiesFlags::AUTOFILLED;
- if (autofilled_value_was_modified_by_user)
- mask |= FieldPropertiesFlags::USER_TYPED;
- field_data_manager.UpdateFieldDataMap(
- control_elements[1], base::ASCIIToUTF16("autofilled_value"), mask);
- field_data_manager.UpdateFieldDataMap(control_elements[2],
- base::ASCIIToUTF16("user_value"),
- FieldPropertiesFlags::USER_TYPED);
-
- std::unique_ptr<PasswordForm> password_form(CreatePasswordFormFromWebForm(
- form, &field_data_manager, nullptr, nullptr));
- ASSERT_TRUE(password_form);
- EXPECT_TRUE(password_form->form_has_autofilled_value);
- }
-}
-
-TEST_F(PasswordFormConversionUtilsTest, CreditCardNumberWithTypePasswordForm) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("Credit-card-owner-name", "John Smith", nullptr);
- builder.AddPasswordField("Credit-card-number", "0000 0000 0000 0000",
- nullptr);
- builder.AddTextField("cvc", "000", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::map<int, PasswordFormFieldPredictionType> predictions_positions;
- predictions_positions[1] = PasswordFormFieldPredictionType::kNotPassword;
-
- FormsPredictionsMap predictions;
- SetPredictions(html, &predictions, predictions_positions);
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, &predictions, false);
- EXPECT_TRUE(password_form);
- EXPECT_TRUE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16("Credit-card-owner-name"),
- password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("John Smith"), password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16("Credit-card-number"),
- password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("0000 0000 0000 0000"),
- password_form->password_value);
-}
-
-TEST_F(PasswordFormConversionUtilsTest, UsernamePredictionFromServer) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("username", "JohnSmith", nullptr);
- // 'autocomplete' attribute cannot override server's prediction.
- builder.AddTextField("Full name", "John A. Smith", "username");
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::map<int, PasswordFormFieldPredictionType> predictions_positions;
- predictions_positions[0] = PasswordFormFieldPredictionType::kUsername;
- FormsPredictionsMap predictions;
- SetPredictions(html, &predictions, predictions_positions);
-
- base::HistogramTester histogram_tester;
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, &predictions, false);
- ASSERT_TRUE(password_form);
- EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("JohnSmith"), password_form->username_value);
- histogram_tester.ExpectUniqueSample(
- "PasswordManager.UsernameDetectionMethod",
- UsernameDetectionMethod::SERVER_SIDE_PREDICTION, 1);
-}
-
-TEST_F(PasswordFormConversionUtilsTest,
- UsernamePredictionFromServerToEmptyField) {
- // Tests that if a form has user input and the username prediction by the
- // server points to an empty field, then the prediction is ignored.
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("empty-field", "", ""); // The prediction points here.
- builder.AddTextField("full-name", "John A. Smith", nullptr);
- builder.AddTextField("username", "JohnSmith", nullptr);
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::map<int, PasswordFormFieldPredictionType> predictions_positions;
- predictions_positions[0] = PasswordFormFieldPredictionType::kUsername;
- FormsPredictionsMap predictions;
- SetPredictions(html, &predictions, predictions_positions);
-
- // The password field has user input.
- WebFormElement form;
- LoadWebFormFromHTML(html, &form, nullptr);
- WebVector<WebFormControlElement> control_elements;
- form.GetFormControlElements(control_elements);
- FieldDataManager field_data_manager;
- field_data_manager.UpdateFieldDataMap(control_elements[3],
- control_elements[3].Value().Utf16(),
- FieldPropertiesFlags::USER_TYPED);
-
- std::unique_ptr<PasswordForm> password_form = CreatePasswordFormFromWebForm(
- form, &field_data_manager, &predictions, &username_detector_cache_);
- ASSERT_TRUE(password_form);
- EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("JohnSmith"), password_form->username_value);
-}
-
-TEST_F(PasswordFormConversionUtilsTest,
- CreditCardVerificationNumberWithTypePasswordForm) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("Credit-card-owner-name", "John Smith", nullptr);
- builder.AddTextField("Credit-card-number", "0000 0000 0000 0000", nullptr);
- builder.AddPasswordField("cvc", "000", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::map<int, PasswordFormFieldPredictionType> predictions_positions;
- predictions_positions[2] = PasswordFormFieldPredictionType::kNotPassword;
-
- FormsPredictionsMap predictions;
- SetPredictions(html, &predictions, predictions_positions);
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, &predictions, false);
- EXPECT_TRUE(password_form);
- EXPECT_TRUE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16("Credit-card-number"),
- password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("0000 0000 0000 0000"),
- password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16("cvc"), password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("000"), password_form->password_value);
-}
-
-TEST_F(PasswordFormConversionUtilsTest,
- CreditCardNumberWithTypePasswordFormWithAutocomplete) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("Credit-card-owner-name", "John Smith", nullptr);
- builder.AddPasswordField("Credit-card-number", "0000 0000 0000 0000",
- "current-password");
- builder.AddTextField("cvc", "000", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::map<int, PasswordFormFieldPredictionType> predictions_positions;
- predictions_positions[1] = PasswordFormFieldPredictionType::kNotPassword;
-
- FormsPredictionsMap predictions;
- SetPredictions(html, &predictions, predictions_positions);
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, &predictions, false);
- EXPECT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16("Credit-card-owner-name"),
- password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("John Smith"), password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16("Credit-card-number"),
- password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("0000 0000 0000 0000"),
- password_form->password_value);
-}
-
-TEST_F(PasswordFormConversionUtilsTest,
- CreditCardVerificationNumberWithTypePasswordFormWithAutocomplete) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("Credit-card-owner-name", "John Smith", nullptr);
- builder.AddTextField("Credit-card-number", "0000 0000 0000 0000", nullptr);
- builder.AddPasswordField("cvc", "000", "new-password");
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::map<int, PasswordFormFieldPredictionType> predictions_positions;
- predictions_positions[2] = PasswordFormFieldPredictionType::kNotPassword;
-
- FormsPredictionsMap predictions;
- SetPredictions(html, &predictions, predictions_positions);
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, &predictions, false);
- ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16("Credit-card-number"),
- password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("0000 0000 0000 0000"),
- password_form->username_value);
- EXPECT_TRUE(password_form->password_element.empty());
- EXPECT_TRUE(password_form->password_value.empty());
- EXPECT_EQ(base::UTF8ToUTF16("cvc"), password_form->new_password_element);
- EXPECT_EQ(base::UTF8ToUTF16("000"), password_form->new_password_value);
-}
-
TEST_F(PasswordFormConversionUtilsTest, IsGaiaReauthFormIgnored) {
struct TestCase {
const char* origin;
@@ -2201,255 +253,4 @@ TEST_F(PasswordFormConversionUtilsTest, IsGaiaWithSkipSavePasswordForm) {
}
}
-TEST_F(PasswordFormConversionUtilsTest,
- IdentifyingFieldsWithoutNameOrIdAttributes) {
- const char* kEmpty = nullptr;
- const struct {
- const char* username_fieldname;
- const char* password_fieldname;
- const char* new_password_fieldname;
- const char* expected_username_element;
- const char* expected_password_element;
- const char* expected_new_password_element;
- } test_cases[] = {
- {"username", "password", "new_password", "username", "password",
- "new_password"},
- {"username", "password", kEmpty, "username", "password",
- "anonymous_new_password"},
- {"username", kEmpty, kEmpty, "username", "anonymous_password",
- "anonymous_new_password"},
- {kEmpty, kEmpty, kEmpty, "anonymous_username", "anonymous_password",
- "anonymous_new_password"},
- };
-
- for (size_t i = 0; i < base::size(test_cases); ++i) {
- SCOPED_TRACE(testing::Message()
- << "Iteration " << i << ", expected_username "
- << test_cases[i].expected_username_element
- << ", expected_password"
- << test_cases[i].expected_password_element
- << ", expected_new_password "
- << test_cases[i].expected_new_password_element);
-
- PasswordFormBuilder builder(kTestFormActionURL);
- if (test_cases[i].username_fieldname == kEmpty) {
- builder.AddAnonymousInputField("text");
- } else {
- builder.AddTextField(test_cases[i].username_fieldname, "", kEmpty);
- }
-
- if (test_cases[i].password_fieldname == kEmpty) {
- builder.AddAnonymousInputField("password");
- } else {
- builder.AddPasswordField(test_cases[i].password_fieldname, "", kEmpty);
- }
-
- if (test_cases[i].new_password_fieldname == kEmpty) {
- builder.AddAnonymousInputField("password");
- } else {
- builder.AddPasswordField(test_cases[i].new_password_fieldname, "",
- kEmpty);
- }
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- EXPECT_TRUE(password_form);
-
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16(test_cases[i].expected_username_element),
- password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16(test_cases[i].expected_password_element),
- password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16(test_cases[i].expected_new_password_element),
- password_form->new_password_element);
- }
-}
-
-TEST_F(PasswordFormConversionUtilsTest, TooManyFieldsToParseForm) {
- PasswordFormBuilder builder(kTestFormActionURL);
- for (size_t i = 0; i < form_util::kMaxParseableFields + 1; ++i)
- builder.AddTextField("id", "value", "autocomplete");
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(builder.ProduceHTML(), nullptr, false);
- EXPECT_FALSE(password_form);
-}
-
-TEST_F(PasswordFormConversionUtilsTest, OnlyCreditCardFields) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("ccname", "johnsmith", "cc-name");
- builder.AddPasswordField("cc_security_code", "0123456789", "cc-csc");
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- EXPECT_TRUE(password_form);
- EXPECT_TRUE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16("ccname"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("johnsmith"), password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16("cc_security_code"),
- password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("0123456789"), password_form->password_value);
-}
-
-TEST_F(PasswordFormConversionUtilsTest,
- FieldsWithAndWithoutCreditCardAttributes) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("username", "johnsmith", nullptr);
- builder.AddTextField("ccname", "john_smith", "cc-name");
- builder.AddPasswordField("cc_security_code", "0123456789", "random cc-csc");
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
-
- ASSERT_TRUE(password_form);
-
- EXPECT_FALSE(password_form->only_for_fallback);
- EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element);
- EXPECT_EQ(base::UTF8ToUTF16("johnsmith"), password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value);
-}
-
-TEST_F(PasswordFormConversionUtilsTest, ResetPasswordForm) {
- // GetPassword (including HTML classifier) should process correctly forms
- // without any text fields.
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
- base::HistogramTester histogram_tester;
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
-
- ASSERT_TRUE(password_form);
-
- EXPECT_TRUE(password_form->username_element.empty());
- EXPECT_TRUE(password_form->username_value.empty());
- EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element);
- EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value);
- histogram_tester.ExpectUniqueSample(
- "PasswordManager.UsernameDetectionMethod",
- UsernameDetectionMethod::NO_USERNAME_DETECTED, 1);
-}
-
-TEST_F(PasswordFormConversionUtilsTest, StickyPasswordType) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("username", "johnsmith", nullptr);
- builder.AddPasswordField("password", "secret", nullptr);
- builder.AddSubmitButton("submit");
- std::string html = builder.ProduceHTML();
-
- std::unique_ptr<PasswordForm> password_form =
- LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
-
- FormData old_form_data;
- ASSERT_TRUE(ExtractFormDataForFirstForm(&old_form_data));
-
- // Change password field to type="text".
- ExecuteJavaScriptForTests(
- "document.getElementById(\"password\").type = \"text\";");
-
- // Validate that - despite the change - the old password field is still
- // recognized as a password field.
- WebFormElement new_form;
- GetFirstForm(&new_form);
- std::unique_ptr<PasswordForm> new_password_form =
- CreatePasswordFormFromWebForm(new_form, nullptr, nullptr,
- &username_detector_cache_);
- ASSERT_TRUE(new_password_form);
-
- EXPECT_EQ(*password_form, *new_password_form);
-
- FormData new_form_data;
- ASSERT_TRUE(ExtractFormDataForFirstForm(&new_form_data));
-
- EXPECT_EQ(old_form_data, new_form_data);
-}
-
-// Check that Chrome remembers the value typed by the user in cases when it gets
-// overridden by the page.
-TEST_F(PasswordFormConversionUtilsTest, TypedValuePreserved) {
- PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextField("fine", "", "username");
- builder.AddPasswordField("mangled", "", "current-password");
- builder.AddTextField("completed_for_user", "", nullptr);
- std::string html = builder.ProduceHTML();
-
- WebFormElement form;
- LoadWebFormFromHTML(html, &form, nullptr);
-
- FieldDataManager field_data_manager;
- WebVector<WebFormControlElement> control_elements;
- form.GetFormControlElements(control_elements);
-
- ASSERT_EQ(3u, control_elements.size());
- ASSERT_EQ("fine", control_elements[0].NameForAutofill().Utf8());
- control_elements[0].SetAutofillValue("same_value");
- field_data_manager.UpdateFieldDataMap(control_elements[0],
- control_elements[0].Value().Utf16(),
- FieldPropertiesFlags::USER_TYPED);
-
- ASSERT_EQ("mangled", control_elements[1].NameForAutofill().Utf8());
- control_elements[1].SetAutofillValue("mangled_value");
- field_data_manager.UpdateFieldDataMap(control_elements[1],
- base::UTF8ToUTF16("original_value"),
- FieldPropertiesFlags::USER_TYPED);
-
- ASSERT_EQ("completed_for_user", control_elements[2].NameForAutofill().Utf8());
- control_elements[2].SetAutofillValue("email@gmail.com");
- field_data_manager.UpdateFieldDataMap(control_elements[2],
- base::UTF8ToUTF16("email"),
- FieldPropertiesFlags::USER_TYPED);
-
- std::unique_ptr<PasswordForm> password_form = CreatePasswordFormFromWebForm(
- form, &field_data_manager, nullptr, nullptr);
-
- ASSERT_TRUE(password_form);
-
- EXPECT_EQ(base::UTF8ToUTF16("same_value"), password_form->username_value);
- EXPECT_EQ(base::UTF8ToUTF16("original_value"), password_form->password_value);
-
- ASSERT_EQ(3u, password_form->form_data.fields.size());
-
- EXPECT_EQ(base::UTF8ToUTF16("same_value"),
- password_form->form_data.fields[0].value);
- EXPECT_EQ(base::string16(), password_form->form_data.fields[0].typed_value);
-
- EXPECT_EQ(base::UTF8ToUTF16("mangled_value"),
- password_form->form_data.fields[1].value);
- EXPECT_EQ(base::UTF8ToUTF16("original_value"),
- password_form->form_data.fields[1].typed_value);
-
- EXPECT_EQ(base::UTF8ToUTF16("email@gmail.com"),
- password_form->form_data.fields[2].value);
- EXPECT_EQ(base::string16(), password_form->form_data.fields[2].typed_value);
-}
-
-// Check that non-text fields are ignored.
-TEST_F(PasswordFormConversionUtilsTest, NonTextFields) {
- PasswordFormBuilder builder(kTestFormActionURL);
- // Avoid calling the text fields anything related to "username" to prevent the
- // local HTML classifier from influencing the test result.
- builder.AddTextField("textField", "", "");
- builder.AddFieldWithType("radioInput", "radio");
- builder.AddPasswordField("password", "", "");
- std::string html = builder.ProduceHTML();
-
- WebFormElement form;
- LoadWebFormFromHTML(html, &form, nullptr);
-
- std::unique_ptr<PasswordForm> password_form =
- CreatePasswordFormFromWebForm(form, nullptr, nullptr, nullptr);
-
- ASSERT_TRUE(password_form);
- EXPECT_EQ(base::UTF8ToUTF16("textField"), password_form->username_element);
-}
-
} // namespace autofill
diff --git a/chromium/components/autofill/content/renderer/password_generation_agent.cc b/chromium/components/autofill/content/renderer/password_generation_agent.cc
index 5aafec2069b..e5095c12eee 100644
--- a/chromium/components/autofill/content/renderer/password_generation_agent.cc
+++ b/chromium/components/autofill/content/renderer/password_generation_agent.cc
@@ -307,15 +307,22 @@ void PasswordGenerationAgent::UserTriggeredGeneratePassword(
UserTriggeredGeneratePasswordCallback callback) {
if (SetUpUserTriggeredGeneration()) {
LogMessage(Logger::STRING_GENERATION_RENDERER_SHOW_MANUAL_GENERATION_POPUP);
+ // If the field is not |type=password|, the list of suggestions
+ // should not be populated with passwords to avoid filling them in a
+ // clear-text field.
+ // |IsPasswordFieldForAutofill()| is deliberately not used.
+ bool is_generation_element_password_type =
+ current_generation_item_->generation_element_.IsPasswordField();
autofill::password_generation::PasswordGenerationUIData
password_generation_ui_data(
- render_frame()->GetRenderView()->ElementBoundsInWindow(
+ render_frame()->ElementBoundsInWindow(
current_generation_item_->generation_element_),
current_generation_item_->generation_element_.MaxLength(),
current_generation_item_->generation_element_.NameForAutofill()
.Utf16(),
current_generation_item_->generation_element_
.UniqueRendererFormControlId(),
+ is_generation_element_password_type,
GetTextDirectionForElement(
current_generation_item_->generation_element_),
current_generation_item_->form_);
@@ -511,15 +518,22 @@ void PasswordGenerationAgent::AutomaticGenerationAvailable() {
DCHECK(current_generation_item_);
DCHECK(!current_generation_item_->generation_element_.IsNull());
LogMessage(Logger::STRING_GENERATION_RENDERER_AUTOMATIC_GENERATION_AVAILABLE);
+ // If the field is not |type=password|, the list of suggestions
+ // should not be populated with passwordS to avoid filling them in a
+ // clear-text field.
+ // |IsPasswordFieldForAutofill()| is deliberately not used.
+ bool is_generation_element_password_type =
+ current_generation_item_->generation_element_.IsPasswordField();
autofill::password_generation::PasswordGenerationUIData
password_generation_ui_data(
- render_frame()->GetRenderView()->ElementBoundsInWindow(
+ render_frame()->ElementBoundsInWindow(
current_generation_item_->generation_element_),
current_generation_item_->generation_element_.MaxLength(),
current_generation_item_->generation_element_.NameForAutofill()
.Utf16(),
current_generation_item_->generation_element_
.UniqueRendererFormControlId(),
+ is_generation_element_password_type,
GetTextDirectionForElement(
current_generation_item_->generation_element_),
current_generation_item_->form_);
@@ -532,9 +546,8 @@ void PasswordGenerationAgent::ShowEditingPopup() {
if (!render_frame())
return;
- gfx::RectF bounding_box =
- render_frame()->GetRenderView()->ElementBoundsInWindow(
- current_generation_item_->generation_element_);
+ gfx::RectF bounding_box = render_frame()->ElementBoundsInWindow(
+ current_generation_item_->generation_element_);
std::unique_ptr<PasswordForm> password_form = CreatePasswordFormToPresave();
DCHECK(password_form);
diff --git a/chromium/components/autofill/content/renderer/provisionally_saved_password_form.cc b/chromium/components/autofill/content/renderer/provisionally_saved_password_form.cc
deleted file mode 100644
index 376eddff494..00000000000
--- a/chromium/components/autofill/content/renderer/provisionally_saved_password_form.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/autofill/content/renderer/provisionally_saved_password_form.h"
-
-#include <utility>
-
-namespace autofill {
-
-ProvisionallySavedPasswordForm::ProvisionallySavedPasswordForm() = default;
-
-ProvisionallySavedPasswordForm::~ProvisionallySavedPasswordForm() = default;
-
-void ProvisionallySavedPasswordForm::Set(
- std::unique_ptr<PasswordForm> password_form,
- const blink::WebFormElement& form_element,
- const blink::WebInputElement& input_element) {
- password_form_ = std::move(password_form);
- form_element_ = form_element;
- input_element_ = input_element;
-}
-
-void ProvisionallySavedPasswordForm::Reset() {
- password_form_.reset();
- form_element_.Reset();
- input_element_.Reset();
-}
-
-bool ProvisionallySavedPasswordForm::IsSet() const {
- return static_cast<bool>(password_form_);
-}
-
-bool ProvisionallySavedPasswordForm::IsPasswordValid() const {
- return IsSet() && !(password_form_->password_value.empty() &&
- password_form_->new_password_value.empty());
-}
-
-void ProvisionallySavedPasswordForm::SetSubmissionIndicatorEvent(
- mojom::SubmissionIndicatorEvent event) {
- if (password_form_) {
- password_form_->submission_event = event;
- password_form_->form_data.submission_event = event;
- }
-}
-
-} // namespace autofill
diff --git a/chromium/components/autofill/content/renderer/provisionally_saved_password_form.h b/chromium/components/autofill/content/renderer/provisionally_saved_password_form.h
deleted file mode 100644
index 89e9b11fa26..00000000000
--- a/chromium/components/autofill/content/renderer/provisionally_saved_password_form.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_AUTOFILL_CONTENT_RENDERER_PROVISIONALLY_SAVED_PASSWORD_FORM_H_
-#define COMPONENTS_AUTOFILL_CONTENT_RENDERER_PROVISIONALLY_SAVED_PASSWORD_FORM_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "components/autofill/core/common/mojom/autofill_types.mojom.h"
-#include "components/autofill/core/common/password_form.h"
-#include "third_party/blink/public/web/web_input_element.h"
-
-namespace autofill {
-
-struct PasswordForm;
-
-// Represents a possibly submitted password form.
-class ProvisionallySavedPasswordForm {
- public:
- ProvisionallySavedPasswordForm();
- ~ProvisionallySavedPasswordForm();
-
- // Sets the PasswordForm and web elements that were used in the PasswordForm
- // update.
- void Set(std::unique_ptr<PasswordForm> password_form,
- const blink::WebFormElement& form_element,
- const blink::WebInputElement& input_element);
- void Reset();
-
- // Returns true if the instance has |password_form_| set, but the actual
- // password data may be invalid (e.g. empty username or password).
- bool IsSet() const;
- // Returns true if |password_form_| has enough information that it is likely
- // filled out.
- bool IsPasswordValid() const;
-
- const PasswordForm& password_form() const {
- DCHECK(IsSet());
- return *password_form_;
- }
- blink::WebFormElement& form_element() { return form_element_; }
- blink::WebInputElement& input_element() { return input_element_; }
-
- void SetSubmissionIndicatorEvent(mojom::SubmissionIndicatorEvent event);
-
- private:
- std::unique_ptr<PasswordForm> password_form_;
- // Last used WebFormElement for the PasswordForm submission. Can be null if
- // the form is unowned.
- blink::WebFormElement form_element_;
- // Last used WebInputElement which led to the PasswordForm update. Can be null
- // if the user has performed a form submission (via a button, for example).
- blink::WebInputElement input_element_;
-
- DISALLOW_COPY_AND_ASSIGN(ProvisionallySavedPasswordForm);
-};
-
-} // namespace autofill
-
-#endif // COMPONENTS_AUTOFILL_CONTENT_RENDERER_PROVISIONALLY_SAVED_PASSWORD_FORM_H_
diff --git a/chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc b/chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
index badd66a6a3b..1cce757d9bb 100644
--- a/chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
+++ b/chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
@@ -8,7 +8,9 @@
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "components/autofill/content/common/mojom/autofill_driver.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace autofill {
@@ -19,14 +21,12 @@ const char kTestText[] = "test";
class FakeContentPasswordManagerDriver : public mojom::PasswordManagerDriver {
public:
- FakeContentPasswordManagerDriver()
- : called_record_save_(false), binding_(this) {}
+ FakeContentPasswordManagerDriver() : called_record_save_(false) {}
~FakeContentPasswordManagerDriver() override {}
- mojom::PasswordManagerDriverPtr CreateInterfacePtrAndBind() {
- mojom::PasswordManagerDriverPtr ptr;
- binding_.Bind(mojo::MakeRequest(&ptr));
- return ptr;
+ mojo::PendingRemote<mojom::PasswordManagerDriver>
+ CreatePendingRemoteAndBind() {
+ return receiver_.BindNewPipeAndPassRemote();
}
bool GetLogMessage(std::string* log) {
@@ -55,8 +55,8 @@ class FakeContentPasswordManagerDriver : public mojom::PasswordManagerDriver {
void HideManualFallbackForSaving() override {}
- void SameDocumentNavigation(
- const autofill::PasswordForm& password_form) override {}
+ void SameDocumentNavigation(autofill::mojom::SubmissionIndicatorEvent
+ submission_indication_event) override {}
void ShowPasswordSuggestions(base::i18n::TextDirection text_direction,
const base::string16& typed_username,
@@ -88,7 +88,7 @@ class FakeContentPasswordManagerDriver : public mojom::PasswordManagerDriver {
// Records data received via RecordSavePasswordProgress() call.
base::Optional<std::string> log_;
- mojo::Binding<mojom::PasswordManagerDriver> binding_;
+ mojo::Receiver<mojom::PasswordManagerDriver> receiver_{this};
};
class TestLogger : public RendererSavePasswordProgressLogger {
@@ -104,9 +104,9 @@ class TestLogger : public RendererSavePasswordProgressLogger {
TEST(RendererSavePasswordProgressLoggerTest, SendLog) {
base::test::SingleThreadTaskEnvironment task_environment;
FakeContentPasswordManagerDriver fake_driver;
- mojom::PasswordManagerDriverPtr driver_ptr =
- fake_driver.CreateInterfacePtrAndBind();
- TestLogger logger(driver_ptr.get());
+ mojo::Remote<mojom::PasswordManagerDriver> driver_remote(
+ fake_driver.CreatePendingRemoteAndBind());
+ TestLogger logger(driver_remote.get());
logger.SendLog(kTestText);
base::RunLoop().RunUntilIdle();
diff --git a/chromium/components/autofill/core/browser/BUILD.gn b/chromium/components/autofill/core/browser/BUILD.gn
index 44b052554fe..ea02a8035e7 100644
--- a/chromium/components/autofill/core/browser/BUILD.gn
+++ b/chromium/components/autofill/core/browser/BUILD.gn
@@ -56,8 +56,6 @@ jumbo_static_library("browser") {
"autofill_handler_proxy.h",
"autofill_ie_toolbar_import_win.cc",
"autofill_ie_toolbar_import_win.h",
- "autofill_internals_service.cc",
- "autofill_internals_service.h",
"autofill_manager.cc",
"autofill_manager.h",
"autofill_manager_test_delegate.h",
@@ -145,12 +143,11 @@ jumbo_static_library("browser") {
"geo/state_names.h",
"geo/subkey_requester.cc",
"geo/subkey_requester.h",
- "logging/log_buffer.cc",
- "logging/log_buffer.h",
"logging/log_buffer_submitter.cc",
"logging/log_buffer_submitter.h",
"logging/log_manager.cc",
"logging/log_manager.h",
+ "logging/log_protobufs.h",
"logging/log_receiver.h",
"logging/log_router.cc",
"logging/log_router.h",
@@ -197,6 +194,8 @@ jumbo_static_library("browser") {
"payments/strike_database_integrator_base.h",
"payments/strike_database_integrator_test_strike_database.cc",
"payments/strike_database_integrator_test_strike_database.h",
+ "payments/upi_vpa_save_manager.cc",
+ "payments/upi_vpa_save_manager.h",
"personal_data_manager.cc",
"personal_data_manager.h",
"personal_data_manager_observer.h",
@@ -296,8 +295,10 @@ jumbo_static_library("browser") {
"ui/mobile_label_formatter.h",
"ui/payments/card_expiration_date_fix_flow_view_delegate_mobile.cc",
"ui/payments/card_expiration_date_fix_flow_view_delegate_mobile.h",
- "ui/payments/card_name_fix_flow_view_delegate_mobile.cc",
- "ui/payments/card_name_fix_flow_view_delegate_mobile.h",
+ "ui/payments/card_name_fix_flow_controller.h",
+ "ui/payments/card_name_fix_flow_controller_impl.cc",
+ "ui/payments/card_name_fix_flow_controller_impl.h",
+ "ui/payments/card_name_fix_flow_view.h",
]
}
@@ -318,6 +319,8 @@ jumbo_static_library("browser") {
"autofill_policy_handler.h",
"payments/credit_card_fido_authenticator.cc",
"payments/credit_card_fido_authenticator.h",
+ "payments/fido_authentication_strike_database.cc",
+ "payments/fido_authentication_strike_database.h",
]
}
@@ -441,6 +444,8 @@ jumbo_static_library("test_support") {
"test_autofill_profile_validator_delayed.h",
"test_autofill_provider.cc",
"test_autofill_provider.h",
+ "test_autofill_tick_clock.cc",
+ "test_autofill_tick_clock.h",
"test_event_waiter.h",
"test_form_data_importer.cc",
"test_form_data_importer.h",
@@ -481,6 +486,7 @@ jumbo_static_library("test_support") {
"//testing/gtest",
"//third_party/libaddressinput:test_support",
"//third_party/libaddressinput:util",
+ "//third_party/re2:re2",
"//ui/accessibility",
"//ui/gfx:test_support",
"//ui/gfx/geometry",
@@ -532,7 +538,6 @@ source_set("unit_tests") {
"autofill_experiments_unittest.cc",
"autofill_external_delegate_unittest.cc",
"autofill_ie_toolbar_import_win_unittest.cc",
- "autofill_internals_service_unittest.cc",
"autofill_manager_unittest.cc",
"autofill_merge_unittest.cc",
"autofill_metrics_unittest.cc",
@@ -565,7 +570,6 @@ source_set("unit_tests") {
"geo/phone_number_i18n_unittest.cc",
"geo/subkey_requester_unittest.cc",
"logging/log_buffer_submitter_unittest.cc",
- "logging/log_buffer_unittest.cc",
"logging/log_manager_unittest.cc",
"logging/log_router_unittest.cc",
"payments/credit_card_access_manager_unittest.cc",
@@ -603,6 +607,7 @@ source_set("unit_tests") {
sources += [
"autofill_assistant_unittest.cc",
"ui/mobile_label_formatter_unittest.cc",
+ "ui/payments/card_name_fix_flow_controller_impl_unittest.cc",
]
}
diff --git a/chromium/components/autofill/core/browser/autocomplete_history_manager_unittest.cc b/chromium/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
index dd8098f25d8..973ecf62bb7 100644
--- a/chromium/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
@@ -150,7 +150,7 @@ class AutocompleteHistoryManagerTest : public testing::Test {
date_last_used);
}
- base::test::TaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
scoped_refptr<MockWebDataService> web_data_service_;
std::unique_ptr<AutocompleteHistoryManager> autocomplete_manager_;
std::unique_ptr<PrefService> prefs_;
diff --git a/chromium/components/autofill/core/browser/autofill_address_util.cc b/chromium/components/autofill/core/browser/autofill_address_util.cc
index 9908b219b85..e621752b495 100644
--- a/chromium/components/autofill/core/browser/autofill_address_util.cc
+++ b/chromium/components/autofill/core/browser/autofill_address_util.cc
@@ -154,38 +154,4 @@ void GetAddressComponents(const std::string& country_code,
}
}
-// Sets data related to the country <select>.
-void SetCountryData(const PersonalDataManager& manager,
- base::DictionaryValue* localized_strings,
- const std::string& ui_language_code) {
- autofill::CountryComboboxModel model;
- model.SetCountries(manager, base::Callback<bool(const std::string&)>(),
- ui_language_code);
- const std::vector<std::unique_ptr<autofill::AutofillCountry>>& countries =
- model.countries();
- localized_strings->SetString("defaultCountryCode",
- countries.front()->country_code());
-
- // An ordered list of options to show in the <select>.
- auto country_list = std::make_unique<base::ListValue>();
- for (size_t i = 0; i < countries.size(); ++i) {
- auto option_details = std::make_unique<base::DictionaryValue>();
- option_details->SetString("name", model.GetItemAt(i));
- option_details->SetString(
- "value", countries[i] ? countries[i]->country_code() : "separator");
- country_list->Append(std::move(option_details));
- }
- localized_strings->Set("autofillCountrySelectList", std::move(country_list));
-
- auto default_country_components = std::make_unique<base::ListValue>();
- std::string default_country_language_code;
- GetAddressComponents(countries.front()->country_code(), ui_language_code,
- default_country_components.get(),
- &default_country_language_code);
- localized_strings->Set("autofillDefaultCountryComponents",
- std::move(default_country_components));
- localized_strings->SetString("autofillDefaultCountryLanguageCode",
- default_country_language_code);
-}
-
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_address_util.h b/chromium/components/autofill/core/browser/autofill_address_util.h
index c962f8db10b..1e8b93f76d0 100644
--- a/chromium/components/autofill/core/browser/autofill_address_util.h
+++ b/chromium/components/autofill/core/browser/autofill_address_util.h
@@ -75,11 +75,6 @@ void GetAddressComponents(const std::string& country_code,
base::ListValue* address_components,
std::string* components_language_code);
-// Sets data related to the country combobox.
-void SetCountryData(const PersonalDataManager& manager,
- base::DictionaryValue* localized_strings,
- const std::string& ui_language_code);
-
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_ADDRESS_UTIL_H_
diff --git a/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.css b/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.css
index 8dcdccf06e3..de7620a179d 100644
--- a/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.css
+++ b/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.css
@@ -66,6 +66,10 @@
background-color: #FFECB3;
}
+.log-entry[scope='AbortParsing'] {
+ background-color: #FFCDD2;
+}
+
.log-entry[scope='Filling'] {
background-color: #D1C4E9;
}
diff --git a/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals_ios.html b/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals_ios.html
new file mode 100644
index 00000000000..f1675379114
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals_ios.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+<head>
+<!-- Copyright 2019 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file. -->
+<meta charset="utf-8">
+
+<!-- TODO(crbug.com/487000): Remove this entire html file once the following is
+injected by web. -->
+<script src="chrome://resources/js/ios/web_ui.js"></script>
+
+<script src="chrome://resources/js/util.js"></script>
+<script src="autofill_and_password_manager_internals.js"></script>
+<link rel="stylesheet" href="chrome://resources/css/chrome_shared.css">
+<link rel="stylesheet" href="autofill_and_password_manager_internals.css">
+</head>
+<body>
+<h1 id="h1-title"></h1>
+<div id="logging-note"></div>
+<div id="logging-note-incognito"></div>
+<div id="version-info">
+ <table>
+ <tr>
+ <td class="label">Version:</td>
+ <td class="version"><span>$i18n{version}</span>
+ (<span>$i18n{official}</span>)
+ <span>$i18n{version_modifier}</span></td>
+ </tr>
+ <tr>
+ <td class="label">Revision:</td>
+ <td class="version"><span>$i18n{cl}</span></td>
+ </tr>
+ <tr>
+ <td class="label">User Agent:</td>
+ <td class="version"><span>$i18n{useragent}</span></td>
+ </tr>
+ <tr>
+ <td class="label">App Locale:</td>
+ <td class="version"><span>$i18n{app_locale}</span></td>
+ </tr>
+ <tr>
+ <td class="label">Variations:</td>
+ <td class="version" id="variations-list"></td>
+ </tr>
+ </table>
+</div>
+<div id="log-entries">
+</div>
+</body>
+</html>
diff --git a/chromium/components/autofill/core/browser/autofill_assistant_unittest.cc b/chromium/components/autofill/core/browser/autofill_assistant_unittest.cc
index 95b0e1aef02..a47451ca2e5 100644
--- a/chromium/components/autofill/core/browser/autofill_assistant_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_assistant_unittest.cc
@@ -148,7 +148,7 @@ class AutofillAssistantTest : public testing::Test {
return static_cast<CardUnmaskDelegate*>(full_card_request);
}
- base::test::TaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
TestAutofillClient autofill_client_;
testing::NiceMock<TestAutofillDriver> autofill_driver_;
TestPersonalDataManager pdm_;
diff --git a/chromium/components/autofill/core/browser/autofill_client.cc b/chromium/components/autofill/core/browser/autofill_client.cc
index 98d69be2b43..aaa1e239912 100644
--- a/chromium/components/autofill/core/browser/autofill_client.cc
+++ b/chromium/components/autofill/core/browser/autofill_client.cc
@@ -23,4 +23,8 @@ LogManager* AutofillClient::GetLogManager() const {
return nullptr;
}
+bool AutofillClient::CloseWebauthnOfferDialog() {
+ return false;
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_client.h b/chromium/components/autofill/core/browser/autofill_client.h
index 09e305852ec..2ed56cfc478 100644
--- a/chromium/components/autofill/core/browser/autofill_client.h
+++ b/chromium/components/autofill/core/browser/autofill_client.h
@@ -6,6 +6,7 @@
#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_CLIENT_H_
#include <memory>
+#include <set>
#include <string>
#include <vector>
@@ -15,6 +16,7 @@
#include "base/strings/string16.h"
#include "base/values.h"
#include "build/build_config.h"
+#include "components/autofill/core/browser/payments/legal_message_line.h"
#include "components/autofill/core/browser/payments/risk_data_loader.h"
#include "components/autofill/core/browser/ui/popup_types.h"
#include "components/security_state/core/security_state.h"
@@ -282,11 +284,11 @@ class AutofillClient : public RiskDataLoader {
virtual void ShowLocalCardMigrationDialog(
base::OnceClosure show_migration_dialog_closure) = 0;
- // Shows a dialog with the given |legal_message| and the |user_email|. Runs
- // |start_migrating_cards_callback| if the user would like the selected cards
- // in the |migratable_credit_cards| to be uploaded to cloud.
+ // Shows a dialog with the given |legal_message_lines| and the |user_email|.
+ // Runs |start_migrating_cards_callback| if the user would like the selected
+ // cards in the |migratable_credit_cards| to be uploaded to cloud.
virtual void ConfirmMigrateLocalCardToCloud(
- std::unique_ptr<base::DictionaryValue> legal_message,
+ const LegalMessageLines& legal_message_lines,
const std::string& user_email,
const std::vector<MigratableCreditCard>& migratable_credit_cards,
LocalCardMigrationCallback start_migrating_cards_callback) = 0;
@@ -304,13 +306,33 @@ class AutofillClient : public RiskDataLoader {
const std::vector<MigratableCreditCard>& migratable_credit_cards,
MigrationDeleteCardCallback delete_local_card_callback) = 0;
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+ // Will show a dialog indicating the card verification is in progress. It is
+ // shown after verification starts only if the WebAuthn is enabled.
+ // Implemented only on desktop.
+ virtual void ShowVerifyPendingDialog(
+ base::OnceClosure cancel_card_verification_callback) = 0;
+
+ // Close the verify pending dialog once the card verificiation is completed or
+ // verification falls back to CVC.
+ virtual void CloseVerifyPendingDialog() = 0;
+#endif
+
// Will show a dialog offering the option to use device's platform
// authenticator in the future instead of CVC to verify the card being
- // unmasked. Runs |callback| is the OK button or the cancel button in the
+ // unmasked. Runs |callback| if the OK button or the cancel button in the
// dialog is clicked. This is only implemented on desktop.
virtual void ShowWebauthnOfferDialog(
WebauthnOfferDialogCallback callback) = 0;
+ // Will close the WebAuthn offer dialog. Returns true if dialog was visible
+ // and has been closed. Implemented only on desktop.
+ virtual bool CloseWebauthnOfferDialog();
+
+ // Will update the WebAuthn offer dialog content to the error state.
+ // Implemented only on desktop.
+ virtual void UpdateWebauthnOfferDialogWithError() {}
+
// Runs |callback| if the |profile| should be imported as personal data.
virtual void ConfirmSaveAutofillProfile(const AutofillProfile& profile,
base::OnceClosure callback) = 0;
@@ -326,11 +348,14 @@ class AutofillClient : public RiskDataLoader {
AutofillClient::SaveCreditCardOptions options,
LocalSaveCardPromptCallback callback) = 0;
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_IOS)
// Display the cardholder name fix flow prompt and run the |callback| if
// the card should be uploaded to payments with updated name from the user.
virtual void ConfirmAccountNameFixFlow(
base::OnceCallback<void(const base::string16&)> callback) = 0;
+#endif // defined(OS_ANDROID) || defined(OS_IOS)
+
+#if defined(OS_ANDROID)
// Display the expiration date fix flow prompt with the |card| details
// and run the |callback| if the card should be uploaded to payments with
// updated expiration date from the user.
@@ -341,8 +366,8 @@ class AutofillClient : public RiskDataLoader {
#endif // defined(OS_ANDROID)
// Runs |callback| once the user makes a decision with respect to the
- // offer-to-save prompt. Displays the contents of |legal_message| to the user.
- // Displays a cardholder name textfield in the bubble if
+ // offer-to-save prompt. Displays the contents of |legal_message_lines|
+ // to the user. Displays a cardholder name textfield in the bubble if
// |options.should_request_name_from_user| is true. Displays
// a pair of expiration date dropdowns in the bubble if
// |should_request_expiration_date_from_user| is true. On desktop, shows the
@@ -352,7 +377,7 @@ class AutofillClient : public RiskDataLoader {
// not offer to save at all.
virtual void ConfirmSaveCreditCardToCloud(
const CreditCard& card,
- std::unique_ptr<base::DictionaryValue> legal_message,
+ const LegalMessageLines& legal_message_lines,
SaveCreditCardOptions options,
UploadSaveCardPromptCallback callback) = 0;
diff --git a/chromium/components/autofill/core/browser/autofill_data_util.cc b/chromium/components/autofill/core/browser/autofill_data_util.cc
index 02d4f378146..35620873ba7 100644
--- a/chromium/components/autofill/core/browser/autofill_data_util.cc
+++ b/chromium/components/autofill/core/browser/autofill_data_util.cc
@@ -55,12 +55,6 @@ const PaymentRequestData kPaymentRequestData[]{
{autofill::kVisaCard, "visa", IDR_AUTOFILL_CC_VISA, IDS_AUTOFILL_CC_VISA},
};
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-const PaymentRequestData kGooglePayBrandingRequestData = {
- "googlePay", "googlePay", IDR_AUTOFILL_GOOGLE_PAY,
- IDS_AUTOFILL_CC_GOOGLE_PAY};
-#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
-
const PaymentRequestData kGenericPaymentRequestData = {
autofill::kGenericCard, "generic", IDR_AUTOFILL_CC_GENERIC,
IDS_AUTOFILL_CC_GENERIC};
@@ -464,70 +458,12 @@ base::string16 JoinNameParts(base::StringPiece16 given,
return base::JoinString(full_name, base::ASCIIToUTF16(separator));
}
-bool ProfileMatchesFullName(base::StringPiece16 full_name,
- const autofill::AutofillProfile& profile) {
- const base::string16 kSpace = base::ASCIIToUTF16(" ");
- const base::string16 kPeriodSpace = base::ASCIIToUTF16(". ");
-
- // First Last
- base::string16 candidate = profile.GetRawInfo(autofill::NAME_FIRST) + kSpace +
- profile.GetRawInfo(autofill::NAME_LAST);
- if (!full_name.compare(candidate)) {
- return true;
- }
-
- // First Middle Last
- candidate = profile.GetRawInfo(autofill::NAME_FIRST) + kSpace +
- profile.GetRawInfo(autofill::NAME_MIDDLE) + kSpace +
- profile.GetRawInfo(autofill::NAME_LAST);
- if (!full_name.compare(candidate)) {
- return true;
- }
-
- // First M Last
- candidate = profile.GetRawInfo(autofill::NAME_FIRST) + kSpace +
- profile.GetRawInfo(autofill::NAME_MIDDLE_INITIAL) + kSpace +
- profile.GetRawInfo(autofill::NAME_LAST);
- if (!full_name.compare(candidate)) {
- return true;
- }
-
- // First M. Last
- candidate = profile.GetRawInfo(autofill::NAME_FIRST) + kSpace +
- profile.GetRawInfo(autofill::NAME_MIDDLE_INITIAL) + kPeriodSpace +
- profile.GetRawInfo(autofill::NAME_LAST);
- if (!full_name.compare(candidate)) {
- return true;
- }
-
- // Last First
- candidate = profile.GetRawInfo(autofill::NAME_LAST) + kSpace +
- profile.GetRawInfo(autofill::NAME_FIRST);
- if (!full_name.compare(candidate)) {
- return true;
- }
-
- // LastFirst
- candidate = profile.GetRawInfo(autofill::NAME_LAST) +
- profile.GetRawInfo(autofill::NAME_FIRST);
- if (!full_name.compare(candidate)) {
- return true;
- }
-
- return false;
-}
-
const PaymentRequestData& GetPaymentRequestData(
const std::string& issuer_network) {
for (const PaymentRequestData& data : kPaymentRequestData) {
if (issuer_network == data.issuer_network)
return data;
}
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
- if (issuer_network == kGooglePayBrandingRequestData.issuer_network) {
- return kGooglePayBrandingRequestData;
- }
-#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
return kGenericPaymentRequestData;
}
diff --git a/chromium/components/autofill/core/browser/autofill_data_util.h b/chromium/components/autofill/core/browser/autofill_data_util.h
index a6060345333..d99dc25369e 100644
--- a/chromium/components/autofill/core/browser/autofill_data_util.h
+++ b/chromium/components/autofill/core/browser/autofill_data_util.h
@@ -96,11 +96,6 @@ base::string16 JoinNameParts(base::StringPiece16 given,
base::StringPiece16 middle,
base::StringPiece16 family);
-// Returns true iff |full_name| is a concatenation of some combination of the
-// first/middle/last (incl. middle initial) in |profile|.
-bool ProfileMatchesFullName(base::StringPiece16 full_name,
- const autofill::AutofillProfile& profile);
-
// Returns the Payment Request API basic card payment spec data for the provided
// autofill credit card |network|. Will set the network and the icon to
// "generic" for any unrecognized type.
diff --git a/chromium/components/autofill/core/browser/autofill_data_util_unittest.cc b/chromium/components/autofill/core/browser/autofill_data_util_unittest.cc
index 7b1ea28d9fa..2646b113750 100644
--- a/chromium/components/autofill/core/browser/autofill_data_util_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_data_util_unittest.cc
@@ -233,33 +233,6 @@ INSTANTIATE_TEST_SUITE_P(
// Has a middle-name, too unusual
));
-TEST(AutofillDataUtilTest, ProfileMatchesFullName) {
- autofill::AutofillProfile profile;
- autofill::test::SetProfileInfo(
- &profile, "First", "Middle", "Last", "fml@example.com", "Acme inc",
- "123 Main", "Apt 2", "Laredo", "TX", "77300", "US", "832-555-1000");
-
- EXPECT_TRUE(ProfileMatchesFullName(base::UTF8ToUTF16("First Last"), profile));
-
- EXPECT_TRUE(
- ProfileMatchesFullName(base::UTF8ToUTF16("First Middle Last"), profile));
-
- EXPECT_TRUE(
- ProfileMatchesFullName(base::UTF8ToUTF16("First M Last"), profile));
-
- EXPECT_TRUE(
- ProfileMatchesFullName(base::UTF8ToUTF16("First M. Last"), profile));
-
- EXPECT_TRUE(
- ProfileMatchesFullName(base::UTF8ToUTF16("Last First"), profile));
-
- EXPECT_TRUE(
- ProfileMatchesFullName(base::UTF8ToUTF16("LastFirst"), profile));
-
- EXPECT_FALSE(
- ProfileMatchesFullName(base::UTF8ToUTF16("Kirby Puckett"), profile));
-}
-
struct ValidCountryCodeTestCase {
std::string country_code;
bool expected_result;
diff --git a/chromium/components/autofill/core/browser/autofill_download_manager.cc b/chromium/components/autofill/core/browser/autofill_download_manager.cc
index 4513830064b..47f0b71fd95 100644
--- a/chromium/components/autofill/core/browser/autofill_download_manager.cc
+++ b/chromium/components/autofill/core/browser/autofill_download_manager.cc
@@ -16,6 +16,7 @@
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
+#include "base/numerics/ranges.h"
#include "base/numerics/safe_conversions.h"
#include "base/rand_util.h"
#include "base/strings/strcat.h"
@@ -24,11 +25,10 @@
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/autofill/core/browser/autofill_driver.h"
-#include "components/autofill/core/browser/autofill_internals_service.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/form_structure.h"
-#include "components/autofill/core/browser/logging/log_buffer.h"
#include "components/autofill/core/browser/logging/log_manager.h"
+#include "components/autofill/core/browser/logging/log_protobufs.h"
#include "components/autofill/core/browser/proto/legacy_proto_bridge.h"
#include "components/autofill/core/browser/proto/server.pb.h"
#include "components/autofill/core/common/autofill_clock.h"
@@ -37,6 +37,8 @@
#include "components/autofill/core/common/autofill_internals/logging_scope.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_switches.h"
+#include "components/autofill/core/common/autofill_tick_clock.h"
+#include "components/autofill/core/common/logging/log_buffer.h"
#include "components/autofill/core/common/mojom/autofill_types.mojom.h"
#include "components/google/core/common/google_util.h"
#include "components/history/core/browser/history_service.h"
@@ -906,7 +908,7 @@ bool AutofillDownloadManager::StartRequest(FormRequestData request_data) {
url_loader_factory.get(),
base::BindOnce(&AutofillDownloadManager::OnSimpleLoaderComplete,
base::Unretained(this), std::move(--url_loaders_.end()),
- std::move(request_data), base::TimeTicks::Now()));
+ std::move(request_data), AutofillTickClock::NowTicks()));
return true;
}
@@ -966,9 +968,9 @@ std::string AutofillDownloadManager::GetCombinedSignature(
int AutofillDownloadManager::GetMaxServerAttempts() {
// This value is constant for the life of the browser, so we cache it
// statically on first use to avoid re-parsing the param on each retry
- // opportunity. The range is forced to be within [1, 20].
- static int max_attempts =
- std::max(1, std::min(20, kAutofillMaxServerAttempts.Get()));
+ // opportunity.
+ static const int max_attempts =
+ base::ClampToRange(kAutofillMaxServerAttempts.Get(), 1, 20);
return max_attempts;
}
@@ -997,7 +999,7 @@ void AutofillDownloadManager::OnSimpleLoaderComplete(
LogHttpResponseData(request_data.request_type, response_code,
simple_loader->NetError(),
- base::TimeTicks::Now() - request_start);
+ AutofillTickClock::NowTicks() - request_start);
// Handle error if there is and return.
if (!success) {
diff --git a/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc b/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc
index d3fbc3484e4..a62afad14f7 100644
--- a/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc
@@ -34,6 +34,7 @@
#include "components/autofill/core/browser/randomized_encoder.h"
#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/form_data.h"
@@ -229,8 +230,9 @@ class AutofillDownloadManagerTest : public AutofillDownloadManager::Observer,
response.signature = form_signature;
response.error = http_error;
response.type_of_response =
- request_type == AutofillDownloadManager::REQUEST_QUERY ?
- REQUEST_QUERY_FAILED : REQUEST_UPLOAD_FAILED;
+ request_type == AutofillDownloadManager::REQUEST_QUERY
+ ? REQUEST_QUERY_FAILED
+ : REQUEST_UPLOAD_FAILED;
responses_.push_back(response);
}
@@ -393,7 +395,8 @@ TEST_F(AutofillDownloadManagerTest, QueryAndUploadTest) {
"<field autofilltype=\"31\" />"
"<field autofilltype=\"33\" />"
"</autofillqueryresponse>",
- "", "<html></html>",
+ "",
+ "<html></html>",
};
// Return them out of sequence.
@@ -408,7 +411,7 @@ TEST_F(AutofillDownloadManagerTest, QueryAndUploadTest) {
// Request 2: Unsuccessful upload.
request = test_url_loader_factory_.GetPendingRequest(2);
test_url_loader_factory_.SimulateResponseWithoutRemovingFromPendingList(
- request, network::CreateResourceResponseHead(net::HTTP_NOT_FOUND),
+ request, network::CreateURLResponseHead(net::HTTP_NOT_FOUND),
responses[2], network::URLLoaderCompletionStatus(net::OK));
histogram.ExpectBucketCount("Autofill.Upload.HttpResponseOrErrorCode",
net::HTTP_NOT_FOUND, 1);
@@ -464,8 +467,7 @@ TEST_F(AutofillDownloadManagerTest, QueryAndUploadTest) {
AutofillMetrics::QUERY_SENT, 2);
histogram.ExpectUniqueSample("Autofill.Query.Method", METHOD_GET, 2);
test_url_loader_factory_.SimulateResponseWithoutRemovingFromPendingList(
- request,
- network::CreateResourceResponseHead(net::HTTP_INTERNAL_SERVER_ERROR),
+ request, network::CreateURLResponseHead(net::HTTP_INTERNAL_SERVER_ERROR),
responses[0], network::URLLoaderCompletionStatus(net::OK));
histogram.ExpectBucketCount("Autofill.Query.HttpResponseOrErrorCode",
net::HTTP_INTERNAL_SERVER_ERROR, 1);
@@ -489,7 +491,7 @@ TEST_F(AutofillDownloadManagerTest, QueryAndUploadTest) {
network::URLLoaderCompletionStatus status(net::OK);
status.exists_in_cache = true;
test_url_loader_factory_.SimulateResponseWithoutRemovingFromPendingList(
- request, network::CreateResourceResponseHead(net::HTTP_OK), responses[0],
+ request, network::CreateURLResponseHead(net::HTTP_OK), responses[0],
status);
// Check Request 5.
@@ -845,9 +847,8 @@ TEST_F(AutofillDownloadManagerTest, BackoffLogic_Query) {
// Request error incurs a retry after 1 second.
test_url_loader_factory_.SimulateResponseWithoutRemovingFromPendingList(
- request,
- network::CreateResourceResponseHead(net::HTTP_INTERNAL_SERVER_ERROR), "",
- network::URLLoaderCompletionStatus(net::OK));
+ request, network::CreateURLResponseHead(net::HTTP_INTERNAL_SERVER_ERROR),
+ "", network::URLLoaderCompletionStatus(net::OK));
EXPECT_EQ(1U, responses_.size());
EXPECT_LT(download_manager_.loader_backoff_.GetTimeUntilRelease(),
@@ -864,7 +865,7 @@ TEST_F(AutofillDownloadManagerTest, BackoffLogic_Query) {
// Next error incurs a retry after 2 seconds.
test_url_loader_factory_.SimulateResponseWithoutRemovingFromPendingList(
request,
- network::CreateResourceResponseHead(net::HTTP_REQUEST_ENTITY_TOO_LARGE),
+ network::CreateURLResponseHead(net::HTTP_REQUEST_ENTITY_TOO_LARGE),
"<html></html>", network::URLLoaderCompletionStatus(net::OK));
EXPECT_EQ(2U, responses_.size());
@@ -915,9 +916,8 @@ TEST_F(AutofillDownloadManagerTest, BackoffLogic_Upload) {
// Error incurs a retry after 1 second.
test_url_loader_factory_.SimulateResponseWithoutRemovingFromPendingList(
- request,
- network::CreateResourceResponseHead(net::HTTP_INTERNAL_SERVER_ERROR), "",
- network::URLLoaderCompletionStatus(net::OK));
+ request, network::CreateURLResponseHead(net::HTTP_INTERNAL_SERVER_ERROR),
+ "", network::URLLoaderCompletionStatus(net::OK));
EXPECT_EQ(1U, responses_.size());
EXPECT_LT(download_manager_.loader_backoff_.GetTimeUntilRelease(),
base::TimeDelta::FromMilliseconds(1100));
@@ -959,8 +959,8 @@ TEST_F(AutofillDownloadManagerTest, BackoffLogic_Upload) {
request = test_url_loader_factory_.GetPendingRequest(2);
test_url_loader_factory_.SimulateResponseWithoutRemovingFromPendingList(
request,
- network::CreateResourceResponseHead(net::HTTP_REQUEST_ENTITY_TOO_LARGE),
- "", network::URLLoaderCompletionStatus(net::OK));
+ network::CreateURLResponseHead(net::HTTP_REQUEST_ENTITY_TOO_LARGE), "",
+ network::URLLoaderCompletionStatus(net::OK));
ASSERT_EQ(test_url_loader_factory_.NumPending(), 0);
histogram.ExpectBucketCount("Autofill.Upload.HttpResponseOrErrorCode",
net::HTTP_REQUEST_ENTITY_TOO_LARGE, 1);
@@ -1012,7 +1012,7 @@ TEST_F(AutofillDownloadManagerTest, RetryLimit_Query) {
// Request error incurs a retry after 1 second.
test_url_loader_factory_.SimulateResponseWithoutRemovingFromPendingList(
request,
- network::CreateResourceResponseHead(net::HTTP_INTERNAL_SERVER_ERROR),
+ network::CreateURLResponseHead(net::HTTP_INTERNAL_SERVER_ERROR),
"<html></html>", network::URLLoaderCompletionStatus(net::OK));
EXPECT_EQ(1U, responses_.size());
@@ -1089,8 +1089,8 @@ TEST_F(AutofillDownloadManagerTest, RetryLimit_Upload) {
// Simulate a server failure.
test_url_loader_factory_.SimulateResponseWithoutRemovingFromPendingList(
request,
- network::CreateResourceResponseHead(net::HTTP_INTERNAL_SERVER_ERROR),
- "", network::URLLoaderCompletionStatus(net::OK));
+ network::CreateURLResponseHead(net::HTTP_INTERNAL_SERVER_ERROR), "",
+ network::URLLoaderCompletionStatus(net::OK));
// Check that it was a failure.
ASSERT_EQ(1U, responses_.size());
@@ -1206,25 +1206,25 @@ TEST_F(AutofillDownloadManagerTest, CacheQueryTest) {
// Limit cache to two forms.
LimitCache(2);
- const char *responses[] = {
- "<autofillqueryresponse>"
+ const char* responses[] = {
+ "<autofillqueryresponse>"
"<field autofilltype=\"0\" />"
"<field autofilltype=\"3\" />"
"<field autofilltype=\"5\" />"
- "</autofillqueryresponse>",
- "<autofillqueryresponse>"
+ "</autofillqueryresponse>",
+ "<autofillqueryresponse>"
"<field autofilltype=\"0\" />"
"<field autofilltype=\"3\" />"
"<field autofilltype=\"5\" />"
"<field autofilltype=\"9\" />"
- "</autofillqueryresponse>",
- "<autofillqueryresponse>"
+ "</autofillqueryresponse>",
+ "<autofillqueryresponse>"
"<field autofilltype=\"0\" />"
"<field autofilltype=\"3\" />"
"<field autofilltype=\"5\" />"
"<field autofilltype=\"9\" />"
"<field autofilltype=\"0\" />"
- "</autofillqueryresponse>",
+ "</autofillqueryresponse>",
};
base::HistogramTester histogram;
@@ -2179,7 +2179,7 @@ TEST_P(AutofillUploadTest, PeriodicReset) {
base::HistogramTester histogram_tester;
TestAutofillClock test_clock;
- test_clock.SetNow(base::Time::Now());
+ test_clock.SetNow(AutofillClock::Now());
// The first attempt should succeed.
EXPECT_TRUE(SendUploadRequest(form_structure, true, {}, "", true));
@@ -2237,7 +2237,7 @@ TEST_P(AutofillUploadTest, ResetOnClearUploadHisotry) {
base::HistogramTester histogram_tester;
TestAutofillClock test_clock;
- test_clock.SetNow(base::Time::Now());
+ test_clock.SetNow(AutofillClock::Now());
// The first attempt should succeed.
EXPECT_TRUE(SendUploadRequest(form_structure, true, {}, "", true));
diff --git a/chromium/components/autofill/core/browser/autofill_driver.h b/chromium/components/autofill/core/browser/autofill_driver.h
index b9e205706e4..e8998205270 100644
--- a/chromium/components/autofill/core/browser/autofill_driver.h
+++ b/chromium/components/autofill/core/browser/autofill_driver.h
@@ -107,9 +107,9 @@ class AutofillDriver {
const base::string16& value) = 0;
// Tells the renderer to set the currently focused node's corresponding
- // accessibility node to |autofill_suggestions_available|.
+ // accessibility node's autofill state to |state|.
virtual void RendererShouldSetSuggestionAvailability(
- bool autofill_suggestions_available) = 0;
+ const mojom::AutofillState state) = 0;
// Informs the renderer that the popup has been hidden.
virtual void PopupHidden() = 0;
diff --git a/chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc b/chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc
index 54c431018dd..48ccf45049e 100644
--- a/chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc
@@ -100,7 +100,7 @@ class AutofillDriverFactoryTest : public testing::Test {
protected:
// For TestAutofillDriver.
- base::test::TaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
MockAutofillClient client_;
diff --git a/chromium/components/autofill/core/browser/autofill_experiments.cc b/chromium/components/autofill/core/browser/autofill_experiments.cc
index 4ad323a4874..dd2bd3874d8 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments.cc
+++ b/chromium/components/autofill/core/browser/autofill_experiments.cc
@@ -12,7 +12,6 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
-#include "components/autofill/core/browser/autofill_internals_service.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/logging/log_manager.h"
#include "components/autofill/core/browser/payments/payments_util.h"
diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate.cc b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
index 60c4d7feb19..a5507ab6194 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
@@ -153,10 +153,10 @@ bool AutofillExternalDelegate::HasActiveScreenReader() const {
}
void AutofillExternalDelegate::OnAutofillAvailabilityEvent(
- bool has_suggestions) {
+ const mojom::AutofillState state) {
// Availability of suggestions should be communicated to Blink because
// accessibility objects live in both the renderer and browser processes.
- driver_->RendererShouldSetSuggestionAvailability(has_suggestions);
+ driver_->RendererShouldSetSuggestionAvailability(state);
}
void AutofillExternalDelegate::SetCurrentDataListValues(
@@ -373,18 +373,6 @@ void AutofillExternalDelegate::ApplyAutofillOptions(
#endif
}
-// On iOS, GooglePayIcon comes at the begining and hence prepended to the list.
-#if defined(OS_IOS)
- if (base::FeatureList::IsEnabled(
- features::kAutofillDownstreamUseGooglePayBrandingOniOS) &&
- is_all_server_suggestions) {
- Suggestion googlepay_icon;
- googlepay_icon.icon = "googlePay";
- googlepay_icon.frontend_id = POPUP_ITEM_ID_GOOGLE_PAY_BRANDING;
- suggestions->insert(suggestions->begin(), googlepay_icon);
- }
-#endif
-
#if defined(OS_ANDROID)
if (IsKeyboardAccessoryEnabled()) {
suggestions->back().icon = "settings";
diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate.h b/chromium/components/autofill/core/browser/autofill_external_delegate.h
index 2e2b8139e78..7cde61e18ac 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate.h
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate.h
@@ -86,9 +86,9 @@ class AutofillExternalDelegate : public AutofillPopupDelegate {
// Returns true if there is a screen reader installed on the machine.
virtual bool HasActiveScreenReader() const;
- // Indicates on focus changed if autofill is available or unavailable, so
- // state can be announced by screen readers.
- virtual void OnAutofillAvailabilityEvent(bool has_suggestions);
+ // Indicates on focus changed if autofill/autocomplete is available or
+ // unavailable, so state can be announced by screen readers.
+ virtual void OnAutofillAvailabilityEvent(const mojom::AutofillState state);
// Set the data list value associated with the current field.
void SetCurrentDataListValues(
diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc b/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc
index a2c018bfd72..89dd815bd17 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc
@@ -36,7 +36,6 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/geometry/rect.h"
-using autofill::features::kAutofillDownstreamUseGooglePayBrandingOniOS;
using base::ASCIIToUTF16;
using testing::_;
@@ -181,7 +180,7 @@ class AutofillExternalDelegateUnitTest : public testing::Test {
kQueryId, suggestions, /*autoselect_first_suggestion=*/false);
}
- base::test::TaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
testing::NiceMock<MockAutofillClient> autofill_client_;
std::unique_ptr<testing::NiceMock<MockAutofillDriver>> autofill_driver_;
@@ -769,54 +768,6 @@ TEST_F(AutofillExternalDelegateUnitTest, ShouldShowGooglePayIcon) {
kQueryId, autofill_item, /*autoselect_first_suggestion=*/false, true);
}
-#if defined(OS_IOS)
-TEST_F(AutofillExternalDelegateUnitTest, ShouldShowGooglePayIconOniOS) {
- // Turn on feature flag.
- base::test::ScopedFeatureList scoped_feature_list_;
- scoped_feature_list_.InitAndEnableFeature(
- kAutofillDownstreamUseGooglePayBrandingOniOS);
- IssueOnQuery(kQueryId);
-
- auto element_icons =
- testing::ElementsAre("googlePay", std::string(), "googlePay");
- EXPECT_CALL(autofill_client_,
- ShowAutofillPopup(_, _, SuggestionVectorIconsAre(element_icons),
- false, PopupType::kPersonalInformation, _));
-
- std::vector<Suggestion> autofill_item;
- autofill_item.push_back(Suggestion());
- autofill_item[0].frontend_id = kAutofillProfileId;
-
- // This should call ShowAutofillPopup.
- external_delegate_->OnSuggestionsReturned(
- kQueryId, autofill_item, /*autoselect_first_suggestion=*/false, true);
-}
-
-TEST_F(AutofillExternalDelegateUnitTest,
- ShouldNotShowGooglePayIconOniOSIfExperimentOff) {
- // Turn on feature flag.
- base::test::ScopedFeatureList scoped_feature_list_;
- scoped_feature_list_.InitAndDisableFeature(
- kAutofillDownstreamUseGooglePayBrandingOniOS);
- IssueOnQuery(kQueryId);
-
- auto element_icons = testing::ElementsAre(
- std::string(),
- std::string() /* Autofill setting item does not have icon. */);
- EXPECT_CALL(autofill_client_,
- ShowAutofillPopup(_, _, SuggestionVectorIconsAre(element_icons),
- false, PopupType::kPersonalInformation, _));
-
- std::vector<Suggestion> autofill_item;
- autofill_item.push_back(Suggestion());
- autofill_item[0].frontend_id = kAutofillProfileId;
-
- // This should call ShowAutofillPopup.
- external_delegate_->OnSuggestionsReturned(
- kQueryId, autofill_item, /*autoselect_first_suggestion=*/false, false);
-}
-#endif // defined(OS_IOS)
-
TEST_F(AutofillExternalDelegateUnitTest,
ShouldNotShowGooglePayIconIfSuggestionsContainLocalCards) {
IssueOnQuery(kQueryId);
diff --git a/chromium/components/autofill/core/browser/autofill_field.cc b/chromium/components/autofill/core/browser/autofill_field.cc
index 7068d125081..1381fb7c800 100644
--- a/chromium/components/autofill/core/browser/autofill_field.cc
+++ b/chromium/components/autofill/core/browser/autofill_field.cc
@@ -14,39 +14,28 @@
namespace autofill {
-AutofillField::AutofillField()
- : server_type_(NO_SERVER_DATA),
- heuristic_type_(UNKNOWN_TYPE),
- overall_type_(AutofillType(NO_SERVER_DATA)),
- html_type_(HTML_TYPE_UNSPECIFIED),
- html_mode_(HTML_MODE_NONE),
- phone_part_(IGNORED),
- credit_card_number_offset_(0),
- previously_autofilled_(false),
- only_fill_when_focused_(false),
- generation_type_(AutofillUploadContents::Field::NO_GENERATION),
- generated_password_changed_(false),
- vote_type_(AutofillUploadContents::Field::NO_INFORMATION) {}
+AutofillField::AutofillField() = default;
+
+AutofillField::AutofillField(FieldSignature field_signature)
+ : field_signature_(field_signature) {}
AutofillField::AutofillField(const FormFieldData& field,
const base::string16& unique_name)
: FormFieldData(field),
unique_name_(unique_name),
- server_type_(NO_SERVER_DATA),
- heuristic_type_(UNKNOWN_TYPE),
- overall_type_(AutofillType(NO_SERVER_DATA)),
- html_type_(HTML_TYPE_UNSPECIFIED),
- html_mode_(HTML_MODE_NONE),
- phone_part_(IGNORED),
- credit_card_number_offset_(0),
- previously_autofilled_(false),
- only_fill_when_focused_(false),
- parseable_name_(field.name),
- generation_type_(AutofillUploadContents::Field::NO_GENERATION),
- generated_password_changed_(false),
- vote_type_(AutofillUploadContents::Field::NO_INFORMATION) {}
-
-AutofillField::~AutofillField() {}
+ parseable_name_(field.name) {
+ field_signature_ =
+ CalculateFieldSignatureByNameAndType(name, form_control_type);
+}
+
+AutofillField::~AutofillField() = default;
+
+std::unique_ptr<AutofillField> AutofillField::CreateForPasswordManagerUpload(
+ FieldSignature field_signature) {
+ std::unique_ptr<AutofillField> field;
+ field.reset(new AutofillField(field_signature));
+ return field;
+}
void AutofillField::set_heuristic_type(ServerFieldType type) {
if (type >= 0 && type < MAX_VALID_FIELD_TYPE &&
@@ -178,7 +167,9 @@ bool AutofillField::IsEmpty() const {
}
FieldSignature AutofillField::GetFieldSignature() const {
- return CalculateFieldSignatureByNameAndType(name, form_control_type);
+ return field_signature_
+ ? *field_signature_
+ : CalculateFieldSignatureByNameAndType(name, form_control_type);
}
std::string AutofillField::FieldSignatureAsStr() const {
diff --git a/chromium/components/autofill/core/browser/autofill_field.h b/chromium/components/autofill/core/browser/autofill_field.h
index e46ff91865a..30856f92d7b 100644
--- a/chromium/components/autofill/core/browser/autofill_field.h
+++ b/chromium/components/autofill/core/browser/autofill_field.h
@@ -43,6 +43,12 @@ class AutofillField : public FormFieldData {
AutofillField(const FormFieldData& field, const base::string16& unique_name);
virtual ~AutofillField();
+ // Creates AutofillField that has bare minimum information for uploading
+ // votes, namely a field signature. Warning: do not use for Autofill code,
+ // since it is likely missing some fields.
+ static std::unique_ptr<AutofillField> CreateForPasswordManagerUpload(
+ FieldSignature field_signature);
+
const base::string16& unique_name() const { return unique_name_; }
ServerFieldType heuristic_type() const { return heuristic_type_; }
@@ -129,9 +135,6 @@ class AutofillField : public FormFieldData {
// field).
bool IsFieldFillable() const;
- void set_default_value(const std::string& value) { default_value_ = value; }
- const std::string& default_value() const { return default_value_; }
-
void set_initial_value_hash(uint32_t value) { initial_value_hash_ = value; }
base::Optional<uint32_t> initial_value_hash() { return initial_value_hash_; }
@@ -181,14 +184,17 @@ class AutofillField : public FormFieldData {
void NormalizePossibleTypesValidities();
private:
+ explicit AutofillField(FieldSignature field_signature);
+
// Whether the heuristics or server predict a credit card field.
bool IsCreditCardPrediction() const;
+ base::Optional<FieldSignature> field_signature_;
// The unique name of this field, generated by Autofill.
base::string16 unique_name_;
// The type of the field, as determined by the Autofill server.
- ServerFieldType server_type_;
+ ServerFieldType server_type_ = NO_SERVER_DATA;
// The possible types of the field, as determined by the Autofill server,
// including |server_type_| as the first item.
@@ -200,7 +206,7 @@ class AutofillField : public FormFieldData {
base::Optional<PasswordRequirementsSpec> password_requirements_;
// The type of the field, as determined by the local heuristics.
- ServerFieldType heuristic_type_;
+ ServerFieldType heuristic_type_ = UNKNOWN_TYPE;
// The type of the field. Overrides all other types (html_type_,
// heuristic_type_, server_type_).
@@ -209,11 +215,11 @@ class AutofillField : public FormFieldData {
AutofillType overall_type_;
// The type of the field, as specified by the site author in HTML.
- HtmlFieldType html_type_;
+ HtmlFieldType html_type_ = HTML_TYPE_UNSPECIFIED;
// The "mode" of the field, as specified by the site author in HTML.
// Currently this is used to distinguish between billing and shipping fields.
- HtmlFieldMode html_mode_;
+ HtmlFieldMode html_mode_ = HTML_MODE_NONE;
// The set of possible types for this field.
ServerFieldTypeSet possible_types_;
@@ -222,10 +228,7 @@ class AutofillField : public FormFieldData {
ServerFieldTypeValidityStatesMap possible_types_validities_;
// Used to track whether this field is a phone prefix or suffix.
- PhonePart phone_part_;
-
- // The default value returned by the Autofill server.
- std::string default_value_;
+ PhonePart phone_part_ = IGNORED;
// A low-entropy hash of the field's initial value before user-interactions or
// automatic fillings. This field is used to detect static placeholders.
@@ -233,13 +236,13 @@ class AutofillField : public FormFieldData {
// Used to hold the position of the first digit to be copied as a substring
// from credit card number.
- size_t credit_card_number_offset_;
+ size_t credit_card_number_offset_ = 0;
// Whether the field was autofilled then later edited.
- bool previously_autofilled_;
+ bool previously_autofilled_ = false;
// Whether the field should be filled when it is not the highlighted field.
- bool only_fill_when_focused_;
+ bool only_fill_when_focused_ = false;
// The parseable name attribute, with unnecessary information removed (such as
// a common prefix shared with other fields). Will be used for heuristics
@@ -247,15 +250,17 @@ class AutofillField : public FormFieldData {
base::string16 parseable_name_;
// The type of password generation event, if it happened.
- AutofillUploadContents::Field::PasswordGenerationType generation_type_;
+ AutofillUploadContents::Field::PasswordGenerationType generation_type_ =
+ AutofillUploadContents::Field::NO_GENERATION;
// Whether the generated password was changed by user.
- bool generated_password_changed_;
+ bool generated_password_changed_ = false;
// The vote type, if the autofill type is USERNAME or any password vote.
// Otherwise, the field is ignored. |vote_type_| provides context as to what
// triggered the vote.
- AutofillUploadContents::Field::VoteType vote_type_;
+ AutofillUploadContents::Field::VoteType vote_type_ =
+ AutofillUploadContents::Field::NO_INFORMATION;
DISALLOW_COPY_AND_ASSIGN(AutofillField);
};
diff --git a/chromium/components/autofill/core/browser/autofill_handler.cc b/chromium/components/autofill/core/browser/autofill_handler.cc
index 065949cfb27..057fda666c7 100644
--- a/chromium/components/autofill/core/browser/autofill_handler.cc
+++ b/chromium/components/autofill/core/browser/autofill_handler.cc
@@ -8,7 +8,10 @@
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/logging/log_manager.h"
#include "components/autofill/core/common/autofill_data_validation.h"
+#include "components/autofill/core/common/autofill_internals/log_message.h"
+#include "components/autofill/core/common/autofill_internals/logging_scope.h"
#include "components/autofill/core/common/autofill_payments_features.h"
+#include "components/autofill/core/common/autofill_tick_clock.h"
#include "components/autofill/core/common/signatures_util.h"
#include "ui/gfx/geometry/rect_f.h"
@@ -82,34 +85,27 @@ void AutofillHandler::OnFormsSeen(const std::vector<FormData>& forms,
// the pointer values.
std::set<FormSignature> new_form_signatures;
for (const FormData& form : forms) {
- const auto parse_form_start_time = TimeTicks::Now();
+ const auto parse_form_start_time = AutofillTickClock::NowTicks();
FormStructure* cached_form_structure = nullptr;
FormStructure* form_structure = nullptr;
// Try to find the FormStructure that corresponds to |form| if the form
// contains credit card fields only.
// |cached_form_structure| may still be nullptr after this call.
- if (base::FeatureList::IsEnabled(features::kAutofillImportDynamicForms)) {
- ignore_result(FindCachedForm(form, &cached_form_structure));
- bool only_contains_credit_card_fields = true;
- if (cached_form_structure) {
- for (const FormType& form_type :
- cached_form_structure->GetFormTypes()) {
- if (form_type != CREDIT_CARD_FORM) {
- only_contains_credit_card_fields = false;
- break;
- }
+ ignore_result(FindCachedForm(form, &cached_form_structure));
+ if (cached_form_structure) {
+ for (const FormType& form_type : cached_form_structure->GetFormTypes()) {
+ if (form_type != CREDIT_CARD_FORM) {
+ cached_form_structure = nullptr;
+ break;
}
}
- if (!only_contains_credit_card_fields) {
- cached_form_structure = nullptr;
- }
}
if (!ParseForm(form, cached_form_structure, &form_structure))
continue;
DCHECK(form_structure);
new_form_signatures.insert(form_structure->form_signature());
- AutofillMetrics::LogParseFormTiming(TimeTicks::Now() -
+ AutofillMetrics::LogParseFormTiming(AutofillTickClock::NowTicks() -
parse_form_start_time);
}
@@ -274,12 +270,17 @@ bool AutofillHandler::ParseForm(const FormData& form,
const FormStructure* cached_form,
FormStructure** parsed_form_structure) {
DCHECK(parsed_form_structure);
- if (form_structures_.size() >= kAutofillHandlerMaxFormCacheSize)
+ if (form_structures_.size() >= kAutofillHandlerMaxFormCacheSize) {
+ if (log_manager_) {
+ log_manager_->Log() << LoggingScope::kAbortParsing
+ << LogMessage::kAbortParsingTooManyForms << form;
+ }
return false;
+ }
auto form_structure = std::make_unique<FormStructure>(form);
form_structure->ParseFieldTypesFromAutocompleteAttributes();
- if (!form_structure->ShouldBeParsed())
+ if (!form_structure->ShouldBeParsed(log_manager_))
return false;
if (cached_form) {
@@ -291,9 +292,8 @@ bool AutofillHandler::ParseForm(const FormData& form,
if (observer_for_testing_)
observer_for_testing_->OnFormParsed();
- if (form_structure.get()->value_from_dynamic_change_form()) {
+ if (form_structure.get()->value_from_dynamic_change_form())
value_from_dynamic_change_form_ = true;
- }
}
form_structure->DetermineHeuristicTypes(log_manager_);
diff --git a/chromium/components/autofill/core/browser/autofill_internals_service.cc b/chromium/components/autofill/core/browser/autofill_internals_service.cc
deleted file mode 100644
index 3f21b7db1d7..00000000000
--- a/chromium/components/autofill/core/browser/autofill_internals_service.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/autofill/core/browser/autofill_internals_service.h"
-
-namespace autofill {
-
-LogBuffer& operator<<(LogBuffer& buf, LoggingScope scope) {
- if (!buf.active())
- return buf;
- return buf << Tag{"div"} << Attrib{"scope", LoggingScopeToString(scope)}
- << Attrib{"class", "log-entry"};
-}
-
-LogBuffer& operator<<(LogBuffer& buf, LogMessage message) {
- if (!buf.active())
- return buf;
- return buf << Tag{"div"} << Attrib{"message", LogMessageToString(message)}
- << Attrib{"class", "log-message"} << LogMessageValue(message);
-}
-
-} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_internals_service.h b/chromium/components/autofill/core/browser/autofill_internals_service.h
deleted file mode 100644
index b5c81130d26..00000000000
--- a/chromium/components/autofill/core/browser/autofill_internals_service.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_INTERNALS_SERVICE_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_INTERNALS_SERVICE_H_
-
-#include "base/macros.h"
-#include "components/autofill/core/browser/logging/log_buffer.h"
-#include "components/autofill/core/browser/logging/log_router.h"
-#include "components/autofill/core/common/autofill_internals/log_message.h"
-#include "components/autofill/core/common/autofill_internals/logging_scope.h"
-
-namespace autofill {
-
-// TODO(crbug.com/928595) This is a temporary home for these operations.
-// Find a properly named file.
-LogBuffer& operator<<(LogBuffer& buf, LoggingScope scope);
-
-LogBuffer& operator<<(LogBuffer& buf, LogMessage message);
-
-} // namespace autofill
-
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_INTERNALS_SERVICE_H_
diff --git a/chromium/components/autofill/core/browser/autofill_manager.cc b/chromium/components/autofill/core/browser/autofill_manager.cc
index 98281bbf87f..a23e3c536e6 100644
--- a/chromium/components/autofill/core/browser/autofill_manager.cc
+++ b/chromium/components/autofill/core/browser/autofill_manager.cc
@@ -42,7 +42,6 @@
#include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill/core/browser/autofill_external_delegate.h"
#include "components/autofill/core/browser/autofill_field.h"
-#include "components/autofill/core/browser/autofill_internals_service.h"
#include "components/autofill/core/browser/autofill_manager_test_delegate.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/autofill_type.h"
@@ -68,9 +67,12 @@
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_data_validation.h"
#include "components/autofill/core/common/autofill_features.h"
+#include "components/autofill/core/common/autofill_internals/log_message.h"
+#include "components/autofill/core/common/autofill_internals/logging_scope.h"
#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_switches.h"
+#include "components/autofill/core/common/autofill_tick_clock.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_data_predictions.h"
@@ -345,6 +347,17 @@ AutofillField* GetBestPossibleCVCField(
return HeuristicallyFindCVCField(form_structure);
}
+// Some autofill types are detected based on values and not based on form
+// features. We may decide that it's an autofill form after submission.
+bool ContainsAutofillableValue(const autofill::FormStructure& form) {
+ return std::any_of(form.begin(), form.end(),
+ [](const std::unique_ptr<autofill::AutofillField>& field) {
+ return base::Contains(field->possible_types(),
+ UPI_VPA) ||
+ IsUPIVirtualPaymentAddress(field->value);
+ });
+}
+
} // namespace
AutofillManager::FillingContext::FillingContext() = default;
@@ -587,8 +600,10 @@ void AutofillManager::OnFormSubmittedImpl(const FormData& form,
enable_ablation_logging_, sync_state_, *submitted_form);
}
- if (!submitted_form->IsAutofillable())
+ if (!submitted_form->IsAutofillable() &&
+ !ContainsAutofillableValue(*submitted_form)) {
return;
+ }
// Update Personal Data with the form's submitted data.
// Also triggers offering local/upload credit card save, if applicable.
@@ -660,8 +675,8 @@ bool AutofillManager::MaybeStartVoteUploadProcess(
base::BindOnce(&AutofillManager::UploadFormDataAsyncCallback,
weak_ptr_factory_.GetWeakPtr(),
base::Owned(form_structure.release()),
- initial_interaction_timestamp_, base::TimeTicks::Now(),
- observed_submission));
+ initial_interaction_timestamp_,
+ AutofillTickClock::NowTicks(), observed_submission));
return true;
}
@@ -927,7 +942,7 @@ void AutofillManager::FillOrPreviewProfileForm(
auto filling_context = std::make_unique<FillingContext>();
filling_context->temp_data_model = profile;
filling_context->filled_field_name = autofill_field->unique_name();
- filling_context->original_fill_time = base::TimeTicks::Now();
+ filling_context->original_fill_time = AutofillTickClock::NowTicks();
entry = std::move(filling_context);
}
}
@@ -993,10 +1008,13 @@ void AutofillManager::OnFocusNoLongerOnForm() {
#if defined(OS_CHROMEOS)
// There is no way of determining whether ChromeVox is in use, so assume it's
// being used.
- external_delegate_->OnAutofillAvailabilityEvent(false);
+ external_delegate_->OnAutofillAvailabilityEvent(
+ mojom::AutofillState::kNoSuggestions);
#else
- if (external_delegate_->HasActiveScreenReader())
- external_delegate_->OnAutofillAvailabilityEvent(false);
+ if (external_delegate_->HasActiveScreenReader()) {
+ external_delegate_->OnAutofillAvailabilityEvent(
+ mojom::AutofillState::kNoSuggestions);
+ }
#endif
}
@@ -1018,8 +1036,10 @@ void AutofillManager::OnFocusOnFormFieldImpl(const FormData& form,
GetAvailableSuggestions(form, field, &suggestions, &context);
external_delegate_->OnAutofillAvailabilityEvent(
- context.suppress_reason == SuppressReason::kNotSuppressed &&
- !suggestions.empty());
+ (context.suppress_reason == SuppressReason::kNotSuppressed &&
+ !suggestions.empty())
+ ? mojom::AutofillState::kAutofillAvailable
+ : mojom::AutofillState::kNoSuggestions);
}
void AutofillManager::OnSelectControlDidChangeImpl(
@@ -1355,6 +1375,9 @@ void AutofillManager::OnSuggestionsReturned(
int query_id,
bool autoselect_first_suggestion,
const std::vector<Suggestion>& suggestions) {
+ external_delegate_->OnAutofillAvailabilityEvent(
+ !suggestions.empty() ? mojom::AutofillState::kAutocompleteAvailable
+ : mojom::AutofillState::kNoSuggestions);
external_delegate_->OnSuggestionsReturned(query_id, suggestions,
autoselect_first_suggestion);
}
@@ -2199,7 +2222,7 @@ bool AutofillManager::ShouldTriggerRefill(const FormStructure& form_structure) {
form_structure);
FillingContext* filling_context = itr->second.get();
- base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeTicks now = AutofillTickClock::NowTicks();
base::TimeDelta delta = now - filling_context->original_fill_time;
if (filling_context->attempted_refill &&
diff --git a/chromium/components/autofill/core/browser/autofill_manager.h b/chromium/components/autofill/core/browser/autofill_manager.h
index 905f5b8ff4a..d0954dea221 100644
--- a/chromium/components/autofill/core/browser/autofill_manager.h
+++ b/chromium/components/autofill/core/browser/autofill_manager.h
@@ -312,9 +312,6 @@ class AutofillManager : public AutofillHandler,
}
// Exposed for testing.
- AutofillExternalDelegate* external_delegate() { return external_delegate_; }
-
- // Exposed for testing.
void set_download_manager(AutofillDownloadManager* manager) {
download_manager_.reset(manager);
}
@@ -673,6 +670,8 @@ class AutofillManager : public AutofillHandler,
CreditCardSelectedFormEvents);
FRIEND_TEST_ALL_PREFIXES(AutofillMetricsIFrameTest,
CreditCardFilledFormEvents);
+ FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest,
+ CreditCardUnmaskingPreflightCall);
FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest, CreditCardGetRealPanDuration);
FRIEND_TEST_ALL_PREFIXES(AutofillMetricsIFrameTest,
CreditCardWillSubmitFormEvents);
diff --git a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
index 3aee9d14555..57355a6eeeb 100644
--- a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -58,6 +58,7 @@
#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_switches.h"
+#include "components/autofill/core/common/autofill_tick_clock.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
@@ -561,6 +562,13 @@ class AutofillManagerTest : public testing::Test {
autofill_manager_->credit_card_access_manager_->cvc_authenticator_
->full_card_request_.get();
DCHECK(full_card_request);
+
+ // Mock user response.
+ payments::FullCardRequest::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ full_card_request->OnUnmaskPromptAccepted(details);
+
+ // Mock payments response.
payments::PaymentsClient::UnmaskResponseDetails response;
full_card_request->OnDidGetRealPan(result,
response.with_real_pan(real_pan));
@@ -5816,8 +5824,8 @@ TEST_F(AutofillManagerTest, OnTextFieldDidChangeAndUnfocus_Upload) {
form.fields[1].value = ASCIIToUTF16("Presley");
form.fields[2].value = ASCIIToUTF16("theking@gmail.com");
// Simulate editing a field.
- autofill_manager_->OnTextFieldDidChange(form, form.fields.front(),
- gfx::RectF(), base::TimeTicks::Now());
+ autofill_manager_->OnTextFieldDidChange(
+ form, form.fields.front(), gfx::RectF(), AutofillTickClock::NowTicks());
// Simulate lost of focus on the form.
autofill_manager_->OnFocusNoLongerOnForm();
@@ -5866,8 +5874,8 @@ TEST_F(AutofillManagerTest, OnTextFieldDidChangeAndNavigation_Upload) {
form.fields[1].value = ASCIIToUTF16("Presley");
form.fields[2].value = ASCIIToUTF16("theking@gmail.com");
// Simulate editing a field.
- autofill_manager_->OnTextFieldDidChange(form, form.fields.front(),
- gfx::RectF(), base::TimeTicks::Now());
+ autofill_manager_->OnTextFieldDidChange(
+ form, form.fields.front(), gfx::RectF(), AutofillTickClock::NowTicks());
// Simulate a navigation so that the pending form is uploaded.
autofill_manager_->Reset();
@@ -5915,7 +5923,8 @@ TEST_F(AutofillManagerTest, OnDidFillAutofillFormDataAndUnfocus_Upload) {
form.fields[0].value = ASCIIToUTF16("Elvis");
form.fields[1].value = ASCIIToUTF16("Presley");
form.fields[2].value = ASCIIToUTF16("theking@gmail.com");
- autofill_manager_->OnDidFillAutofillFormData(form, base::TimeTicks::Now());
+ autofill_manager_->OnDidFillAutofillFormData(form,
+ AutofillTickClock::NowTicks());
// Simulate lost of focus on the form.
autofill_manager_->OnFocusNoLongerOnForm();
@@ -7670,6 +7679,58 @@ TEST_F(AutofillManagerTest,
HasSubstr("Autofill.FormEvents.Address"))));
}
+// Test that we import data when the field type is determined by the value and
+// without any heuristics on the attributes.
+TEST_F(AutofillManagerTest, ImportDataWhenValueDetected) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kAutofillSaveAndFillVPA);
+
+ FormData form;
+ form.url = GURL("https://wwww.foo.com");
+
+ FormFieldData field;
+ test::CreateTestFormField("VPA:", "vpa", "", "text", &field);
+ form.fields.push_back(field);
+
+ FormsSeen({form});
+ autofill_manager_->SetExpectedSubmittedFieldTypes({{UPI_VPA}});
+ autofill_manager_->SetExpectedObservedSubmission(true);
+ autofill_manager_->SetCallParentUploadFormData(true);
+ form.submission_event =
+ mojom::SubmissionIndicatorEvent::SAME_DOCUMENT_NAVIGATION;
+
+ form.fields[0].value = ASCIIToUTF16("user@indianbank");
+ FormSubmitted(form);
+
+ EXPECT_EQ(1, personal_data_.num_times_save_vpa_called());
+}
+
+// Test that we do not import VPA data when in incognito.
+TEST_F(AutofillManagerTest, DontImportVPAWhenIncognito) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kAutofillSaveAndFillVPA);
+ autofill_driver_->SetIsIncognito(true);
+
+ FormData form;
+ form.url = GURL("https://wwww.foo.com");
+
+ FormFieldData field;
+ test::CreateTestFormField("VPA:", "vpa", "", "text", &field);
+ form.fields.push_back(field);
+
+ FormsSeen({form});
+ autofill_manager_->SetExpectedSubmittedFieldTypes({{UPI_VPA}});
+ autofill_manager_->SetExpectedObservedSubmission(true);
+ autofill_manager_->SetCallParentUploadFormData(true);
+ form.submission_event =
+ mojom::SubmissionIndicatorEvent::SAME_DOCUMENT_NAVIGATION;
+
+ form.fields[0].value = ASCIIToUTF16("user@indianbank");
+ FormSubmitted(form);
+
+ EXPECT_EQ(0, personal_data_.num_times_save_vpa_called());
+}
+
// Test param indicates if there is an active screen reader.
class OnFocusOnFormFieldTest : public AutofillManagerTest,
public testing::WithParamInterface<bool> {
diff --git a/chromium/components/autofill/core/browser/autofill_merge_unittest.cc b/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
index a845b3daed5..b3d5aff7e5c 100644
--- a/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
@@ -20,6 +20,7 @@
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/data_driven_test.h"
+#include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
#include "components/autofill/core/browser/form_data_importer.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/geo/country_names.h"
@@ -128,11 +129,9 @@ class PersonalDataManagerMock : public PersonalDataManager {
};
PersonalDataManagerMock::PersonalDataManagerMock()
- : PersonalDataManager("en-US") {
-}
+ : PersonalDataManager("en-US") {}
-PersonalDataManagerMock::~PersonalDataManagerMock() {
-}
+PersonalDataManagerMock::~PersonalDataManagerMock() {}
void PersonalDataManagerMock::Reset() {
profiles_.clear();
@@ -141,8 +140,8 @@ void PersonalDataManagerMock::Reset() {
std::string PersonalDataManagerMock::SaveImportedProfile(
const AutofillProfile& profile) {
std::vector<AutofillProfile> profiles;
- std::string merged_guid =
- MergeProfile(profile, &profiles_, "en-US", &profiles);
+ std::string merged_guid = AutofillProfileComparator::MergeProfile(
+ profile, &profiles_, "en-US", &profiles);
if (merged_guid == profile.guid())
profiles_.push_back(std::make_unique<AutofillProfile>(profile));
return merged_guid;
@@ -202,8 +201,7 @@ AutofillMergeTest::AutofillMergeTest() : DataDrivenTest(GetTestDataDir()) {
}
}
-AutofillMergeTest::~AutofillMergeTest() {
-}
+AutofillMergeTest::~AutofillMergeTest() {}
void AutofillMergeTest::SetUp() {
test::DisableSystemServices(nullptr);
@@ -247,8 +245,7 @@ void AutofillMergeTest::MergeProfiles(const std::string& profiles,
do {
++separator_pos;
} while (separator_pos < line.size() && line[separator_pos] == ' ');
- base::string16 value =
- base::UTF8ToUTF16(line.substr(separator_pos));
+ base::string16 value = base::UTF8ToUTF16(line.substr(separator_pos));
base::ReplaceFirstSubstringAfterOffset(
&value, 0, base::ASCIIToUTF16("\\n"), base::ASCIIToUTF16("\n"));
@@ -279,12 +276,15 @@ void AutofillMergeTest::MergeProfiles(const std::string& profiles,
// Import the profile.
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> unused_imported_vpa;
form_data_importer_->ImportFormData(form_structure,
true, // address autofill enabled,
true, // credit card autofill enabled
false, // should return local card
- &imported_credit_card);
+ &imported_credit_card,
+ &unused_imported_vpa);
EXPECT_FALSE(imported_credit_card);
+ EXPECT_FALSE(unused_imported_vpa.has_value());
// Clear the |form| to start a new profile.
form.fields.clear();
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.cc b/chromium/components/autofill/core/browser/autofill_metrics.cc
index e2ad2699390..ad4203a2a02 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics.cc
@@ -22,6 +22,7 @@
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_prefs.h"
+#include "components/autofill/core/common/autofill_tick_clock.h"
#include "components/autofill/core/common/form_data.h"
#include "services/metrics/public/cpp/metrics_utils.h"
#include "services/metrics/public/cpp/ukm_builders.h"
@@ -767,10 +768,17 @@ void AutofillMetrics::LogSaveCardPromptMetricBySecurityLevel(
histogram_name += "Local";
}
- base::UmaHistogramEnumeration(
- security_state::GetSecurityLevelHistogramName(
- histogram_name, security_level),
- metric, NUM_SAVE_CARD_PROMPT_METRICS);
+ base::UmaHistogramEnumeration(security_state::GetSecurityLevelHistogramName(
+ histogram_name, security_level),
+ metric, NUM_SAVE_CARD_PROMPT_METRICS);
+}
+
+// static
+void AutofillMetrics::LogCreditCardUploadFeedbackMetric(
+ CreditCardUploadFeedbackMetric metric) {
+ DCHECK_LT(metric, NUM_CREDIT_CARD_UPLOAD_FEEDBACK_METRICS);
+ UMA_HISTOGRAM_ENUMERATION("Autofill.CreditCardUploadFeedback", metric,
+ NUM_CREDIT_CARD_UPLOAD_FEEDBACK_METRICS);
}
// static
@@ -922,6 +930,117 @@ void AutofillMetrics::LogSaveCardWithFirstAndLastNameComplete(bool is_local) {
}
// static
+void AutofillMetrics::LogCardUnmaskDurationAfterWebauthn(
+ const base::TimeDelta& duration,
+ AutofillClient::PaymentsRpcResult result) {
+ std::string suffix;
+ switch (result) {
+ case AutofillClient::SUCCESS:
+ suffix = "Success";
+ break;
+ case AutofillClient::TRY_AGAIN_FAILURE:
+ case AutofillClient::PERMANENT_FAILURE:
+ suffix = "Failure";
+ break;
+ case AutofillClient::NETWORK_ERROR:
+ suffix = "NetworkError";
+ break;
+ case AutofillClient::NONE:
+ NOTREACHED();
+ return;
+ }
+ base::UmaHistogramLongTimes("Autofill.BetterAuth.CardUnmaskDuration.Fido",
+ duration);
+ base::UmaHistogramLongTimes(
+ "Autofill.BetterAuth.CardUnmaskDuration.Fido." + suffix, duration);
+}
+
+// static
+void AutofillMetrics::LogCardUnmaskPreflightCalled() {
+ UMA_HISTOGRAM_BOOLEAN("Autofill.BetterAuth.CardUnmaskPreflightCalled", true);
+}
+
+// static
+void AutofillMetrics::LogCardUnmaskPreflightDuration(
+ const base::TimeDelta& duration) {
+ base::UmaHistogramLongTimes("Autofill.BetterAuth.CardUnmaskPreflightDuration",
+ duration);
+}
+
+// static
+void AutofillMetrics::LogWebauthnOptChangeCalled(
+ bool request_to_opt_in,
+ bool is_checkout_flow,
+ WebauthnOptInParameters metric) {
+ if (!request_to_opt_in) {
+ DCHECK(!is_checkout_flow);
+ base::UmaHistogramBoolean(
+ "Autofill.BetterAuth.OptOutCalled.FromSettingsPage", true);
+ return;
+ }
+
+ std::string histogram_name = "Autofill.BetterAuth.OptInCalled.";
+ histogram_name += is_checkout_flow ? "FromCheckoutFlow" : "FromSettingsPage";
+ base::UmaHistogramEnumeration(histogram_name, metric);
+}
+
+// static
+void AutofillMetrics::LogWebauthnOptInPromoShown(bool is_checkout_flow) {
+ std::string suffix =
+ is_checkout_flow ? "FromCheckoutFlow" : "FromSettingsPage";
+ base::UmaHistogramBoolean("Autofill.BetterAuth.OptInPromoShown." + suffix,
+ true);
+}
+
+// static
+void AutofillMetrics::LogWebauthnOptInPromoUserDecision(
+ bool is_checkout_flow,
+ WebauthnOptInPromoUserDecisionMetric metric) {
+ std::string suffix =
+ (is_checkout_flow ? "FromCheckoutFlow" : "FromSettingsPage");
+ base::UmaHistogramEnumeration(
+ "Autofill.BetterAuth.OptInPromoUserDecision." + suffix, metric);
+}
+
+// static
+void AutofillMetrics::LogCardUnmaskTypeDecision(
+ CardUnmaskTypeDecisionMetric metric) {
+ base::UmaHistogramEnumeration("Autofill.BetterAuth.CardUnmaskTypeDecision",
+ metric);
+}
+
+// static
+void AutofillMetrics::LogUserPerceivedLatencyOnCardSelection(
+ PreflightCallEvent event,
+ bool fido_auth_enabled) {
+ std::string histogram_name =
+ "Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection.";
+ histogram_name += fido_auth_enabled ? "OptedIn" : "OptedOut";
+ base::UmaHistogramEnumeration(histogram_name, event);
+}
+
+// static
+void AutofillMetrics::LogWebauthnResult(WebauthnFlowEvent event,
+ WebauthnResultMetric metric) {
+ std::string histogram_name = "Autofill.BetterAuth.WebauthnResult.";
+ switch (event) {
+ case WebauthnFlowEvent::kImmediateAuthentication:
+ histogram_name += "ImmediateAuthentication";
+ break;
+ case WebauthnFlowEvent::kAuthenticationAfterCvc:
+ histogram_name += "AuthenticationAfterCVC";
+ break;
+ case WebauthnFlowEvent::kCheckoutOptIn:
+ histogram_name += "CheckoutOptIn";
+ break;
+ case WebauthnFlowEvent::kSettingsPageOptIn:
+ histogram_name += "SettingsPageOptIn";
+ break;
+ }
+ base::UmaHistogramEnumeration(histogram_name, metric);
+}
+
+// static
void AutofillMetrics::LogUnmaskPromptEvent(UnmaskPromptEvent event) {
UMA_HISTOGRAM_ENUMERATION("Autofill.UnmaskPrompt.Events", event,
NUM_UNMASK_PROMPT_EVENTS);
@@ -1186,10 +1305,9 @@ void AutofillMetrics::LogUserHappinessBySecurityLevel(
return;
}
- base::UmaHistogramEnumeration(
- security_state::GetSecurityLevelHistogramName(
- histogram_name, security_level),
- metric, NUM_USER_HAPPINESS_METRICS);
+ base::UmaHistogramEnumeration(security_state::GetSecurityLevelHistogramName(
+ histogram_name, security_level),
+ metric, NUM_USER_HAPPINESS_METRICS);
}
// static
@@ -1974,8 +2092,9 @@ int64_t AutofillMetrics::FormInteractionsUkmLogger::MillisecondsSinceFormParsed(
const base::TimeTicks& form_parsed_timestamp) const {
DCHECK(!form_parsed_timestamp.is_null());
// Use the pinned timestamp as the current time if it's set.
- base::TimeTicks now =
- pinned_timestamp_.is_null() ? base::TimeTicks::Now() : pinned_timestamp_;
+ base::TimeTicks now = pinned_timestamp_.is_null()
+ ? AutofillTickClock::NowTicks()
+ : pinned_timestamp_;
return ukm::GetExponentialBucketMin(
(now - form_parsed_timestamp).InMilliseconds(),
@@ -1987,7 +2106,7 @@ AutofillMetrics::UkmTimestampPin::UkmTimestampPin(
: logger_(logger) {
DCHECK(logger_);
DCHECK(!logger_->has_pinned_timestamp());
- logger_->set_pinned_timestamp(base::TimeTicks::Now());
+ logger_->set_pinned_timestamp(AutofillTickClock::NowTicks());
}
AutofillMetrics::UkmTimestampPin::~UkmTimestampPin() {
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.h b/chromium/components/autofill/core/browser/autofill_metrics.h
index 7ebd53ccb73..278be51a96c 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.h
+++ b/chromium/components/autofill/core/browser/autofill_metrics.h
@@ -6,6 +6,7 @@
#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_METRICS_H_
#include <stddef.h>
+#include <memory>
#include <set>
#include <string>
#include <utility>
@@ -119,6 +120,8 @@ class AutofillMetrics {
// All the required conditions were satisfied even though the form is
// dynamic changed.
UPLOAD_OFFERED_FROM_DYNAMIC_CHANGE_FORM = 1 << 17,
+ // The legal message was invalid.
+ UPLOAD_NOT_OFFERED_INVALID_LEGAL_MESSAGE = 1 << 18,
// Update |kNumCardUploadDecisionMetrics| when adding new enum here.
};
@@ -299,6 +302,17 @@ class AutofillMetrics {
NUM_SAVE_CARD_PROMPT_METRICS,
};
+ enum CreditCardUploadFeedbackMetric {
+ // The loading indicator animation which indicates uploading is in progress
+ // is successfully shown.
+ CREDIT_CARD_UPLOAD_FEEDBACK_LOADING_ANIMATION_SHOWN,
+ // The credit card icon with the saving failure badge is shown.
+ CREDIT_CARD_UPLOAD_FEEDBACK_FAILURE_ICON_SHOWN,
+ // The failure icon is clicked and the save card failure bubble is shown.
+ CREDIT_CARD_UPLOAD_FEEDBACK_FAILURE_BUBBLE_SHOWN,
+ NUM_CREDIT_CARD_UPLOAD_FEEDBACK_METRICS,
+ };
+
// Metrics to measure user interaction with the Manage Cards view
// shown when user clicks on the save card icon after accepting
// to save a card.
@@ -492,7 +506,9 @@ class AutofillMetrics {
NOT_OFFERED_SINGLE_LOCAL_CARD = 7,
// User used an unsupported local card, we will abort the migration.
NOT_OFFERED_USE_UNSUPPORTED_LOCAL_CARD = 8,
- kMaxValue = NOT_OFFERED_USE_UNSUPPORTED_LOCAL_CARD,
+ // Legal message was invalid, we will abort the migration.
+ NOT_OFFERED_INVALID_LEGAL_MESSAGE = 9,
+ kMaxValue = NOT_OFFERED_INVALID_LEGAL_MESSAGE,
};
// Metrics to track events when local credit card migration is offered.
@@ -680,6 +696,79 @@ class AutofillMetrics {
NUM_UNMASK_PROMPT_EVENTS,
};
+ // Events related to user-perceived latency due to GetDetailsForGetRealPan
+ // call.
+ enum class PreflightCallEvent {
+ // Returned before card chosen.
+ kPreflightCallReturnedBeforeCardChosen = 0,
+ // Did not return before card was chosen. When opted-in, this means
+ // the UI had to wait for the call to return. When opted-out, this means we
+ // did not offer to opt-in.
+ kCardChosenBeforePreflightCallReturned = 1,
+ // Preflight call was irrelevant; skipped waiting.
+ kDidNotChooseMaskedCard = 2,
+ kMaxValue = kDidNotChooseMaskedCard,
+ };
+
+ // Metric for tracking which authentication method was used for a user with
+ // FIDO authentication enabled.
+ enum class CardUnmaskTypeDecisionMetric {
+ // Only WebAuthn prompt was shown.
+ kFidoOnly = 0,
+ // CVC authentication was required in addition to WebAuthn.
+ kCvcThenFido = 1,
+ kMaxValue = kCvcThenFido,
+ };
+
+ // Possible scenarios where a WebAuthn prompt may show.
+ enum class WebauthnFlowEvent {
+ // WebAuthn is immediately prompted for unmasking.
+ kImmediateAuthentication = 0,
+ // WebAuthn is prompted after a CVC check.
+ kAuthenticationAfterCvc = 1,
+ // WebAuthn is prompted after being offered to opt-in from a checkout flow.
+ kCheckoutOptIn = 2,
+ // WebAuthn is prompted after being offered to opt-in from the settings
+ // page.
+ kSettingsPageOptIn = 3,
+ kMaxValue = kSettingsPageOptIn,
+ };
+
+ // The result of a WebAuthn user-verification prompt.
+ enum class WebauthnResultMetric {
+ // User-verification succeeded.
+ kSuccess = 0,
+ // Other checks failed (e.g. invalid domain, algorithm unsupported, etc.)
+ kOtherError = 1,
+ // User either failed verification or cancelled.
+ kNotAllowedError = 2,
+ kMaxValue = kNotAllowedError,
+ };
+
+ // The user decision for the WebAuthn opt-in promo.
+ enum class WebauthnOptInPromoUserDecisionMetric {
+ // User accepted promo.
+ kAccepted = 0,
+ // User immediately declined promo.
+ kDeclinedImmediately = 1,
+ // Once user accepts the dialog, a round-trip call to Payments is sent,
+ // which is required for user authentication. The user has the option to
+ // cancel the dialog before the round-trip call is returned.
+ kDeclinedAfterAccepting = 2,
+ kMaxValue = kDeclinedAfterAccepting,
+ };
+
+ // The parameters with which opt change was called.
+ enum class WebauthnOptInParameters {
+ // Call made to fetch a challenge.
+ kFetchingChallenge = 0,
+ // Call made with signature of creation challenge.
+ kWithCreationChallenge = 1,
+ // Call made with signature of request challenge.
+ kWithRequestChallenge = 2,
+ kMaxValue = kWithRequestChallenge,
+ };
+
// Possible results of Payments RPCs.
enum PaymentsRpcResult {
// Request succeeded.
@@ -955,6 +1044,8 @@ class AutofillMetrics {
SaveCardPromptMetric metric,
bool is_uploading,
security_state::SecurityLevel security_level);
+ static void LogCreditCardUploadFeedbackMetric(
+ CreditCardUploadFeedbackMetric metric);
static void LogManageCardsPromptMetric(ManageCardsPromptMetric metric,
bool is_uploading);
static void LogScanCreditCardPromptMetric(ScanCreditCardPromptMetric metric);
@@ -1028,6 +1119,48 @@ class AutofillMetrics {
static void LogUserHappinessByProfileFormType(UserHappinessMetric metric,
uint32_t profile_form_bitmask);
+ // Logs the card fetch latency after a WebAuthn prompt.
+ static void LogCardUnmaskDurationAfterWebauthn(
+ const base::TimeDelta& duration,
+ AutofillClient::PaymentsRpcResult result);
+
+ // Logs the count of calls to PaymentsClient::GetUnmaskDetails() (aka
+ // GetDetailsForGetRealPan).
+ static void LogCardUnmaskPreflightCalled();
+
+ // Logs the duration of the PaymentsClient::GetUnmaskDetails() call (aka
+ // GetDetailsForGetRealPan).
+ static void LogCardUnmaskPreflightDuration(const base::TimeDelta& duration);
+
+ // Logs the count of calls to PaymentsClient::OptChange() (aka
+ // UpdateAutofillUserPreference).
+ static void LogWebauthnOptChangeCalled(bool request_to_opt_in,
+ bool is_checkout_flow,
+ WebauthnOptInParameters metric);
+
+ // Logs the number of times the opt-in promo for enabling FIDO authentication
+ // for card unmasking has been shown.
+ static void LogWebauthnOptInPromoShown(bool is_checkout_flow);
+
+ // Logs the user response to the opt-in promo for enabling FIDO authentication
+ // for card unmasking.
+ static void LogWebauthnOptInPromoUserDecision(
+ bool is_checkout_flow,
+ WebauthnOptInPromoUserDecisionMetric metric);
+
+ // Logs which unmask type was used for a user with FIDO authentication
+ // enabled.
+ static void LogCardUnmaskTypeDecision(CardUnmaskTypeDecisionMetric metric);
+
+ // Logs the existence of any user-perceived latency between selecting a Google
+ // Payments server card and seeing a card unmask prompt.
+ static void LogUserPerceivedLatencyOnCardSelection(PreflightCallEvent event,
+ bool fido_auth_enabled);
+
+ // Logs the result of a WebAuthn prompt.
+ static void LogWebauthnResult(WebauthnFlowEvent event,
+ WebauthnResultMetric metric);
+
// Logs |event| to the unmask prompt events histogram.
static void LogUnmaskPromptEvent(UnmaskPromptEvent event);
@@ -1258,13 +1391,6 @@ class AutofillMetrics {
// autofilled to support synthetic fields.
static void LogHiddenOrPresentationalSelectFieldsFilled();
- // Logs the the |ukm_entry_name| with the specified |url| and the specified
- // |metrics|. Returns whether the ukm was sucessfully logged.
- static bool LogUkm(ukm::UkmRecorder* ukm_recorder,
- const GURL& url,
- const std::string& ukm_entry_name,
- const std::vector<std::pair<const char*, int>>& metrics);
-
// Converts form type to bit vector to store in UKM.
static int64_t FormTypesToBitVector(const std::set<FormType>& form_types);
@@ -1288,7 +1414,7 @@ class AutofillMetrics {
private:
static void Log(AutocompleteEvent event);
- static const int kNumCardUploadDecisionMetrics = 18;
+ static const int kNumCardUploadDecisionMetrics = 19;
DISALLOW_IMPLICIT_CONSTRUCTORS(AutofillMetrics);
};
diff --git a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
index 33cc102717a..1eac2646442 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -21,6 +21,7 @@
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
+#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill/core/browser/autofill_external_delegate.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
@@ -28,6 +29,7 @@
#include "components/autofill/core/browser/metrics/credit_card_form_event_logger.h"
#include "components/autofill/core/browser/metrics/form_events.h"
#include "components/autofill/core/browser/mock_autocomplete_history_manager.h"
+#include "components/autofill/core/browser/payments/credit_card_access_manager.h"
#include "components/autofill/core/browser/payments/test_credit_card_save_manager.h"
#include "components/autofill/core/browser/payments/test_payments_client.h"
#include "components/autofill/core/browser/personal_data_manager.h"
@@ -35,6 +37,7 @@
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
#include "components/autofill/core/browser/test_autofill_manager.h"
+#include "components/autofill/core/browser/test_autofill_tick_clock.h"
#include "components/autofill/core/browser/test_form_data_importer.h"
#include "components/autofill/core/browser/test_form_structure.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
@@ -43,6 +46,8 @@
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_features.h"
+#include "components/autofill/core/common/autofill_payments_features.h"
+#include "components/autofill/core/common/autofill_tick_clock.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/prefs/pref_service.h"
@@ -57,6 +62,10 @@
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"
+#if !defined(OS_IOS)
+#include "components/autofill/core/browser/payments/test_credit_card_fido_authenticator.h"
+#endif
+
using base::ASCIIToUTF16;
using base::Bucket;
using base::TimeTicks;
@@ -268,6 +277,10 @@ class AutofillMetricsTest : public testing::Test {
bool include_masked_server_credit_card,
bool include_full_server_credit_card);
+ // If set to true, then user is capable of using FIDO authentication for card
+ // unmasking.
+ void SetFidoEligibility(bool is_verifiable);
+
// Mocks a RPC response from payments.
void OnDidGetRealPan(AutofillClient::PaymentsRpcResult result,
const std::string& real_pan);
@@ -343,6 +356,13 @@ void AutofillMetricsTest::SetUp() {
autofill_manager_.get(), autofill_driver_.get());
autofill_manager_->SetExternalDelegate(external_delegate_.get());
+#if !defined(OS_IOS)
+ autofill_manager_->credit_card_access_manager()
+ ->set_fido_authenticator_for_testing(
+ std::make_unique<TestCreditCardFIDOAuthenticator>(
+ autofill_driver_.get(), &autofill_client_));
+#endif
+
// Initialize the TestPersonalDataManager with some default data.
CreateTestAutofillProfiles();
}
@@ -392,6 +412,22 @@ void AutofillMetricsTest::RecreateProfile(bool is_server) {
personal_data_->Refresh();
}
+void AutofillMetricsTest::SetFidoEligibility(bool is_verifiable) {
+ CreditCardAccessManager* access_manager =
+ autofill_manager_->credit_card_access_manager();
+#if !defined(OS_IOS)
+ static_cast<TestCreditCardFIDOAuthenticator*>(
+ access_manager->GetOrCreateFIDOAuthenticator())
+ ->SetUserVerifiable(is_verifiable);
+#endif
+ static_cast<payments::TestPaymentsClient*>(
+ autofill_client_.GetPaymentsClient())
+ ->AllowFidoRegistration(true);
+ access_manager->is_authentication_in_progress_ = false;
+ access_manager->can_fetch_unmask_details_.Signal();
+ access_manager->is_user_verifiable_ = base::nullopt;
+}
+
void AutofillMetricsTest::OnDidGetRealPan(
AutofillClient::PaymentsRpcResult result,
const std::string& real_pan) {
@@ -400,6 +436,12 @@ void AutofillMetricsTest::OnDidGetRealPan(
->GetOrCreateCVCAuthenticator()
->full_card_request_.get();
DCHECK(full_card_request);
+
+ // Fake user response.
+ payments::FullCardRequest::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ full_card_request->OnUnmaskPromptAccepted(details);
+
payments::PaymentsClient::UnmaskResponseDetails response;
full_card_request->OnDidGetRealPan(result, response.with_real_pan(real_pan));
}
@@ -1809,7 +1851,7 @@ TEST_F(AutofillMetricsTest, TimingMetrics) {
// Simulate a OnFormsSeen() call that should trigger the recording.
std::vector<FormData> forms;
forms.push_back(form);
- autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
// Because these metrics are related to timing, it is not possible to know in
// advance which bucket the sample will fall into, so we just need to make
@@ -2655,7 +2697,7 @@ TEST_F(AutofillMetricsTest,
base::test::ScopedFeatureList features;
features.InitAndEnableFeature(
kAutofillEnforceMinRequiredFieldsForHeuristics);
- autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
autofill_manager_->Reset();
EXPECT_EQ(0ul, test_ukm_recorder_->entries_count());
@@ -2668,7 +2710,7 @@ TEST_F(AutofillMetricsTest,
// Expect the "form parsed without field type hints" metric and the
// "form loaded" form interaction event to be logged.
{
- autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
autofill_manager_->Reset();
VerifyDeveloperEngagementUkm(
@@ -2718,7 +2760,7 @@ TEST_F(AutofillMetricsTest,
// Expect the "form parsed without field type hints" metric and the
// "form loaded" form interaction event to be logged.
{
- autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
autofill_manager_->Reset();
VerifyDeveloperEngagementUkm(
@@ -2760,7 +2802,7 @@ TEST_F(AutofillMetricsTest, UkmDeveloperEngagement_LogUpiVpaTypeHint) {
// interaction event to be logged.
{
SCOPED_TRACE("VPA is the only hint");
- autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
VerifyDeveloperEngagementUkm(
test_ukm_recorder_, forms.back(), /*is_for_credit_card=*/false,
@@ -2777,7 +2819,7 @@ TEST_F(AutofillMetricsTest, UkmDeveloperEngagement_LogUpiVpaTypeHint) {
{
SCOPED_TRACE("VPA and other autocomplete hint present");
- autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
VerifyDeveloperEngagementUkm(
test_ukm_recorder_, forms.back(), /*is_for_credit_card=*/false,
@@ -3254,7 +3296,7 @@ TEST_F(AutofillMetricsTest, UpiVpaUkmTest) {
std::vector<FormData> forms(1, form);
{
- autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
VerifySubmitFormUkm(test_ukm_recorder_, forms.back(),
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
@@ -4252,6 +4294,124 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardFilledFormEvents) {
}
}
+// Test that we log preflight calls for credit card unmasking.
+TEST_F(AutofillMetricsTest, CreditCardUnmaskingPreflightCall) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillCreditCardAuthentication);
+ std::string preflight_call_metric =
+ "Autofill.BetterAuth.CardUnmaskPreflightCalled";
+ std::string preflight_latency_metric =
+ "Autofill.BetterAuth.CardUnmaskPreflightDuration";
+
+ // Set up our form data.
+ FormData form;
+ FormFieldData field;
+ std::vector<ServerFieldType> field_types;
+ test::CreateTestFormField("Credit card", "card", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_NUMBER);
+
+ // Simulate having seen this form on page load.
+ // |form_structure| will be owned by |autofill_manager_|.
+ autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+ {
+ // Create local cards and set user as eligible for FIDO authentication.
+ base::HistogramTester histogram_tester;
+ RecreateCreditCards(true /* include_local_credit_card */,
+ false /* include_masked_server_credit_card */,
+ false /* include_full_server_credit_card */);
+ SetFidoEligibility(true);
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ form.fields[0]);
+ // If no masked server cards are available, then no preflight call is made.
+ histogram_tester.ExpectTotalCount(preflight_call_metric, 0);
+ histogram_tester.ExpectTotalCount(preflight_latency_metric, 0);
+ }
+
+ {
+ // Create masked server cards and set user as ineligible for FIDO
+ // authentication.
+ base::HistogramTester histogram_tester;
+ RecreateCreditCards(false /* include_local_credit_card */,
+ true /* include_masked_server_credit_card */,
+ false /* include_full_server_credit_card */);
+ SetFidoEligibility(false);
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ form.fields[0]);
+ // If user is not verifiable, then no preflight call is made.
+ histogram_tester.ExpectTotalCount(preflight_call_metric, 0);
+ histogram_tester.ExpectTotalCount(preflight_latency_metric, 0);
+ }
+
+ {
+ // Create full server cards and set user as eligible for FIDO
+ // authentication.
+ base::HistogramTester histogram_tester;
+ RecreateCreditCards(false /* include_local_credit_card */,
+ false /* include_masked_server_credit_card */,
+ true /* include_full_server_credit_card */);
+ SetFidoEligibility(false);
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ form.fields[0]);
+ // If no masked server cards are available, then no preflight call is made.
+ histogram_tester.ExpectTotalCount(preflight_call_metric, 0);
+ histogram_tester.ExpectTotalCount(preflight_latency_metric, 0);
+ }
+
+ {
+ // Create masked server cards and set user as eligible for FIDO
+ // authentication.
+ base::HistogramTester histogram_tester;
+ RecreateCreditCards(false /* include_local_credit_card */,
+ true /* include_masked_server_credit_card */,
+ false /* include_full_server_credit_card */);
+ SetFidoEligibility(true);
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ form.fields[0]);
+ std::string guid(
+ "10000000-0000-0000-0000-000000000002"); // masked server card
+ autofill_manager_->FillOrPreviewForm(
+ AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
+ autofill_manager_->MakeFrontendID(guid, std::string()));
+ // Preflight call is made only if a masked server card is available and the
+ // user is eligible for FIDO authentication (except iOS).
+#if defined(OS_IOS)
+ histogram_tester.ExpectTotalCount(preflight_call_metric, 0);
+ histogram_tester.ExpectTotalCount(preflight_latency_metric, 0);
+#else
+ histogram_tester.ExpectTotalCount(preflight_call_metric, 1);
+ histogram_tester.ExpectTotalCount(preflight_latency_metric, 1);
+#endif
+ }
+
+ {
+ // Create all types of cards and set user as eligible for FIDO
+ // authentication.
+ base::HistogramTester histogram_tester;
+ RecreateCreditCards(true /* include_local_credit_card */,
+ true /* include_masked_server_credit_card */,
+ true /* include_full_server_credit_card */);
+ SetFidoEligibility(true);
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ form.fields[0]);
+ std::string guid(
+ "10000000-0000-0000-0000-000000000002"); // masked server card
+ autofill_manager_->FillOrPreviewForm(
+ AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
+ autofill_manager_->MakeFrontendID(guid, std::string()));
+ // Preflight call is made only if a masked server card is available and the
+ // user is eligible for FIDO authentication (except iOS).
+#if defined(OS_IOS)
+ histogram_tester.ExpectTotalCount(preflight_call_metric, 0);
+ histogram_tester.ExpectTotalCount(preflight_latency_metric, 0);
+#else
+ histogram_tester.ExpectTotalCount(preflight_call_metric, 1);
+ histogram_tester.ExpectTotalCount(preflight_latency_metric, 1);
+#endif
+ }
+}
+
// Test that we log submitted form events for credit cards.
TEST_F(AutofillMetricsTest, CreditCardGetRealPanDuration) {
// Creating masked card
@@ -4400,12 +4560,10 @@ TEST_P(AutofillMetricsIFrameTest,
SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_WRONG_SIZE_CARD,
- 1);
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_WRONG_SIZE_CARD, 1);
histogram_tester.ExpectBucketCount(
credit_card_form_events_frame_histogram_,
- FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_WRONG_SIZE_CARD,
- 1);
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_WRONG_SIZE_CARD, 1);
}
TEST_P(AutofillMetricsIFrameTest,
@@ -4447,12 +4605,10 @@ TEST_P(AutofillMetricsIFrameTest,
SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_FAIL_LUHN_CHECK_CARD,
- 1);
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_FAIL_LUHN_CHECK_CARD, 1);
histogram_tester.ExpectBucketCount(
credit_card_form_events_frame_histogram_,
- FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_FAIL_LUHN_CHECK_CARD,
- 1);
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_FAIL_LUHN_CHECK_CARD, 1);
}
TEST_P(AutofillMetricsIFrameTest,
@@ -4495,12 +4651,10 @@ TEST_P(AutofillMetricsIFrameTest,
SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_UNKNOWN_CARD,
- 1);
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_UNKNOWN_CARD, 1);
histogram_tester.ExpectBucketCount(
credit_card_form_events_frame_histogram_,
- FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_UNKNOWN_CARD,
- 1);
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_UNKNOWN_CARD, 1);
}
TEST_P(AutofillMetricsIFrameTest,
@@ -4543,12 +4697,10 @@ TEST_P(AutofillMetricsIFrameTest,
SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD,
- 1);
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD, 1);
histogram_tester.ExpectBucketCount(
credit_card_form_events_frame_histogram_,
- FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD,
- 1);
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD, 1);
}
TEST_P(AutofillMetricsIFrameTest,
@@ -4596,27 +4748,22 @@ TEST_P(AutofillMetricsIFrameTest,
SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD,
- 0);
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD, 0);
histogram_tester.ExpectBucketCount(
credit_card_form_events_frame_histogram_,
- FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD,
- 0);
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_UNKNOWN_CARD,
- 0);
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_UNKNOWN_CARD, 0);
histogram_tester.ExpectBucketCount(
credit_card_form_events_frame_histogram_,
- FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD,
- 0);
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD, 0);
histogram_tester.ExpectBucketCount(
credit_card_form_events_frame_histogram_,
- FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD,
- 0);
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD, 0);
}
TEST_F(AutofillMetricsTest, ShouldNotLogFormEventNoCardForAddressForm) {
@@ -5020,12 +5167,10 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
credit_card_form_events_frame_histogram_,
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard",
FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE,
1);
@@ -5052,12 +5197,10 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
credit_card_form_events_frame_histogram_,
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0);
}
// Reset the autofill manager state and purge UKM logs.
@@ -5098,12 +5241,10 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
credit_card_form_events_frame_histogram_,
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
@@ -5130,12 +5271,10 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
credit_card_form_events_frame_histogram_,
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0);
VerifyUkm(
test_ukm_recorder_, form, UkmSuggestionsShownType::kEntryName,
@@ -5364,12 +5503,10 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) {
FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
credit_card_form_events_frame_histogram_,
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard",
FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE,
1);
@@ -5396,12 +5533,10 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) {
FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
credit_card_form_events_frame_histogram_,
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0);
}
// Reset the autofill manager state.
@@ -5441,12 +5576,10 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) {
FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
credit_card_form_events_frame_histogram_,
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
@@ -5473,12 +5606,10 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) {
FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
credit_card_form_events_frame_histogram_,
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0);
}
}
@@ -6167,8 +6298,7 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
@@ -6183,8 +6313,7 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0);
// Check if FormEvent UKM is logged properly
auto entries =
@@ -6308,8 +6437,7 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
@@ -6324,8 +6452,7 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0);
// Check if FormEvent UKM is logged properly
auto entries =
test_ukm_recorder_->GetEntriesByName(UkmFormEventType::kEntryName);
@@ -6358,8 +6485,7 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
@@ -6374,8 +6500,7 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
- FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
- 0);
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0);
// Check if FormEvent UKM is logged properly
auto entries =
test_ukm_recorder_->GetEntriesByName(UkmFormEventType::kEntryName);
@@ -6566,7 +6691,8 @@ TEST_F(AutofillMetricsTest, AutofillIsDisabledAtPageLoad) {
TEST_F(AutofillMetricsTest, DaysSinceLastUse_CreditCard) {
base::HistogramTester histogram_tester;
CreditCard credit_card;
- credit_card.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(21));
+ credit_card.set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(21));
credit_card.RecordAndLogUse();
histogram_tester.ExpectBucketCount("Autofill.DaysSinceLastUse.CreditCard", 21,
1);
@@ -6576,7 +6702,7 @@ TEST_F(AutofillMetricsTest, DaysSinceLastUse_CreditCard) {
TEST_F(AutofillMetricsTest, DaysSinceLastUse_Profile) {
base::HistogramTester histogram_tester;
AutofillProfile profile;
- profile.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(13));
+ profile.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(13));
profile.RecordAndLogUse();
histogram_tester.ExpectBucketCount("Autofill.DaysSinceLastUse.Profile", 13,
1);
@@ -6605,7 +6731,7 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
// Expect no notifications when the form is first seen.
{
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
histogram_tester.ExpectTotalCount("Autofill.FormSubmittedState", 0);
VerifyDeveloperEngagementUkm(
@@ -6911,7 +7037,7 @@ TEST_F(
{
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
- autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
VerifyDeveloperEngagementUkm(
test_ukm_recorder_, form, /*is_for_credit_card=*/false,
{FormType::ADDRESS_FORM},
@@ -7463,7 +7589,12 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_AddressForm) {
}
// Verify that we correctly log metrics tracking the duration of form fill.
+// TODO(crbug.com/1009364) Test is flake on many builders.
TEST_F(AutofillMetricsTest, FormFillDuration) {
+ base::TimeTicks now = AutofillTickClock::NowTicks();
+ TestAutofillTickClock test_clock;
+ test_clock.SetNowTicks(now);
+
// Load a fillable form.
FormData form;
form.name = ASCIIToUTF16("TestForm");
@@ -7502,8 +7633,13 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
// Expect only form load metrics to be logged if the form is submitted without
// user interaction.
{
+ SCOPED_TRACE("Test 1");
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+ base::TimeTicks parse_time = autofill_manager_->form_structures()
+ .begin()
+ ->second->form_parsed_timestamp();
+ test_clock.SetNowTicks(parse_time + base::TimeDelta::FromMicroseconds(17));
autofill_manager_->OnFormSubmitted(form, false,
SubmissionSource::FORM_SUBMISSION);
@@ -7521,14 +7657,16 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
// Expect metric to be logged if the user manually edited a form field.
{
+ SCOPED_TRACE("Test 2");
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
base::TimeTicks parse_time = autofill_manager_->form_structures()
.begin()
->second->form_parsed_timestamp();
autofill_manager_->OnTextFieldDidChange(
form, form.fields.front(), gfx::RectF(),
parse_time + base::TimeDelta::FromMicroseconds(3));
+ test_clock.SetNowTicks(parse_time + base::TimeDelta::FromMicroseconds(17));
autofill_manager_->OnFormSubmitted(form, false,
SubmissionSource::FORM_SUBMISSION);
@@ -7548,13 +7686,15 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
// Expect metric to be logged if the user autofilled the form.
form.fields[0].is_autofilled = true;
{
+ SCOPED_TRACE("Test 3");
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
base::TimeTicks parse_time = autofill_manager_->form_structures()
.begin()
->second->form_parsed_timestamp();
autofill_manager_->OnDidFillAutofillFormData(
form, parse_time + base::TimeDelta::FromMicroseconds(5));
+ test_clock.SetNowTicks(parse_time + base::TimeDelta::FromMicroseconds(17));
autofill_manager_->OnFormSubmitted(form, false,
SubmissionSource::FORM_SUBMISSION);
@@ -7575,17 +7715,20 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
// and autofilled others. Messages can arrive out of order, so make sure they
// take precedence appropriately.
{
+ SCOPED_TRACE("Test 4");
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
base::TimeTicks parse_time = autofill_manager_->form_structures()
.begin()
->second->form_parsed_timestamp();
autofill_manager_->OnDidFillAutofillFormData(
form, parse_time + base::TimeDelta::FromMicroseconds(5));
+
autofill_manager_->OnTextFieldDidChange(
form, form.fields.front(), gfx::RectF(),
parse_time + base::TimeDelta::FromMicroseconds(3));
+ test_clock.SetNowTicks(parse_time + base::TimeDelta::FromMicroseconds(17));
autofill_manager_->OnFormSubmitted(form, false,
SubmissionSource::FORM_SUBMISSION);
@@ -7605,17 +7748,19 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
// Make sure that loading another form doesn't affect metrics from the first
// form.
{
+ SCOPED_TRACE("Test 5");
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
base::TimeTicks parse_time = autofill_manager_->form_structures()
.begin()
->second->form_parsed_timestamp();
- autofill_manager_->OnFormsSeen(second_forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(second_forms, AutofillTickClock::NowTicks());
autofill_manager_->OnDidFillAutofillFormData(
form, parse_time + base::TimeDelta::FromMicroseconds(5));
autofill_manager_->OnTextFieldDidChange(
form, form.fields.front(), gfx::RectF(),
parse_time + base::TimeDelta::FromMicroseconds(3));
+ test_clock.SetNowTicks(parse_time + base::TimeDelta::FromMicroseconds(17));
autofill_manager_->OnFormSubmitted(form, false,
SubmissionSource::FORM_SUBMISSION);
@@ -7635,14 +7780,16 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
// Make sure that submitting a form that was loaded later will report the
// later loading time.
{
+ SCOPED_TRACE("Test 6");
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
- autofill_manager_->OnFormsSeen(second_forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+ autofill_manager_->OnFormsSeen(second_forms, AutofillTickClock::NowTicks());
base::TimeTicks parse_time{};
for (const auto& kv : autofill_manager_->form_structures()) {
if (kv.second->form_parsed_timestamp() > parse_time)
parse_time = kv.second->form_parsed_timestamp();
}
+ test_clock.SetNowTicks(parse_time + base::TimeDelta::FromMicroseconds(17));
autofill_manager_->OnFormSubmitted(second_form, false,
SubmissionSource::FORM_SUBMISSION);
@@ -7941,7 +8088,7 @@ TEST_F(AutofillMetricsTest, ProfileActionOnFormSubmitted) {
// Expect to log NEW_PROFILE_CREATED for the metric since a new profile is
// submitted.
- autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
autofill_manager_->OnFormSubmitted(form, false,
SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
@@ -7954,7 +8101,7 @@ TEST_F(AutofillMetricsTest, ProfileActionOnFormSubmitted) {
// Expect to log EXISTING_PROFILE_USED for the metric since the same profile
// is submitted.
- autofill_manager_->OnFormsSeen(second_forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(second_forms, AutofillTickClock::NowTicks());
autofill_manager_->OnFormSubmitted(second_form, false,
SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
@@ -7967,7 +8114,7 @@ TEST_F(AutofillMetricsTest, ProfileActionOnFormSubmitted) {
// Expect to log NEW_PROFILE_CREATED for the metric since a new profile is
// submitted.
- autofill_manager_->OnFormsSeen(third_forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(third_forms, AutofillTickClock::NowTicks());
autofill_manager_->OnFormSubmitted(third_form, false,
SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
@@ -7980,7 +8127,7 @@ TEST_F(AutofillMetricsTest, ProfileActionOnFormSubmitted) {
// Expect to log EXISTING_PROFILE_UPDATED for the metric since the profile was
// updated.
- autofill_manager_->OnFormsSeen(fourth_forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(fourth_forms, AutofillTickClock::NowTicks());
autofill_manager_->OnFormSubmitted(fourth_form, false,
SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
@@ -8434,9 +8581,9 @@ TEST_F(AutofillMetricsTest, LogUserHappinessBySecurityLevel) {
base::HistogramTester histogram_tester;
AutofillMetrics::LogUserHappinessBySecurityLevel(
AutofillMetrics::FIELD_WAS_AUTOFILLED, PASSWORD_FORM,
- security_state::SecurityLevel::HTTP_SHOW_WARNING);
+ security_state::SecurityLevel::WARNING);
histogram_tester.ExpectBucketCount(
- "Autofill.UserHappiness.Password.HTTP_SHOW_WARNING",
+ "Autofill.UserHappiness.Password.WARNING",
AutofillMetrics::FIELD_WAS_AUTOFILLED, 1);
}
@@ -8496,16 +8643,14 @@ TEST_F(AutofillMetricsTest, LogUserHappinessBySecurityLevel_FromFormEvents) {
// Simulate suggestions shown twice with separate popups.
{
base::HistogramTester histogram_tester;
- autofill_client_.set_security_level(
- security_state::SecurityLevel::HTTP_SHOW_WARNING);
+ autofill_client_.set_security_level(security_state::SecurityLevel::WARNING);
autofill_manager_->DidShowSuggestions(true, form, field);
autofill_manager_->DidShowSuggestions(true, form, field);
- histogram_tester.ExpectBucketCount(
- "Autofill.UserHappiness.Address.HTTP_SHOW_WARNING",
- AutofillMetrics::SUGGESTIONS_SHOWN, 2);
- histogram_tester.ExpectBucketCount(
- "Autofill.UserHappiness.Address.HTTP_SHOW_WARNING",
- AutofillMetrics::SUGGESTIONS_SHOWN_ONCE, 1);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.Address.WARNING",
+ AutofillMetrics::SUGGESTIONS_SHOWN, 2);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.Address.WARNING",
+ AutofillMetrics::SUGGESTIONS_SHOWN_ONCE,
+ 1);
}
}
@@ -8751,9 +8896,9 @@ TEST_F(AutofillMetricsTest, LogSaveCardPromptMetricBySecurityLevel) {
base::HistogramTester histogram_tester;
AutofillMetrics::LogSaveCardPromptMetricBySecurityLevel(
AutofillMetrics::SAVE_CARD_PROMPT_END_ACCEPTED, /*is_uploading=*/true,
- security_state::SecurityLevel::HTTP_SHOW_WARNING);
+ security_state::SecurityLevel::WARNING);
histogram_tester.ExpectBucketCount(
- "Autofill.SaveCreditCardPrompt.Upload.HTTP_SHOW_WARNING",
+ "Autofill.SaveCreditCardPrompt.Upload.WARNING",
AutofillMetrics::SAVE_CARD_PROMPT_END_ACCEPTED, 1);
}
@@ -8914,7 +9059,7 @@ TEST_F(AutofillMetricsTest, FormEventMetrics_BySyncState) {
FormData form;
FormStructure form_structure(form);
std::vector<FormData> forms(1, form);
- autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
+ autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
autofill_manager_->Reset();
{
diff --git a/chromium/components/autofill/core/browser/autofill_test_utils.cc b/chromium/components/autofill/core/browser/autofill_test_utils.cc
index 9ff57ce1937..727f5b9aa82 100644
--- a/chromium/components/autofill/core/browser/autofill_test_utils.cc
+++ b/chromium/components/autofill/core/browser/autofill_test_utils.cc
@@ -8,6 +8,7 @@
#include "base/guid.h"
#include "base/rand_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
@@ -17,6 +18,7 @@
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/webdata/autofill_table.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/form_data.h"
@@ -118,6 +120,7 @@ void CreateTestAddressFormData(FormData* form,
mojom::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
form->url = GURL("http://myform.com/form.html");
form->action = GURL("http://myform.com/submit.html");
+ form->is_action_empty = true;
form->main_frame_origin =
url::Origin::Create(GURL("https://myform_root.com/form.html"));
types->clear();
@@ -254,8 +257,9 @@ void CreateTestCreditCardFormData(FormData* form,
form->fields.push_back(field);
}
-inline void check_and_set(
- FormGroup* profile, ServerFieldType type, const char* value) {
+inline void check_and_set(FormGroup* profile,
+ ServerFieldType type,
+ const char* value) {
if (value)
profile->SetRawInfo(type, base::UTF8ToUTF16(value));
}
@@ -278,34 +282,16 @@ AutofillProfile GetFullValidProfileForChina() {
AutofillProfile GetFullProfile() {
AutofillProfile profile(base::GenerateGUID(), kEmptyOrigin);
- SetProfileInfo(&profile,
- "John",
- "H.",
- "Doe",
- "johndoe@hades.com",
- "Underworld",
- "666 Erebus St.",
- "Apt 8",
- "Elysium", "CA",
- "91111",
- "US",
- "16502111111");
+ SetProfileInfo(&profile, "John", "H.", "Doe", "johndoe@hades.com",
+ "Underworld", "666 Erebus St.", "Apt 8", "Elysium", "CA",
+ "91111", "US", "16502111111");
return profile;
}
AutofillProfile GetFullProfile2() {
AutofillProfile profile(base::GenerateGUID(), kEmptyOrigin);
- SetProfileInfo(&profile,
- "Jane",
- "A.",
- "Smith",
- "jsmith@example.com",
- "ACME",
- "123 Main Street",
- "Unit 1",
- "Greensdale", "MI",
- "48838",
- "US",
+ SetProfileInfo(&profile, "Jane", "A.", "Smith", "jsmith@example.com", "ACME",
+ "123 Main Street", "Unit 1", "Greensdale", "MI", "48838", "US",
"13105557889");
return profile;
}
@@ -466,7 +452,7 @@ CreditCard GetRandomCreditCard(CreditCard::RecordType record_type) {
};
constexpr size_t kNumNetworks = sizeof(kNetworks) / sizeof(kNetworks[0]);
base::Time::Exploded now;
- base::Time::Now().LocalExplode(&now);
+ AutofillClock::Now().LocalExplode(&now);
CreditCard credit_card =
(record_type == CreditCard::LOCAL_CARD)
@@ -541,16 +527,23 @@ void SetProfileInfo(AutofillProfile* profile,
}
void SetProfileInfoWithGuid(AutofillProfile* profile,
- const char* guid, const char* first_name, const char* middle_name,
- const char* last_name, const char* email, const char* company,
- const char* address1, const char* address2, const char* city,
- const char* state, const char* zipcode, const char* country,
- const char* phone) {
+ const char* guid,
+ const char* first_name,
+ const char* middle_name,
+ const char* last_name,
+ const char* email,
+ const char* company,
+ const char* address1,
+ const char* address2,
+ const char* city,
+ const char* state,
+ const char* zipcode,
+ const char* country,
+ const char* phone) {
if (guid)
profile->set_guid(guid);
- SetProfileInfo(profile, first_name, middle_name, last_name, email,
- company, address1, address2, city, state, zipcode, country,
- phone);
+ SetProfileInfo(profile, first_name, middle_name, last_name, email, company,
+ address1, address2, city, state, zipcode, country, phone);
}
void SetCreditCardInfo(CreditCard* credit_card,
@@ -725,20 +718,25 @@ std::string ObfuscatedCardDigitsAsUTF8(const std::string& str) {
internal::GetObfuscatedStringForCardDigits(base::ASCIIToUTF16(str)));
}
+std::string NextMonth() {
+ base::Time::Exploded now;
+ base::Time::Now().LocalExplode(&now);
+ return base::NumberToString(now.month % 12 + 1);
+}
std::string LastYear() {
base::Time::Exploded now;
base::Time::Now().LocalExplode(&now);
- return std::to_string(now.year - 1);
+ return base::NumberToString(now.year - 1);
}
std::string NextYear() {
base::Time::Exploded now;
base::Time::Now().LocalExplode(&now);
- return std::to_string(now.year + 1);
+ return base::NumberToString(now.year + 1);
}
std::string TenYearsFromNow() {
base::Time::Exploded now;
base::Time::Now().LocalExplode(&now);
- return std::to_string(now.year + 10);
+ return base::NumberToString(now.year + 10);
}
} // namespace test
diff --git a/chromium/components/autofill/core/browser/autofill_test_utils.h b/chromium/components/autofill/core/browser/autofill_test_utils.h
index 678a211d5d4..db80caea7a8 100644
--- a/chromium/components/autofill/core/browser/autofill_test_utils.h
+++ b/chromium/components/autofill/core/browser/autofill_test_utils.h
@@ -176,11 +176,19 @@ void SetProfileInfo(AutofillProfile* profile,
const char* phone);
void SetProfileInfoWithGuid(AutofillProfile* profile,
- const char* guid, const char* first_name, const char* middle_name,
- const char* last_name, const char* email, const char* company,
- const char* address1, const char* address2, const char* city,
- const char* state, const char* zipcode, const char* country,
- const char* phone);
+ const char* guid,
+ const char* first_name,
+ const char* middle_name,
+ const char* last_name,
+ const char* email,
+ const char* company,
+ const char* address1,
+ const char* address2,
+ const char* city,
+ const char* state,
+ const char* zipcode,
+ const char* country,
+ const char* phone);
// A unit testing utility that is common to a number of the Autofill unit
// tests. |SetCreditCardInfo| provides a quick way to populate a credit card
@@ -258,6 +266,7 @@ void GenerateTestAutofillPopup(
std::string ObfuscatedCardDigitsAsUTF8(const std::string& str);
+std::string NextMonth();
std::string LastYear();
std::string NextYear();
std::string TenYearsFromNow();
diff --git a/chromium/components/autofill/core/browser/autofill_type.cc b/chromium/components/autofill/core/browser/autofill_type.cc
index d141a0dbcd3..4d0d4241c79 100644
--- a/chromium/components/autofill/core/browser/autofill_type.cc
+++ b/chromium/components/autofill/core/browser/autofill_type.cc
@@ -56,6 +56,10 @@ FieldTypeGroup GroupTypeOfServerFieldType(ServerFieldType field_type) {
case ADDRESS_HOME_STREET_ADDRESS:
case ADDRESS_HOME_SORTING_CODE:
case ADDRESS_HOME_DEPENDENT_LOCALITY:
+ case ADDRESS_HOME_STREET:
+ case ADDRESS_HOME_HOUSE_NUMBER:
+ case ADDRESS_HOME_FLOOR:
+ case ADDRESS_HOME_OTHER_SUBUNIT:
return ADDRESS_HOME;
case ADDRESS_BILLING_LINE1:
@@ -439,78 +443,6 @@ ServerFieldType AutofillType::GetStorableType() const {
return UNKNOWN_TYPE;
}
-// static
-ServerFieldType AutofillType::GetEquivalentBillingFieldType(
- ServerFieldType field_type) {
- switch (field_type) {
- case ADDRESS_HOME_LINE1:
- return ADDRESS_BILLING_LINE1;
-
- case ADDRESS_HOME_LINE2:
- return ADDRESS_BILLING_LINE2;
-
- case ADDRESS_HOME_APT_NUM:
- return ADDRESS_BILLING_APT_NUM;
-
- case ADDRESS_HOME_CITY:
- return ADDRESS_BILLING_CITY;
-
- case ADDRESS_HOME_STATE:
- return ADDRESS_BILLING_STATE;
-
- case ADDRESS_HOME_ZIP:
- return ADDRESS_BILLING_ZIP;
-
- case ADDRESS_HOME_COUNTRY:
- return ADDRESS_BILLING_COUNTRY;
-
- case ADDRESS_HOME_STREET_ADDRESS:
- return ADDRESS_BILLING_STREET_ADDRESS;
-
- case ADDRESS_HOME_SORTING_CODE:
- return ADDRESS_BILLING_SORTING_CODE;
-
- case ADDRESS_HOME_DEPENDENT_LOCALITY:
- return ADDRESS_BILLING_DEPENDENT_LOCALITY;
-
- case PHONE_HOME_WHOLE_NUMBER:
- return PHONE_BILLING_WHOLE_NUMBER;
-
- case PHONE_HOME_NUMBER:
- return PHONE_BILLING_NUMBER;
-
- case PHONE_HOME_CITY_CODE:
- return PHONE_BILLING_CITY_CODE;
-
- case PHONE_HOME_COUNTRY_CODE:
- return PHONE_BILLING_COUNTRY_CODE;
-
- case PHONE_HOME_CITY_AND_NUMBER:
- return PHONE_BILLING_CITY_AND_NUMBER;
-
- case NAME_FIRST:
- return NAME_BILLING_FIRST;
-
- case NAME_MIDDLE:
- return NAME_BILLING_MIDDLE;
-
- case NAME_LAST:
- return NAME_BILLING_LAST;
-
- case NAME_MIDDLE_INITIAL:
- return NAME_BILLING_MIDDLE_INITIAL;
-
- case NAME_FULL:
- return NAME_BILLING_FULL;
-
- case NAME_SUFFIX:
- return NAME_BILLING_SUFFIX;
-
- default:
- return field_type;
- }
-}
-
std::string AutofillType::ToString() const {
if (IsUnknown())
return "UNKNOWN_TYPE";
@@ -788,6 +720,14 @@ std::string AutofillType::ServerFieldTypeToString(ServerFieldType type) {
return "NOT_USERNAME";
case UPI_VPA:
return "UPI_VPA";
+ case ADDRESS_HOME_STREET:
+ return "ADDRESS_HOME_STREET";
+ case ADDRESS_HOME_HOUSE_NUMBER:
+ return "ADDRESS_HOME_HOUSE_NUMBER";
+ case ADDRESS_HOME_FLOOR:
+ return "ADDRESS_HOME_FLOOR";
+ case ADDRESS_HOME_OTHER_SUBUNIT:
+ return "ADDRESS_HOME_OTHER_SUBUNIT";
case AMBIGUOUS_TYPE:
return "AMBIGUOUS_TYPE";
case MAX_VALID_FIELD_TYPE:
diff --git a/chromium/components/autofill/core/browser/autofill_type.h b/chromium/components/autofill/core/browser/autofill_type.h
index 893567a9214..0e65d1fa05a 100644
--- a/chromium/components/autofill/core/browser/autofill_type.h
+++ b/chromium/components/autofill/core/browser/autofill_type.h
@@ -24,7 +24,7 @@ FieldTypeGroup GroupTypeOfHtmlFieldType(HtmlFieldType field_type,
// and for associating form fields with form values in the Web Database.
class AutofillType {
public:
- explicit AutofillType(ServerFieldType field_type);
+ explicit AutofillType(ServerFieldType field_type = NO_SERVER_DATA);
AutofillType(HtmlFieldType field_type, HtmlFieldMode mode);
AutofillType(const AutofillType& autofill_type) = default;
AutofillType& operator=(const AutofillType& autofill_type) = default;
@@ -48,11 +48,6 @@ class AutofillType {
// Serializes |this| type to a string.
std::string ToString() const;
- // Maps |field_type| to the corresponding billing field type if the field type
- // is an address, name, or phone number type.
- static ServerFieldType GetEquivalentBillingFieldType(
- ServerFieldType field_type);
-
// Translates the ServerFieldType values into the corresponding strings.
static std::string ServerFieldTypeToString(ServerFieldType type);
diff --git a/chromium/components/autofill/core/browser/data_driven_test.cc b/chromium/components/autofill/core/browser/data_driven_test.cc
index d30b91f2432..2a399402bf5 100644
--- a/chromium/components/autofill/core/browser/data_driven_test.cc
+++ b/chromium/components/autofill/core/browser/data_driven_test.cc
@@ -9,6 +9,7 @@
#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/re2/src/re2/re2.h"
namespace autofill {
namespace {
@@ -30,6 +31,24 @@ bool WriteFile(const base::FilePath& file, const std::string& content) {
return write_size == static_cast<int>(content.length());
}
+// Removes lines starting with (optional) whitespace and a #.
+void StripComments(std::string* content) {
+ RE2::GlobalReplace(
+ content,
+ // Enable multi-line mode, ^ and $ match begin/end line in addition to
+ // begin/end text.
+ "(?m)"
+ // Search for start of lines (^), ignore spaces (\\s*), and then look for
+ // '#'.
+ "^\\s*#"
+ // Consume all characters (.*) until end of line ($).
+ ".*$"
+ // Consume the line wrapping so that the entire line is gone.
+ "[\\r\\n]*",
+ // Replace entire line with empty string.
+ "");
+}
+
} // namespace
void DataDrivenTest::RunDataDrivenTest(
@@ -81,6 +100,8 @@ void DataDrivenTest::RunOneDataDrivenTest(
ASSERT_TRUE(WriteFile(output_file, output));
return;
}
+ // Remove comment lines (lead by '#' character).
+ StripComments(&output_file_contents);
if (is_expected_to_pass) {
EXPECT_EQ(output_file_contents, output);
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_data_model_unittest.cc b/chromium/components/autofill/core/browser/data_model/autofill_data_model_unittest.cc
index b8762af5f1c..b24e914c5d2 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_data_model_unittest.cc
+++ b/chromium/components/autofill/core/browser/data_model/autofill_data_model_unittest.cc
@@ -11,6 +11,7 @@
#include "base/time/time.h"
#include "components/autofill/core/browser/data_model/autofill_metadata.h"
#include "components/autofill/core/browser/test_autofill_clock.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -120,7 +121,7 @@ struct HasGreaterFrecencyThanTestCase {
Expectation expectation;
};
-base::Time now = base::Time::Now();
+base::Time now = AutofillClock::Now();
class HasGreaterFrecencyThanTest
: public testing::TestWithParam<HasGreaterFrecencyThanTestCase> {};
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_profile.cc b/chromium/components/autofill/core/browser/data_model/autofill_profile.cc
index 125a506ba17..60aeae68441 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_profile.cc
+++ b/chromium/components/autofill/core/browser/data_model/autofill_profile.cc
@@ -482,14 +482,6 @@ bool AutofillProfile::operator!=(const AutofillProfile& profile) const {
return !operator==(profile);
}
-bool AutofillProfile::IsSubsetOf(const AutofillProfile& profile,
- const std::string& app_locale) const {
- ServerFieldTypeSet types;
- GetSupportedTypes(&types);
- return IsSubsetOfForFieldSet(AutofillProfileComparator(app_locale), profile,
- app_locale, types);
-}
-
bool AutofillProfile::IsSubsetOfForFieldSet(
const AutofillProfileComparator& comparator,
const AutofillProfile& profile,
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_profile.h b/chromium/components/autofill/core/browser/data_model/autofill_profile.h
index 768dc5103d4..a984548e313 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_profile.h
+++ b/chromium/components/autofill/core/browser/data_model/autofill_profile.h
@@ -124,10 +124,6 @@ class AutofillProfile : public AutofillDataModel {
bool operator==(const AutofillProfile& profile) const;
virtual bool operator!=(const AutofillProfile& profile) const;
- // Returns true if this AutofillProfile's data is a subset of |profile|'s.
- bool IsSubsetOf(const AutofillProfile& profile,
- const std::string& app_locale) const;
-
// Like IsSubsetOf, but considers only the given |types|.
bool IsSubsetOfForFieldSet(const AutofillProfileComparator& comparator,
const AutofillProfile& profile,
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.cc b/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.cc
index 9b41b0b77d0..ac578d38a0f 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.cc
+++ b/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.cc
@@ -16,8 +16,10 @@
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/address_rewriter.h"
#include "components/autofill/core/browser/autofill_data_util.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/geo/autofill_country.h"
#include "components/autofill/core/browser/geo/state_names.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "third_party/libphonenumber/phonenumber_api.h"
using base::UTF16ToUTF8;
@@ -829,6 +831,70 @@ bool AutofillProfileComparator::MergeAddresses(const AutofillProfile& p1,
}
// static
+std::string AutofillProfileComparator::MergeProfile(
+ const AutofillProfile& new_profile,
+ std::vector<std::unique_ptr<AutofillProfile>>* existing_profiles,
+ const std::string& app_locale,
+ std::vector<AutofillProfile>* merged_profiles) {
+ merged_profiles->clear();
+
+ // Sort the existing profiles in decreasing order of frecency, so the "best"
+ // profiles are checked first. Put the verified profiles last so the non
+ // verified profiles get deduped among themselves before reaching the verified
+ // profiles.
+ // TODO(crbug.com/620521): Remove the check for verified from the sort.
+ base::Time comparison_time = AutofillClock::Now();
+ std::sort(existing_profiles->begin(), existing_profiles->end(),
+ [comparison_time](const std::unique_ptr<AutofillProfile>& a,
+ const std::unique_ptr<AutofillProfile>& b) {
+ if (a->IsVerified() != b->IsVerified())
+ return !a->IsVerified();
+ return a->HasGreaterFrecencyThan(b.get(), comparison_time);
+ });
+
+ // Set to true if |existing_profiles| already contains an equivalent profile.
+ bool matching_profile_found = false;
+ std::string guid = new_profile.guid();
+
+ // If we have already saved this address, merge in any missing values.
+ // Only merge with the first match. Merging the new profile into the existing
+ // one preserves the validity of credit card's billing address reference.
+ AutofillProfileComparator comparator(app_locale);
+ for (const auto& existing_profile : *existing_profiles) {
+ if (!matching_profile_found &&
+ comparator.AreMergeable(new_profile, *existing_profile) &&
+ existing_profile->SaveAdditionalInfo(new_profile, app_locale)) {
+ // Unverified profiles should always be updated with the newer data,
+ // whereas verified profiles should only ever be overwritten by verified
+ // data. If an automatically aggregated profile would overwrite a
+ // verified profile, just drop it.
+ matching_profile_found = true;
+ guid = existing_profile->guid();
+
+ // We set the modification date so that immediate requests for profiles
+ // will properly reflect the fact that this profile has been modified
+ // recently. After writing to the database and refreshing the local copies
+ // the profile will have a very slightly newer time reflecting what's
+ // actually stored in the database.
+ existing_profile->set_modification_date(AutofillClock::Now());
+ }
+ merged_profiles->push_back(*existing_profile);
+ }
+
+ // If the new profile was not merged with an existing one, add it to the list.
+ if (!matching_profile_found) {
+ merged_profiles->push_back(new_profile);
+ // Similar to updating merged profiles above, set the modification date on
+ // new profiles.
+ merged_profiles->back().set_modification_date(AutofillClock::Now());
+ AutofillMetrics::LogProfileActionOnFormSubmitted(
+ AutofillMetrics::NEW_PROFILE_CREATED);
+ }
+
+ return guid;
+}
+
+// static
std::set<base::StringPiece16> AutofillProfileComparator::UniqueTokens(
base::StringPiece16 s) {
std::vector<base::StringPiece16> tokens = base::SplitStringPiece(
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.h b/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.h
index 127c828743b..525bf0703a2 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.h
+++ b/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.h
@@ -138,6 +138,16 @@ class AutofillProfileComparator {
// App locale used when this comparator instance was created.
const std::string app_locale() const { return app_locale_; }
+ // Merges |new_profile| into one of the |existing_profiles| if possible;
+ // otherwise appends |new_profile| to the end of that list. Fills
+ // |merged_profiles| with the result. Returns the |guid| of the new or updated
+ // profile.
+ static std::string MergeProfile(
+ const AutofillProfile& new_profile,
+ std::vector<std::unique_ptr<AutofillProfile>>* existing_profiles,
+ const std::string& app_locale,
+ std::vector<AutofillProfile>* merged_profiles);
+
protected:
// The result type returned by CompareTokens.
enum CompareTokensResult {
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator_unittest.cc b/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator_unittest.cc
index af44b882387..445c4cafbc3 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator_unittest.cc
+++ b/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator_unittest.cc
@@ -12,6 +12,7 @@
#include "components/autofill/core/browser/data_model/contact_info.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/geo/country_names.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_features.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -41,6 +42,7 @@ using autofill::PHONE_HOME_WHOLE_NUMBER;
// Classes, Functions, and other Symbols
using autofill::Address;
+using autofill::AutofillClock;
using autofill::AutofillProfile;
using autofill::AutofillType;
using autofill::CompanyInfo;
@@ -785,15 +787,15 @@ TEST_F(AutofillProfileComparatorTest, MergeCJKNames) {
// the most recent profile if there is a conflict. The ordering is
// p1 > p2 > p3 > p4 > p5, with p1 being the most recent.
AutofillProfile p1 = CreateProfileWithName(name1);
- p1.set_use_date(base::Time::Now());
+ p1.set_use_date(AutofillClock::Now());
AutofillProfile p2 = CreateProfileWithName(name2);
- p2.set_use_date(base::Time::Now() - base::TimeDelta::FromHours(1));
+ p2.set_use_date(AutofillClock::Now() - base::TimeDelta::FromHours(1));
AutofillProfile p3 = CreateProfileWithName(name3);
- p3.set_use_date(base::Time::Now() - base::TimeDelta::FromHours(2));
+ p3.set_use_date(AutofillClock::Now() - base::TimeDelta::FromHours(2));
AutofillProfile p4 = CreateProfileWithName(name4);
- p4.set_use_date(base::Time::Now() - base::TimeDelta::FromHours(3));
+ p4.set_use_date(AutofillClock::Now() - base::TimeDelta::FromHours(3));
AutofillProfile p5 = CreateProfileWithName(name5);
- p5.set_use_date(base::Time::Now() - base::TimeDelta::FromHours(4));
+ p5.set_use_date(AutofillClock::Now() - base::TimeDelta::FromHours(4));
AutofillProfile p6 = CreateProfileWithName(name6);
AutofillProfile p7 = CreateProfileWithName(name7);
@@ -831,7 +833,7 @@ TEST_F(AutofillProfileComparatorTest, MergeEmailAddresses) {
EmailInfo email_a;
email_a.SetRawInfo(EMAIL_ADDRESS, UTF8ToUTF16(kEmailA));
AutofillProfile profile_a = CreateProfileWithEmail(kEmailA);
- profile_a.set_use_date(base::Time::Now());
+ profile_a.set_use_date(AutofillClock::Now());
EmailInfo email_b;
email_b.SetRawInfo(EMAIL_ADDRESS, UTF8ToUTF16(kEmailB));
@@ -859,7 +861,7 @@ TEST_F(AutofillProfileComparatorTest, MergeCompanyNames) {
CompanyInfo company_a;
company_a.SetRawInfo(COMPANY_NAME, UTF8ToUTF16(kCompanyA));
AutofillProfile profile_a = CreateProfileWithCompanyName(kCompanyA);
- profile_a.set_use_date(base::Time::Now());
+ profile_a.set_use_date(AutofillClock::Now());
// Company Name B is post_normalization identical to Company Name A. The use
// date will be used to choose between them.
@@ -879,7 +881,7 @@ TEST_F(AutofillProfileComparatorTest, MergeCompanyNames) {
CompanyInfo company_d;
company_d.SetRawInfo(COMPANY_NAME, UTF8ToUTF16(kCompanyD));
AutofillProfile profile_d = CreateProfileWithCompanyName(kCompanyD);
- profile_a.set_use_date(base::Time::Now());
+ profile_a.set_use_date(AutofillClock::Now());
MergeCompanyNamesAndExpect(profile_a, profile_a, company_a);
MergeCompanyNamesAndExpect(profile_a, profile_b, company_b);
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_profile_unittest.cc b/chromium/components/autofill/core/browser/data_model/autofill_profile_unittest.cc
index de503b8f649..58f336978d6 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_profile_unittest.cc
+++ b/chromium/components/autofill/core/browser/data_model/autofill_profile_unittest.cc
@@ -22,6 +22,7 @@
#include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/test_autofill_clock.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/form_field_data.h"
@@ -673,31 +674,6 @@ TEST(AutofillProfileTest, CreateInferredLabelsFlattensMultiLineValues) {
EXPECT_EQ(ASCIIToUTF16("88 Nowhere Ave., Apt. 42"), labels[0]);
}
-TEST(AutofillProfileTest, IsSubsetOfForProfiles) {
- AutofillProfile profile1 =
- AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin);
- test::SetProfileInfo(&profile1, "Genevieve", "", "Fox",
- "genevieve@hotmail.com", "", "274 Main St", "",
- "Northhampton", "MA", "01060", "US", "");
-
- AutofillProfile profile2 =
- AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin);
- test::SetProfileInfo(&profile2, "Genevieve", "", "Fox",
- "genevieve@hotmail.com", "", "", "", "", "", "", "US",
- "");
-
- AutofillProfile profile3 =
- AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin);
- test::SetProfileInfo(&profile3, "Genevieve", "", "Fuller",
- "genevieve@hotmail.com", "", "", "", "", "", "", "US",
- "");
-
- EXPECT_FALSE(profile1.IsSubsetOf(profile2, "en-US"));
- EXPECT_TRUE(profile2.IsSubsetOf(profile1, "en-US"));
- EXPECT_FALSE(profile2.IsSubsetOf(profile3, "en-US"));
- EXPECT_FALSE(profile3.IsSubsetOf(profile2, "en-US"));
-}
-
TEST(AutofillProfileTest, IsSubsetOfForFieldSet_DifferentMiddleNames) {
AutofillProfile profile1 =
AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin);
@@ -2210,7 +2186,7 @@ TEST_P(HasGreaterFrescocencyTest, HasGreaterFrescocency) {
test_case.server_validity_state_b,
AutofillDataModel::SERVER);
- const base::Time now = base::Time::Now();
+ const base::Time now = AutofillClock::Now();
if (test_case.expectation == EQUAL) {
EXPECT_EQ(profile_a.HasGreaterFrecencyThan(&profile_b, now),
@@ -2249,7 +2225,7 @@ TEST_P(HasGreaterFrescocencyTest, PriorityCheck) {
profile_invalid.set_use_count(100);
profile_valid.set_use_count(10);
- const base::Time now = base::Time::Now();
+ const base::Time now = AutofillClock::Now();
const base::Time past = now - base::TimeDelta::FromDays(1);
profile_invalid.set_use_date(now);
diff --git a/chromium/components/autofill/core/browser/data_model/contact_info.cc b/chromium/components/autofill/core/browser/data_model/contact_info.cc
index 895e1ed0a52..668230e72f0 100644
--- a/chromium/components/autofill/core/browser/data_model/contact_info.cc
+++ b/chromium/components/autofill/core/browser/data_model/contact_info.cc
@@ -47,31 +47,6 @@ bool NameInfo::operator==(const NameInfo& other) const {
family_ == other.family_ && full_ == other.full_;
}
-bool NameInfo::ParsedNamesAreEqual(const NameInfo& info) const {
- return given_ == info.given_ && middle_ == info.middle_ &&
- family_ == info.family_;
-}
-
-void NameInfo::OverwriteName(const NameInfo& new_name) {
- if (!new_name.given_.empty())
- given_ = new_name.given_;
-
- // For the middle name, don't overwrite a full middle name with an initial.
- if (!new_name.middle_.empty() &&
- (middle_.size() <= 1 || new_name.middle_.size() > 1))
- middle_ = new_name.middle_;
-
- if (!new_name.family_.empty())
- family_ = new_name.family_;
-
- if (!new_name.full_.empty())
- full_ = new_name.full_;
-}
-
-bool NameInfo::NamePartsAreEmpty() const {
- return given_.empty() && middle_.empty() && family_.empty();
-}
-
base::string16 NameInfo::GetRawInfo(ServerFieldType type) const {
DCHECK_EQ(NAME, AutofillType(type).group());
switch (type) {
@@ -250,15 +225,26 @@ void CompanyInfo::SetRawInfo(ServerFieldType type,
}
bool CompanyInfo::IsValidOrVerified(const base::string16& value) const {
- if (!base::FeatureList::IsEnabled(
- autofill::features::kAutofillRejectCompanyBirthyear))
- return true;
-
- if (profile_ && profile_->IsVerified())
+ if (profile_ && profile_->IsVerified()) {
return true;
-
- // Companies that are of the format of a four digit birth year are not valid.
- return !MatchesPattern(value, base::UTF8ToUTF16("^(19|20)\\d{2}$"));
+ }
+ // |value| is a birthyear:
+ if (base::FeatureList::IsEnabled(
+ autofill::features::kAutofillRejectCompanyBirthyear) &&
+ MatchesPattern(value, base::UTF8ToUTF16("^(19|20)\\d{2}$"))) {
+ return false;
+ }
+ // |value| is a social title:
+ if (base::FeatureList::IsEnabled(
+ autofill::features::kAutofillRejectCompanySocialTitle) &&
+ MatchesPattern(value, base::UTF8ToUTF16(
+ "^(Ms\\.?|Mrs\\.?|Mr\\.?|Miss|Mistress|Mister|"
+ "Frau|Herr|"
+ "Mlle|Mme|M\\.|"
+ "Dr\\.?|Prof\\.?)$"))) {
+ return false;
+ }
+ return true;
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/data_model/contact_info.h b/chromium/components/autofill/core/browser/data_model/contact_info.h
index b838253f118..cedfe7bedcb 100644
--- a/chromium/components/autofill/core/browser/data_model/contact_info.h
+++ b/chromium/components/autofill/core/browser/data_model/contact_info.h
@@ -26,18 +26,6 @@ class NameInfo : public FormGroup {
bool operator==(const NameInfo& other) const;
bool operator!=(const NameInfo& other) const { return !operator==(other); }
- // Compares |NameInfo| objects for |given_|, |middle_| and |family_| names.
- // The comparison is case sensitive.
- bool ParsedNamesAreEqual(const NameInfo& info) const;
-
- // For every non-empty NameInfo part in |new_name|, the corresponding NameInfo
- // part in | this | is overwritten.Special logic so that a middle initial may
- // not overwrite a full middle name.
- void OverwriteName(const NameInfo& new_name);
-
- // Returns true if all the name parts (first, middle and last) are empty.
- bool NamePartsAreEmpty() const;
-
// FormGroup:
base::string16 GetRawInfo(ServerFieldType type) const override;
void SetRawInfo(ServerFieldType type, const base::string16& value) override;
diff --git a/chromium/components/autofill/core/browser/data_model/contact_info_unittest.cc b/chromium/components/autofill/core/browser/data_model/contact_info_unittest.cc
index a5e64b41128..e0bcfceb9d8 100644
--- a/chromium/components/autofill/core/browser/data_model/contact_info_unittest.cc
+++ b/chromium/components/autofill/core/browser/data_model/contact_info_unittest.cc
@@ -183,223 +183,119 @@ TEST(NameInfoTest, GetFullName) {
name.GetInfo(AutofillType(NAME_FULL), "en-US"));
}
-struct ParsedNamesAreEqualTestCase {
- std::string starting_names[3];
- std::string additional_names[3];
- bool expected_result;
-};
+TEST(CompanyTest, CompanyNameYear) {
+ base::test::ScopedFeatureList scoped_features;
+ scoped_features.InitWithFeatures(
+ /*enabled_features=*/{features::kAutofillRejectCompanyBirthyear},
+ /*disabled_features=*/{});
-class ParsedNamesAreEqualTest
- : public testing::TestWithParam<ParsedNamesAreEqualTestCase> {};
+ AutofillProfile profile;
+ CompanyInfo company(&profile);
+ ASSERT_FALSE(profile.IsVerified());
-TEST_P(ParsedNamesAreEqualTest, ParsedNamesAreEqual) {
- auto test_case = GetParam();
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Google"));
+ EXPECT_EQ(UTF8ToUTF16("Google"), company.GetRawInfo(COMPANY_NAME));
- // Construct the starting_profile.
- NameInfo starting_profile;
- starting_profile.SetRawInfo(NAME_FIRST,
- UTF8ToUTF16(test_case.starting_names[0]));
- starting_profile.SetRawInfo(NAME_MIDDLE,
- UTF8ToUTF16(test_case.starting_names[1]));
- starting_profile.SetRawInfo(NAME_LAST,
- UTF8ToUTF16(test_case.starting_names[2]));
-
- // Construct the additional_profile.
- NameInfo additional_profile;
- additional_profile.SetRawInfo(NAME_FIRST,
- UTF8ToUTF16(test_case.additional_names[0]));
- additional_profile.SetRawInfo(NAME_MIDDLE,
- UTF8ToUTF16(test_case.additional_names[1]));
- additional_profile.SetRawInfo(NAME_LAST,
- UTF8ToUTF16(test_case.additional_names[2]));
-
- // Verify the test expectations.
- EXPECT_EQ(test_case.expected_result,
- starting_profile.ParsedNamesAreEqual(additional_profile));
-}
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1987"));
+ EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
-INSTANTIATE_TEST_SUITE_P(
- ContactInfoTest,
- ParsedNamesAreEqualTest,
- testing::Values(
- // Identical name comparison.
- ParsedNamesAreEqualTestCase{{"Marion", "Mitchell", "Morrison"},
- {"Marion", "Mitchell", "Morrison"},
- true},
-
- // Case-sensitive comparisons.
- ParsedNamesAreEqualTestCase{{"Marion", "Mitchell", "Morrison"},
- {"Marion", "Mitchell", "MORRISON"},
- false},
- ParsedNamesAreEqualTestCase{{"Marion", "Mitchell", "Morrison"},
- {"MARION", "Mitchell", "MORRISON"},
- false},
- ParsedNamesAreEqualTestCase{{"Marion", "Mitchell", "Morrison"},
- {"MARION", "MITCHELL", "MORRISON"},
- false},
- ParsedNamesAreEqualTestCase{{"Marion", "", "Mitchell Morrison"},
- {"MARION", "", "MITCHELL MORRISON"},
- false},
- ParsedNamesAreEqualTestCase{{"Marion Mitchell", "", "Morrison"},
- {"MARION MITCHELL", "", "MORRISON"},
- false},
-
- // Identical full names but different canonical forms.
- ParsedNamesAreEqualTestCase{{"Marion", "Mitchell", "Morrison"},
- {"Marion", "", "Mitchell Morrison"},
- false},
- ParsedNamesAreEqualTestCase{{"Marion", "Mitchell", "Morrison"},
- {"Marion Mitchell", "", "MORRISON"},
- false},
-
- // Different names.
- ParsedNamesAreEqualTestCase{{"Marion", "Mitchell", "Morrison"},
- {"Marion", "M.", "Morrison"},
- false},
- ParsedNamesAreEqualTestCase{{"Marion", "Mitchell", "Morrison"},
- {"MARION", "M.", "MORRISON"},
- false},
- ParsedNamesAreEqualTestCase{{"Marion", "Mitchell", "Morrison"},
- {"David", "Mitchell", "Morrison"},
- false},
-
- // Non-ASCII characters.
- ParsedNamesAreEqualTestCase{{"M\xc3\xa1rion Mitchell", "", "Morrison"},
- {"M\xc3\xa1rion Mitchell", "", "Morrison"},
- true}));
-
-struct OverwriteNameTestCase {
- std::string existing_name[4];
- std::string new_name[4];
- std::string expected_name[4];
-};
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("It was 1987."));
+ EXPECT_EQ(UTF8ToUTF16("It was 1987."), company.GetRawInfo(COMPANY_NAME));
-class OverwriteNameTest : public testing::TestWithParam<OverwriteNameTestCase> {
-};
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1987 was the year."));
+ EXPECT_EQ(UTF8ToUTF16("1987 was the year."),
+ company.GetRawInfo(COMPANY_NAME));
-TEST_P(OverwriteNameTest, OverwriteName) {
- auto test_case = GetParam();
- // Construct the starting_profile.
- NameInfo existing_name;
- existing_name.SetRawInfo(NAME_FIRST, UTF8ToUTF16(test_case.existing_name[0]));
- existing_name.SetRawInfo(NAME_MIDDLE,
- UTF8ToUTF16(test_case.existing_name[1]));
- existing_name.SetRawInfo(NAME_LAST, UTF8ToUTF16(test_case.existing_name[2]));
- existing_name.SetRawInfo(NAME_FULL, UTF8ToUTF16(test_case.existing_name[3]));
-
- // Construct the additional_profile.
- NameInfo new_name;
- new_name.SetRawInfo(NAME_FIRST, UTF8ToUTF16(test_case.new_name[0]));
- new_name.SetRawInfo(NAME_MIDDLE, UTF8ToUTF16(test_case.new_name[1]));
- new_name.SetRawInfo(NAME_LAST, UTF8ToUTF16(test_case.new_name[2]));
- new_name.SetRawInfo(NAME_FULL, UTF8ToUTF16(test_case.new_name[3]));
-
- existing_name.OverwriteName(new_name);
-
- // Verify the test expectations.
- EXPECT_EQ(UTF8ToUTF16(test_case.expected_name[0]),
- existing_name.GetRawInfo(NAME_FIRST));
- EXPECT_EQ(UTF8ToUTF16(test_case.expected_name[1]),
- existing_name.GetRawInfo(NAME_MIDDLE));
- EXPECT_EQ(UTF8ToUTF16(test_case.expected_name[2]),
- existing_name.GetRawInfo(NAME_LAST));
- EXPECT_EQ(UTF8ToUTF16(test_case.expected_name[3]),
- existing_name.GetRawInfo(NAME_FULL));
-}
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Yes, 1987 was the year."));
+ EXPECT_EQ(UTF8ToUTF16("Yes, 1987 was the year."),
+ company.GetRawInfo(COMPANY_NAME));
-INSTANTIATE_TEST_SUITE_P(
- ContactInfoTest,
- OverwriteNameTest,
- testing::Values(
- // Missing information in the original name gets filled with the new
- // name's information.
- OverwriteNameTestCase{
- {"", "", "", ""},
- {"Marion", "Mitchell", "Morrison", "Marion Mitchell Morrison"},
- {"Marion", "Mitchell", "Morrison", "Marion Mitchell Morrison"},
- },
- // The new name's values overwrite the exsiting name values if they are
- // different
- OverwriteNameTestCase{
- {"Marion", "Mitchell", "Morrison", "Marion Mitchell Morrison"},
- {"Mario", "Mitchell", "Thompson", "Mario Mitchell Morrison"},
- {"Mario", "Mitchell", "Thompson", "Mario Mitchell Morrison"},
- },
- // An existing name values do not get replaced with empty values.
- OverwriteNameTestCase{
- {"Marion", "Mitchell", "Morrison", "Marion Mitchell Morrison"},
- {"", "", "", ""},
- {"Marion", "Mitchell", "Morrison", "Marion Mitchell Morrison"},
- },
- // An existing full middle not does not get replaced by a middle name
- // initial.
- OverwriteNameTestCase{
- {"Marion", "Mitchell", "Morrison", "Marion Mitchell Morrison"},
- {"Marion", "M", "Morrison", "Marion Mitchell Morrison"},
- {"Marion", "Mitchell", "Morrison", "Marion Mitchell Morrison"},
- },
- // An existing middle name initial is overwritten by the new profile's
- // middle name value.
- OverwriteNameTestCase{
- {"Marion", "M", "Morrison", "Marion Mitchell Morrison"},
- {"Marion", "Mitchell", "Morrison", "Marion Mitchell Morrison"},
- {"Marion", "Mitchell", "Morrison", "Marion Mitchell Morrison"},
- },
- // A NameInfo with only the full name set overwritten with a NameInfo
- // with only the name parts set result in a NameInfo with all the name
- // parts and name full set.
- OverwriteNameTestCase{
- {"", "", "", "Marion Mitchell Morrison"},
- {"Marion", "Mitchell", "Morrison", ""},
- {"Marion", "Mitchell", "Morrison", "Marion Mitchell Morrison"},
- },
- // A NameInfo with only the name parts set overwritten with a NameInfo
- // with only the full name set result in a NameInfo with all the name
- // parts and name full set.
- OverwriteNameTestCase{
- {"Marion", "Mitchell", "Morrison", ""},
- {"", "", "", "Marion Mitchell Morrison"},
- {"Marion", "Mitchell", "Morrison", "Marion Mitchell Morrison"},
- }));
-
-struct NamePartsAreEmptyTestCase {
- std::string first;
- std::string middle;
- std::string last;
- std::string full;
- bool expected_result;
-};
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("2019"));
+ EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
-class NamePartsAreEmptyTest
- : public testing::TestWithParam<NamePartsAreEmptyTestCase> {};
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1818"));
+ EXPECT_EQ(UTF8ToUTF16("1818"), company.GetRawInfo(COMPANY_NAME));
-TEST_P(NamePartsAreEmptyTest, NamePartsAreEmpty) {
- auto test_case = GetParam();
- // Construct the NameInfo.
- NameInfo name;
- name.SetRawInfo(NAME_FIRST, UTF8ToUTF16(test_case.first));
- name.SetRawInfo(NAME_MIDDLE, UTF8ToUTF16(test_case.middle));
- name.SetRawInfo(NAME_LAST, UTF8ToUTF16(test_case.last));
- name.SetRawInfo(NAME_FULL, UTF8ToUTF16(test_case.full));
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("2345"));
+ EXPECT_EQ(UTF8ToUTF16("2345"), company.GetRawInfo(COMPANY_NAME));
- // Verify the test expectations.
- EXPECT_EQ(test_case.expected_result, name.NamePartsAreEmpty());
-}
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr"));
+ EXPECT_EQ(UTF8ToUTF16("Mr"), company.GetRawInfo(COMPANY_NAME));
-INSTANTIATE_TEST_SUITE_P(
- ContactInfoTest,
- NamePartsAreEmptyTest,
- testing::Values(NamePartsAreEmptyTestCase{"", "", "", "", true},
- NamePartsAreEmptyTestCase{"", "", "",
- "Marion Mitchell Morrison", true},
- NamePartsAreEmptyTestCase{"Marion", "", "", "", false},
- NamePartsAreEmptyTestCase{"", "Mitchell", "", "", false},
- NamePartsAreEmptyTestCase{"", "", "Morrison", "", false}));
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr."));
+ EXPECT_EQ(UTF8ToUTF16("Mr."), company.GetRawInfo(COMPANY_NAME));
-TEST(CompanyTest, CompanyNameYear) {
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mrs"));
+ EXPECT_EQ(UTF8ToUTF16("Mrs"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mrs."));
+ EXPECT_EQ(UTF8ToUTF16("Mrs."), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr. & Mrs."));
+ EXPECT_EQ(UTF8ToUTF16("Mr. & Mrs."), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr. & Mrs. Smith"));
+ EXPECT_EQ(UTF8ToUTF16("Mr. & Mrs. Smith"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Frau"));
+ EXPECT_EQ(UTF8ToUTF16("Frau"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Frau Doktor"));
+ EXPECT_EQ(UTF8ToUTF16("Frau Doktor"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Herr"));
+ EXPECT_EQ(UTF8ToUTF16("Herr"), company.GetRawInfo(COMPANY_NAME));
+
+ profile.set_origin("Not empty");
+ ASSERT_TRUE(profile.IsVerified());
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Google"));
+ EXPECT_EQ(UTF8ToUTF16("Google"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1987"));
+ EXPECT_EQ(UTF8ToUTF16("1987"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("2019"));
+ EXPECT_EQ(UTF8ToUTF16("2019"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1818"));
+ EXPECT_EQ(UTF8ToUTF16("1818"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("2345"));
+ EXPECT_EQ(UTF8ToUTF16("2345"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr"));
+ EXPECT_EQ(UTF8ToUTF16("Mr"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr."));
+ EXPECT_EQ(UTF8ToUTF16("Mr."), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mrs"));
+ EXPECT_EQ(UTF8ToUTF16("Mrs"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mrs."));
+ EXPECT_EQ(UTF8ToUTF16("Mrs."), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr. & Mrs."));
+ EXPECT_EQ(UTF8ToUTF16("Mr. & Mrs."), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr. & Mrs. Smith"));
+ EXPECT_EQ(UTF8ToUTF16("Mr. & Mrs. Smith"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Frau"));
+ EXPECT_EQ(UTF8ToUTF16("Frau"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Frau Doktor"));
+ EXPECT_EQ(UTF8ToUTF16("Frau Doktor"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Herr"));
+ EXPECT_EQ(UTF8ToUTF16("Herr"), company.GetRawInfo(COMPANY_NAME));
+}
+
+TEST(CompanyTest, CompanyNameSocialTitle) {
base::test::ScopedFeatureList scoped_features;
scoped_features.InitWithFeatures(
- /*enabled_features=*/{features::kAutofillRejectCompanyBirthyear},
+ /*enabled_features=*/{features::kAutofillRejectCompanySocialTitle},
/*disabled_features=*/{});
AutofillProfile profile;
@@ -410,7 +306,7 @@ TEST(CompanyTest, CompanyNameYear) {
EXPECT_EQ(UTF8ToUTF16("Google"), company.GetRawInfo(COMPANY_NAME));
company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1987"));
- EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
+ EXPECT_EQ(UTF8ToUTF16("1987"), company.GetRawInfo(COMPANY_NAME));
company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("It was 1987."));
EXPECT_EQ(UTF8ToUTF16("It was 1987."), company.GetRawInfo(COMPANY_NAME));
@@ -424,7 +320,7 @@ TEST(CompanyTest, CompanyNameYear) {
company.GetRawInfo(COMPANY_NAME));
company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("2019"));
- EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
+ EXPECT_EQ(UTF8ToUTF16("2019"), company.GetRawInfo(COMPANY_NAME));
company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1818"));
EXPECT_EQ(UTF8ToUTF16("1818"), company.GetRawInfo(COMPANY_NAME));
@@ -432,6 +328,33 @@ TEST(CompanyTest, CompanyNameYear) {
company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("2345"));
EXPECT_EQ(UTF8ToUTF16("2345"), company.GetRawInfo(COMPANY_NAME));
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr"));
+ EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr."));
+ EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mrs"));
+ EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mrs."));
+ EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr. & Mrs."));
+ EXPECT_EQ(UTF8ToUTF16("Mr. & Mrs."), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr. & Mrs. Smith"));
+ EXPECT_EQ(UTF8ToUTF16("Mr. & Mrs. Smith"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Frau"));
+ EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Frau Doktor"));
+ EXPECT_EQ(UTF8ToUTF16("Frau Doktor"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Herr"));
+ EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
+
profile.set_origin("Not empty");
ASSERT_TRUE(profile.IsVerified());
@@ -449,6 +372,33 @@ TEST(CompanyTest, CompanyNameYear) {
company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("2345"));
EXPECT_EQ(UTF8ToUTF16("2345"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr"));
+ EXPECT_EQ(UTF8ToUTF16("Mr"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr."));
+ EXPECT_EQ(UTF8ToUTF16("Mr."), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mrs"));
+ EXPECT_EQ(UTF8ToUTF16("Mrs"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mrs."));
+ EXPECT_EQ(UTF8ToUTF16("Mrs."), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr. & Mrs."));
+ EXPECT_EQ(UTF8ToUTF16("Mr. & Mrs."), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr. & Mrs. Smith"));
+ EXPECT_EQ(UTF8ToUTF16("Mr. & Mrs. Smith"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Frau"));
+ EXPECT_EQ(UTF8ToUTF16("Frau"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Frau Doktor"));
+ EXPECT_EQ(UTF8ToUTF16("Frau Doktor"), company.GetRawInfo(COMPANY_NAME));
+
+ company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Herr"));
+ EXPECT_EQ(UTF8ToUTF16("Herr"), company.GetRawInfo(COMPANY_NAME));
}
TEST(CompanyTest, CompanyNameYearCopy) {
@@ -488,4 +438,41 @@ TEST(CompanyTest, CompanyNameYearIsEqual) {
EXPECT_EQ(company_old, company_young);
}
+TEST(CompanyTest, CompanyNameSocialTitleCopy) {
+ base::test::ScopedFeatureList scoped_features;
+ scoped_features.InitWithFeatures(
+ /*enabled_features=*/{features::kAutofillRejectCompanySocialTitle},
+ /*disabled_features=*/{});
+
+ AutofillProfile profile;
+ ASSERT_FALSE(profile.IsVerified());
+
+ CompanyInfo company_google(&profile);
+ CompanyInfo company_year(&profile);
+
+ company_google.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Google"));
+ company_year.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Prof."));
+
+ company_google = company_year;
+ EXPECT_EQ(UTF8ToUTF16(""), company_google.GetRawInfo(COMPANY_NAME));
+}
+
+TEST(CompanyTest, CompanyNameSocialTitleIsEqual) {
+ base::test::ScopedFeatureList scoped_features;
+ scoped_features.InitWithFeatures(
+ /*enabled_features=*/{features::kAutofillRejectCompanySocialTitle},
+ /*disabled_features=*/{});
+
+ AutofillProfile profile;
+ ASSERT_FALSE(profile.IsVerified());
+
+ CompanyInfo company_old(&profile);
+ CompanyInfo company_young(&profile);
+
+ company_old.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Dr"));
+ company_young.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Prof"));
+
+ EXPECT_EQ(company_old, company_young);
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/data_model/credit_card.cc b/chromium/components/autofill/core/browser/data_model/credit_card.cc
index 4235a1b05a7..32c713d40c8 100644
--- a/chromium/components/autofill/core/browser/data_model/credit_card.cc
+++ b/chromium/components/autofill/core/browser/data_model/credit_card.cc
@@ -539,6 +539,7 @@ void CreditCard::operator=(const CreditCard& credit_card) {
bank_name_ = credit_card.bank_name_;
temp_card_first_name_ = credit_card.temp_card_first_name_;
temp_card_last_name_ = credit_card.temp_card_last_name_;
+ cloud_token_data_ = credit_card.cloud_token_data_;
set_guid(credit_card.guid());
set_origin(credit_card.origin());
@@ -707,6 +708,11 @@ bool CreditCard::HasValidCardNumber() const {
return IsValidCreditCardNumber(number_);
}
+bool CreditCard::HasValidExpirationYear() const {
+ return IsValidCreditCardExpirationYear(expiration_year_,
+ AutofillClock::Now());
+}
+
bool CreditCard::HasValidExpirationDate() const {
return IsValidCreditCardExpirationDate(expiration_year_, expiration_month_,
AutofillClock::Now());
diff --git a/chromium/components/autofill/core/browser/data_model/credit_card.h b/chromium/components/autofill/core/browser/data_model/credit_card.h
index 0a4c3d65e27..bb074847459 100644
--- a/chromium/components/autofill/core/browser/data_model/credit_card.h
+++ b/chromium/components/autofill/core/browser/data_model/credit_card.h
@@ -16,6 +16,7 @@
#include "base/strings/string_piece_forward.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/data_model/autofill_data_model.h"
+#include "components/sync/protocol/sync.pb.h"
namespace autofill {
@@ -142,6 +143,13 @@ class CreditCard : public AutofillDataModel {
const std::string& server_id() const { return server_id_; }
void set_server_id(const std::string& server_id) { server_id_ = server_id; }
+ const sync_pb::CloudTokenData& cloud_token_data() const {
+ return cloud_token_data_;
+ }
+ void set_cloud_token_data(const sync_pb::CloudTokenData& cloud_token_data) {
+ cloud_token_data_ = cloud_token_data;
+ }
+
// For use in STL containers.
void operator=(const CreditCard& credit_card);
@@ -190,6 +198,9 @@ class CreditCard : public AutofillDataModel {
// not complete.
bool HasValidCardNumber() const;
+ // Returns true if credit card has valid expiration year.
+ bool HasValidExpirationYear() const;
+
// Returns true if credit card has valid expiration date.
bool HasValidExpirationDate() const;
@@ -351,6 +362,9 @@ class CreditCard : public AutofillDataModel {
// since we only store the full name.
base::string16 temp_card_first_name_;
base::string16 temp_card_last_name_;
+
+ // Info of tokenizized credit card if available.
+ sync_pb::CloudTokenData cloud_token_data_;
};
// So we can compare CreditCards with EXPECT_EQ().
diff --git a/chromium/components/autofill/core/browser/data_model/credit_card_unittest.cc b/chromium/components/autofill/core/browser/data_model/credit_card_unittest.cc
index beda49cdaf0..c420cd5dc54 100644
--- a/chromium/components/autofill/core/browser/data_model/credit_card_unittest.cc
+++ b/chromium/components/autofill/core/browser/data_model/credit_card_unittest.cc
@@ -60,7 +60,7 @@ const char* const kInvalidNumbers[] = {
// Use this function to generate a year in the future.
base::string16 GetYearInTheFuture() {
base::Time::Exploded now;
- base::Time::Now().LocalExplode(&now);
+ AutofillClock::Now().LocalExplode(&now);
return base::NumberToString16(now.year + 4);
}
@@ -1023,7 +1023,7 @@ TEST(CreditCardTest,
TEST(CreditCardTest, IsValidCardNumberAndExpiryDate) {
CreditCard card;
// Invalid because expired
- const base::Time now(base::Time::Now());
+ const base::Time now(AutofillClock::Now());
base::Time::Exploded now_exploded;
now.LocalExplode(&now_exploded);
card.SetRawInfo(CREDIT_CARD_EXP_MONTH,
@@ -1547,7 +1547,7 @@ class ShouldUpdateExpirationTest
class TestingTimes {
public:
TestingTimes() {
- now_ = base::Time::Now();
+ now_ = AutofillClock::Now();
(now_ - base::TimeDelta::FromDays(365)).LocalExplode(&last_year_);
(now_ - base::TimeDelta::FromDays(31)).LocalExplode(&last_month_);
now_.LocalExplode(&current_);
diff --git a/chromium/components/autofill/core/browser/field_types.h b/chromium/components/autofill/core/browser/field_types.h
index 3080ba16f68..e874de0c453 100644
--- a/chromium/components/autofill/core/browser/field_types.h
+++ b/chromium/components/autofill/core/browser/field_types.h
@@ -189,9 +189,26 @@ enum ServerFieldType {
// https://en.wikipedia.org/wiki/Unified_Payments_Interface
UPI_VPA = 102,
+ // Just the street name of an address, no house number.
+ // Currently not used by Chrome.
+ ADDRESS_HOME_STREET = 103,
+
+ // House number of an address, may be alphanumeric.
+ // Currently not used by Chrome.
+ ADDRESS_HOME_HOUSE_NUMBER = 104,
+
+ // Floor within in a building, may be alphanumeric.
+ // Currently not used by Chrome.
+ ADDRESS_HOME_FLOOR = 105,
+
+ // A catch-all for other type of subunits (only used until something more
+ // precise is defined).
+ // Currently not used by Chrome.
+ ADDRESS_HOME_OTHER_SUBUNIT = 106,
+
// No new types can be added without a corresponding change to the Autofill
// server.
- MAX_VALID_FIELD_TYPE = 103,
+ MAX_VALID_FIELD_TYPE = 107,
};
// The list of all HTML autocomplete field type hints supported by Chrome.
diff --git a/chromium/components/autofill/core/browser/form_data_importer.cc b/chromium/components/autofill/core/browser/form_data_importer.cc
index 5851f7d6358..4323f547479 100644
--- a/chromium/components/autofill/core/browser/form_data_importer.cc
+++ b/chromium/components/autofill/core/browser/form_data_importer.cc
@@ -103,6 +103,8 @@ FormDataImporter::FormDataImporter(AutofillClient* client,
payments_client,
app_locale,
personal_data_manager)),
+ upi_vpa_save_manager_(
+ std::make_unique<UpiVpaSaveManager>(personal_data_manager)),
local_card_migration_manager_(
std::make_unique<LocalCardMigrationManager>(client,
payments_client,
@@ -118,6 +120,7 @@ void FormDataImporter::ImportFormData(const FormStructure& submitted_form,
bool profile_autofill_enabled,
bool credit_card_autofill_enabled) {
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> detected_vpa;
bool is_credit_card_upstream_enabled =
credit_card_save_manager_->IsCreditCardUploadEnabled();
@@ -128,7 +131,13 @@ void FormDataImporter::ImportFormData(const FormStructure& submitted_form,
ImportFormData(submitted_form, profile_autofill_enabled,
credit_card_autofill_enabled,
/*should_return_local_card=*/is_credit_card_upstream_enabled,
- &imported_credit_card);
+ &imported_credit_card, &detected_vpa);
+
+ if (detected_vpa && credit_card_autofill_enabled &&
+ base::FeatureList::IsEnabled(features::kAutofillSaveAndFillVPA)) {
+ upi_vpa_save_manager_->OfferLocalSave(*detected_vpa);
+ }
+
// If no card was successfully imported from the form, return.
if (imported_credit_card_record_type_ ==
ImportedCreditCardRecordType::NO_CARD) {
@@ -214,7 +223,8 @@ bool FormDataImporter::ImportFormData(
bool profile_autofill_enabled,
bool credit_card_autofill_enabled,
bool should_return_local_card,
- std::unique_ptr<CreditCard>* imported_credit_card) {
+ std::unique_ptr<CreditCard>* imported_credit_card,
+ base::Optional<std::string>* imported_vpa) {
// We try the same |form| for both credit card and address import/update.
// - ImportCreditCard may update an existing card, or fill
// |imported_credit_card| with an extracted card. See .h for details of
@@ -226,6 +236,7 @@ bool FormDataImporter::ImportFormData(
if (credit_card_autofill_enabled) {
cc_import = ImportCreditCard(submitted_form, should_return_local_card,
imported_credit_card);
+ *imported_vpa = ImportVPA(submitted_form);
}
// - ImportAddressProfiles may eventually save or update one or more address
// profiles.
@@ -233,7 +244,8 @@ bool FormDataImporter::ImportFormData(
if (profile_autofill_enabled) {
address_import = ImportAddressProfiles(submitted_form);
}
- if (cc_import || address_import)
+
+ if (cc_import || address_import || imported_vpa->has_value())
return true;
personal_data_manager_->MarkObserversInsufficientFormDataForImport();
@@ -535,4 +547,13 @@ CreditCard FormDataImporter::ExtractCreditCardFromForm(
return candidate_credit_card;
}
+base::Optional<std::string> FormDataImporter::ImportVPA(
+ const FormStructure& form) {
+ for (const auto& field : form) {
+ if (IsUPIVirtualPaymentAddress(field->value))
+ return base::UTF16ToUTF8(field->value);
+ }
+ return base::nullopt;
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/form_data_importer.h b/chromium/components/autofill/core/browser/form_data_importer.h
index 1fd598e0ba2..e81346a28bf 100644
--- a/chromium/components/autofill/core/browser/form_data_importer.h
+++ b/chromium/components/autofill/core/browser/form_data_importer.h
@@ -17,8 +17,11 @@
#include "components/autofill/core/browser/payments/credit_card_save_manager.h"
#include "components/autofill/core/browser/payments/local_card_migration_manager.h"
#include "components/autofill/core/browser/payments/payments_client.h"
+#include "components/autofill/core/browser/payments/upi_vpa_save_manager.h"
#include "components/autofill/core/browser/personal_data_manager.h"
+class SaveCardOfferObserver;
+
namespace autofill {
// Manages logic for importing address profiles and credit card information from
@@ -87,13 +90,16 @@ class FormDataImporter {
// data. If the form contains credit card data already present in a local
// credit card entry *and* |should_return_local_card| is true, the data is
// stored into |imported_credit_card| so that we can prompt the user whether
- // to upload it. Returns |true| if sufficient address or credit card data
+ // to upload it. If the form contains UPI/VPA data and
+ // |credit_card_autofill_enabled| is true, the VPA value will be stored into
+ // |imported_vpa|. Returns |true| if sufficient address or credit card data
// was found. Exposed for testing.
bool ImportFormData(const FormStructure& form,
bool profile_autofill_enabled,
bool credit_card_autofill_enabled,
bool should_return_local_card,
- std::unique_ptr<CreditCard>* imported_credit_card);
+ std::unique_ptr<CreditCard>* imported_credit_card,
+ base::Optional<std::string>* imported_vpa);
// Go through the |form| fields and attempt to extract and import valid
// address profiles. Returns true on extraction success of at least one
@@ -120,6 +126,10 @@ class FormDataImporter {
CreditCard ExtractCreditCardFromForm(const FormStructure& form,
bool* hasDuplicateFieldType);
+ // Go through the |form| fields and find a UPI/VPA value to import. The return
+ // value will be empty if no VPA was found.
+ base::Optional<std::string> ImportVPA(const FormStructure& form);
+
// Whether a dynamic change form is imported.
bool from_dynamic_change_form_ = false;
@@ -133,6 +143,9 @@ class FormDataImporter {
// Responsible for managing credit card save flows (local or upload).
std::unique_ptr<CreditCardSaveManager> credit_card_save_manager_;
+ // Responsible for managing UPI/VPA save flows.
+ std::unique_ptr<UpiVpaSaveManager> upi_vpa_save_manager_;
+
// Responsible for migrating locally saved credit cards to Google Pay.
std::unique_ptr<LocalCardMigrationManager> local_card_migration_manager_;
@@ -155,6 +168,7 @@ class FormDataImporter {
friend class LocalCardMigrationBrowserTest;
friend class SaveCardBubbleViewsFullFormBrowserTest;
friend class SaveCardInfobarEGTestHelper;
+ friend class ::SaveCardOfferObserver;
FRIEND_TEST_ALL_PREFIXES(AutofillMergeTest, MergeProfiles);
FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
AllowDuplicateMaskedServerCardIfFlagEnabled);
@@ -197,6 +211,8 @@ class FormDataImporter {
ImportFormData_SecondImportResetsCreditCardRecordType);
FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
ImportFormData_TwoAddressesOneCreditCard);
+ FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
+ ImportFormData_DontSetVPAWhenOnlyCreditCardExists);
FRIEND_TEST_ALL_PREFIXES(
FormDataImporterTest,
Metrics_SubmittedServerCardExpirationStatus_FullServerCardMatch);
@@ -218,6 +234,9 @@ class FormDataImporter {
FRIEND_TEST_ALL_PREFIXES(
FormDataImporterTest,
Metrics_SubmittedDifferentServerCardExpirationStatus_EmptyExpirationYear);
+ FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest, ImportVPA);
+ FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest, ImportVPADisabled);
+ FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest, ImportVPAIgnoreNonVPA);
DISALLOW_COPY_AND_ASSIGN(FormDataImporter);
};
diff --git a/chromium/components/autofill/core/browser/form_data_importer_unittest.cc b/chromium/components/autofill/core/browser/form_data_importer_unittest.cc
index 703f2ae0d00..55ec7e1b5b8 100644
--- a/chromium/components/autofill/core/browser/form_data_importer_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_data_importer_unittest.cc
@@ -223,8 +223,8 @@ class FormDataImporterTestBase {
run_loop.Run();
}
- base::test::TaskEnvironment task_environment_{
- base::test::TaskEnvironment::MainThreadType::UI};
+ base::test::SingleThreadTaskEnvironment task_environment_{
+ base::test::SingleThreadTaskEnvironment::MainThreadType::UI};
std::unique_ptr<PrefService> prefs_;
scoped_refptr<AutofillWebDataService> autofill_database_service_;
scoped_refptr<WebDatabaseService> web_database_;
@@ -2138,10 +2138,11 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/true, &imported_credit_card));
+ /*should_return_local_card=*/true, &imported_credit_card, &imported_vpa));
ASSERT_TRUE(imported_credit_card);
// |imported_credit_card_record_type_| should be LOCAL_CARD because upload was
// offered and the card is a local card already on the device.
@@ -2163,7 +2164,8 @@ TEST_F(FormDataImporterTest,
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure2, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/true, &imported_credit_card2));
+ /*should_return_local_card=*/true, &imported_credit_card2,
+ &imported_vpa));
ASSERT_TRUE(imported_credit_card2);
// |imported_credit_card_record_type_| should be NEW_CARD because the imported
// card is not already on the device.
@@ -2202,7 +2204,8 @@ TEST_F(FormDataImporterTest,
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure3, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/false,
- /*should_return_local_card=*/true, &imported_credit_card3));
+ /*should_return_local_card=*/true, &imported_credit_card3,
+ &imported_vpa));
// |imported_credit_card_record_type_| should be NO_CARD because no valid card
// was imported from the form.
ASSERT_TRUE(form_data_importer_->imported_credit_card_record_type_ ==
@@ -2222,10 +2225,11 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/true, &imported_credit_card));
+ /*should_return_local_card=*/true, &imported_credit_card, &imported_vpa));
ASSERT_TRUE(imported_credit_card);
// |imported_credit_card_record_type_| should be NEW_CARD because the imported
// card is not already on the device.
@@ -2259,10 +2263,11 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/true, &imported_credit_card));
+ /*should_return_local_card=*/true, &imported_credit_card, &imported_vpa));
ASSERT_TRUE(imported_credit_card);
// |imported_credit_card_record_type_| should be LOCAL_CARD because upload was
// offered and the card is a local card already on the device.
@@ -2296,10 +2301,11 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/true, &imported_credit_card));
+ /*should_return_local_card=*/true, &imported_credit_card, &imported_vpa));
ASSERT_FALSE(imported_credit_card);
// |imported_credit_card_record_type_| should be SERVER_CARD.
ASSERT_TRUE(form_data_importer_->imported_credit_card_record_type_ ==
@@ -2332,10 +2338,11 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/true, &imported_credit_card));
+ /*should_return_local_card=*/true, &imported_credit_card, &imported_vpa));
ASSERT_FALSE(imported_credit_card);
// |imported_credit_card_record_type_| should be SERVER_CARD.
ASSERT_TRUE(form_data_importer_->imported_credit_card_record_type_ ==
@@ -2355,10 +2362,11 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/true, &imported_credit_card));
+ /*should_return_local_card=*/true, &imported_credit_card, &imported_vpa));
ASSERT_FALSE(imported_credit_card);
// |imported_credit_card_record_type_| should be NO_CARD because no valid card
// was successfully imported from the form.
@@ -2382,10 +2390,11 @@ TEST_F(
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/true, &imported_credit_card));
+ /*should_return_local_card=*/true, &imported_credit_card, &imported_vpa));
ASSERT_FALSE(imported_credit_card);
// |imported_credit_card_record_type_| should be NO_CARD because no valid card
// was successfully imported from the form.
@@ -2409,10 +2418,11 @@ TEST_F(
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/true, &imported_credit_card));
+ /*should_return_local_card=*/true, &imported_credit_card, &imported_vpa));
ASSERT_TRUE(imported_credit_card);
// |imported_credit_card_record_type_| should be NEW_CARD because card was
// successfully imported from the form via the expiration date fix flow.
@@ -2450,10 +2460,11 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/true, &imported_credit_card));
+ /*should_return_local_card=*/true, &imported_credit_card, &imported_vpa));
ASSERT_FALSE(imported_credit_card);
// |imported_credit_card_record_type_| should be NO_CARD because the form
// doesn't have credit card section.
@@ -2497,11 +2508,13 @@ TEST_F(FormDataImporterTest, ImportFormData_OneAddressOneCreditCard) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
ASSERT_TRUE(imported_credit_card);
personal_data_manager_->OnAcceptedLocalCreditCardSave(*imported_credit_card);
@@ -2583,11 +2596,13 @@ TEST_F(FormDataImporterTest, ImportFormData_TwoAddressesOneCreditCard) {
.WillRepeatedly(QuitMessageLoop(&run_loop));
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.Times(testing::AnyNumber());
+ base::Optional<std::string> imported_vpa;
// Still returns true because the credit card import was successful.
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
run_loop.Run();
ASSERT_TRUE(imported_credit_card);
@@ -2642,10 +2657,12 @@ TEST_F(FormDataImporterTest, ImportFormData_AddressesDisabledOneCreditCard) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/false,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
ASSERT_TRUE(imported_credit_card);
personal_data_manager_->OnAcceptedLocalCreditCardSave(*imported_credit_card);
@@ -2698,11 +2715,13 @@ TEST_F(FormDataImporterTest, ImportFormData_OneAddressCreditCardDisabled) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/false,
- /*should_return_local_card=*/false, &imported_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
ASSERT_FALSE(imported_credit_card);
WaitForOnPersonalDataChanged();
@@ -2758,11 +2777,13 @@ TEST_F(FormDataImporterTest, ImportFormData_AddressCreditCardDisabled) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/false,
/*credit_card_autofill_enabled=*/false,
- /*should_return_local_card=*/false, &imported_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
ASSERT_FALSE(imported_credit_card);
// Test that addresses were not saved.
@@ -2815,10 +2836,12 @@ TEST_F(FormDataImporterTest, DontDuplicateMaskedServerCard) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
ASSERT_FALSE(imported_credit_card);
}
@@ -2852,11 +2875,13 @@ TEST_F(FormDataImporterTest, ImportFormData_HiddenCreditCardFormAfterEntered) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
// Still returns true because the credit card import was successful.
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
ASSERT_TRUE(imported_credit_card);
personal_data_manager_->OnAcceptedLocalCreditCardSave(*imported_credit_card);
@@ -2872,6 +2897,27 @@ TEST_F(FormDataImporterTest, ImportFormData_HiddenCreditCardFormAfterEntered) {
EXPECT_EQ(0, expected_card.Compare(*results[0]));
}
+// Ensures that no VPA value is returned when there's a credit card and no VPA.
+TEST_F(FormDataImporterTest,
+ ImportFormData_DontSetVPAWhenOnlyCreditCardExists) {
+ // Simulate a form submission with a new credit card.
+ FormData form;
+ form.url = GURL("https://wwww.foo.com");
+
+ AddFullCreditCardForm(&form, "Biggie Smalls", "4111 1111 1111 1111", "01",
+ "2999");
+
+ FormStructure form_structure(form);
+ form_structure.DetermineHeuristicTypes();
+ std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
+ EXPECT_TRUE(form_data_importer_->ImportFormData(
+ form_structure, /*profile_autofill_enabled=*/true,
+ /*credit_card_autofill_enabled=*/true,
+ /*should_return_local_card=*/true, &imported_credit_card, &imported_vpa));
+ ASSERT_FALSE(imported_vpa.has_value());
+}
+
TEST_F(FormDataImporterTest, DontDuplicateFullServerCard) {
EnableWalletCardImport();
@@ -2914,11 +2960,13 @@ TEST_F(FormDataImporterTest, DontDuplicateFullServerCard) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
EXPECT_FALSE(imported_credit_card);
}
@@ -2959,11 +3007,13 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
EXPECT_FALSE(imported_credit_card);
histogram_tester.ExpectUniqueSample(
"Autofill.SubmittedServerCardExpirationStatus",
@@ -3010,11 +3060,13 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
EXPECT_FALSE(imported_credit_card);
}
@@ -3058,11 +3110,13 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
EXPECT_FALSE(imported_credit_card);
}
@@ -3107,11 +3161,13 @@ TEST_F(
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
EXPECT_TRUE(imported_credit_card);
}
@@ -3153,11 +3209,13 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
EXPECT_FALSE(imported_credit_card);
histogram_tester.ExpectUniqueSample(
"Autofill.SubmittedServerCardExpirationStatus",
@@ -3202,11 +3260,13 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
EXPECT_FALSE(imported_credit_card);
histogram_tester.ExpectUniqueSample(
"Autofill.SubmittedServerCardExpirationStatus",
@@ -3252,14 +3312,86 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+ base::Optional<std::string> imported_vpa;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
EXPECT_FALSE(imported_credit_card);
histogram_tester.ExpectUniqueSample(
"Autofill.SubmittedServerCardExpirationStatus",
AutofillMetrics::MASKED_SERVER_CARD_EXPIRATION_DATE_DID_NOT_MATCH, 1);
}
+TEST_F(FormDataImporterTest, ImportVPA) {
+ FormData form;
+ form.url = GURL("https://wwww.foo.com");
+
+ FormFieldData field;
+ test::CreateTestFormField("VPA:", "vpa", "user@indianbank", "text", &field);
+ form.fields.push_back(field);
+
+ FormStructure form_structure(form);
+ form_structure.DetermineHeuristicTypes();
+
+ std::unique_ptr<CreditCard> imported_credit_card; // Discarded.
+ base::Optional<std::string> imported_vpa;
+
+ EXPECT_TRUE(form_data_importer_->ImportFormData(
+ form_structure, /*profile_autofill_enabled=*/false,
+ /*credit_card_autofill_enabled=*/true,
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
+
+ ASSERT_TRUE(imported_vpa.has_value());
+ EXPECT_EQ(imported_vpa.value(), "user@indianbank");
+}
+
+TEST_F(FormDataImporterTest, ImportVPADisabled) {
+ FormData form;
+ form.url = GURL("https://wwww.foo.com");
+
+ FormFieldData field;
+ test::CreateTestFormField("VPA:", "vpa", "user@indianbank", "text", &field);
+ form.fields.push_back(field);
+
+ FormStructure form_structure(form);
+ form_structure.DetermineHeuristicTypes();
+
+ std::unique_ptr<CreditCard> imported_credit_card; // Discarded.
+ base::Optional<std::string> imported_vpa;
+
+ EXPECT_FALSE(form_data_importer_->ImportFormData(
+ form_structure, /*profile_autofill_enabled=*/false,
+ /*credit_card_autofill_enabled=*/false,
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
+
+ EXPECT_FALSE(imported_vpa.has_value());
+}
+
+TEST_F(FormDataImporterTest, ImportVPAIgnoreNonVPA) {
+ FormData form;
+ form.url = GURL("https://wwww.foo.com");
+
+ FormFieldData field;
+ test::CreateTestFormField("VPA:", "vpa", "user@gmail.com", "text", &field);
+ form.fields.push_back(field);
+
+ FormStructure form_structure(form);
+ form_structure.DetermineHeuristicTypes();
+
+ std::unique_ptr<CreditCard> imported_credit_card; // Discarded.
+ base::Optional<std::string> imported_vpa;
+
+ EXPECT_FALSE(form_data_importer_->ImportFormData(
+ form_structure, /*profile_autofill_enabled=*/false,
+ /*credit_card_autofill_enabled=*/false,
+ /*should_return_local_card=*/false, &imported_credit_card,
+ &imported_vpa));
+
+ EXPECT_FALSE(imported_vpa.has_value());
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/form_parsing/autofill_scanner.h b/chromium/components/autofill/core/browser/form_parsing/autofill_scanner.h
index 336e5562852..5adf96d9ccd 100644
--- a/chromium/components/autofill/core/browser/form_parsing/autofill_scanner.h
+++ b/chromium/components/autofill/core/browser/form_parsing/autofill_scanner.h
@@ -45,9 +45,6 @@ class AutofillScanner {
// |RewindTo()|.
size_t SaveCursor();
- // This is only for logging purposes.
- size_t CursorIndex() { return static_cast<size_t>(cursor_ - begin_); }
-
private:
void Init(const std::vector<AutofillField*>& fields);
diff --git a/chromium/components/autofill/core/browser/form_parsing/field_candidates.cc b/chromium/components/autofill/core/browser/form_parsing/field_candidates.cc
index f3dc3b5b9dc..e60965ab5a8 100644
--- a/chromium/components/autofill/core/browser/form_parsing/field_candidates.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/field_candidates.cc
@@ -45,8 +45,4 @@ ServerFieldType FieldCandidates::BestHeuristicType() const {
return static_cast<ServerFieldType>(index);
}
-const std::vector<FieldCandidate>& FieldCandidates::field_candidates() const {
- return field_candidates_;
-}
-
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/form_parsing/field_candidates.h b/chromium/components/autofill/core/browser/form_parsing/field_candidates.h
index d4520921f42..f1ef7246213 100644
--- a/chromium/components/autofill/core/browser/form_parsing/field_candidates.h
+++ b/chromium/components/autofill/core/browser/form_parsing/field_candidates.h
@@ -44,11 +44,6 @@ class FieldCandidates {
// Determines the best type based on the current possible types.
ServerFieldType BestHeuristicType() const;
- // Returns the underlying candidates.
- //
- // This reference is only valid while the FieldCandidates object is valid.
- const std::vector<FieldCandidate>& field_candidates() const;
-
private:
// Internal storage for all the possible types for a given field.
std::vector<FieldCandidate> field_candidates_;
diff --git a/chromium/components/autofill/core/browser/form_parsing/form_field.cc b/chromium/components/autofill/core/browser/form_parsing/form_field.cc
index 266bd688bfe..d801580967b 100644
--- a/chromium/components/autofill/core/browser/form_parsing/form_field.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/form_field.cc
@@ -17,7 +17,6 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_field.h"
-#include "components/autofill/core/browser/autofill_internals_service.h"
#include "components/autofill/core/browser/form_parsing/address_field.h"
#include "components/autofill/core/browser/form_parsing/autofill_scanner.h"
#include "components/autofill/core/browser/form_parsing/credit_card_field.h"
diff --git a/chromium/components/autofill/core/browser/form_structure.cc b/chromium/components/autofill/core/browser/form_structure.cc
index 22b536cd140..542afd7f8b3 100644
--- a/chromium/components/autofill/core/browser/form_structure.cc
+++ b/chromium/components/autofill/core/browser/form_structure.cc
@@ -35,21 +35,25 @@
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/form_parsing/field_candidates.h"
#include "components/autofill/core/browser/form_parsing/form_field.h"
-#include "components/autofill/core/browser/logging/log_buffer.h"
+#include "components/autofill/core/browser/logging/log_manager.h"
#include "components/autofill/core/browser/proto/legacy_proto_bridge.h"
#include "components/autofill/core/browser/randomized_encoder.h"
#include "components/autofill/core/browser/rationalization_util.h"
#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_features.h"
+#include "components/autofill/core/common/autofill_internals/log_message.h"
+#include "components/autofill/core/common/autofill_internals/logging_scope.h"
#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/autofill/core/common/autofill_regex_constants.h"
#include "components/autofill/core/common/autofill_regexes.h"
+#include "components/autofill/core/common/autofill_tick_clock.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_data_predictions.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/form_field_data_predictions.h"
+#include "components/autofill/core/common/logging/log_buffer.h"
#include "components/autofill/core/common/signatures_util.h"
#include "components/security_state/core/security_state.h"
#include "url/origin.h"
@@ -409,13 +413,6 @@ void EncodePasswordAttributesVote(
upload->set_password_has_lowercase_letter(
password_attributes_vote.second);
break;
- case PasswordAttribute::kHasUppercaseLetter:
- upload->set_password_has_uppercase_letter(
- password_attributes_vote.second);
- break;
- case PasswordAttribute::kHasNumeric:
- upload->set_password_has_numeric(password_attributes_vote.second);
- break;
case PasswordAttribute::kHasSpecialSymbol:
upload->set_password_has_special_symbol(password_attributes_vote.second);
if (password_attributes_vote.second)
@@ -568,22 +565,13 @@ FormStructure::FormStructure(const FormData& form)
name_attribute_(form.name_attribute),
form_name_(form.name),
button_titles_(form.button_titles),
- submission_event_(SubmissionIndicatorEvent::NONE),
source_url_(form.url),
target_url_(form.action),
main_frame_origin_(form.main_frame_origin),
- autofill_count_(0),
- active_field_count_(0),
- upload_required_(USE_UPLOAD_RATES),
- has_author_specified_types_(false),
- has_author_specified_sections_(false),
- has_author_specified_upi_vpa_hint_(false),
- was_parsed_for_autocomplete_attributes_(false),
- has_password_field_(false),
is_form_tag_(form.is_form_tag),
is_formless_checkout_(form.is_formless_checkout),
all_fields_are_passwords_(!form.fields.empty()),
- form_parsed_timestamp_(base::TimeTicks::Now()),
+ form_parsed_timestamp_(AutofillTickClock::NowTicks()),
passwords_were_revealed_(false),
password_symbol_vote_(0),
developer_engagement_metrics_(0),
@@ -613,10 +601,19 @@ FormStructure::FormStructure(const FormData& form)
ProcessExtractedFields();
}
-FormStructure::~FormStructure() {}
+FormStructure::FormStructure(
+ FormSignature form_signature,
+ const std::vector<FieldSignature>& field_signatures)
+ : form_signature_(form_signature) {
+ for (const auto& signature : field_signatures)
+ fields_.push_back(AutofillField::CreateForPasswordManagerUpload(signature));
+}
+
+FormStructure::~FormStructure() = default;
void FormStructure::DetermineHeuristicTypes(LogManager* log_manager) {
- const auto determine_heuristic_types_start_time = base::TimeTicks::Now();
+ const auto determine_heuristic_types_start_time =
+ AutofillTickClock::NowTicks();
// First, try to detect field types based on each field's |autocomplete|
// attribute value.
@@ -660,7 +657,7 @@ void FormStructure::DetermineHeuristicTypes(LogManager* log_manager) {
RationalizeFieldTypePredictions();
AutofillMetrics::LogDetermineHeuristicTypesTiming(
- base::TimeTicks::Now() - determine_heuristic_types_start_time);
+ AutofillTickClock::NowTicks() - determine_heuristic_types_start_time);
}
bool FormStructure::EncodeUploadRequest(
@@ -826,6 +823,14 @@ void FormStructure::ProcessQueryResponse(
if (heuristic_type != UNKNOWN_TYPE)
heuristics_detected_fillable_field = true;
+ // Clears the server prediction for CVC-fields if the corresponding Finch
+ // feature is not enabled.
+ if (!base::FeatureList::IsEnabled(
+ autofill::features::kAutofillUseServerCVCPrediction) &&
+ field_type == ServerFieldType::CREDIT_CARD_VERIFICATION_CODE) {
+ field_type = ServerFieldType::NO_SERVER_DATA;
+ }
+
field->set_server_type(field_type);
std::vector<AutofillQueryResponseContents::Field::FieldPrediction>
server_predictions;
@@ -913,6 +918,14 @@ bool FormStructure::IsAutofillFieldMetadataEnabled() {
return base::StartsWith(group_name, "Enabled", base::CompareCase::SENSITIVE);
}
+std::unique_ptr<FormStructure> FormStructure::CreateForPasswordManagerUpload(
+ FormSignature form_signature,
+ const std::vector<FieldSignature>& field_signatures) {
+ std::unique_ptr<FormStructure> form;
+ form.reset(new FormStructure(form_signature, field_signatures));
+ return form;
+}
+
std::string FormStructure::FormSignatureAsStr() const {
return base::NumberToString(form_signature());
}
@@ -951,10 +964,15 @@ void FormStructure::UpdateAutofillCount() {
}
}
-bool FormStructure::ShouldBeParsed() const {
+bool FormStructure::ShouldBeParsed(LogManager* log_manager) const {
// Exclude URLs not on the web via HTTP(S).
- if (!HasAllowedScheme(source_url_))
+ if (!HasAllowedScheme(source_url_)) {
+ if (log_manager) {
+ log_manager->Log() << LoggingScope::kAbortParsing
+ << LogMessage::kAbortParsingNotAllowedScheme << *this;
+ }
return false;
+ }
size_t min_required_fields =
std::min({MinRequiredFieldsForHeuristics(), MinRequiredFieldsForQuery(),
@@ -963,6 +981,11 @@ bool FormStructure::ShouldBeParsed() const {
(!all_fields_are_passwords() ||
active_field_count() < kRequiredFieldsForFormsWithOnlyPasswordFields) &&
!has_author_specified_types_) {
+ if (log_manager) {
+ log_manager->Log() << LoggingScope::kAbortParsing
+ << LogMessage::kAbortParsingNotEnoughFields
+ << active_field_count() << *this;
+ }
return false;
}
@@ -971,6 +994,11 @@ bool FormStructure::ShouldBeParsed() const {
base::UTF8ToUTF16(kUrlSearchActionRe);
if (MatchesPattern(base::UTF8ToUTF16(target_url_.path_piece()),
kUrlSearchActionPattern)) {
+ if (log_manager) {
+ log_manager->Log() << LoggingScope::kAbortParsing
+ << LogMessage::kAbortParsingUrlMatchesSearchRegex
+ << *this;
+ }
return false;
}
@@ -979,6 +1007,11 @@ bool FormStructure::ShouldBeParsed() const {
has_text_field |= it->form_control_type != "select-one";
}
+ if (!has_text_field && log_manager) {
+ log_manager->Log() << LoggingScope::kAbortParsing
+ << LogMessage::kAbortParsingFormHasNoTextfield << *this;
+ }
+
return has_text_field;
}
@@ -1031,9 +1064,7 @@ void FormStructure::RetrieveFromCache(
bool is_credit_card_field =
AutofillType(cached_field->second->Type().GetStorableType())
.group() == CREDIT_CARD;
- if (should_keep_cached_value && is_credit_card_field &&
- base::FeatureList::IsEnabled(
- features::kAutofillImportDynamicForms)) {
+ if (should_keep_cached_value && is_credit_card_field) {
field->value = cached_field->second->value;
value_from_dynamic_change_form_ = true;
} else if (field->value == cached_field->second->value) {
@@ -2194,6 +2225,7 @@ LogBuffer& operator<<(LogBuffer& buffer, const FormStructure& form) {
base::NumberToString(
HashFormSignature(form.form_signature()))});
buffer << Tr{} << "Form name:" << form.form_name();
+ buffer << Tr{} << "Unique renderer Id:" << form.unique_renderer_id();
buffer << Tr{} << "Target URL:" << form.target_url();
for (size_t i = 0; i < form.field_count(); ++i) {
buffer << Tag{"tr"};
diff --git a/chromium/components/autofill/core/browser/form_structure.h b/chromium/components/autofill/core/browser/form_structure.h
index 7a90138c297..4117c49e0aa 100644
--- a/chromium/components/autofill/core/browser/form_structure.h
+++ b/chromium/components/autofill/core/browser/form_structure.h
@@ -44,8 +44,6 @@ class LogManager;
// Password attributes (whether a password has special symbols, numeric, etc.)
enum class PasswordAttribute {
kHasLowercaseLetter,
- kHasUppercaseLetter,
- kHasNumeric,
kHasSpecialSymbol,
kPasswordAttributesCount
};
@@ -111,6 +109,13 @@ class FormStructure {
// Returns whether sending autofill field metadata to the server is enabled.
static bool IsAutofillFieldMetadataEnabled();
+ // Creates FormStructure that has bare minimum information for uploading
+ // votes, namely form and field signatures. Warning: do not use for Autofill
+ // code, since it is likely missing some fields.
+ static std::unique_ptr<FormStructure> CreateForPasswordManagerUpload(
+ FormSignature form_signature,
+ const std::vector<FieldSignature>& field_signatures);
+
// Return the form signature as string.
std::string FormSignatureAsStr() const;
@@ -130,7 +135,7 @@ class FormStructure {
void UpdateAutofillCount();
// Returns true if this form matches the structural requirements for Autofill.
- bool ShouldBeParsed() const;
+ bool ShouldBeParsed(LogManager* log_manager = nullptr) const;
// Returns true if heuristic autofill type detection should be attempted for
// this form.
@@ -237,10 +242,6 @@ class FormStructure {
return has_author_specified_types_;
}
- bool has_author_specified_sections() const {
- return has_author_specified_sections_;
- }
-
bool has_author_specified_upi_vpa_hint() const {
return has_author_specified_upi_vpa_hint_;
}
@@ -414,6 +415,9 @@ class FormStructure {
size_t current_section_ptr = 0;
};
+ FormStructure(FormSignature form_signature,
+ const std::vector<FieldSignature>& field_signatures);
+
// A function to fine tune the credit cards related predictions. For example:
// lone credit card fields in an otherwise non-credit-card related form is
// unlikely to be correct, the function will override that prediction.
@@ -526,7 +530,8 @@ class FormStructure {
// The type of the event that was taken as an indication that the form has
// been successfully submitted.
- mojom::SubmissionIndicatorEvent submission_event_;
+ mojom::SubmissionIndicatorEvent submission_event_ =
+ mojom::SubmissionIndicatorEvent::NONE;
// The source URL.
GURL source_url_;
@@ -538,50 +543,50 @@ class FormStructure {
url::Origin main_frame_origin_;
// The number of fields able to be auto-filled.
- size_t autofill_count_;
+ size_t autofill_count_ = 0;
// A vector of all the input fields in the form.
std::vector<std::unique_ptr<AutofillField>> fields_;
// The number of fields that are part of the form signature and that are
// included in queries to the Autofill server.
- size_t active_field_count_;
+ size_t active_field_count_ = 0;
// Whether the server expects us to always upload, never upload, or default
// to the stored upload rates.
- UploadRequired upload_required_;
+ UploadRequired upload_required_ = USE_UPLOAD_RATES;
// Whether the form includes any field types explicitly specified by the site
// author, via the |autocompletetype| attribute.
- bool has_author_specified_types_;
+ bool has_author_specified_types_ = false;
// Whether the form includes any sections explicitly specified by the site
// author, via the autocomplete attribute.
- bool has_author_specified_sections_;
+ bool has_author_specified_sections_ = false;
// Whether the form includes a field that explicitly sets it autocomplete
// type to "upi-vpa".
- bool has_author_specified_upi_vpa_hint_;
+ bool has_author_specified_upi_vpa_hint_ = false;
// Whether the form was parsed for autocomplete attribute, thus assigning
// the real values of |has_author_specified_types_| and
// |has_author_specified_sections_|.
- bool was_parsed_for_autocomplete_attributes_;
+ bool was_parsed_for_autocomplete_attributes_ = false;
// True if the form contains at least one password field.
- bool has_password_field_;
+ bool has_password_field_ = false;
// True if the form is a <form>.
- bool is_form_tag_;
+ bool is_form_tag_ = true;
// True if the form is made of unowned fields (i.e., not within a <form> tag)
// in what appears to be a checkout flow. This attribute is only calculated
// and used if features::kAutofillRestrictUnownedFieldsToFormlessCheckout is
// enabled, to prevent heuristics from running on formless non-checkout.
- bool is_formless_checkout_;
+ bool is_formless_checkout_ = false;
// True if all form fields are password fields.
- bool all_fields_are_passwords_;
+ bool all_fields_are_passwords_ = false;
// The unique signature for this form, composed of the target url domain,
// the form name, and the form field names in a 64-bit hash.
@@ -595,7 +600,7 @@ class FormStructure {
// True iff the form is a password form and the user has seen the password
// value before accepting the prompt to save. Used for crowdsourcing.
- bool passwords_were_revealed_;
+ bool passwords_were_revealed_ = false;
// The vote about password attributes (e.g. whether the password has a numeric
// character).
@@ -605,7 +610,7 @@ class FormStructure {
// field contains nosified information about a special symbol in a
// user-created password stored as ASCII code. The default value of 0
// indicates that no symbol was set.
- int password_symbol_vote_;
+ int password_symbol_vote_ = 0;
// Noisified password length for crowdsourcing. If |password_attributes_vote_|
// has no value, |password_length_vote_| should be ignored.
@@ -614,7 +619,7 @@ class FormStructure {
// Used to record whether developer has used autocomplete markup or
// UPI-VPA hints, This is a bitmask of DeveloperEngagementMetric and set in
// DetermineHeuristicTypes().
- int developer_engagement_metrics_;
+ int developer_engagement_metrics_ = 0;
mojom::SubmissionSource submission_source_ = mojom::SubmissionSource::NONE;
@@ -634,7 +639,6 @@ class FormStructure {
};
LogBuffer& operator<<(LogBuffer& buffer, const FormStructure& form);
-
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_STRUCTURE_H_
diff --git a/chromium/components/autofill/core/browser/form_structure_unittest.cc b/chromium/components/autofill/core/browser/form_structure_unittest.cc
index 7ebf1c72000..f0b086f2d8c 100644
--- a/chromium/components/autofill/core/browser/form_structure_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_structure_unittest.cc
@@ -2592,7 +2592,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithMatchingValidities) {
form_structure = std::make_unique<FormStructure>(form);
form_structure->set_password_attributes_vote(
- std::make_pair(PasswordAttribute::kHasNumeric, true));
+ std::make_pair(PasswordAttribute::kHasLowercaseLetter, true));
form_structure->set_password_length_vote(10u);
ASSERT_EQ(form_structure->field_count(), possible_field_types.size());
@@ -2623,7 +2623,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithMatchingValidities) {
upload.set_autofill_used(false);
upload.set_data_present("144200030e");
upload.set_passwords_revealed(false);
- upload.set_password_has_numeric(true);
+ upload.set_password_has_lowercase_letter(true);
upload.set_password_length(10u);
upload.set_action_signature(15724779818122431245U);
upload.set_submission_event(
@@ -2685,7 +2685,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithMatchingValidities) {
form_structure = std::make_unique<FormStructure>(form);
form_structure->set_password_attributes_vote(
- std::make_pair(PasswordAttribute::kHasNumeric, true));
+ std::make_pair(PasswordAttribute::kHasLowercaseLetter, true));
form_structure->set_password_length_vote(10u);
ASSERT_EQ(form_structure->field_count(), possible_field_types.size());
@@ -2787,7 +2787,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithNonMatchingValidities) {
form_structure = std::make_unique<FormStructure>(form);
form_structure->set_password_attributes_vote(
- std::make_pair(PasswordAttribute::kHasNumeric, true));
+ std::make_pair(PasswordAttribute::kHasLowercaseLetter, true));
form_structure->set_password_length_vote(10u);
ASSERT_EQ(form_structure->field_count(), possible_field_types.size());
@@ -2818,7 +2818,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithNonMatchingValidities) {
upload.set_autofill_used(false);
upload.set_data_present("144200030e");
upload.set_passwords_revealed(false);
- upload.set_password_has_numeric(true);
+ upload.set_password_has_lowercase_letter(true);
upload.set_password_length(10u);
upload.set_action_signature(15724779818122431245U);
@@ -2918,7 +2918,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithMultipleValidities) {
form_structure = std::make_unique<FormStructure>(form);
form_structure->set_password_attributes_vote(
- std::make_pair(PasswordAttribute::kHasNumeric, true));
+ std::make_pair(PasswordAttribute::kHasLowercaseLetter, true));
form_structure->set_password_length_vote(10u);
ASSERT_EQ(form_structure->field_count(), possible_field_types.size());
@@ -2949,7 +2949,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithMultipleValidities) {
upload.set_autofill_used(false);
upload.set_data_present("144200030e");
upload.set_passwords_revealed(false);
- upload.set_password_has_numeric(true);
+ upload.set_password_has_lowercase_letter(true);
upload.set_password_length(10u);
upload.set_action_signature(15724779818122431245U);
upload.set_submission_event(
@@ -3044,7 +3044,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest) {
form_structure = std::make_unique<FormStructure>(form);
form_structure->set_password_attributes_vote(
- std::make_pair(PasswordAttribute::kHasNumeric, true));
+ std::make_pair(PasswordAttribute::kHasLowercaseLetter, true));
form_structure->set_password_length_vote(10u);
form_structure->set_submission_event(
SubmissionIndicatorEvent::HTML_FORM_SUBMISSION);
@@ -3078,7 +3078,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest) {
upload.set_autofill_used(false);
upload.set_data_present("144200030e");
upload.set_passwords_revealed(false);
- upload.set_password_has_numeric(true);
+ upload.set_password_has_lowercase_letter(true);
upload.set_password_length(10u);
upload.set_action_signature(15724779818122431245U);
upload.set_has_form_tag(true);
@@ -3130,7 +3130,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest) {
form_structure = std::make_unique<FormStructure>(form);
form_structure->set_password_attributes_vote(
- std::make_pair(PasswordAttribute::kHasNumeric, true));
+ std::make_pair(PasswordAttribute::kHasLowercaseLetter, true));
form_structure->set_password_length_vote(10u);
form_structure->set_submission_event(
SubmissionIndicatorEvent::HTML_FORM_SUBMISSION);
@@ -7123,4 +7123,19 @@ TEST_F(FormStructureTest, OneFieldPasswordFormShouldNotBeUpload) {
EXPECT_FALSE(FormStructure(form).ShouldBeUploaded());
}
+// Checks that CreateForPasswordManagerUpload builds FormStructure
+// which is encodable (i.e. ready for uploading).
+TEST_F(FormStructureTest, CreateForPasswordManagerUpload) {
+ std::unique_ptr<FormStructure> form =
+ FormStructure::CreateForPasswordManagerUpload(
+ 1234 /* form_signature */, {1, 10, 100} /* field_signatures */);
+ AutofillUploadContents upload;
+ EXPECT_EQ(1234u, form->form_signature());
+ ASSERT_EQ(3u, form->field_count());
+ ASSERT_EQ(100u, form->field(2)->GetFieldSignature());
+ EXPECT_TRUE(form->EncodeUploadRequest(
+ {} /* available_field_types */, false /* form_was_autofilled */,
+ "" /*login_form_signature*/, true /*observed_submission*/, &upload));
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/logging/log_buffer_submitter.h b/chromium/components/autofill/core/browser/logging/log_buffer_submitter.h
index 5925e842eda..ef6c411bdd0 100644
--- a/chromium/components/autofill/core/browser/logging/log_buffer_submitter.h
+++ b/chromium/components/autofill/core/browser/logging/log_buffer_submitter.h
@@ -6,7 +6,7 @@
#define COMPONENTS_AUTOFILL_CORE_BROWSER_LOGGING_LOG_BUFFER_SUBMITTER_H_
#include "base/macros.h"
-#include "components/autofill/core/browser/logging/log_buffer.h"
+#include "components/autofill/core/common/logging/log_buffer.h"
namespace autofill {
diff --git a/chromium/components/autofill/core/browser/logging/log_protobufs.h b/chromium/components/autofill/core/browser/logging/log_protobufs.h
new file mode 100644
index 00000000000..a2008a3a2fa
--- /dev/null
+++ b/chromium/components/autofill/core/browser/logging/log_protobufs.h
@@ -0,0 +1,31 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_LOGGING_LOG_PROTOBUFS_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_LOGGING_LOG_PROTOBUFS_H_
+
+#include "components/autofill/core/common/logging/log_buffer.h"
+#include "third_party/protobuf/src/google/protobuf/repeated_field.h"
+
+namespace autofill {
+
+// Serialize a repeated field in a protobuf. This function is not part of
+// log_buffer.h because that would create a dependency of the renderer process
+// to protobufs.
+template <typename T>
+LogBuffer& operator<<(LogBuffer& buf,
+ const ::google::protobuf::RepeatedField<T>& values) {
+ buf << "[";
+ for (int i = 0; i < values.size(); ++i) {
+ if (i)
+ buf << ", ";
+ buf << values.Get(i);
+ }
+ buf << "]";
+ return buf;
+}
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_LOGGING_LOG_PROTOBUFS_H_
diff --git a/chromium/components/autofill/core/browser/logging/log_router.cc b/chromium/components/autofill/core/browser/logging/log_router.cc
index 3ab3a1bfabc..f31dd7cb997 100644
--- a/chromium/components/autofill/core/browser/logging/log_router.cc
+++ b/chromium/components/autofill/core/browser/logging/log_router.cc
@@ -6,9 +6,9 @@
#include "base/stl_util.h"
#include "base/strings/string_split.h"
-#include "components/autofill/core/browser/logging/log_buffer.h"
#include "components/autofill/core/browser/logging/log_manager.h"
#include "components/autofill/core/browser/logging/log_receiver.h"
+#include "components/autofill/core/common/logging/log_buffer.h"
#include "net/base/escape.h"
namespace autofill {
diff --git a/chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc b/chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc
index b969466c133..fcd2b80680a 100644
--- a/chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc
+++ b/chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc
@@ -10,9 +10,9 @@
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "build/branding_buildflags.h"
+#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
-#include "components/autofill/core/browser/payments/legal_message_line.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_payments_features.h"
@@ -32,7 +32,7 @@ AutofillSaveCardInfoBarDelegateMobile::AutofillSaveCardInfoBarDelegateMobile(
bool upload,
AutofillClient::SaveCreditCardOptions options,
const CreditCard& card,
- std::unique_ptr<base::DictionaryValue> legal_message,
+ const LegalMessageLines& legal_message_lines,
AutofillClient::UploadSaveCardPromptCallback
upload_save_card_prompt_callback,
AutofillClient::LocalSaveCardPromptCallback local_save_card_prompt_callback,
@@ -51,22 +51,11 @@ AutofillSaveCardInfoBarDelegateMobile::AutofillSaveCardInfoBarDelegateMobile(
card_label_(card.NetworkAndLastFourDigits()),
card_sub_label_(card.AbbreviatedExpirationDateForDisplay(false)),
card_last_four_digits_(card.LastFourDigits()),
+ legal_message_lines_(legal_message_lines),
is_off_the_record_(is_off_the_record) {
DCHECK_EQ(upload, !upload_save_card_prompt_callback_.is_null());
DCHECK_EQ(upload, local_save_card_prompt_callback_.is_null());
- if (legal_message) {
- if (!LegalMessageLine::Parse(*legal_message, &legal_messages_,
- /*escape_apostrophes=*/true)) {
- AutofillMetrics::LogCreditCardInfoBarMetric(
- AutofillMetrics::INFOBAR_NOT_SHOWN_INVALID_LEGAL_MESSAGE, upload_,
- options_,
- pref_service_->GetInteger(
- prefs::kAutofillAcceptSaveCreditCardPromptState));
- return;
- }
- }
-
AutofillMetrics::LogCreditCardInfoBarMetric(
AutofillMetrics::INFOBAR_SHOWN, upload_, options_,
pref_service_->GetInteger(
@@ -86,12 +75,6 @@ void AutofillSaveCardInfoBarDelegateMobile::OnLegalMessageLinkClicked(
infobar()->owner()->OpenURL(url, WindowOpenDisposition::NEW_FOREGROUND_TAB);
}
-bool AutofillSaveCardInfoBarDelegateMobile::LegalMessagesParsedSuccessfully() {
- // If we are uploading to the server, verify that legal lines have been parsed
- // into |legal_messages_|.
- return !upload_ || !legal_messages_.empty();
-}
-
bool AutofillSaveCardInfoBarDelegateMobile::IsGooglePayBrandingEnabled() const {
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
return upload_;
@@ -136,10 +119,22 @@ AutofillSaveCardInfoBarDelegateMobile::GetIdentifier() const {
bool AutofillSaveCardInfoBarDelegateMobile::ShouldExpire(
const NavigationDetails& details) const {
+#if defined(OS_IOS)
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillSaveCardDismissOnNavigation)) {
+ // Expire the Infobar unless the navigation was triggered by the form that
+ // presented the Infobar, or the navigation is a redirect.
+ return !details.is_form_submission && !details.is_redirect;
+ } else {
+ // Use the default behavior used by Android.
+ return false;
+ }
+#else // defined(OS_IOS)
// The user has submitted a form, causing the page to navigate elsewhere. We
// don't want the infobar to be expired at this point, because the user won't
// get a chance to answer the question.
return false;
+#endif // defined(OS_IOS)
}
void AutofillSaveCardInfoBarDelegateMobile::InfoBarDismissed() {
diff --git a/chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.h b/chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.h
index bd7e72e577c..f0dcb5f84f8 100644
--- a/chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.h
+++ b/chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.h
@@ -17,10 +17,6 @@
class PrefService;
-namespace base {
-class DictionaryValue;
-}
-
namespace autofill {
class CreditCard;
@@ -33,7 +29,7 @@ class AutofillSaveCardInfoBarDelegateMobile : public ConfirmInfoBarDelegate {
bool upload,
AutofillClient::SaveCreditCardOptions options,
const CreditCard& card,
- std::unique_ptr<base::DictionaryValue> legal_message,
+ const LegalMessageLines& legal_message_lines,
AutofillClient::UploadSaveCardPromptCallback
upload_save_card_prompt_callback,
AutofillClient::LocalSaveCardPromptCallback
@@ -47,15 +43,13 @@ class AutofillSaveCardInfoBarDelegateMobile : public ConfirmInfoBarDelegate {
int issuer_icon_id() const { return issuer_icon_id_; }
const base::string16& card_label() const { return card_label_; }
const base::string16& card_sub_label() const { return card_sub_label_; }
- const LegalMessageLines& legal_messages() const { return legal_messages_; }
+ const LegalMessageLines& legal_message_lines() const {
+ return legal_message_lines_;
+ }
// Called when a link in the legal message text was clicked.
void OnLegalMessageLinkClicked(GURL url);
- // Ensures the InfoBar is not shown if legal messages failed to parse.
- // Legal messages are only specified for the upload case, not for local save.
- bool LegalMessagesParsedSuccessfully();
-
// Google Pay branding is enabled with a flag and only for cards upstreamed
// to Google.
bool IsGooglePayBrandingEnabled() const;
@@ -117,8 +111,8 @@ class AutofillSaveCardInfoBarDelegateMobile : public ConfirmInfoBarDelegate {
// The last four digits of the card for which save is being offered.
base::string16 card_last_four_digits_;
- // The legal messages to show in the content of the infobar.
- LegalMessageLines legal_messages_;
+ // The legal message lines to show in the content of the infobar.
+ const LegalMessageLines& legal_message_lines_;
// Whether the save is offered while off the record
bool is_off_the_record_;
diff --git a/chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc b/chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc
index 787a9e3428d..263b8d89025 100644
--- a/chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc
+++ b/chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc
@@ -18,10 +18,11 @@ namespace browser_sync {
AutofillWalletModelTypeController::AutofillWalletModelTypeController(
syncer::ModelType type,
- std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk,
+ std::unique_ptr<syncer::ModelTypeControllerDelegate>
+ delegate_for_full_sync_mode,
PrefService* pref_service,
syncer::SyncService* sync_service)
- : ModelTypeController(type, std::move(delegate_on_disk)),
+ : ModelTypeController(type, std::move(delegate_for_full_sync_mode)),
pref_service_(pref_service),
sync_service_(sync_service) {
DCHECK(type == syncer::AUTOFILL_WALLET_DATA ||
@@ -34,13 +35,15 @@ AutofillWalletModelTypeController::AutofillWalletModelTypeController(
AutofillWalletModelTypeController::AutofillWalletModelTypeController(
syncer::ModelType type,
- std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk,
- std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_in_memory,
+ std::unique_ptr<syncer::ModelTypeControllerDelegate>
+ delegate_for_full_sync_mode,
+ std::unique_ptr<syncer::ModelTypeControllerDelegate>
+ delegate_for_transport_mode,
PrefService* pref_service,
syncer::SyncService* sync_service)
: ModelTypeController(type,
- std::move(delegate_on_disk),
- std::move(delegate_in_memory)),
+ std::move(delegate_for_full_sync_mode),
+ std::move(delegate_for_transport_mode)),
pref_service_(pref_service),
sync_service_(sync_service) {
DCHECK(type == syncer::AUTOFILL_WALLET_DATA ||
diff --git a/chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h b/chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h
index 6cc8addad3b..03d0312c094 100644
--- a/chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h
+++ b/chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h
@@ -29,13 +29,16 @@ class AutofillWalletModelTypeController : public syncer::ModelTypeController,
// |sync_client| must outlive this object.
AutofillWalletModelTypeController(
syncer::ModelType type,
- std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk,
+ std::unique_ptr<syncer::ModelTypeControllerDelegate>
+ delegate_for_full_sync_mode,
PrefService* pref_service,
syncer::SyncService* sync_service);
AutofillWalletModelTypeController(
syncer::ModelType type,
- std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk,
- std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_in_memory,
+ std::unique_ptr<syncer::ModelTypeControllerDelegate>
+ delegate_for_full_sync_mode,
+ std::unique_ptr<syncer::ModelTypeControllerDelegate>
+ delegate_for_transport_mode,
PrefService* pref_service,
syncer::SyncService* sync_service);
~AutofillWalletModelTypeController() override;
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_access_manager.cc b/chromium/components/autofill/core/browser/payments/credit_card_access_manager.cc
index ab11f3c6a1b..196fd861e58 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_access_manager.cc
+++ b/chromium/components/autofill/core/browser/payments/credit_card_access_manager.cc
@@ -25,14 +25,20 @@
#include "components/autofill/core/browser/metrics/credit_card_form_event_logger.h"
#include "components/autofill/core/browser/payments/payments_client.h"
#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/common/autofill_clock.h"
+#include "components/autofill/core/common/autofill_tick_clock.h"
#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
+#if !defined(OS_IOS)
+#include "components/autofill/core/browser/payments/fido_authentication_strike_database.h"
+#endif
+
namespace autofill {
namespace {
// Timeout to wait for unmask details from Google Payments in milliseconds.
-constexpr int64_t kUnmaskDetailsResponseTimeout = 1000;
+constexpr int64_t kUnmaskDetailsResponseTimeoutMs = 1000;
// Time to wait between multiple calls to GetUnmaskDetails().
constexpr int64_t kDelayForGetUnmaskDetails = 3 * 60 * 1000; // 3 min
@@ -40,7 +46,7 @@ constexpr int64_t kDelayForGetUnmaskDetails = 3 * 60 * 1000; // 3 min
bool WaitForEvent(base::WaitableEvent* event) {
event->declare_only_used_while_idle();
return event->TimedWait(
- base::TimeDelta::FromMilliseconds(kUnmaskDetailsResponseTimeout));
+ base::TimeDelta::FromMilliseconds(kUnmaskDetailsResponseTimeoutMs));
}
// Used with PostTaskWithDelay() to signal event after a timeout.
@@ -71,7 +77,13 @@ CreditCardAccessManager::CreditCardAccessManager(
base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED),
can_fetch_unmask_details_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::SIGNALED) {}
+ base::WaitableEvent::InitialState::SIGNALED) {
+#if !defined(OS_IOS)
+ // This is to initialize StrikeDatabase is if it hasn't been already, so that
+ // its cache would be loaded and ready to use when the first CCAM is created.
+ client_->GetStrikeDatabase();
+#endif
+}
CreditCardAccessManager::~CreditCardAccessManager() {}
@@ -199,20 +211,28 @@ void CreditCardAccessManager::GetUnmaskDetailsIfUserIsVerifiable(
// If user is verifiable, then make preflight call to payments to fetch unmask
// details, otherwise the only option is to perform CVC Auth, which does not
// require any. Do nothing if request is already in progress.
- if (is_user_verifiable_ && !unmask_details_request_in_progress_) {
+ if (is_user_verifiable_.value_or(false) &&
+ !unmask_details_request_in_progress_) {
unmask_details_request_in_progress_ = true;
payments_client_->GetUnmaskDetails(
base::BindOnce(&CreditCardAccessManager::OnDidGetUnmaskDetails,
weak_ptr_factory_.GetWeakPtr()),
personal_data_manager_->app_locale());
+ preflight_call_timestamp_ = AutofillTickClock::NowTicks();
+ AutofillMetrics::LogCardUnmaskPreflightCalled();
}
}
void CreditCardAccessManager::OnDidGetUnmaskDetails(
AutofillClient::PaymentsRpcResult result,
AutofillClient::UnmaskDetails& unmask_details) {
+ // Log latency for preflight call.
+ AutofillMetrics::LogCardUnmaskPreflightDuration(
+ AutofillTickClock::NowTicks() - preflight_call_timestamp_);
+
unmask_details_request_in_progress_ = false;
- unmask_details_.offer_fido_opt_in = unmask_details.offer_fido_opt_in;
+ unmask_details_.offer_fido_opt_in = unmask_details.offer_fido_opt_in &&
+ !payments_client_->is_off_the_record();
unmask_details_.unmask_auth_method = unmask_details.unmask_auth_method;
unmask_details_.fido_request_options =
std::move(unmask_details.fido_request_options);
@@ -243,13 +263,28 @@ void CreditCardAccessManager::FetchCreditCard(
const CreditCard* card,
base::WeakPtr<Accessor> accessor,
const base::TimeTicks& form_parsed_timestamp) {
+ // Return error if authentication is already in progress or card is nullptr.
if (is_authentication_in_progress_ || !card) {
accessor->OnCreditCardFetched(/*did_succeed=*/false, nullptr);
return;
}
+ // Latency metrics should only be logged if the user is verifiable and the
+ // flag is turned on. If flag is turned off, then |is_user_verifiable_| is not
+ // set.
+#if !defined(OS_IOS)
+ bool should_log_latency_metrics = is_user_verifiable_.value_or(false);
+#endif
+ // Return immediately if local card and log that unmask details were ignored.
if (card->record_type() != CreditCard::MASKED_SERVER_CARD) {
accessor->OnCreditCardFetched(/*did_succeed=*/true, card);
+#if !defined(OS_IOS)
+ if (should_log_latency_metrics) {
+ AutofillMetrics::LogUserPerceivedLatencyOnCardSelection(
+ AutofillMetrics::PreflightCallEvent::kDidNotChooseMaskedCard,
+ GetOrCreateFIDOAuthenticator()->IsUserOptedIn());
+ }
+#endif
return;
}
@@ -258,7 +293,32 @@ void CreditCardAccessManager::FetchCreditCard(
form_parsed_timestamp_ = form_parsed_timestamp;
is_authentication_in_progress_ = true;
- if (AuthenticationRequiresUnmaskDetails()) {
+ bool get_unmask_details_returned =
+ ready_to_start_authentication_.IsSignaled();
+ bool user_is_opted_in = AuthenticationRequiresUnmaskDetails();
+ bool should_wait_to_authenticate =
+ user_is_opted_in && !get_unmask_details_returned;
+
+ // Logging metrics.
+#if !defined(OS_IOS)
+ if (should_log_latency_metrics) {
+ AutofillMetrics::LogUserPerceivedLatencyOnCardSelection(
+ get_unmask_details_returned
+ ? AutofillMetrics::PreflightCallEvent::
+ kPreflightCallReturnedBeforeCardChosen
+ : AutofillMetrics::PreflightCallEvent::
+ kCardChosenBeforePreflightCallReturned,
+ GetOrCreateFIDOAuthenticator()->IsUserOptedIn());
+ }
+#endif
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+ // On desktop, show the verify pending dialog for opted-in user.
+ if (user_is_opted_in)
+ ShowVerifyPendingDialog();
+#endif
+
+ if (should_wait_to_authenticate) {
// Wait for |ready_to_start_authentication_| to be signaled by
// OnDidGetUnmaskDetails() or until timeout before calling Authenticate().
base::PostTaskAndReplyWithResult(
@@ -267,37 +327,69 @@ void CreditCardAccessManager::FetchCreditCard(
base::BindOnce(&CreditCardAccessManager::Authenticate,
weak_ptr_factory_.GetWeakPtr()));
} else {
- Authenticate();
+ Authenticate(get_unmask_details_returned);
}
}
-void CreditCardAccessManager::FIDOAuthOptChange(bool opt_in,
- base::Value creation_options) {
+void CreditCardAccessManager::FIDOAuthOptChange(bool opt_in) {
#if defined(OS_IOS)
return;
#else
if (opt_in) {
- GetOrCreateFIDOAuthenticator()->Register(std::move(creation_options));
+ GetOrCreateFIDOAuthenticator()->ShowWebauthnOfferDialog(
+ /*card_authorization_token=*/std::string());
} else {
GetOrCreateFIDOAuthenticator()->OptOut();
+ GetOrCreateFIDOAuthenticator()
+ ->GetOrCreateFidoAuthenticationStrikeDatabase()
+ ->AddStrikes(
+ FidoAuthenticationStrikeDatabase::kStrikesToAddWhenUserOptsOut);
}
#endif
}
-void CreditCardAccessManager::Authenticate(bool did_get_unmask_details) {
+void CreditCardAccessManager::OnSettingsPageFIDOAuthToggled(bool opt_in) {
+#if defined(OS_IOS)
+ return;
+#else
+ // TODO(crbug/949269): Add a rate limiter to counter spam clicking.
+ FIDOAuthOptChange(opt_in);
+#endif
+}
+
+void CreditCardAccessManager::Authenticate(bool get_unmask_details_returned) {
// Reset now that we have started authentication.
ready_to_start_authentication_.Reset();
unmask_details_request_in_progress_ = false;
- // Do not use FIDO if card is not listed in unmask details, as each Card must
- // be CVC authed at least once per device.
- bool card_is_eligible_for_fido =
- did_get_unmask_details &&
- unmask_details_.unmask_auth_method ==
- AutofillClient::UnmaskAuthMethod::FIDO &&
+ bool fido_auth_suggested =
+ get_unmask_details_returned && unmask_details_.unmask_auth_method ==
+ AutofillClient::UnmaskAuthMethod::FIDO;
+
+ bool card_is_authorized_for_fido =
+ fido_auth_suggested &&
unmask_details_.fido_eligible_card_ids.find(card_->server_id()) !=
unmask_details_.fido_eligible_card_ids.end();
+ // If FIDO authentication was suggested, but card is not in authorized list,
+ // must authenticate with CVC followed by FIDO in order to authorize this card
+ // for future FIDO use.
+ should_follow_up_cvc_with_fido_auth_ =
+ fido_auth_suggested && !card_is_authorized_for_fido;
+
+ // Only use FIDO if card is authorized and not expired.
+ bool card_is_eligible_for_fido =
+ card_is_authorized_for_fido && !card_->IsExpired(AutofillClock::Now());
+
+ // If FIDO auth was suggested, logging which authentication method was
+ // actually used.
+ if (fido_auth_suggested && !card_->IsExpired(AutofillClock::Now())) {
+ AutofillMetrics::LogCardUnmaskTypeDecision(
+ card_is_eligible_for_fido
+ ? AutofillMetrics::CardUnmaskTypeDecisionMetric::kFidoOnly
+ : AutofillMetrics::CardUnmaskTypeDecisionMetric::kCvcThenFido);
+ }
+
if (card_is_eligible_for_fido) {
#if defined(OS_IOS)
NOTREACHED();
@@ -308,6 +400,11 @@ void CreditCardAccessManager::Authenticate(bool did_get_unmask_details) {
std::move(unmask_details_.fido_request_options));
#endif
} else {
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+ // Close the verify pending dialog if it enters CVC authentication flow
+ // since the card unmask prompt will pop up.
+ client_->CloseVerifyPendingDialog();
+#endif
GetOrCreateCVCAuthenticator()->Authenticate(
card_, weak_ptr_factory_.GetWeakPtr(), personal_data_manager_,
form_parsed_timestamp_);
@@ -338,23 +435,48 @@ void CreditCardAccessManager::OnCVCAuthenticationComplete(
response.cvc);
can_fetch_unmask_details_.Signal();
- if (!response.did_succeed)
+ if (!response.did_succeed || response.card_authorization_token.empty())
return;
#if defined(OS_ANDROID)
- // Now that unmask flow is complete, on Android, if GetRealPan includes
- // |creation_options|, completely hand over registration flow to
- // CreditCardFIDOAuthenticator.
+ // Opt-in was already offered at this point for Android.
+ bool should_offer_fido_auth = false;
+#elif !defined(OS_IOS)
+ bool should_offer_fido_auth =
+ unmask_details_.offer_fido_opt_in &&
+ !GetOrCreateFIDOAuthenticator()
+ ->GetOrCreateFidoAuthenticationStrikeDatabase()
+ ->IsMaxStrikesLimitReached();
+#endif
+
+#if !defined(OS_IOS)
+ // Now that unmask flow is complete and form is filled, the remaining flows
+ // will be completely handed over to CreditCardFIDOAuthenticator.
+ // If the GetRealPan response includes |creation_options| or
+ // |request_options|, that means the user showed intention to opt-in while
+ // unmasking (this can only happen on Android) and must complete the challenge
+ // before successfully opting-in. If UnmaskDetails contained
+ // |request_options|, that means the user is already opted-into FIDO auth, and
+ // this is the first time use of a new card, and must complete the challenge
+ // to successfully authorize the card. Otherwise, if on desktop and eligible,
+ // show the dialog that offers opting-in to FIDO authentication in the future.
if (response.creation_options.has_value()) {
DCHECK(response.creation_options->is_dict());
GetOrCreateFIDOAuthenticator()->Register(
- response.creation_options->Clone());
+ response.card_authorization_token, response.creation_options->Clone());
+ } else if (response.request_options.has_value()) {
+ DCHECK(response.request_options->is_dict());
+ GetOrCreateFIDOAuthenticator()->Authorize(
+ response.card_authorization_token, response.request_options->Clone());
+ } else if (should_offer_fido_auth) {
+ GetOrCreateFIDOAuthenticator()->ShowWebauthnOfferDialog(
+ response.card_authorization_token);
+ } else if (should_follow_up_cvc_with_fido_auth_) {
+ DCHECK(unmask_details_.fido_request_options.is_dict());
+ GetOrCreateFIDOAuthenticator()->Authorize(
+ response.card_authorization_token,
+ std::move(unmask_details_.fido_request_options));
}
-#elif !defined(OS_IOS)
- // CreditCardFIDOAuthenticator does not exist on iOS.
- // On desktop, prompts dialog to show the authentication offer.
- if (unmask_details_.offer_fido_opt_in)
- GetOrCreateFIDOAuthenticator()->ShowWebauthnOfferDialog();
#endif
}
@@ -362,6 +484,13 @@ void CreditCardAccessManager::OnCVCAuthenticationComplete(
void CreditCardAccessManager::OnFIDOAuthenticationComplete(
bool did_succeed,
const CreditCard* card) {
+#if !defined(OS_ANDROID)
+ // Close the verify pending dialog. If FIDO authentication succeeded, card is
+ // filled to the form, otherwise fall back to CVC authentication which does
+ // not need the verify pending dialog either.
+ client_->CloseVerifyPendingDialog();
+#endif
+
if (did_succeed) {
is_authentication_in_progress_ = false;
accessor_->OnCreditCardFetched(did_succeed, card);
@@ -376,6 +505,10 @@ void CreditCardAccessManager::OnFIDOAuthenticationComplete(
}
#endif
+bool CreditCardAccessManager::IsLocalCard(const CreditCard* card) {
+ return card && card->record_type() == CreditCard::LOCAL_CARD;
+}
+
bool CreditCardAccessManager::AuthenticationRequiresUnmaskDetails() {
#if defined(OS_IOS)
return false;
@@ -385,8 +518,18 @@ bool CreditCardAccessManager::AuthenticationRequiresUnmaskDetails() {
#endif
}
-bool CreditCardAccessManager::IsLocalCard(const CreditCard* card) {
- return card && card->record_type() == CreditCard::LOCAL_CARD;
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+void CreditCardAccessManager::ShowVerifyPendingDialog() {
+ client_->ShowVerifyPendingDialog(
+ base::BindOnce(&CreditCardAccessManager::OnDidCancelCardVerification,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void CreditCardAccessManager::OnDidCancelCardVerification() {
+ payments_client_->CancelRequest();
+ unmask_details_request_in_progress_ = false;
+ is_authentication_in_progress_ = false;
}
+#endif
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_access_manager.h b/chromium/components/autofill/core/browser/payments/credit_card_access_manager.h
index 0307279777c..7c6868a2761 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_access_manager.h
+++ b/chromium/components/autofill/core/browser/payments/credit_card_access_manager.h
@@ -91,8 +91,11 @@ class CreditCardAccessManager : public CreditCardCVCAuthenticator::Requester,
// If |opt_in| = true, opts the user into using FIDO authentication for card
// unmasking. Otherwise, opts the user out. If |creation_options| is set,
// WebAuthn registration prompt will be invoked to create a new credential.
- void FIDOAuthOptChange(bool opt_in,
- base::Value creation_options = base::Value());
+ void FIDOAuthOptChange(bool opt_in);
+
+ // Makes a call to FIDOAuthOptChange() with |opt_in|.
+ // TODO(crbug/949269): Add a rate limiter to counter spam clicking.
+ void OnSettingsPageFIDOAuthToggled(bool opt_in);
CreditCardCVCAuthenticator* GetOrCreateCVCAuthenticator();
@@ -128,10 +131,12 @@ class CreditCardAccessManager : public CreditCardCVCAuthenticator::Requester,
void OnDidGetUnmaskDetails(AutofillClient::PaymentsRpcResult result,
AutofillClient::UnmaskDetails& unmask_details);
- // Calls either CreditCardFIDOAuthenticator::Authenticate() or
- // CreditCardCVCAuthenticator::Authenticate() depending on the response
- // contained in |unmask_details_|.
- void Authenticate(bool did_get_unmask_details = false);
+ // If OnDidGetUnmaskDetails() was invoked by PaymentsClient, then
+ // |get_unmask_details_returned| should be set to true. Based on the
+ // contents of |unmask_details_|, either FIDO authentication or CVC
+ // authentication will be prompted. If |get_unmask_details_returned| is false,
+ // then only CVC authentication will be prompted.
+ void Authenticate(bool get_unmask_details_returned = false);
// CreditCardCVCAuthenticator::Requester:
void OnCVCAuthenticationComplete(
@@ -156,10 +161,25 @@ class CreditCardAccessManager : public CreditCardCVCAuthenticator::Requester,
// immediately.
bool AuthenticationRequiresUnmaskDetails();
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+ // After card verification starts, shows the verify pending dialog if WebAuthn
+ // is enabled, indicating some verification steps are in progress.
+ void ShowVerifyPendingDialog();
+
+ // The callback function invoked when the cancel button in the verify pending
+ // dialog is clicked. Will cancel the attempt to fetch unmask details.
+ void OnDidCancelCardVerification();
+#endif
+
// Is set to true only when waiting for the callback to
// OnCVCAuthenticationComplete() to be executed.
bool is_authentication_in_progress_ = false;
+ // Set to true if the card selected needs to be authenticated through CVC
+ // first, and then FIDO. This happens when a user is opted-in but has not
+ // previously authenticated this card with CVC on this device.
+ bool should_follow_up_cvc_with_fido_auth_ = false;
+
// The associated autofill driver. Weak reference.
AutofillDriver* const driver_;
@@ -178,6 +198,9 @@ class CreditCardAccessManager : public CreditCardCVCAuthenticator::Requester,
// For logging metrics. May be NULL for tests.
CreditCardFormEventLogger* form_event_logger_;
+ // Timestamp used for metrics.
+ base::TimeTicks preflight_call_timestamp_;
+
// Meant for histograms recorded in FullCardRequest.
base::TimeTicks form_parsed_timestamp_;
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc b/chromium/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
index f45ea4e58c5..c149dee68a7 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
@@ -69,6 +69,7 @@
#include "url/gurl.h"
#if !defined(OS_IOS)
+#include "components/autofill/core/browser/payments/fido_authentication_strike_database.h"
#include "components/autofill/core/browser/payments/test_credit_card_fido_authenticator.h"
#endif
@@ -126,13 +127,13 @@ class TestAccessor : public CreditCardAccessManager::Accessor {
std::string NextYear() {
base::Time::Exploded now;
- base::Time::Now().LocalExplode(&now);
+ AutofillClock::Now().LocalExplode(&now);
return base::NumberToString(now.year + 1);
}
std::string NextMonth() {
base::Time::Exploded now;
- base::Time::Now().LocalExplode(&now);
+ AutofillClock::Now().LocalExplode(&now);
return base::NumberToString(now.month % 12 + 1);
}
@@ -165,6 +166,8 @@ class CreditCardAccessManagerTest : public testing::Test {
autofill_client_.GetIdentityManager(), &personal_data_manager_);
autofill_client_.set_test_payments_client(
std::unique_ptr<payments::TestPaymentsClient>(payments_client_));
+ autofill_client_.set_test_strike_database(
+ std::make_unique<TestStrikeDatabase>());
credit_card_access_manager_ = std::make_unique<CreditCardAccessManager>(
autofill_driver_.get(), &autofill_client_, &personal_data_manager_,
nullptr);
@@ -188,6 +191,15 @@ class CreditCardAccessManagerTest : public testing::Test {
return credit_card_access_manager_->is_authentication_in_progress();
}
+ void ResetFetchCreditCard() {
+ // Resets all variables related to credit card fetching.
+ credit_card_access_manager_->is_authentication_in_progress_ = false;
+ credit_card_access_manager_->can_fetch_unmask_details_.Signal();
+ credit_card_access_manager_->is_user_verifiable_ = base::nullopt;
+ }
+
+ void ClearCards() { personal_data_manager_.ClearCreditCards(); }
+
void CreateLocalCard(std::string guid, std::string number = std::string()) {
CreditCard local_card = CreditCard();
test::SetCreditCardInfo(&local_card, "Elvis Presley", number.c_str(),
@@ -195,7 +207,6 @@ class CreditCardAccessManagerTest : public testing::Test {
local_card.set_guid(guid);
local_card.set_record_type(CreditCard::LOCAL_CARD);
- personal_data_manager_.ClearCreditCards();
personal_data_manager_.AddCreditCard(local_card);
}
@@ -207,7 +218,6 @@ class CreditCardAccessManagerTest : public testing::Test {
masked_server_card.set_guid(guid);
masked_server_card.set_record_type(CreditCard::MASKED_SERVER_CARD);
- personal_data_manager_.ClearCreditCards();
personal_data_manager_.AddServerCreditCard(masked_server_card);
}
@@ -218,22 +228,27 @@ class CreditCardAccessManagerTest : public testing::Test {
// Returns true if full card request was sent from CVC auth.
bool GetRealPanForCVCAuth(AutofillClient::PaymentsRpcResult result,
const std::string& real_pan,
- bool fido_opt_in = false) {
+ bool fido_opt_in = false,
+ bool follow_with_fido_auth = false) {
payments::FullCardRequest* full_card_request =
GetCVCAuthenticator()->full_card_request_.get();
if (!full_card_request)
return false;
+ // Mock user response.
+ payments::FullCardRequest::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ full_card_request->OnUnmaskPromptAccepted(details);
+
payments::PaymentsClient::UnmaskResponseDetails response;
#if !defined(OS_IOS)
+ response.card_authorization_token = "dummy_card_authorization_token";
if (fido_opt_in) {
- response.fido_creation_options =
- base::Value(base::Value::Type::DICTIONARY);
- response.fido_creation_options->SetKey("relying_party_id",
- base::Value(kGooglePaymentsRpid));
- response.fido_creation_options->SetKey("challenge",
- base::Value(kTestChallenge));
+ response.fido_creation_options = GetTestCreationOptions();
+ }
+ if (follow_with_fido_auth) {
+ response.fido_request_options = GetTestRequestOptions();
}
#endif
full_card_request->OnDidGetRealPan(result,
@@ -242,7 +257,43 @@ class CreditCardAccessManagerTest : public testing::Test {
}
#if !defined(OS_IOS)
+ void ClearStrikes() {
+ return GetFIDOAuthenticator()
+ ->GetOrCreateFidoAuthenticationStrikeDatabase()
+ ->ClearAllStrikes();
+ }
+
+ int GetStrikes() {
+ return GetFIDOAuthenticator()
+ ->GetOrCreateFidoAuthenticationStrikeDatabase()
+ ->GetStrikes();
+ }
+
+ base::Value GetTestRequestOptions() {
+ base::Value request_options = base::Value(base::Value::Type::DICTIONARY);
+ request_options.SetKey("challenge", base::Value(kTestChallenge));
+ request_options.SetKey("relying_party_id",
+ base::Value(kGooglePaymentsRpid));
+
+ base::Value key_info(base::Value::Type::DICTIONARY);
+ key_info.SetKey("credential_id", base::Value(kCredentialId));
+ request_options.SetKey("key_info", base::Value(base::Value::Type::LIST));
+ request_options.FindKeyOfType("key_info", base::Value::Type::LIST)
+ ->GetList()
+ .push_back(std::move(key_info));
+ return request_options;
+ }
+
+ base::Value GetTestCreationOptions() {
+ base::Value creation_options = base::Value(base::Value::Type::DICTIONARY);
+ creation_options.SetKey("challenge", base::Value(kTestChallenge));
+ creation_options.SetKey("relying_party_id",
+ base::Value(kGooglePaymentsRpid));
+ return creation_options;
+ }
+
void SetUserOptedIn(bool user_is_opted_in) {
+ scoped_feature_list_.Reset();
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillCreditCardAuthentication);
::autofill::prefs::SetCreditCardFIDOAuthEnabled(autofill_client_.GetPrefs(),
@@ -267,9 +318,22 @@ class CreditCardAccessManagerTest : public testing::Test {
// Mocks an OptChange response from Payments Client.
void OptChange(AutofillClient::PaymentsRpcResult result,
bool user_is_opted_in,
- base::Value creation_options = base::Value()) {
- GetFIDOAuthenticator()->OnDidGetOptChangeResult(
- result, user_is_opted_in, std::move(creation_options));
+ bool include_creation_options = false,
+ bool include_request_options = false) {
+ payments::PaymentsClient::OptChangeResponseDetails response;
+ response.user_is_opted_in = user_is_opted_in;
+ if (include_creation_options) {
+ response.fido_creation_options = GetTestCreationOptions();
+ }
+ if (include_request_options) {
+ response.fido_request_options = GetTestRequestOptions();
+ }
+ GetFIDOAuthenticator()->OnDidGetOptChangeResult(result, response);
+ }
+
+ // Mocks user response for the offer dialog.
+ void AcceptWebauthnOfferDialog(bool did_accept) {
+ GetFIDOAuthenticator()->OnWebauthnOfferDialogUserResponse(did_accept);
}
TestCreditCardFIDOAuthenticator* GetFIDOAuthenticator() {
@@ -456,10 +520,87 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardCVCTryAgainFailure) {
EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
}
+// Ensures that CardUnmaskPreflightCalled metrics are logged correctly.
+TEST_F(CreditCardAccessManagerTest, CardUnmaskPreflightCalledMetric) {
+ std::string preflight_call_metric =
+ "Autofill.BetterAuth.CardUnmaskPreflightCalled";
+ std::string preflight_latency_metric =
+ "Autofill.BetterAuth.CardUnmaskPreflightDuration";
+
+ {
+ // Create local card and set user as eligible for FIDO auth.
+ base::HistogramTester histogram_tester;
+ ClearCards();
+ CreateLocalCard(kTestGUID, kTestNumber);
+#if !defined(OS_IOS)
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+#endif
+ ResetFetchCreditCard();
+
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ InvokeUnmaskDetailsTimeout();
+ WaitForCallbacks();
+
+ // If only local cards are available, then no preflight call is made.
+ histogram_tester.ExpectTotalCount(preflight_call_metric, 0);
+ histogram_tester.ExpectTotalCount(preflight_latency_metric, 0);
+ }
+
+ {
+ // Create server card and set user as ineligible for FIDO auth.
+ base::HistogramTester histogram_tester;
+ ClearCards();
+ CreateServerCard(kTestGUID, kTestNumber);
+#if !defined(OS_IOS)
+ GetFIDOAuthenticator()->SetUserVerifiable(false);
+#endif
+ ResetFetchCreditCard();
+
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ InvokeUnmaskDetailsTimeout();
+ WaitForCallbacks();
+
+ // If user is not verifiable, then no preflight call is made.
+ histogram_tester.ExpectTotalCount(preflight_call_metric, 0);
+ histogram_tester.ExpectTotalCount(preflight_latency_metric, 0);
+ }
+
+ {
+ // Create server card and set user as eligible for FIDO auth.
+ base::HistogramTester histogram_tester;
+ ClearCards();
+ CreateServerCard(kTestGUID, kTestNumber);
+#if !defined(OS_IOS)
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+#endif
+ ResetFetchCreditCard();
+
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ InvokeUnmaskDetailsTimeout();
+ WaitForCallbacks();
+
+ // Preflight call is made only if a server card is available and the user is
+ // eligible for FIDO authentication, except on iOS.
+#if defined(OS_IOS)
+ histogram_tester.ExpectTotalCount(preflight_call_metric, 0);
+ histogram_tester.ExpectTotalCount(preflight_latency_metric, 0);
+#else
+ histogram_tester.ExpectTotalCount(preflight_call_metric, 1);
+ histogram_tester.ExpectTotalCount(preflight_latency_metric, 1);
+#endif
+ }
+}
+
#if !defined(OS_IOS)
// Ensures that FetchCreditCard() returns the full PAN upon a successful
// WebAuthn verification and response from payments.
TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOSuccess) {
+ base::HistogramTester histogram_tester;
+ std::string unmask_decision_histogram_name =
+ "Autofill.BetterAuth.CardUnmaskTypeDecision";
+ std::string webauthn_result_histogram_name =
+ "Autofill.BetterAuth.WebauthnResult.ImmediateAuthentication";
+
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
@@ -484,10 +625,26 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOSuccess) {
EXPECT_EQ(kCredentialId,
BytesToBase64(GetFIDOAuthenticator()->GetCredentialId()));
EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
+
+ histogram_tester.ExpectUniqueSample(
+ unmask_decision_histogram_name,
+ AutofillMetrics::CardUnmaskTypeDecisionMetric::kFidoOnly, 1);
+ histogram_tester.ExpectUniqueSample(
+ webauthn_result_histogram_name,
+ AutofillMetrics::WebauthnResultMetric::kSuccess, 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.BetterAuth.CardUnmaskDuration.Fido", 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.BetterAuth.CardUnmaskDuration.Fido.Success", 1);
}
// Ensures that CVC prompt is invoked after WebAuthn fails.
-TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOFailureCVCFallback) {
+TEST_F(CreditCardAccessManagerTest,
+ FetchServerCardFIDOVerificationFailureCVCFallback) {
+ base::HistogramTester histogram_tester;
+ std::string histogram_name =
+ "Autofill.BetterAuth.WebauthnResult.ImmediateAuthentication";
+
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
@@ -515,6 +672,55 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOFailureCVCFallback) {
EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber));
EXPECT_TRUE(accessor_->did_succeed());
EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
+
+ histogram_tester.ExpectUniqueSample(
+ histogram_name, AutofillMetrics::WebauthnResultMetric::kNotAllowedError,
+ 1);
+}
+
+// Ensures that CVC prompt is invoked after payments returns an error from
+// GetRealPan via FIDO.
+TEST_F(CreditCardAccessManagerTest,
+ FetchServerCardFIDOServerFailureCVCFallback) {
+ base::HistogramTester histogram_tester;
+ std::string histogram_name =
+ "Autofill.BetterAuth.WebauthnResult.ImmediateAuthentication";
+
+ CreateServerCard(kTestGUID, kTestNumber);
+ CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+ SetUserOptedIn(true);
+ payments_client_->AddFidoEligibleCard(card->server_id(), kCredentialId,
+ kGooglePaymentsRpid);
+
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ WaitForCallbacks();
+
+ credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
+ WaitForCallbacks();
+
+ // FIDO Failure.
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::AUTHENTICATION_FLOW,
+ GetFIDOAuthenticator()->current_flow());
+ TestCreditCardFIDOAuthenticator::GetAssertion(GetFIDOAuthenticator(),
+ /*did_succeed=*/true);
+ EXPECT_TRUE(
+ GetRealPanForFIDOAuth(AutofillClient::PERMANENT_FAILURE, kTestNumber));
+ EXPECT_FALSE(accessor_->did_succeed());
+
+ // Followed by a fallback to CVC.
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::NONE_FLOW,
+ GetFIDOAuthenticator()->current_flow());
+ EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber));
+ EXPECT_TRUE(accessor_->did_succeed());
+ EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
+
+ histogram_tester.ExpectUniqueSample(
+ histogram_name, AutofillMetrics::WebauthnResultMetric::kSuccess, 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.BetterAuth.CardUnmaskDuration.Fido", 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.BetterAuth.CardUnmaskDuration.Fido.Failure", 1);
}
// Ensures WebAuthn call is not made if Request Options is missing a Credential
@@ -561,14 +767,161 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOTimeoutCVCFallback) {
EXPECT_TRUE(accessor_->did_succeed());
EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
}
-#endif
-// TODO(crbug.com/991037): Add tests for desktop separately after the
-// WebauthnOfferDelegate functions are implemented since the flows are different
-// on desktop and Android.
+// Ensures that FetchCreditCard() returns the full PAN upon a successful
+// WebAuthn verification and response from payments.
+TEST_F(CreditCardAccessManagerTest,
+ Metrics_LoggingExistenceOfUserPerceivedLatency) {
+ // Setting up a FIDO-enabled user with a local card and a server card.
+ std::string server_guid = "00000000-0000-0000-0000-000000000001";
+ std::string local_guid = "00000000-0000-0000-0000-000000000003";
+ CreateServerCard(server_guid, "4594299181086168");
+ CreateLocalCard(local_guid, "4409763681177079");
+ CreditCard* server_card =
+ credit_card_access_manager_->GetCreditCard(server_guid);
+ CreditCard* local_card =
+ credit_card_access_manager_->GetCreditCard(local_guid);
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+
+ for (bool user_is_opted_in : {true, false}) {
+ std::string histogram_name =
+ "Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection.";
+ histogram_name += user_is_opted_in ? "OptedIn" : "OptedOut";
+ SetUserOptedIn(user_is_opted_in);
+
+ {
+ // Preflight call ignored because local card was chosen.
+ base::HistogramTester histogram_tester;
+
+ ResetFetchCreditCard();
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ WaitForCallbacks();
+
+ credit_card_access_manager_->FetchCreditCard(local_card,
+ accessor_->GetWeakPtr());
+ WaitForCallbacks();
+
+ histogram_tester.ExpectUniqueSample(
+ histogram_name,
+ AutofillMetrics::PreflightCallEvent::kDidNotChooseMaskedCard, 1);
+ }
+
+ {
+ // Preflight call returned after card was chosen.
+ base::HistogramTester histogram_tester;
+ payments_client_->ShouldReturnUnmaskDetailsImmediately(false);
+
+ ResetFetchCreditCard();
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ credit_card_access_manager_->FetchCreditCard(server_card,
+ accessor_->GetWeakPtr());
+ WaitForCallbacks();
+
+ histogram_tester.ExpectUniqueSample(
+ histogram_name,
+ AutofillMetrics::PreflightCallEvent::
+ kCardChosenBeforePreflightCallReturned,
+ 1);
+ }
+
+ {
+ // Preflight call returned before card was chosen.
+ base::HistogramTester histogram_tester;
+ // This is important because CreditCardFIDOAuthenticator will update the
+ // opted-in pref according to GetDetailsForGetRealPan response.
+ payments_client_->AllowFidoRegistration(!user_is_opted_in);
+
+ ResetFetchCreditCard();
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ WaitForCallbacks();
+
+ credit_card_access_manager_->FetchCreditCard(server_card,
+ accessor_->GetWeakPtr());
+ WaitForCallbacks();
+
+ histogram_tester.ExpectUniqueSample(
+ histogram_name,
+ AutofillMetrics::PreflightCallEvent::
+ kPreflightCallReturnedBeforeCardChosen,
+ 1);
+ }
+ }
+}
+
+// Ensures that use of new card invokes authorization flow when user is
+// opted-in.
+TEST_F(CreditCardAccessManagerTest, FIDONewCardAuthorization) {
+ base::HistogramTester histogram_tester;
+ std::string unmask_decision_histogram_name =
+ "Autofill.BetterAuth.CardUnmaskTypeDecision";
+ std::string webauthn_result_histogram_name =
+ "Autofill.BetterAuth.WebauthnResult.AuthenticationAfterCVC";
+
+ CreateServerCard(kTestGUID, kTestNumber);
+ CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
+ // Opt the user in, but don't include the card above.
+ std::string other_server_id = "00000000-0000-0000-0000-000000000034";
+ payments_client_->AddFidoEligibleCard(other_server_id, kCredentialId,
+ kGooglePaymentsRpid);
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+ SetUserOptedIn(true);
+
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ WaitForCallbacks();
+
+ credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
+ InvokeUnmaskDetailsTimeout();
+ WaitForCallbacks();
+
+ EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber,
+ /*fido_opt_in=*/false,
+ /*follow_with_fido_auth=*/true));
+
+ // Mock user response and OptChange payments call.
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::FOLLOWUP_AFTER_CVC_AUTH_FLOW,
+ GetFIDOAuthenticator()->current_flow());
+ TestCreditCardFIDOAuthenticator::GetAssertion(GetFIDOAuthenticator(),
+ /*did_succeed=*/true);
+ OptChange(AutofillClient::SUCCESS, true);
+
+ histogram_tester.ExpectUniqueSample(
+ unmask_decision_histogram_name,
+ AutofillMetrics::CardUnmaskTypeDecisionMetric::kCvcThenFido, 1);
+ histogram_tester.ExpectUniqueSample(
+ webauthn_result_histogram_name,
+ AutofillMetrics::WebauthnResultMetric::kSuccess, 1);
+}
+
+// Ensures expired cards always invoke a CVC prompt instead of WebAuthn.
+TEST_F(CreditCardAccessManagerTest, FetchExpiredServerCardInvokesCvcPrompt) {
+ // Creating an expired server card and opting the user in with authorized
+ // card.
+ CreateServerCard(kTestGUID, kTestNumber);
+ CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
+ card->SetExpirationYearFromString(base::UTF8ToUTF16("2010"));
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+ SetUserOptedIn(true);
+ payments_client_->AddFidoEligibleCard(card->server_id(), kCredentialId,
+ kGooglePaymentsRpid);
+
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ WaitForCallbacks();
+
+ credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
+ WaitForCallbacks();
+
+ // Expect CVC prompt to be invoked.
+ EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber));
+ EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
+}
+
#if defined(OS_ANDROID)
// Ensures that the WebAuthn enrollment prompt is invoked after user opts in.
-TEST_F(CreditCardAccessManagerTest, FIDOEnrollmentSuccess) {
+TEST_F(CreditCardAccessManagerTest, FIDOEnrollmentSuccess_Android) {
+ base::HistogramTester histogram_tester;
+ std::string histogram_name =
+ "Autofill.BetterAuth.WebauthnResult.CheckoutOptIn";
+
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
@@ -593,10 +946,17 @@ TEST_F(CreditCardAccessManagerTest, FIDOEnrollmentSuccess) {
EXPECT_EQ(kTestChallenge,
BytesToBase64(GetFIDOAuthenticator()->GetChallenge()));
EXPECT_TRUE(GetFIDOAuthenticator()->IsUserOptedIn());
+
+ histogram_tester.ExpectUniqueSample(
+ histogram_name, AutofillMetrics::WebauthnResultMetric::kSuccess, 1);
}
// Ensures that the failed user verification disallows enrollment.
TEST_F(CreditCardAccessManagerTest, FIDOEnrollmentUserVerificationFailure) {
+ base::HistogramTester histogram_tester;
+ std::string histogram_name =
+ "Autofill.BetterAuth.WebauthnResult.CheckoutOptIn";
+
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
@@ -614,6 +974,10 @@ TEST_F(CreditCardAccessManagerTest, FIDOEnrollmentUserVerificationFailure) {
/*did_succeed=*/false);
EXPECT_FALSE(GetFIDOAuthenticator()->IsUserOptedIn());
+
+ histogram_tester.ExpectUniqueSample(
+ histogram_name, AutofillMetrics::WebauthnResultMetric::kNotAllowedError,
+ 1);
}
// Ensures that enrollment does not happen if the server returns a failure.
@@ -637,7 +1001,304 @@ TEST_F(CreditCardAccessManagerTest, FIDOEnrollmentServerFailure) {
EXPECT_FALSE(GetFIDOAuthenticator()->IsUserOptedIn());
}
-#endif
+
+#else // defined(OS_ANDROID)
+// Ensures that the WebAuthn enrollment prompt is invoked after user opts in. In
+// this case, the user is not yet enrolled server-side, and thus receives
+// |creation_options|.
+TEST_F(CreditCardAccessManagerTest,
+ FIDOEnrollmentSuccess_CreationOptions_Desktop) {
+ base::HistogramTester histogram_tester;
+ std::string webauthn_result_histogram_name =
+ "Autofill.BetterAuth.WebauthnResult.CheckoutOptIn";
+ std::string opt_in_histogram_name =
+ "Autofill.BetterAuth.OptInCalled.FromCheckoutFlow";
+ std::string promo_shown_histogram_name =
+ "Autofill.BetterAuth.OptInPromoShown.FromCheckoutFlow";
+ std::string promo_user_decision_histogram_name =
+ "Autofill.BetterAuth.OptInPromoUserDecision.FromCheckoutFlow";
+
+ ClearStrikes();
+ CreateServerCard(kTestGUID, kTestNumber);
+ CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+ SetUserOptedIn(false);
+ payments_client_->AllowFidoRegistration(true);
+
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
+ WaitForCallbacks();
+
+ // Mock user and payments response.
+ EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber,
+ /*fido_opt_in=*/false));
+ AcceptWebauthnOfferDialog(/*did_accept=*/true);
+
+ OptChange(AutofillClient::SUCCESS, /*user_is_opted_in=*/false,
+ /*include_creation_options=*/true);
+
+ // Mock user response and OptChange payments call.
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_WITH_CHALLENGE_FLOW,
+ GetFIDOAuthenticator()->current_flow());
+ TestCreditCardFIDOAuthenticator::MakeCredential(GetFIDOAuthenticator(),
+ /*did_succeed=*/true);
+ OptChange(AutofillClient::SUCCESS, /*user_is_opted_in=*/true);
+
+ EXPECT_EQ(kGooglePaymentsRpid, GetFIDOAuthenticator()->GetRelyingPartyId());
+ EXPECT_EQ(kTestChallenge,
+ BytesToBase64(GetFIDOAuthenticator()->GetChallenge()));
+ EXPECT_TRUE(GetFIDOAuthenticator()->IsUserOptedIn());
+ EXPECT_EQ(0, GetStrikes());
+ histogram_tester.ExpectUniqueSample(
+ webauthn_result_histogram_name,
+ AutofillMetrics::WebauthnResultMetric::kSuccess, 1);
+ histogram_tester.ExpectTotalCount(opt_in_histogram_name, 2);
+ histogram_tester.ExpectBucketCount(
+ opt_in_histogram_name,
+ AutofillMetrics::WebauthnOptInParameters::kFetchingChallenge, 1);
+ histogram_tester.ExpectBucketCount(
+ opt_in_histogram_name,
+ AutofillMetrics::WebauthnOptInParameters::kWithCreationChallenge, 1);
+ histogram_tester.ExpectTotalCount(promo_shown_histogram_name, 1);
+ histogram_tester.ExpectUniqueSample(
+ promo_user_decision_histogram_name,
+ AutofillMetrics::WebauthnOptInPromoUserDecisionMetric::kAccepted, 1);
+}
+
+// Ensures that the correct number of strikes are added when the user declines
+// the WebAuthn offer.
+TEST_F(CreditCardAccessManagerTest, FIDOEnrollment_OfferDeclined_Desktop) {
+ base::HistogramTester histogram_tester;
+ std::string promo_shown_histogram_name =
+ "Autofill.BetterAuth.OptInPromoShown.FromCheckoutFlow";
+ std::string promo_user_decision_histogram_name =
+ "Autofill.BetterAuth.OptInPromoUserDecision.FromCheckoutFlow";
+
+ ClearStrikes();
+ CreateServerCard(kTestGUID, kTestNumber);
+ CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+ SetUserOptedIn(false);
+ payments_client_->AllowFidoRegistration(true);
+
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
+ WaitForCallbacks();
+
+ // Mock user and payments response.
+ EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber,
+ /*fido_opt_in=*/false));
+ AcceptWebauthnOfferDialog(/*did_accept=*/false);
+ EXPECT_EQ(
+ FidoAuthenticationStrikeDatabase::kStrikesToAddWhenOptInOfferDeclined,
+ GetStrikes());
+ histogram_tester.ExpectTotalCount(promo_shown_histogram_name, 1);
+ histogram_tester.ExpectUniqueSample(
+ promo_user_decision_histogram_name,
+ AutofillMetrics::WebauthnOptInPromoUserDecisionMetric::
+ kDeclinedImmediately,
+ 1);
+}
+
+// Ensures that the correct number of strikes are added when the user declines
+// the WebAuthn offer.
+TEST_F(CreditCardAccessManagerTest,
+ FIDOEnrollment_OfferDeclinedAfterAccepting_Desktop) {
+ base::HistogramTester histogram_tester;
+ std::string promo_shown_histogram_name =
+ "Autofill.BetterAuth.OptInPromoShown.FromCheckoutFlow";
+ std::string promo_user_decision_histogram_name =
+ "Autofill.BetterAuth.OptInPromoUserDecision.FromCheckoutFlow";
+
+ ClearStrikes();
+ CreateServerCard(kTestGUID, kTestNumber);
+ CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+ SetUserOptedIn(false);
+ payments_client_->AllowFidoRegistration(true);
+
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
+ WaitForCallbacks();
+
+ // Mock user and payments response.
+ EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber,
+ /*fido_opt_in=*/false));
+ AcceptWebauthnOfferDialog(/*did_accept=*/true);
+ AcceptWebauthnOfferDialog(/*did_accept=*/false);
+ EXPECT_EQ(
+ FidoAuthenticationStrikeDatabase::kStrikesToAddWhenOptInOfferDeclined,
+ GetStrikes());
+ histogram_tester.ExpectTotalCount(promo_shown_histogram_name, 1);
+ histogram_tester.ExpectUniqueSample(
+ promo_user_decision_histogram_name,
+ AutofillMetrics::WebauthnOptInPromoUserDecisionMetric::
+ kDeclinedAfterAccepting,
+ 1);
+}
+
+// Ensures that the correct number of strikes are added when the user fails to
+// complete user-verification for an opt-in attempt.
+TEST_F(CreditCardAccessManagerTest,
+ FIDOEnrollment_UserVerificationFailed_Desktop) {
+ base::HistogramTester histogram_tester;
+ std::string webauthn_result_histogram_name =
+ "Autofill.BetterAuth.WebauthnResult.CheckoutOptIn";
+ std::string opt_in_histogram_name =
+ "Autofill.BetterAuth.OptInCalled.FromCheckoutFlow";
+
+ ClearStrikes();
+ CreateServerCard(kTestGUID, kTestNumber);
+ CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+ SetUserOptedIn(false);
+ payments_client_->AllowFidoRegistration(true);
+
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
+ InvokeUnmaskDetailsTimeout();
+ WaitForCallbacks();
+
+ // Mock user and payments response.
+ EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber,
+ /*fido_opt_in=*/false));
+ WaitForCallbacks();
+ AcceptWebauthnOfferDialog(/*did_accept=*/true);
+
+ OptChange(AutofillClient::SUCCESS, /*user_is_opted_in=*/false,
+ /*include_creation_options=*/true);
+
+ // Mock user response.
+ TestCreditCardFIDOAuthenticator::MakeCredential(GetFIDOAuthenticator(),
+ /*did_succeed=*/false);
+ EXPECT_EQ(FidoAuthenticationStrikeDatabase::
+ kStrikesToAddWhenUserVerificationFailsOnOptInAttempt,
+ GetStrikes());
+ histogram_tester.ExpectUniqueSample(
+ webauthn_result_histogram_name,
+ AutofillMetrics::WebauthnResultMetric::kNotAllowedError, 1);
+ histogram_tester.ExpectUniqueSample(
+ opt_in_histogram_name,
+ AutofillMetrics::WebauthnOptInParameters::kFetchingChallenge, 1);
+}
+
+// Ensures that the WebAuthn enrollment prompt is invoked after user opts in. In
+// this case, the user is already enrolled server-side, and thus receives
+// |request_options|.
+TEST_F(CreditCardAccessManagerTest,
+ FIDOEnrollmentSuccess_RequestOptions_Desktop) {
+ base::HistogramTester histogram_tester;
+ std::string webauthn_result_histogram_name =
+ "Autofill.BetterAuth.WebauthnResult.CheckoutOptIn";
+ std::string opt_in_histogram_name =
+ "Autofill.BetterAuth.OptInCalled.FromCheckoutFlow";
+
+ CreateServerCard(kTestGUID, kTestNumber);
+ CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+ SetUserOptedIn(false);
+ payments_client_->AllowFidoRegistration(true);
+
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
+ WaitForCallbacks();
+
+ // Mock user and payments response.
+ EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber,
+ /*fido_opt_in=*/false));
+ WaitForCallbacks();
+ AcceptWebauthnOfferDialog(/*did_accept=*/true);
+
+ OptChange(AutofillClient::SUCCESS, /*user_is_opted_in=*/false,
+ /*include_creation_options=*/false,
+ /*include_request_options=*/true);
+
+ // Mock user response and OptChange payments call.
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_WITH_CHALLENGE_FLOW,
+ GetFIDOAuthenticator()->current_flow());
+ TestCreditCardFIDOAuthenticator::GetAssertion(GetFIDOAuthenticator(),
+ /*did_succeed=*/true);
+ OptChange(AutofillClient::SUCCESS, /*user_is_opted_in=*/true);
+
+ EXPECT_EQ(kGooglePaymentsRpid, GetFIDOAuthenticator()->GetRelyingPartyId());
+ EXPECT_EQ(kTestChallenge,
+ BytesToBase64(GetFIDOAuthenticator()->GetChallenge()));
+ EXPECT_TRUE(GetFIDOAuthenticator()->IsUserOptedIn());
+
+ histogram_tester.ExpectUniqueSample(
+ webauthn_result_histogram_name,
+ AutofillMetrics::WebauthnResultMetric::kSuccess, 1);
+ histogram_tester.ExpectTotalCount(opt_in_histogram_name, 2);
+ histogram_tester.ExpectBucketCount(
+ opt_in_histogram_name,
+ AutofillMetrics::WebauthnOptInParameters::kFetchingChallenge, 1);
+ histogram_tester.ExpectBucketCount(
+ opt_in_histogram_name,
+ AutofillMetrics::WebauthnOptInParameters::kWithRequestChallenge, 1);
+}
+
+// Ensures WebAuthn result is logged correctly for a settings page opt-in.
+TEST_F(CreditCardAccessManagerTest, SettingsPage_FIDOEnrollment) {
+ base::HistogramTester histogram_tester;
+ std::string webauthn_histogram_name =
+ "Autofill.BetterAuth.WebauthnResult.SettingsPageOptIn";
+ std::string opt_in_histogram_name =
+ "Autofill.BetterAuth.OptInCalled.FromSettingsPage";
+ std::string promo_shown_histogram_name =
+ "Autofill.BetterAuth.OptInPromoShown.FromSettingsPage";
+ std::string promo_user_decision_histogram_name =
+ "Autofill.BetterAuth.OptInPromoUserDecision.FromSettingsPage";
+
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+
+ for (bool did_succeed : {false, true}) {
+ SetUserOptedIn(false);
+ credit_card_access_manager_->OnSettingsPageFIDOAuthToggled(true);
+
+ // Mock user and payments response.
+ AcceptWebauthnOfferDialog(/*did_accept=*/true);
+ OptChange(AutofillClient::SUCCESS, /*user_is_opted_in=*/false,
+ /*include_creation_options=*/true);
+ // Mock user response and payments response.
+ TestCreditCardFIDOAuthenticator::MakeCredential(GetFIDOAuthenticator(),
+ did_succeed);
+
+ histogram_tester.ExpectBucketCount(
+ webauthn_histogram_name,
+ did_succeed ? AutofillMetrics::WebauthnResultMetric::kSuccess
+ : AutofillMetrics::WebauthnResultMetric::kNotAllowedError,
+ 1);
+ }
+
+ histogram_tester.ExpectTotalCount(webauthn_histogram_name, 2);
+ histogram_tester.ExpectTotalCount(opt_in_histogram_name, 3);
+ histogram_tester.ExpectBucketCount(
+ opt_in_histogram_name,
+ AutofillMetrics::WebauthnOptInParameters::kFetchingChallenge, 2);
+ histogram_tester.ExpectBucketCount(
+ opt_in_histogram_name,
+ AutofillMetrics::WebauthnOptInParameters::kWithCreationChallenge, 1);
+ histogram_tester.ExpectTotalCount(promo_shown_histogram_name, 2);
+ histogram_tester.ExpectUniqueSample(
+ promo_user_decision_histogram_name,
+ AutofillMetrics::WebauthnOptInPromoUserDecisionMetric::kAccepted, 2);
+}
+
+// Ensure proper metrics are logged when user opts-out from settings page.
+TEST_F(CreditCardAccessManagerTest, SettingsPage_OptOut) {
+ base::HistogramTester histogram_tester;
+ std::string histogram_name =
+ "Autofill.BetterAuth.OptOutCalled.FromSettingsPage";
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+ SetUserOptedIn(false);
+
+ credit_card_access_manager_->OnSettingsPageFIDOAuthToggled(false);
+ OptChange(AutofillClient::SUCCESS, /*user_is_opted_in=*/false);
+
+ histogram_tester.ExpectTotalCount(histogram_name, 1);
+}
+#endif // defined(OS_ANDROID)
+#endif // !defined(OS_IOS)
// Ensures that |is_authentication_in_progress_| is set correctly.
TEST_F(CreditCardAccessManagerTest, AuthenticationInProgress) {
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.cc b/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.cc
index 7a021d8d032..d8f1cb1c685 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.cc
+++ b/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.cc
@@ -41,14 +41,16 @@ void CreditCardCVCAuthenticator::OnFullCardRequestSucceeded(
const payments::FullCardRequest& full_card_request,
const CreditCard& card,
const base::string16& cvc) {
+ payments::PaymentsClient::UnmaskResponseDetails response =
+ full_card_request.unmask_response_details();
requester_->OnCVCAuthenticationComplete(
CVCAuthenticationResponse()
.with_did_succeed(true)
.with_card(&card)
.with_cvc(cvc)
- .with_creation_options(
- std::move(full_card_request.unmask_response_details()
- .fido_creation_options)));
+ .with_creation_options(std::move(response.fido_creation_options))
+ .with_request_options(std::move(response.fido_request_options))
+ .with_card_authorization_token(response.card_authorization_token));
}
void CreditCardCVCAuthenticator::OnFullCardRequestFailed() {
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h b/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h
index 05ad5b7f02e..a470eb83e10 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h
+++ b/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h
@@ -42,10 +42,21 @@ class CreditCardCVCAuthenticator
creation_options = std::move(v);
return *this;
}
+ CVCAuthenticationResponse& with_request_options(
+ base::Optional<base::Value> v) {
+ request_options = std::move(v);
+ return *this;
+ }
+ CVCAuthenticationResponse& with_card_authorization_token(std::string s) {
+ card_authorization_token = s;
+ return *this;
+ }
bool did_succeed = false;
const CreditCard* card = nullptr;
base::string16 cvc = base::string16();
base::Optional<base::Value> creation_options = base::nullopt;
+ base::Optional<base::Value> request_options = base::nullopt;
+ std::string card_authorization_token = std::string();
};
class Requester {
public:
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc b/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc
index 58a13a370b8..d036800e783 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc
@@ -51,6 +51,7 @@
#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_switches.h"
+#include "components/autofill/core/common/autofill_tick_clock.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/prefs/pref_service.h"
#include "components/security_state/core/security_state.h"
@@ -75,13 +76,13 @@ const char kTestNumber[] = "4234567890123456"; // Visa
std::string NextYear() {
base::Time::Exploded now;
- base::Time::Now().LocalExplode(&now);
+ AutofillClock::Now().LocalExplode(&now);
return base::NumberToString(now.year + 1);
}
std::string NextMonth() {
base::Time::Exploded now;
- base::Time::Now().LocalExplode(&now);
+ AutofillClock::Now().LocalExplode(&now);
return base::NumberToString(now.month % 12 + 1);
}
@@ -144,6 +145,13 @@ class CreditCardCVCAuthenticatorTest : public testing::Test {
payments::FullCardRequest* full_card_request =
cvc_authenticator_->full_card_request_.get();
DCHECK(full_card_request);
+
+ // Mock user response.
+ payments::FullCardRequest::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ full_card_request->OnUnmaskPromptAccepted(details);
+
+ // Mock payments response.
payments::PaymentsClient::UnmaskResponseDetails response;
full_card_request->OnDidGetRealPan(result,
response.with_real_pan(real_pan));
@@ -165,7 +173,7 @@ TEST_F(CreditCardCVCAuthenticatorTest, AuthenticateServerCardSuccess) {
cvc_authenticator_->Authenticate(&card, requester_->GetWeakPtr(),
&personal_data_manager_,
- base::TimeTicks::Now());
+ AutofillTickClock::NowTicks());
OnDidGetRealPan(AutofillClient::SUCCESS, kTestNumber);
EXPECT_TRUE(requester_->did_succeed());
@@ -177,7 +185,7 @@ TEST_F(CreditCardCVCAuthenticatorTest, AuthenticateServerCardNetworkError) {
cvc_authenticator_->Authenticate(&card, requester_->GetWeakPtr(),
&personal_data_manager_,
- base::TimeTicks::Now());
+ AutofillTickClock::NowTicks());
OnDidGetRealPan(AutofillClient::NETWORK_ERROR, std::string());
EXPECT_FALSE(requester_->did_succeed());
@@ -188,7 +196,7 @@ TEST_F(CreditCardCVCAuthenticatorTest, AuthenticateServerCardPermanentFailure) {
cvc_authenticator_->Authenticate(&card, requester_->GetWeakPtr(),
&personal_data_manager_,
- base::TimeTicks::Now());
+ AutofillTickClock::NowTicks());
OnDidGetRealPan(AutofillClient::PERMANENT_FAILURE, std::string());
EXPECT_FALSE(requester_->did_succeed());
@@ -199,7 +207,7 @@ TEST_F(CreditCardCVCAuthenticatorTest, AuthenticateServerCardTryAgainFailure) {
cvc_authenticator_->Authenticate(&card, requester_->GetWeakPtr(),
&personal_data_manager_,
- base::TimeTicks::Now());
+ AutofillTickClock::NowTicks());
OnDidGetRealPan(AutofillClient::TRY_AGAIN_FAILURE, std::string());
EXPECT_FALSE(requester_->did_succeed());
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc b/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc
index e6c15670b42..6cb340e60d9 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc
+++ b/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc
@@ -12,8 +12,11 @@
#include "base/containers/flat_set.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
+#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_client.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/payments/fido_authentication_strike_database.h"
#include "components/autofill/core/browser/payments/payments_client.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/common/autofill_payments_features.h"
@@ -28,8 +31,6 @@ namespace autofill {
namespace {
// Default timeout for user to respond to WebAuthn prompt.
constexpr int kWebAuthnTimeoutMs = 3 * 60 * 1000; // 3 minutes
-// Timeout to wait for synchronous version of IsUserVerifiable().
-constexpr int kIsUserVerifiableTimeoutMs = 1000;
constexpr char kGooglePaymentsRpid[] = "google.com";
constexpr char kGooglePaymentsRpName[] = "Google Payments";
@@ -60,10 +61,14 @@ CreditCardFIDOAuthenticator::CreditCardFIDOAuthenticator(AutofillDriver* driver,
CreditCardFIDOAuthenticator::~CreditCardFIDOAuthenticator() {}
-void CreditCardFIDOAuthenticator::ShowWebauthnOfferDialog() {
+void CreditCardFIDOAuthenticator::ShowWebauthnOfferDialog(
+ std::string card_authorization_token) {
+ card_authorization_token_ = card_authorization_token;
autofill_client_->ShowWebauthnOfferDialog(base::BindRepeating(
&CreditCardFIDOAuthenticator::OnWebauthnOfferDialogUserResponse,
weak_ptr_factory_.GetWeakPtr()));
+ AutofillMetrics::LogWebauthnOptInPromoShown(
+ /*is_checkout_flow=*/!card_authorization_token_.empty());
}
void CreditCardFIDOAuthenticator::Authenticate(
@@ -83,31 +88,50 @@ void CreditCardFIDOAuthenticator::Authenticate(
}
}
-void CreditCardFIDOAuthenticator::Register(base::Value creation_options) {
+void CreditCardFIDOAuthenticator::Register(std::string card_authorization_token,
+ base::Value creation_options) {
// If |creation_options| is set, then must enroll a new credential. Otherwise
// directly send request to payments for opting in.
+ card_authorization_token_ = card_authorization_token;
if (creation_options.is_dict()) {
if (IsValidCreationOptions(creation_options)) {
current_flow_ = OPT_IN_WITH_CHALLENGE_FLOW;
MakeCredential(ParseCreationOptions(creation_options));
}
} else {
- current_flow_ = OPT_IN_WITHOUT_CHALLENGE_FLOW;
- OptChange(/*opt_in=*/true);
+ current_flow_ = OPT_IN_FETCH_CHALLENGE_FLOW;
+ OptChange();
+ }
+}
+
+void CreditCardFIDOAuthenticator::Authorize(
+ std::string card_authorization_token,
+ base::Value request_options) {
+ card_authorization_token_ = card_authorization_token;
+ if (IsValidRequestOptions(request_options)) {
+ // If user is already opted-in, then a new card is trying to be
+ // authorized. Otherwise, a user with a credential on file is trying to
+ // opt-in.
+ current_flow_ = IsUserOptedIn() ? FOLLOWUP_AFTER_CVC_AUTH_FLOW
+ : OPT_IN_WITH_CHALLENGE_FLOW;
+ GetAssertion(ParseRequestOptions(std::move(request_options)));
}
}
void CreditCardFIDOAuthenticator::OptOut() {
current_flow_ = OPT_OUT_FLOW;
- OptChange(/*opt_in=*/false);
+ card_authorization_token_ = std::string();
+ OptChange();
}
void CreditCardFIDOAuthenticator::IsUserVerifiable(
base::OnceCallback<void(bool)> callback) {
if (base::FeatureList::IsEnabled(
features::kAutofillCreditCardAuthentication)) {
- autofill_driver_->ConnectToAuthenticator(
- authenticator_.BindNewPipeAndPassReceiver());
+ if (!authenticator_.is_bound()) {
+ autofill_driver_->ConnectToAuthenticator(
+ authenticator_.BindNewPipeAndPassReceiver());
+ }
authenticator_->IsUserVerifyingPlatformAuthenticatorAvailable(
std::move(callback));
} else {
@@ -115,21 +139,6 @@ void CreditCardFIDOAuthenticator::IsUserVerifiable(
}
}
-bool CreditCardFIDOAuthenticator::IsUserVerifiable() {
- if (user_is_verifiable_.has_value())
- return user_is_verifiable_.value();
-
- IsUserVerifiable(
- base::BindOnce(&CreditCardFIDOAuthenticator::SetUserIsVerifiable,
- weak_ptr_factory_.GetWeakPtr()));
-
- user_is_verifiable_callback_received_.declare_only_used_while_idle();
- user_is_verifiable_callback_received_.TimedWait(
- base::TimeDelta::FromMilliseconds(kIsUserVerifiableTimeoutMs));
-
- return user_is_verifiable_.value_or(false);
-}
-
bool CreditCardFIDOAuthenticator::IsUserOptedIn() {
return base::FeatureList::IsEnabled(
features::kAutofillCreditCardAuthentication) &&
@@ -157,10 +166,41 @@ void CreditCardFIDOAuthenticator::SyncUserOptIn(
is_user_opted_in);
}
+FidoAuthenticationStrikeDatabase*
+CreditCardFIDOAuthenticator::GetOrCreateFidoAuthenticationStrikeDatabase() {
+ if (!fido_authentication_strike_database_) {
+ fido_authentication_strike_database_ =
+ std::make_unique<FidoAuthenticationStrikeDatabase>(
+ FidoAuthenticationStrikeDatabase(
+ autofill_client_->GetStrikeDatabase()));
+ }
+ return fido_authentication_strike_database_.get();
+}
+
void CreditCardFIDOAuthenticator::GetAssertion(
PublicKeyCredentialRequestOptionsPtr request_options) {
- autofill_driver_->ConnectToAuthenticator(
- authenticator_.BindNewPipeAndPassReceiver());
+ if (!authenticator_.is_bound()) {
+ autofill_driver_->ConnectToAuthenticator(
+ authenticator_.BindNewPipeAndPassReceiver());
+ }
+#if !defined(OS_ANDROID)
+ // On desktop, during an opt-in flow, close the WebAuthn offer dialog and get
+ // ready to show the OS level authentication dialog. If dialog is already
+ // closed, then the offer was declined during the fetching challenge process,
+ // and thus returned early.
+ if (current_flow_ == OPT_IN_WITH_CHALLENGE_FLOW) {
+ if (autofill_client_->CloseWebauthnOfferDialog()) {
+ // Now that the dialog has closed and will proceed to a WebAuthn prompt,
+ // the user must have accepted the dialog without cancelling.
+ AutofillMetrics::LogWebauthnOptInPromoUserDecision(
+ /*is_checkout_flow=*/!card_authorization_token_.empty(),
+ AutofillMetrics::WebauthnOptInPromoUserDecisionMetric::kAccepted);
+ } else {
+ current_flow_ = NONE_FLOW;
+ return;
+ }
+ }
+#endif
authenticator_->GetAssertion(
std::move(request_options),
base::BindOnce(&CreditCardFIDOAuthenticator::OnDidGetAssertion,
@@ -169,92 +209,222 @@ void CreditCardFIDOAuthenticator::GetAssertion(
void CreditCardFIDOAuthenticator::MakeCredential(
PublicKeyCredentialCreationOptionsPtr creation_options) {
- autofill_driver_->ConnectToAuthenticator(
- authenticator_.BindNewPipeAndPassReceiver());
+ if (!authenticator_.is_bound()) {
+ autofill_driver_->ConnectToAuthenticator(
+ authenticator_.BindNewPipeAndPassReceiver());
+ }
+#if !defined(OS_ANDROID)
+ // On desktop, close the WebAuthn offer dialog and get ready to show the OS
+ // level authentication dialog. If dialog is already closed, then the offer
+ // was declined during the fetching challenge process, and thus returned
+ // early.
+ if (autofill_client_->CloseWebauthnOfferDialog()) {
+ // Now that the dialog has closed and will proceed to a WebAuthn prompt,
+ // the user must have accepted the dialog without cancelling.
+ AutofillMetrics::LogWebauthnOptInPromoUserDecision(
+ /*is_checkout_flow=*/!card_authorization_token_.empty(),
+ AutofillMetrics::WebauthnOptInPromoUserDecisionMetric::kAccepted);
+ } else {
+ current_flow_ = NONE_FLOW;
+ return;
+ }
+#endif
authenticator_->MakeCredential(
std::move(creation_options),
base::BindOnce(&CreditCardFIDOAuthenticator::OnDidMakeCredential,
weak_ptr_factory_.GetWeakPtr()));
}
-void CreditCardFIDOAuthenticator::OptChange(bool opt_in,
- base::Value attestation_response) {
+void CreditCardFIDOAuthenticator::OptChange(
+ base::Value authenticator_response) {
payments::PaymentsClient::OptChangeRequestDetails request_details;
request_details.app_locale =
autofill_client_->GetPersonalDataManager()->app_locale();
- request_details.opt_in = opt_in;
- if (attestation_response.is_dict()) {
+
+ switch (current_flow_) {
+ case OPT_IN_WITH_CHALLENGE_FLOW:
+ case OPT_IN_FETCH_CHALLENGE_FLOW:
+ request_details.reason =
+ payments::PaymentsClient::OptChangeRequestDetails::ENABLE_FIDO_AUTH;
+ break;
+ case OPT_OUT_FLOW:
+ request_details.reason =
+ payments::PaymentsClient::OptChangeRequestDetails::DISABLE_FIDO_AUTH;
+ break;
+ case FOLLOWUP_AFTER_CVC_AUTH_FLOW:
+ request_details.reason = payments::PaymentsClient::
+ OptChangeRequestDetails::ADD_CARD_FOR_FIDO_AUTH;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ // If |authenticator_response| is set, that means the user just signed a
+ // challenge. In which case, if |card_authorization_token_| is not empty, then
+ // that will be required to bind a previous CVC check with this signature.
+ // This will opt the user in and authorize the card corresponding to
+ // |card_authorization_token_|.
+ // If |authenticator_response| is not set, that means the user was fetching a
+ // challenge, in which case |card_authorization_token_| will be required for
+ // the subsequent OptChange call.
+ AutofillMetrics::WebauthnOptInParameters opt_change_metric;
+ bool is_checkout_flow = !card_authorization_token_.empty();
+ if (authenticator_response.is_dict()) {
request_details.fido_authenticator_response =
- std::move(attestation_response);
+ std::move(authenticator_response);
+ opt_change_metric =
+ request_details.fido_authenticator_response.FindKey(
+ "fido_assertion_info")
+ ? AutofillMetrics::WebauthnOptInParameters::kWithRequestChallenge
+ : AutofillMetrics::WebauthnOptInParameters::kWithCreationChallenge;
+ if (!card_authorization_token_.empty()) {
+ request_details.card_authorization_token = card_authorization_token_;
+ card_authorization_token_ = std::string();
+ }
+ } else {
+ opt_change_metric =
+ AutofillMetrics::WebauthnOptInParameters::kFetchingChallenge;
}
payments_client_->OptChange(
request_details,
base::BindOnce(&CreditCardFIDOAuthenticator::OnDidGetOptChangeResult,
weak_ptr_factory_.GetWeakPtr()));
+
+ // Logging call if user was attempting to change their opt-in state.
+ if (current_flow_ != FOLLOWUP_AFTER_CVC_AUTH_FLOW) {
+ bool request_to_opt_in = (current_flow_ != OPT_OUT_FLOW);
+ AutofillMetrics::LogWebauthnOptChangeCalled(
+ request_to_opt_in, is_checkout_flow, opt_change_metric);
+ }
}
void CreditCardFIDOAuthenticator::OnDidGetAssertion(
AuthenticatorStatus status,
GetAssertionAuthenticatorResponsePtr assertion_response) {
+ LogWebauthnResult(status);
+
// End the flow if there was an authentication error.
if (status != AuthenticatorStatus::SUCCESS) {
+ // Report failure to |requester_| if card unmasking was requested.
+ if (current_flow_ == AUTHENTICATION_FLOW)
+ requester_->OnFIDOAuthenticationComplete(/*did_succeed=*/false);
+
+ // Treat failure to perform user verification as a strong signal not to
+ // offer opt-in in the future.
+ if (current_flow_ == OPT_IN_WITH_CHALLENGE_FLOW) {
+ GetOrCreateFidoAuthenticationStrikeDatabase()->AddStrikes(
+ FidoAuthenticationStrikeDatabase::
+ kStrikesToAddWhenUserVerificationFailsOnOptInAttempt);
+ }
+
current_flow_ = NONE_FLOW;
- requester_->OnFIDOAuthenticationComplete(/*did_succeed=*/false);
return;
}
- base::Value response = ParseAssertionResponse(std::move(assertion_response));
- full_card_request_.reset(new payments::FullCardRequest(
- autofill_client_, autofill_client_->GetPaymentsClient(),
- autofill_client_->GetPersonalDataManager(), form_parsed_timestamp_));
- full_card_request_->GetFullCardViaFIDO(
- *card_, AutofillClient::UNMASK_FOR_AUTOFILL,
- weak_ptr_factory_.GetWeakPtr(), std::move(response));
+ if (current_flow_ == AUTHENTICATION_FLOW) {
+ base::Value response =
+ ParseAssertionResponse(std::move(assertion_response));
+ full_card_request_.reset(new payments::FullCardRequest(
+ autofill_client_, autofill_client_->GetPaymentsClient(),
+ autofill_client_->GetPersonalDataManager(), form_parsed_timestamp_));
+ full_card_request_->GetFullCardViaFIDO(
+ *card_, AutofillClient::UNMASK_FOR_AUTOFILL,
+ weak_ptr_factory_.GetWeakPtr(), std::move(response));
+ } else {
+ DCHECK(current_flow_ == FOLLOWUP_AFTER_CVC_AUTH_FLOW ||
+ current_flow_ == OPT_IN_WITH_CHALLENGE_FLOW);
+ base::Value response = base::Value(base::Value::Type::DICTIONARY);
+ response.SetKey("fido_assertion_info",
+ ParseAssertionResponse(std::move(assertion_response)));
+ OptChange(std::move(response));
+ }
}
void CreditCardFIDOAuthenticator::OnDidMakeCredential(
AuthenticatorStatus status,
MakeCredentialAuthenticatorResponsePtr attestation_response) {
+ LogWebauthnResult(status);
+
// End the flow if there was an authentication error.
if (status != AuthenticatorStatus::SUCCESS) {
+ // Treat failure to perform user verification as a strong signal not to
+ // offer opt-in in the future.
+ if (current_flow_ == OPT_IN_WITH_CHALLENGE_FLOW) {
+ GetOrCreateFidoAuthenticationStrikeDatabase()->AddStrikes(
+ FidoAuthenticationStrikeDatabase::
+ kStrikesToAddWhenUserVerificationFailsOnOptInAttempt);
+ }
+
current_flow_ = NONE_FLOW;
return;
}
- OptChange(/*opt_in=*/true,
- ParseAttestationResponse(std::move(attestation_response)));
+ OptChange(ParseAttestationResponse(std::move(attestation_response)));
}
void CreditCardFIDOAuthenticator::OnDidGetOptChangeResult(
AutofillClient::PaymentsRpcResult result,
- bool user_is_opted_in,
- base::Value creation_options) {
- DCHECK(current_flow_ == OPT_IN_WITHOUT_CHALLENGE_FLOW ||
+ payments::PaymentsClient::OptChangeResponseDetails& response) {
+ DCHECK(current_flow_ == OPT_IN_FETCH_CHALLENGE_FLOW ||
current_flow_ == OPT_OUT_FLOW ||
- current_flow_ == OPT_IN_WITH_CHALLENGE_FLOW);
+ current_flow_ == OPT_IN_WITH_CHALLENGE_FLOW ||
+ current_flow_ == FOLLOWUP_AFTER_CVC_AUTH_FLOW);
+
+ // Update user preference to keep in sync with server.
+ ::autofill::prefs::SetCreditCardFIDOAuthEnabled(
+ autofill_client_->GetPrefs(),
+ response.user_is_opted_in.value_or(IsUserOptedIn()));
+
// End the flow if the server responded with an error.
if (result != AutofillClient::PaymentsRpcResult::SUCCESS) {
+ if (current_flow_ == OPT_IN_FETCH_CHALLENGE_FLOW)
+ autofill_client_->UpdateWebauthnOfferDialogWithError();
current_flow_ = NONE_FLOW;
return;
}
- // If response contains |creation_options| and the last opt-in attempt did not
- // include a challenge, then invoke WebAuthn registration prompt. Otherwise,
- // set pref to enable FIDO Authentication for card unmask and end the flow.
- if (creation_options.is_dict() &&
- current_flow_ == OPT_IN_WITHOUT_CHALLENGE_FLOW) {
- Register(std::move(creation_options));
+ // If response contains |creation_options| or |request_options| and the last
+ // opt-in attempt did not include a challenge, then invoke WebAuthn
+ // registration/verification prompt. Otherwise end the flow.
+ if (current_flow_ == OPT_IN_FETCH_CHALLENGE_FLOW) {
+ if (response.fido_creation_options.has_value()) {
+ Register(card_authorization_token_,
+ std::move(response.fido_creation_options.value()));
+ } else if (response.fido_request_options.has_value()) {
+ Authorize(card_authorization_token_,
+ std::move(response.fido_request_options.value()));
+ }
} else {
- ::autofill::prefs::SetCreditCardFIDOAuthEnabled(
- autofill_client_->GetPrefs(), user_is_opted_in);
current_flow_ = NONE_FLOW;
}
}
void CreditCardFIDOAuthenticator::OnWebauthnOfferDialogUserResponse(
bool did_accept) {
- // TODO(crbug.com/): Register and start fetching authentication challenge if
- // |did_accept|, otherwise cancel any ongoing request.
+ if (did_accept) {
+ // Wait until GetAssertion()/MakeCredential() to log user acceptance, since
+ // user still has the option to cancel the dialog while the challenge is
+ // being fetched.
+ Register(card_authorization_token_);
+ } else {
+ // If user declined, log user decision. User may have initially accepted the
+ // dialog, but then chose to cancel while the challenge was being fetched.
+ AutofillMetrics::LogWebauthnOptInPromoUserDecision(
+ /*is_checkout_flow=*/!card_authorization_token_.empty(),
+ current_flow_ == OPT_IN_FETCH_CHALLENGE_FLOW
+ ? AutofillMetrics::WebauthnOptInPromoUserDecisionMetric::
+ kDeclinedAfterAccepting
+ : AutofillMetrics::WebauthnOptInPromoUserDecisionMetric::
+ kDeclinedImmediately);
+ payments_client_->CancelRequest();
+ card_authorization_token_ = std::string();
+ current_flow_ = NONE_FLOW;
+ GetOrCreateFidoAuthenticationStrikeDatabase()->AddStrikes(
+ FidoAuthenticationStrikeDatabase::kStrikesToAddWhenOptInOfferDeclined);
+ ::autofill::prefs::SetCreditCardFIDOAuthEnabled(
+ autofill_client_->GetPrefs(), false);
+ }
}
void CreditCardFIDOAuthenticator::OnFullCardRequestSucceeded(
@@ -356,6 +526,23 @@ CreditCardFIDOAuthenticator::ParseCreationOptions(
options->adjusted_timeout = base::TimeDelta::FromMilliseconds(
timeout ? timeout->GetInt() : kWebAuthnTimeoutMs);
+ const auto* attestation =
+ creation_options.FindStringKey("attestation_conveyance_preference");
+ if (!attestation || base::EqualsCaseInsensitiveASCII(*attestation, "NONE")) {
+ options->attestation = AttestationConveyancePreference::kNone;
+ } else if (base::EqualsCaseInsensitiveASCII(*attestation, "INDIRECT")) {
+ options->attestation = AttestationConveyancePreference::kIndirect;
+ } else if (base::EqualsCaseInsensitiveASCII(*attestation, "DIRECT")) {
+ options->attestation = AttestationConveyancePreference::kDirect;
+ } else {
+ NOTREACHED();
+ }
+
+ // Only allow user-verifying platform authenticators.
+ options->authenticator_selection = AuthenticatorSelectionCriteria(
+ AuthenticatorAttachment::kPlatform, /*require_resident_key=*/false,
+ UserVerificationRequirement::kRequired);
+
// List of keys that Payments already knows about, and so should not make a
// new credential.
const auto* excluded_keys_list =
@@ -398,7 +585,8 @@ CreditCardFIDOAuthenticator::ParseCredentialDescriptor(
base::Value CreditCardFIDOAuthenticator::ParseAssertionResponse(
GetAssertionAuthenticatorResponsePtr assertion_response) {
base::Value response = base::Value(base::Value::Type::DICTIONARY);
- response.SetKey("credential_id", base::Value(assertion_response->info->id));
+ response.SetKey("credential_id",
+ BytesToBase64(assertion_response->info->raw_id));
response.SetKey("authenticator_data",
BytesToBase64(assertion_response->authenticator_data));
response.SetKey("client_data",
@@ -423,7 +611,7 @@ base::Value CreditCardFIDOAuthenticator::ParseAttestationResponse(
base::Value authenticator_transport_list =
base::Value(base::Value::Type::LIST);
for (FidoTransportProtocol protocol : attestation_response->transports) {
- authenticator_transport_list.GetList().push_back(
+ authenticator_transport_list.Append(
base::Value(base::ToUpperASCII(device::ToString(protocol))));
}
@@ -462,9 +650,38 @@ bool CreditCardFIDOAuthenticator::IsValidCreationOptions(
creation_options.FindStringKey("challenge");
}
-void CreditCardFIDOAuthenticator::SetUserIsVerifiable(bool user_is_verifiable) {
- user_is_verifiable_ = user_is_verifiable;
- user_is_verifiable_callback_received_.Signal();
-}
+void CreditCardFIDOAuthenticator::LogWebauthnResult(
+ AuthenticatorStatus status) {
+ AutofillMetrics::WebauthnFlowEvent event;
+ switch (current_flow_) {
+ case AUTHENTICATION_FLOW:
+ event = AutofillMetrics::WebauthnFlowEvent::kImmediateAuthentication;
+ break;
+ case FOLLOWUP_AFTER_CVC_AUTH_FLOW:
+ event = AutofillMetrics::WebauthnFlowEvent::kAuthenticationAfterCvc;
+ break;
+ case OPT_IN_WITH_CHALLENGE_FLOW:
+ event = card_authorization_token_.empty()
+ ? AutofillMetrics::WebauthnFlowEvent::kSettingsPageOptIn
+ : AutofillMetrics::WebauthnFlowEvent::kCheckoutOptIn;
+ break;
+ default:
+ NOTREACHED();
+ return;
+ }
+ AutofillMetrics::WebauthnResultMetric metric;
+ switch (status) {
+ case AuthenticatorStatus::SUCCESS:
+ metric = AutofillMetrics::WebauthnResultMetric::kSuccess;
+ break;
+ case AuthenticatorStatus::NOT_ALLOWED_ERROR:
+ metric = AutofillMetrics::WebauthnResultMetric::kNotAllowedError;
+ break;
+ default:
+ metric = AutofillMetrics::WebauthnResultMetric::kOtherError;
+ break;
+ }
+ AutofillMetrics::LogWebauthnResult(event, metric);
+}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.h b/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.h
index 01aef853526..e7d89ad1950 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.h
+++ b/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.h
@@ -11,6 +11,7 @@
#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/autofill_driver.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/payments/fido_authentication_strike_database.h"
#include "components/autofill/core/browser/payments/full_card_request.h"
#include "components/autofill/core/browser/payments/payments_client.h"
#include "device/fido/fido_constants.h"
@@ -29,6 +30,9 @@ using blink::mojom::PublicKeyCredentialCreationOptions;
using blink::mojom::PublicKeyCredentialCreationOptionsPtr;
using blink::mojom::PublicKeyCredentialRequestOptions;
using blink::mojom::PublicKeyCredentialRequestOptionsPtr;
+using device::AttestationConveyancePreference;
+using device::AuthenticatorAttachment;
+using device::AuthenticatorSelectionCriteria;
using device::CredentialType;
using device::FidoTransportProtocol;
using device::PublicKeyCredentialDescriptor;
@@ -53,9 +57,11 @@ class CreditCardFIDOAuthenticator
// Registration flow, including a challenge to sign.
OPT_IN_WITH_CHALLENGE_FLOW,
// Opt-in attempt flow, no challenge to sign.
- OPT_IN_WITHOUT_CHALLENGE_FLOW,
+ OPT_IN_FETCH_CHALLENGE_FLOW,
// Opt-out flow.
OPT_OUT_FLOW,
+ // Authorization of a new card.
+ FOLLOWUP_AFTER_CVC_AUTH_FLOW,
};
class Requester {
public:
@@ -68,16 +74,25 @@ class CreditCardFIDOAuthenticator
~CreditCardFIDOAuthenticator() override;
// Offer the option to use WebAuthn for authenticating future card unmasking.
- void ShowWebauthnOfferDialog();
+ void ShowWebauthnOfferDialog(std::string card_authorization_token);
- // Authentication
+ // Invokes Authentication flow. Responds to |accessor_| with full pan.
void Authenticate(const CreditCard* card,
base::WeakPtr<Requester> requester,
base::TimeTicks form_parsed_timestamp,
base::Value request_options);
- // Registration
- void Register(base::Value creation_options = base::Value());
+ // Invokes Registration flow. Sends credentials created from
+ // |creation_options| along with the |card_authorization_token| to Payments in
+ // order to enroll the user and authorize the corresponding card.
+ void Register(std::string card_authorization_token = std::string(),
+ base::Value creation_options = base::Value());
+
+ // Invokes an Authorization flow. Sends signature created from
+ // |request_options| along with the |card_authorization_token| to Payments in
+ // order to authorize the corresponding card.
+ void Authorize(std::string card_authorization_token,
+ base::Value request_options);
// Opts the user out.
void OptOut();
@@ -87,15 +102,16 @@ class CreditCardFIDOAuthenticator
// and enabled. Otherwise invokes callback with false.
virtual void IsUserVerifiable(base::OnceCallback<void(bool)> callback);
- // The synchronous version of IsUserVerifiable. Used on settings page load.
- bool IsUserVerifiable();
-
// Returns true only if the user has opted-in to use WebAuthn for autofill.
virtual bool IsUserOptedIn();
// Ensures that local user opt-in pref is in-sync with payments server.
void SyncUserOptIn(AutofillClient::UnmaskDetails& unmask_details);
+ // Retrieves the strike database for offering FIDO authentication.
+ FidoAuthenticationStrikeDatabase*
+ GetOrCreateFidoAuthenticationStrikeDatabase();
+
// Returns the current flow.
Flow current_flow() { return current_flow_; }
@@ -124,7 +140,7 @@ class CreditCardFIDOAuthenticator
PublicKeyCredentialCreationOptionsPtr creation_options);
// Makes a request to payments to either opt-in or opt-out the user.
- void OptChange(bool opt_in, base::Value attestation_response = base::Value());
+ void OptChange(base::Value authenticator_response = base::Value());
// The callback invoked from the WebAuthn prompt including the
// |assertion_response|, which will be sent to Google Payments to retrieve
@@ -141,9 +157,9 @@ class CreditCardFIDOAuthenticator
MakeCredentialAuthenticatorResponsePtr attestation_response);
// Sets prefstore to enable credit card authentication if rpc was successful.
- void OnDidGetOptChangeResult(AutofillClient::PaymentsRpcResult result,
- bool user_is_opted_in,
- base::Value creation_options = base::Value());
+ void OnDidGetOptChangeResult(
+ AutofillClient::PaymentsRpcResult result,
+ payments::PaymentsClient::OptChangeResponseDetails& response);
// The callback invoked from the WebAuthn offer dialog when it is accepted or
// declined/cancelled.
@@ -184,8 +200,8 @@ class CreditCardFIDOAuthenticator
// Returns true if |request_options| contains a challenge.
bool IsValidCreationOptions(const base::Value& creation_options);
- // Sets the value for |user_is_verifiable_|.
- void SetUserIsVerifiable(bool user_is_verifiable);
+ // Logs the result of a WebAuthn prompt.
+ void LogWebauthnResult(AuthenticatorStatus status);
// Card being unmasked.
const CreditCard* card_;
@@ -193,6 +209,10 @@ class CreditCardFIDOAuthenticator
// The current flow in progress.
Flow current_flow_ = NONE_FLOW;
+ // Token used for authorizing new cards. Helps tie CVC auth and FIDO calls
+ // together in order to support FIDO-only unmasking on future attempts.
+ std::string card_authorization_token_;
+
// Meant for histograms recorded in FullCardRequest.
base::TimeTicks form_parsed_timestamp_;
@@ -215,8 +235,10 @@ class CreditCardFIDOAuthenticator
// Weak pointer to object that is requesting authentication.
base::WeakPtr<Requester> requester_;
- // Set when callback for IsUserVerifiable() is invoked with passed value.
- base::Optional<bool> user_is_verifiable_ = base::nullopt;
+ // Strike database to ensure we limit the number of times we offer fido
+ // authentication.
+ std::unique_ptr<FidoAuthenticationStrikeDatabase>
+ fido_authentication_strike_database_;
// Signaled when callback for IsUserVerifiable() is invoked.
base::WaitableEvent user_is_verifiable_callback_received_;
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc b/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc
index 3ec70dc08e8..1146593947d 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc
@@ -53,6 +53,7 @@
#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_switches.h"
+#include "components/autofill/core/common/autofill_tick_clock.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/prefs/pref_service.h"
#include "components/security_state/core/security_state.h"
@@ -85,10 +86,11 @@ constexpr char kTestChallenge[] = "VGhpcyBpcyBhIHRlc3QgY2hhbGxlbmdl";
const char kTestCredentialId[] = "VGhpcyBpcyBhIHRlc3QgQ3JlZGVudGlhbCBJRC4=";
// Base64 encoding of "This is a test signature".
const char kTestSignature[] = "VGhpcyBpcyBhIHRlc3Qgc2lnbmF0dXJl";
+const char kTestAuthToken[] = "dummy_card_authorization_token";
std::string NextMonth() {
base::Time::Exploded now;
- base::Time::Now().LocalExplode(&now);
+ AutofillClock::Now().LocalExplode(&now);
return base::NumberToString(now.month % 12 + 1);
}
@@ -133,6 +135,8 @@ class CreditCardFIDOAuthenticatorTest : public testing::Test {
autofill_client_.GetIdentityManager(), &personal_data_manager_);
autofill_client_.set_test_payments_client(
std::unique_ptr<payments::TestPaymentsClient>(payments_client));
+ autofill_client_.set_test_strike_database(
+ std::make_unique<TestStrikeDatabase>());
fido_authenticator_ = std::make_unique<CreditCardFIDOAuthenticator>(
autofill_driver_.get(), &autofill_client_);
}
@@ -218,9 +222,19 @@ class CreditCardFIDOAuthenticatorTest : public testing::Test {
// Mocks an OptChange response from Payments Client.
void OptChange(AutofillClient::PaymentsRpcResult result,
bool user_is_opted_in,
- base::Value creation_options = base::Value()) {
- fido_authenticator_->OnDidGetOptChangeResult(result, user_is_opted_in,
- std::move(creation_options));
+ bool include_creation_options = false,
+ bool include_request_options = false) {
+ payments::PaymentsClient::OptChangeResponseDetails response;
+ response.user_is_opted_in = user_is_opted_in;
+ if (include_creation_options) {
+ response.fido_creation_options =
+ GetTestCreationOptions(kTestChallenge, kTestRelyingPartyId);
+ }
+ if (include_request_options) {
+ response.fido_request_options = GetTestRequestOptions(
+ kTestChallenge, kTestRelyingPartyId, kTestCredentialId);
+ }
+ fido_authenticator_->OnDidGetOptChangeResult(result, response);
}
protected:
@@ -291,10 +305,6 @@ TEST_F(CreditCardFIDOAuthenticatorTest, IsUserVerifiable_False) {
EXPECT_FALSE(requester_->is_user_verifiable().value());
}
-TEST_F(CreditCardFIDOAuthenticatorTest, Sync_IsUserVerifiable_False) {
- EXPECT_FALSE(fido_authenticator_->IsUserVerifiable());
-}
-
TEST_F(CreditCardFIDOAuthenticatorTest, ParseRequestOptions) {
base::Value request_options_json = GetTestRequestOptions(
kTestChallenge, kTestRelyingPartyId, kTestCredentialId);
@@ -311,7 +321,7 @@ TEST_F(CreditCardFIDOAuthenticatorTest, ParseAssertionResponse) {
GetAssertionAuthenticatorResponsePtr assertion_response_ptr =
GetAssertionAuthenticatorResponse::New();
assertion_response_ptr->info = blink::mojom::CommonCredentialInfo::New();
- assertion_response_ptr->info->id = kTestCredentialId;
+ assertion_response_ptr->info->raw_id = Base64ToBytes(kTestCredentialId);
assertion_response_ptr->signature = Base64ToBytes(kTestSignature);
base::Value assertion_response_json =
@@ -332,6 +342,14 @@ TEST_F(CreditCardFIDOAuthenticatorTest, ParseCreationOptions) {
std::move(creation_options_json));
EXPECT_EQ(kTestChallenge, BytesToBase64(creation_options_ptr->challenge));
EXPECT_EQ(kTestRelyingPartyId, creation_options_ptr->relying_party.id);
+
+ // Ensure only platform authenticators are allowed.
+ EXPECT_EQ(AuthenticatorAttachment::kPlatform,
+ creation_options_ptr->authenticator_selection
+ ->authenticator_attachment());
+ EXPECT_EQ(UserVerificationRequirement::kRequired,
+ creation_options_ptr->authenticator_selection
+ ->user_verification_requirement());
}
TEST_F(CreditCardFIDOAuthenticatorTest, ParseAttestationResponse) {
@@ -351,7 +369,7 @@ TEST_F(CreditCardFIDOAuthenticatorTest, AuthenticateCard_BadRequestOptions) {
CreditCard card = CreateServerCard(kTestGUID, kTestNumber);
fido_authenticator_->Authenticate(&card, requester_->GetWeakPtr(),
- base::TimeTicks::Now(),
+ AutofillTickClock::NowTicks(),
base::Value(base::Value::Type::DICTIONARY));
EXPECT_FALSE(requester_->did_succeed());
}
@@ -360,9 +378,10 @@ TEST_F(CreditCardFIDOAuthenticatorTest,
AuthenticateCard_UserVerificationFailed) {
CreditCard card = CreateServerCard(kTestGUID, kTestNumber);
- fido_authenticator_->Authenticate(&card, requester_->GetWeakPtr(),
- base::TimeTicks::Now(),
- base::Value(base::Value::Type::DICTIONARY));
+ fido_authenticator_->Authenticate(
+ &card, requester_->GetWeakPtr(), AutofillTickClock::NowTicks(),
+ GetTestRequestOptions(kTestChallenge, kTestRelyingPartyId,
+ kTestCredentialId));
TestCreditCardFIDOAuthenticator::GetAssertion(fido_authenticator_.get(),
/*did_succeed=*/false);
@@ -374,7 +393,7 @@ TEST_F(CreditCardFIDOAuthenticatorTest,
CreditCard card = CreateServerCard(kTestGUID, kTestNumber);
fido_authenticator_->Authenticate(
- &card, requester_->GetWeakPtr(), base::TimeTicks::Now(),
+ &card, requester_->GetWeakPtr(), AutofillTickClock::NowTicks(),
GetTestRequestOptions(kTestChallenge, kTestRelyingPartyId,
kTestCredentialId));
EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::AUTHENTICATION_FLOW,
@@ -392,7 +411,7 @@ TEST_F(CreditCardFIDOAuthenticatorTest, AuthenticateCard_Success) {
CreditCard card = CreateServerCard(kTestGUID, kTestNumber);
fido_authenticator_->Authenticate(
- &card, requester_->GetWeakPtr(), base::TimeTicks::Now(),
+ &card, requester_->GetWeakPtr(), AutofillTickClock::NowTicks(),
GetTestRequestOptions(kTestChallenge, kTestRelyingPartyId,
kTestCredentialId));
EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::AUTHENTICATION_FLOW,
@@ -410,31 +429,45 @@ TEST_F(CreditCardFIDOAuthenticatorTest, AuthenticateCard_Success) {
TEST_F(CreditCardFIDOAuthenticatorTest, OptIn_PaymentsResponseError) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillCreditCardAuthentication);
+ base::HistogramTester histogram_tester;
+ std::string histogram_name =
+ "Autofill.BetterAuth.OptInCalled.FromCheckoutFlow";
+
EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
- fido_authenticator_->Register();
- EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_WITHOUT_CHALLENGE_FLOW,
+ fido_authenticator_->Register(kTestAuthToken);
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_FETCH_CHALLENGE_FLOW,
fido_authenticator_->current_flow());
// Mock payments response.
OptChange(AutofillClient::PaymentsRpcResult::NETWORK_ERROR,
/*user_is_opted_in=*/false);
EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+ histogram_tester.ExpectUniqueSample(
+ histogram_name,
+ AutofillMetrics::WebauthnOptInParameters::kFetchingChallenge, 1);
}
TEST_F(CreditCardFIDOAuthenticatorTest, OptIn_Success) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillCreditCardAuthentication);
+ base::HistogramTester histogram_tester;
+ std::string histogram_name =
+ "Autofill.BetterAuth.OptInCalled.FromCheckoutFlow";
+
EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
- fido_authenticator_->Register();
- EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_WITHOUT_CHALLENGE_FLOW,
+ fido_authenticator_->Register(kTestAuthToken);
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_FETCH_CHALLENGE_FLOW,
fido_authenticator_->current_flow());
// Mock payments response.
OptChange(AutofillClient::PaymentsRpcResult::SUCCESS,
/*user_is_opted_in=*/true);
EXPECT_TRUE(fido_authenticator_->IsUserOptedIn());
+ histogram_tester.ExpectUniqueSample(
+ histogram_name,
+ AutofillMetrics::WebauthnOptInParameters::kFetchingChallenge, 1);
}
TEST_F(CreditCardFIDOAuthenticatorTest, Register_BadCreationOptions) {
@@ -443,6 +476,7 @@ TEST_F(CreditCardFIDOAuthenticatorTest, Register_BadCreationOptions) {
EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
fido_authenticator_->Register(
+ kTestAuthToken,
GetTestCreationOptions(/*challenge=*/"", kTestRelyingPartyId));
EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
@@ -454,6 +488,7 @@ TEST_F(CreditCardFIDOAuthenticatorTest, Register_UserResponseFailure) {
EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
fido_authenticator_->Register(
+ kTestAuthToken,
GetTestCreationOptions(kTestChallenge, kTestRelyingPartyId));
EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_WITH_CHALLENGE_FLOW,
fido_authenticator_->current_flow());
@@ -467,9 +502,14 @@ TEST_F(CreditCardFIDOAuthenticatorTest, Register_UserResponseFailure) {
TEST_F(CreditCardFIDOAuthenticatorTest, Register_Success) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillCreditCardAuthentication);
+ base::HistogramTester histogram_tester;
+ std::string histogram_name =
+ "Autofill.BetterAuth.OptInCalled.FromCheckoutFlow";
+
EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
fido_authenticator_->Register(
+ kTestAuthToken,
GetTestCreationOptions(kTestChallenge, kTestRelyingPartyId));
EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_WITH_CHALLENGE_FLOW,
fido_authenticator_->current_flow());
@@ -480,22 +520,29 @@ TEST_F(CreditCardFIDOAuthenticatorTest, Register_Success) {
OptChange(AutofillClient::PaymentsRpcResult::SUCCESS,
/*user_is_opted_in=*/true);
EXPECT_TRUE(fido_authenticator_->IsUserOptedIn());
+
+ histogram_tester.ExpectUniqueSample(
+ histogram_name,
+ AutofillMetrics::WebauthnOptInParameters::kWithCreationChallenge, 1);
}
TEST_F(CreditCardFIDOAuthenticatorTest,
Register_EnrollAttemptReturnsCreationOptions) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillCreditCardAuthentication);
+ base::HistogramTester histogram_tester;
+ std::string histogram_name =
+ "Autofill.BetterAuth.OptInCalled.FromCheckoutFlow";
+
EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
- fido_authenticator_->Register();
- EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_WITHOUT_CHALLENGE_FLOW,
+ fido_authenticator_->Register(kTestAuthToken);
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_FETCH_CHALLENGE_FLOW,
fido_authenticator_->current_flow());
// Mock payments response with challenge to invoke enrollment flow.
OptChange(AutofillClient::PaymentsRpcResult::SUCCESS,
- /*user_is_opted_in=*/false,
- GetTestCreationOptions(kTestChallenge, kTestRelyingPartyId));
+ /*user_is_opted_in=*/false, /*include_creation_options=*/true);
EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_WITH_CHALLENGE_FLOW,
fido_authenticator_->current_flow());
EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
@@ -506,11 +553,67 @@ TEST_F(CreditCardFIDOAuthenticatorTest,
OptChange(AutofillClient::PaymentsRpcResult::SUCCESS,
/*user_is_opted_in=*/true);
EXPECT_TRUE(fido_authenticator_->IsUserOptedIn());
+
+ histogram_tester.ExpectTotalCount(histogram_name, 2);
+ histogram_tester.ExpectBucketCount(
+ histogram_name,
+ AutofillMetrics::WebauthnOptInParameters::kFetchingChallenge, 1);
+ histogram_tester.ExpectBucketCount(
+ histogram_name,
+ AutofillMetrics::WebauthnOptInParameters::kWithCreationChallenge, 1);
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest,
+ Register_OptInAttemptReturnsRequestOptions) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillCreditCardAuthentication);
+ EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+
+ fido_authenticator_->Register(kTestAuthToken);
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_FETCH_CHALLENGE_FLOW,
+ fido_authenticator_->current_flow());
+
+ // Mock payments response with challenge to invoke opt-in flow.
+ OptChange(AutofillClient::PaymentsRpcResult::SUCCESS,
+ /*user_is_opted_in=*/false, /*include_creation_options=*/false,
+ /*include_request_options=*/true);
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_WITH_CHALLENGE_FLOW,
+ fido_authenticator_->current_flow());
+ EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+
+ // Mock user response and second payments response.
+ TestCreditCardFIDOAuthenticator::GetAssertion(fido_authenticator_.get(),
+ /*did_succeed=*/true);
+ OptChange(AutofillClient::PaymentsRpcResult::SUCCESS,
+ /*user_is_opted_in=*/true);
+ EXPECT_TRUE(fido_authenticator_->IsUserOptedIn());
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest, Register_NewCardAuthorization) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillCreditCardAuthentication);
+ ::autofill::prefs::SetCreditCardFIDOAuthEnabled(autofill_client_.GetPrefs(),
+ true);
+ EXPECT_TRUE(fido_authenticator_->IsUserOptedIn());
+
+ fido_authenticator_->Authorize(
+ kTestAuthToken, GetTestRequestOptions(kTestChallenge, kTestRelyingPartyId,
+ kTestCredentialId));
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::FOLLOWUP_AFTER_CVC_AUTH_FLOW,
+ fido_authenticator_->current_flow());
+
+ // Mock user response and second payments response.
+ TestCreditCardFIDOAuthenticator::GetAssertion(fido_authenticator_.get(),
+ /*did_succeed=*/true);
+ OptChange(AutofillClient::PaymentsRpcResult::SUCCESS,
+ /*user_is_opted_in=*/true);
+ EXPECT_TRUE(fido_authenticator_->IsUserOptedIn());
}
TEST_F(CreditCardFIDOAuthenticatorTest, OptOut_Success) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillCreditCardAuthentication);
+ base::HistogramTester histogram_tester;
::autofill::prefs::SetCreditCardFIDOAuthEnabled(autofill_client_.GetPrefs(),
true);
@@ -524,6 +627,8 @@ TEST_F(CreditCardFIDOAuthenticatorTest, OptOut_Success) {
OptChange(AutofillClient::PaymentsRpcResult::SUCCESS,
/*user_is_opted_in=*/false);
EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+ histogram_tester.ExpectTotalCount(
+ "Autofill.BetterAuth.OptOutCalled.FromSettingsPage", 1);
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_save_manager.cc b/chromium/components/autofill/core/browser/payments/credit_card_save_manager.cc
index 05b70b7d8dc..111a45e9567 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_save_manager.cc
+++ b/chromium/components/autofill/core/browser/payments/credit_card_save_manager.cc
@@ -41,7 +41,9 @@
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_payments_features.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_util.h"
+#include "components/prefs/pref_service.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "url/gurl.h"
@@ -311,6 +313,11 @@ void CreditCardSaveManager::OnDidUploadCard(
// removed.
GetCreditCardSaveStrikeDatabase()->ClearStrikes(
base::UTF16ToUTF8(upload_request_.card.LastFourDigits()));
+
+ // After a card is successfully saved to server, notifies the
+ // |personal_data_manager_|. PDM uses this information to update the avatar
+ // button UI.
+ personal_data_manager_->OnCreditCardSaved(/*is_local_card=*/false);
} else if (show_save_prompt_.has_value() && show_save_prompt_.value()) {
// If the upload failed and the bubble was actually shown (NOT just the
// icon), count that as a strike against offering upload in the future.
@@ -322,6 +329,9 @@ void CreditCardSaveManager::OnDidUploadCard(
// Show credit card upload feedback.
client_->CreditCardUploadCompleted(result == AutofillClient::SUCCESS);
+
+ if (observer_for_testing_)
+ observer_for_testing_->OnShowCardSavedFeedback();
}
CreditCardSaveStrikeDatabase*
@@ -352,6 +362,23 @@ void CreditCardSaveManager::OnDidGetUploadDetails(
if (observer_for_testing_)
observer_for_testing_->OnReceivedGetUploadDetailsResponse();
if (result == AutofillClient::SUCCESS) {
+ LegalMessageLine::Parse(*legal_message, &legal_message_lines_,
+ /*escape_apostrophes=*/true);
+
+ if (legal_message_lines_.empty()) {
+ // Parsing legal messages failed, so upload should not be offered.
+ // Offer local card save if card is not already saved locally.
+ if (!uploading_local_card_) {
+ AttemptToOfferCardLocalSave(from_dynamic_change_form_,
+ has_non_focusable_field_,
+ upload_request_.card);
+ }
+ upload_decision_metrics_ |=
+ AutofillMetrics::UPLOAD_NOT_OFFERED_INVALID_LEGAL_MESSAGE;
+ LogCardUploadDecisions(upload_decision_metrics_);
+ return;
+ }
+
// Do *not* call payments_client_->Prepare() here. We shouldn't send
// credentials until the user has explicitly accepted a prompt to upload.
if (!supported_card_bin_ranges.empty() &&
@@ -369,7 +396,6 @@ void CreditCardSaveManager::OnDidGetUploadDetails(
return;
}
upload_request_.context_token = context_token;
- legal_message_ = base::DictionaryValue::From(std::move(legal_message));
OfferCardUploadSave();
} else {
// If the upload details request failed and we *know* we have all possible
@@ -449,7 +475,7 @@ void CreditCardSaveManager::OfferCardUploadSave() {
if (!is_mobile_build || show_save_prompt_.value_or(true)) {
user_did_accept_upload_prompt_ = false;
client_->ConfirmSaveCreditCardToCloud(
- upload_request_.card, std::move(legal_message_),
+ upload_request_.card, legal_message_lines_,
AutofillClient::SaveCreditCardOptions()
.with_from_dynamic_change_form(from_dynamic_change_form_)
.with_has_non_focusable_field(has_non_focusable_field_)
@@ -750,25 +776,27 @@ void CreditCardSaveManager::OnUserDidDecideOnUploadSave(
const AutofillClient::UserProvidedCardDetails& user_provided_card_details) {
switch (user_decision) {
case AutofillClient::ACCEPTED:
-// On Android, requesting cardholder name or expiration date is a two step
-// flow.
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_IOS)
+ // On Android and iOS, requesting cardholder name is a two step flow.
if (should_request_name_from_user_) {
client_->ConfirmAccountNameFixFlow(base::BindOnce(
&CreditCardSaveManager::OnUserDidAcceptAccountNameFixFlow,
weak_ptr_factory_.GetWeakPtr()));
+#if defined(OS_ANDROID)
+ // On Android, requesting expiration date is a two step flow.
} else if (should_request_expiration_date_from_user_) {
client_->ConfirmExpirationDateFixFlow(
upload_request_.card,
base::BindOnce(
&CreditCardSaveManager::OnUserDidAcceptExpirationDateFixFlow,
weak_ptr_factory_.GetWeakPtr()));
+#endif // defined(OS_ANDROID)
} else {
OnUserDidAcceptUploadHelper(user_provided_card_details);
}
#else
OnUserDidAcceptUploadHelper(user_provided_card_details);
-#endif
+#endif // defined(OS_ANDROID) || defined(OS_IOS)
break;
case AutofillClient::DECLINED:
@@ -780,7 +808,7 @@ void CreditCardSaveManager::OnUserDidDecideOnUploadSave(
personal_data_manager_->OnUserAcceptedUpstreamOffer();
}
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_IOS)
void CreditCardSaveManager::OnUserDidAcceptAccountNameFixFlow(
const base::string16& cardholder_name) {
DCHECK(should_request_name_from_user_);
@@ -789,7 +817,9 @@ void CreditCardSaveManager::OnUserDidAcceptAccountNameFixFlow(
/*expiration_date_month=*/base::string16(),
/*expiration_date_year=*/base::string16()});
}
+#endif
+#if defined(OS_ANDROID)
void CreditCardSaveManager::OnUserDidAcceptExpirationDateFixFlow(
const base::string16& month,
const base::string16& year) {
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_save_manager.h b/chromium/components/autofill/core/browser/payments/credit_card_save_manager.h
index 0fe7b67101f..941d7c0f7ba 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_save_manager.h
+++ b/chromium/components/autofill/core/browser/payments/credit_card_save_manager.h
@@ -19,11 +19,14 @@
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/payments/credit_card_save_strike_database.h"
+#include "components/autofill/core/browser/payments/legal_message_line.h"
#include "components/autofill/core/browser/payments/local_card_migration_strike_database.h"
#include "components/autofill/core/browser/payments/payments_client.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "url/origin.h"
+class SaveCardOfferObserver;
+
namespace autofill {
// Manages logic for determining whether upload credit card save to Google
@@ -79,12 +82,14 @@ class CreditCardSaveManager {
// particular actions occur.
class ObserverForTest {
public:
- virtual void OnOfferLocalSave() = 0;
- virtual void OnDecideToRequestUploadSave() = 0;
- virtual void OnReceivedGetUploadDetailsResponse() = 0;
- virtual void OnSentUploadCardRequest() = 0;
- virtual void OnReceivedUploadCardResponse() = 0;
- virtual void OnStrikeChangeComplete() = 0;
+ virtual ~ObserverForTest() {}
+ virtual void OnOfferLocalSave() {}
+ virtual void OnDecideToRequestUploadSave() {}
+ virtual void OnReceivedGetUploadDetailsResponse() {}
+ virtual void OnSentUploadCardRequest() {}
+ virtual void OnReceivedUploadCardResponse() {}
+ virtual void OnShowCardSavedFeedback() {}
+ virtual void OnStrikeChangeComplete() {}
};
// The parameters should outlive the CreditCardSaveManager.
@@ -138,10 +143,14 @@ class CreditCardSaveManager {
friend class TestCreditCardSaveManager;
friend class SaveCardBubbleViewsFullFormBrowserTest;
friend class SaveCardInfobarEGTestHelper;
+ friend class ::SaveCardOfferObserver;
+ FRIEND_TEST_ALL_PREFIXES(
+ SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
+ StrikeDatabase_Upload_FullFlowTest);
FRIEND_TEST_ALL_PREFIXES(SaveCardBubbleViewsFullFormBrowserTest,
StrikeDatabase_Local_FullFlowTest);
- FRIEND_TEST_ALL_PREFIXES(SaveCardBubbleViewsFullFormBrowserTest,
- StrikeDatabase_Upload_FullFlowTest);
+ FRIEND_TEST_ALL_PREFIXES(SaveCardBubbleViewsFullFormBrowserTestForStatusChip,
+ Feedback_CardSavingAnimation);
// Returns the CreditCardSaveStrikeDatabase for |client_|.
CreditCardSaveStrikeDatabase* GetCreditCardSaveStrikeDatabase();
@@ -210,12 +219,14 @@ class CreditCardSaveManager {
const AutofillClient::UserProvidedCardDetails&
user_provided_card_details);
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_IOS)
// Upload the card details with the user provided cardholder_name.
// Only relevant for mobile as fix flow is two steps on mobile compared to
// one step on desktop.
void OnUserDidAcceptAccountNameFixFlow(const base::string16& cardholder_name);
+#endif // defined(OS_ANDROID) || defined(OS_IOS)
+#if defined(OS_ANDROID)
// Upload the card details with the user provided expiration date month and
// year. Only relevant for mobile as fix flow is two steps on mobile compared
// to one step on desktop.
@@ -332,8 +343,8 @@ class CreditCardSaveManager {
// The origin of the top level frame from which a form is uploaded.
url::Origin pending_upload_request_origin_;
- // The returned legal message from a GetUploadDetails call to Google Payments.
- std::unique_ptr<base::DictionaryValue> legal_message_;
+ // The parsed lines from the legal message returned from GetUploadDetails.
+ LegalMessageLines legal_message_lines_;
std::unique_ptr<CreditCardSaveStrikeDatabase>
credit_card_save_strike_database_;
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc b/chromium/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
index 721fab518e0..bf87aceff4b 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
@@ -17,6 +17,7 @@
#include "base/guid.h"
#include "base/metrics/metrics_hashes.h"
#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
@@ -75,18 +76,6 @@ using UkmDeveloperEngagementType = ukm::builders::Autofill_DeveloperEngagement;
const base::Time kArbitraryTime = base::Time::FromDoubleT(25);
const base::Time kMuchLaterTime = base::Time::FromDoubleT(5000);
-std::string NextYear() {
- base::Time::Exploded now;
- base::Time::Now().LocalExplode(&now);
- return std::to_string(now.year + 1);
-}
-
-std::string NextMonth() {
- base::Time::Exploded now;
- base::Time::Now().LocalExplode(&now);
- return std::to_string(now.month % 12 + 1);
-}
-
// Used to configure form for |CreateTestCreditCardFormData|.
struct CreditCardFormOptions {
CreditCardFormOptions& with_is_https(bool b) {
@@ -281,8 +270,8 @@ class CreditCardSaveManagerTest : public testing::Test {
// Edit the data, and submit.
form.fields[1].value = ASCIIToUTF16("4111111111111111");
- form.fields[2].value = ASCIIToUTF16(NextMonth());
- form.fields[3].value = ASCIIToUTF16(NextYear());
+ form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ form.fields[3].value = ASCIIToUTF16(test::NextYear());
FormSubmitted(form);
EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
}
@@ -426,8 +415,8 @@ TEST_F(CreditCardSaveManagerTest, MAYBE_CreditCardSavedWhenAutocompleteOff) {
// Edit the data, and submit.
form.fields[1].value = ASCIIToUTF16("4111111111111111");
- form.fields[2].value = ASCIIToUTF16(NextMonth());
- form.fields[3].value = ASCIIToUTF16(NextYear());
+ form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ form.fields[3].value = ASCIIToUTF16(test::NextYear());
FormSubmitted(form);
EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
}
@@ -445,8 +434,8 @@ TEST_F(CreditCardSaveManagerTest, InvalidCreditCardNumberIsNotSaved) {
std::string card("4408041234567890");
ASSERT_FALSE(autofill::IsValidCreditCardNumber(ASCIIToUTF16(card)));
form.fields[1].value = ASCIIToUTF16(card);
- form.fields[2].value = ASCIIToUTF16(NextMonth());
- form.fields[3].value = ASCIIToUTF16(NextYear());
+ form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ form.fields[3].value = ASCIIToUTF16(test::NextYear());
FormSubmitted(form);
EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
}
@@ -470,8 +459,8 @@ TEST_F(CreditCardSaveManagerTest, CreditCardDisabledDoesNotSave) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -505,8 +494,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_OnlyCountryInAddresses) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -570,8 +559,8 @@ TEST_F(CreditCardSaveManagerTest, LocalCreditCard_FirstAndLastName) {
credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
credit_card_form.fields[1].value = ASCIIToUTF16("Master");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -636,8 +625,8 @@ TEST_F(CreditCardSaveManagerTest, LocalCreditCard_LastAndFirstName) {
credit_card_form.fields[0].value = ASCIIToUTF16("Master");
credit_card_form.fields[1].value = ASCIIToUTF16("Flo");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -709,8 +698,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_WithNonFocusableField) {
credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
credit_card_form.fields[1].value = ASCIIToUTF16("Master");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -755,8 +744,8 @@ TEST_F(CreditCardSaveManagerTest, LocalCreditCard_WithNonFocusableField) {
credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
credit_card_form.fields[1].value = ASCIIToUTF16("Master");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
@@ -782,8 +771,8 @@ TEST_F(CreditCardSaveManagerTest,
credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
credit_card_form.fields[1].value = ASCIIToUTF16("Master");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
@@ -815,8 +804,8 @@ TEST_F(CreditCardSaveManagerTest,
credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
credit_card_form.fields[1].value = ASCIIToUTF16("Master");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
@@ -858,8 +847,8 @@ TEST_F(
credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
credit_card_form.fields[1].value = ASCIIToUTF16("Master");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
@@ -897,8 +886,8 @@ TEST_F(CreditCardSaveManagerTest,
credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
credit_card_form.fields[1].value = ASCIIToUTF16("Master");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
@@ -923,8 +912,8 @@ TEST_F(CreditCardSaveManagerTest,
credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
credit_card_form.fields[1].value = ASCIIToUTF16("Master");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
@@ -951,8 +940,8 @@ TEST_F(CreditCardSaveManagerTest,
credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
credit_card_form.fields[1].value = ASCIIToUTF16("Master");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
@@ -983,8 +972,8 @@ TEST_F(CreditCardSaveManagerTest,
credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
credit_card_form.fields[1].value = ASCIIToUTF16("Master");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
@@ -1025,8 +1014,8 @@ TEST_F(
credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
credit_card_form.fields[1].value = ASCIIToUTF16("Master");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
@@ -1063,8 +1052,8 @@ TEST_F(CreditCardSaveManagerTest,
credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
credit_card_form.fields[1].value = ASCIIToUTF16("Master");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
@@ -1090,8 +1079,8 @@ TEST_F(CreditCardSaveManagerTest, SaveCreditCardOptions_WithoutDynamicForms) {
credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
credit_card_form.fields[1].value = ASCIIToUTF16("Master");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
@@ -1125,8 +1114,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_FirstAndLastName) {
credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
credit_card_form.fields[1].value = ASCIIToUTF16("Master");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -1199,8 +1188,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_LastAndFirstName) {
credit_card_form.fields[0].value = ASCIIToUTF16("Master");
credit_card_form.fields[1].value = ASCIIToUTF16("Flo");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -1251,8 +1240,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCardAndSaveCopy) {
const char* const card_number = "4111111111111111";
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16(card_number);
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
@@ -1268,8 +1257,12 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCardAndSaveCopy) {
EXPECT_EQ(CreditCard::OK, saved_card->GetServerStatus());
EXPECT_EQ(base::ASCIIToUTF16("1111"), saved_card->LastFourDigits());
EXPECT_EQ(kVisaCard, saved_card->network());
- EXPECT_EQ(std::stoi(NextMonth()), saved_card->expiration_month());
- EXPECT_EQ(std::stoi(NextYear()), saved_card->expiration_year());
+ int month;
+ EXPECT_TRUE(base::StringToInt(test::NextMonth(), &month));
+ EXPECT_EQ(month, saved_card->expiration_month());
+ int year;
+ EXPECT_TRUE(base::StringToInt(test::NextYear(), &year));
+ EXPECT_EQ(year, saved_card->expiration_year());
EXPECT_EQ(server_id, saved_card->server_id());
EXPECT_EQ(CreditCard::FULL_SERVER_CARD, saved_card->record_type());
EXPECT_EQ(base::ASCIIToUTF16(card_number), saved_card->number());
@@ -1305,8 +1298,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_DisableLocalSave) {
const char* const card_number = "4111111111111111";
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16(card_number);
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
@@ -1335,8 +1328,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_FeatureNotEnabled) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -1370,8 +1363,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_CvcUnavailable) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // CVC MISSING
base::HistogramTester histogram_tester;
@@ -1408,8 +1401,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_CvcInvalidLength) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("1234");
base::HistogramTester histogram_tester;
@@ -1465,8 +1458,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_MultipleCvcFields) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // CVC MISSING
credit_card_form.fields[5].value = ASCIIToUTF16("123");
@@ -1516,8 +1509,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoCvcFieldOnForm) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
base::HistogramTester histogram_tester;
@@ -1571,8 +1564,8 @@ TEST_F(CreditCardSaveManagerTest,
// Enter an invalid cvc in "Random Field" and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("1234");
base::HistogramTester histogram_tester;
@@ -1627,8 +1620,8 @@ TEST_F(CreditCardSaveManagerTest,
// Enter a valid cvc in "Random Field" and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -1685,8 +1678,8 @@ TEST_F(CreditCardSaveManagerTest,
// Enter a valid cvc in "Random Field" and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -1717,8 +1710,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoProfileAvailable) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Bob Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -1763,8 +1756,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoRecentlyUsedProfile) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -1798,8 +1791,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // CVC MISSING
base::HistogramTester histogram_tester;
@@ -1839,8 +1832,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoNameAvailable) {
// Edit the data, but don't include a name, and submit.
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -1878,8 +1871,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, but don't include a name, and submit.
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -1936,8 +1929,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_ZipCodesConflict) {
// Edit the data and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -1984,8 +1977,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2031,8 +2024,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_ZipCodesHavePrefixMatch) {
// Edit the data and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2073,8 +2066,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoZipCodeAvailable) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2118,8 +2111,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_CCFormHasMiddleInitial) {
// submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo W. Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2157,8 +2150,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoMiddleInitialInCCForm) {
// Edit the data, but do not use middle initial.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2192,8 +2185,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the name by adding a middle name.
credit_card_form.fields[0].value = ASCIIToUTF16("John Quincy Adams");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2236,8 +2229,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_CCFormHasAddressMiddleName) {
// Edit the name by removing middle name.
credit_card_form.fields[0].value = ASCIIToUTF16("John Adams");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2289,8 +2282,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NamesCanMismatch) {
// Edit the data, but use yet another name, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Bob Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2346,8 +2339,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_IgnoreOldProfiles) {
// Edit the data, but use yet another name, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Master Blaster");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2386,8 +2379,8 @@ TEST_F(
// Edit the data, but don't include a name, and submit.
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2429,8 +2422,8 @@ TEST_F(
// Edit the data, but include a conflicting name, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Jane Doe");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2468,8 +2461,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2504,8 +2497,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2538,8 +2531,8 @@ TEST_F(
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2584,8 +2577,8 @@ TEST_F(
// Edit the data, but don't include a name, and submit.
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2632,8 +2625,8 @@ TEST_F(
// Edit the data, but include a conflicting name, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Jane Doe");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2675,8 +2668,8 @@ TEST_F(
// Edit the data, but don't include a name, and submit.
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2718,8 +2711,8 @@ TEST_F(
// Edit the data, but include a conflicting name, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Jane Doe");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -2763,8 +2756,8 @@ TEST_F(
// Edit the data, but don't include a name, and submit.
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
// With the offer-to-save decision deferred to Google Payments, Payments can
@@ -2832,8 +2825,8 @@ TEST_F(
// Edit the data, include a expiration date, and submit this time.
credit_card_form.fields[0].value = ASCIIToUTF16("Jane Doe");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
@@ -3053,7 +3046,7 @@ TEST_F(CreditCardSaveManagerTest,
credit_card_form.fields[0].value = ASCIIToUTF16("John Smith");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
credit_card_form.fields[2].value = ASCIIToUTF16("");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -3095,7 +3088,7 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("John Smith");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
credit_card_form.fields[3].value = ASCIIToUTF16("");
credit_card_form.fields[4].value = ASCIIToUTF16("123");
@@ -3226,8 +3219,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -3269,8 +3262,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_UploadDetailsFails) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -3302,7 +3295,8 @@ TEST_F(CreditCardSaveManagerTest, DuplicateMaskedCreditCard_NoUpload) {
// enter below.
CreditCard credit_card(CreditCard::MASKED_SERVER_CARD, "a123");
test::SetCreditCardInfo(&credit_card, "Flo Master", "1111",
- NextMonth().c_str(), NextYear().c_str(), "1");
+ test::NextMonth().c_str(), test::NextYear().c_str(),
+ "1");
credit_card.SetNetworkForMaskedCard(kVisaCard);
personal_data_.AddServerCreditCard(credit_card);
@@ -3314,8 +3308,8 @@ TEST_F(CreditCardSaveManagerTest, DuplicateMaskedCreditCard_NoUpload) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
// Local save prompt should not be shown as there is alredy masked
@@ -3334,8 +3328,8 @@ TEST_F(CreditCardSaveManagerTest, NothingIfNothingFound) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16(""); // No name set
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // No CVC set
// Submit the form and check what detected_values for an upload save would be.
@@ -3364,8 +3358,8 @@ TEST_F(CreditCardSaveManagerTest, DetectCvc) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16(""); // No name set
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
// Submit the form and ensure the detected_values for an upload save contained
@@ -3386,8 +3380,8 @@ TEST_F(CreditCardSaveManagerTest, DetectCardholderName) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("John Smith");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // No CVC set
// Submit the form and ensure the detected_values for an upload save contained
@@ -3415,8 +3409,8 @@ TEST_F(CreditCardSaveManagerTest, DetectAddressName) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16(""); // No name set
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // No CVC set
// Submit the form and ensure the detected_values for an upload save contained
@@ -3444,8 +3438,8 @@ TEST_F(CreditCardSaveManagerTest, DetectCardholderAndAddressNameIfMatching) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("John Smith");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // No CVC set
// Submit the form and ensure the detected_values for an upload save contained
@@ -3474,8 +3468,8 @@ TEST_F(CreditCardSaveManagerTest, DetectNoUniqueNameIfNamesConflict) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Miles Prower"); // Conflict!
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // No CVC set
// Submit the form and check what detected_values for an upload save would be.
@@ -3502,8 +3496,8 @@ TEST_F(CreditCardSaveManagerTest, DetectPostalCode) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16(""); // No name set
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // No CVC set
// Submit the form and ensure the detected_values for an upload save contained
@@ -3535,8 +3529,8 @@ TEST_F(CreditCardSaveManagerTest, DetectNoUniquePostalCodeIfZipsConflict) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16(""); // No name set
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // No CVC set
// Submit the form and check what detected_values for an upload save would be.
@@ -3560,8 +3554,8 @@ TEST_F(CreditCardSaveManagerTest, DetectAddressLine) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16(""); // No name set
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // No CVC set
// Submit the form and ensure the detected_values for an upload save contained
@@ -3589,8 +3583,8 @@ TEST_F(CreditCardSaveManagerTest, DetectLocality) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16(""); // No name set
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // No CVC set
// Submit the form and ensure the detected_values for an upload save contained
@@ -3617,8 +3611,8 @@ TEST_F(CreditCardSaveManagerTest, DetectAdministrativeArea) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16(""); // No name set
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // No CVC set
// Submit the form and ensure the detected_values for an upload save contained
@@ -3646,8 +3640,8 @@ TEST_F(CreditCardSaveManagerTest, DetectCountryCode) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16(""); // No name set
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // No CVC set
// Submit the form and ensure the detected_values for an upload save contained
@@ -3674,8 +3668,8 @@ TEST_F(CreditCardSaveManagerTest, DetectHasGooglePaymentAccount) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16(""); // No name set
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // No CVC set
// Submit the form and ensure the detected_values for an upload save contained
@@ -3708,8 +3702,8 @@ TEST_F(CreditCardSaveManagerTest, DetectEverythingAtOnce) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("John Smith");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
// Submit the form and ensure the detected_values for an upload save contained
@@ -3747,8 +3741,8 @@ TEST_F(CreditCardSaveManagerTest, DetectSubsetOfPossibleFields) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Miles Prower"); // Conflict!
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
// Submit the form and ensure the detected_values for an upload save contained
@@ -3795,8 +3789,8 @@ TEST_F(CreditCardSaveManagerTest, DetectAddressComponentsAcrossProfiles) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16(""); // No name set
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // No CVC set
// Submit the form and ensure the detected_values for an upload save contained
@@ -3835,8 +3829,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16(""); // No name!
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // No CVC!
base::HistogramTester histogram_tester;
@@ -3895,8 +3889,8 @@ TEST_F(
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("John Smith");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -3938,8 +3932,8 @@ TEST_F(
credit_card_form.fields[0].value = ASCIIToUTF16("John");
credit_card_form.fields[1].value = ASCIIToUTF16("Smith");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -3983,8 +3977,8 @@ TEST_F(
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16(""); // No name!
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // No CVC!
base::HistogramTester histogram_tester;
@@ -4014,8 +4008,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // No CVC!
base::HistogramTester histogram_tester;
@@ -4057,8 +4051,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16(""); // No name!
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -4106,8 +4100,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Miles Prower"); // Conflict!
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -4157,8 +4151,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -4213,8 +4207,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -4256,8 +4250,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16(""); // No name!
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16(""); // No CVC!
base::HistogramTester histogram_tester;
@@ -4297,7 +4291,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_UploadOfLocalCard) {
// enter below.
CreditCard local_card;
test::SetCreditCardInfo(&local_card, "Flo Master", "4111111111111111",
- NextMonth().c_str(), NextYear().c_str(), "1");
+ test::NextMonth().c_str(), test::NextYear().c_str(),
+ "1");
local_card.set_record_type(CreditCard::LOCAL_CARD);
personal_data_.AddCreditCard(local_card);
@@ -4320,8 +4315,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_UploadOfLocalCard) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -4360,8 +4355,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_UploadOfNewCard) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -4392,7 +4387,8 @@ TEST_F(CreditCardSaveManagerTest,
// enter below.
CreditCard local_card;
test::SetCreditCardInfo(&local_card, "Flo Master", "4111111111111111",
- NextMonth().c_str(), NextYear().c_str(), "1");
+ test::NextMonth().c_str(), test::NextYear().c_str(),
+ "1");
local_card.set_record_type(CreditCard::LOCAL_CARD);
personal_data_.AddCreditCard(local_card);
@@ -4415,8 +4411,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -4450,8 +4446,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
// Confirm that upload happened and that no experiment flag state was sent in
@@ -4480,8 +4476,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
// Confirm that the preflight request contained
@@ -4509,8 +4505,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
// Confirm that the preflight request contained the correct UploadCardSource.
@@ -4540,8 +4536,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -4589,8 +4585,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -4631,8 +4627,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -4678,8 +4674,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_MaxStrikesDisallowsSave) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -4725,8 +4721,8 @@ TEST_F(CreditCardSaveManagerTest,
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -4776,8 +4772,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_MaxStrikesStillAllowsSave) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -4817,8 +4813,8 @@ TEST_F(CreditCardSaveManagerTest, LocallySaveCreditCard_ClearStrikesOnAdd) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
@@ -4858,8 +4854,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_ClearStrikesOnAdd) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
@@ -4891,8 +4887,8 @@ TEST_F(CreditCardSaveManagerTest, LocallySaveCreditCard_NumStrikesLoggedOnAdd) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -4936,8 +4932,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NumStrikesLoggedOnAdd) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -5018,8 +5014,8 @@ TEST_F(CreditCardSaveManagerTest,
credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
credit_card_form.fields[1].value = ASCIIToUTF16("Master");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -5069,8 +5065,8 @@ TEST_F(CreditCardSaveManagerTest,
credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
credit_card_form.fields[1].value = ASCIIToUTF16("Master");
credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
base::HistogramTester histogram_tester;
@@ -5098,8 +5094,8 @@ TEST_F(CreditCardSaveManagerTest, UploadSaveNotOfferedForUnsupportedCard) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("5454545454545454");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
// Since card isn't in any of the supported ranges, local save should be
@@ -5125,15 +5121,16 @@ TEST_F(CreditCardSaveManagerTest, LocalSaveNotOfferedForSavedUnsupportedCard) {
// enter below.
CreditCard local_card;
test::SetCreditCardInfo(&local_card, "Flo Master", "5454545454545454",
- NextMonth().c_str(), NextYear().c_str(), "1");
+ test::NextMonth().c_str(), test::NextYear().c_str(),
+ "1");
local_card.set_record_type(CreditCard::LOCAL_CARD);
personal_data_.AddCreditCard(local_card);
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("5454545454545454");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
// Since card is already saved, local save should not be offered.
@@ -5157,8 +5154,8 @@ TEST_F(CreditCardSaveManagerTest, UploadSaveOfferedForSupportedCard) {
// Edit the data, and submit.
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
// Since card is in one of the supported ranges(4111-4113), upload save should
@@ -5168,4 +5165,40 @@ TEST_F(CreditCardSaveManagerTest, UploadSaveOfferedForSupportedCard) {
EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
}
+// Tests that if payment client returns an invalid legal message upload should
+// not be offered.
+TEST_F(CreditCardSaveManagerTest, InvalidLegalMessageInOnDidGetUploadDetails) {
+ payments_client_->SetUseInvalidLegalMessageInGetUploadDetails(true);
+
+ // Create, fill and submit an address form in order to establish a recent
+ // profile which can be selected for the upload request.
+ FormData address_form;
+ test::CreateTestAddressFormData(&address_form);
+ FormsSeen(std::vector<FormData>(1, address_form));
+
+ ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form);
+ FormSubmitted(address_form);
+
+ // Set up our credit card form data.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form, CreditCardFormOptions());
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+
+ // Edit the data, and submit.
+ const char* const card_number = "4111111111111111";
+ credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
+ credit_card_form.fields[1].value = ASCIIToUTF16(card_number);
+ credit_card_form.fields[2].value = ASCIIToUTF16(test::NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(test::NextYear());
+ credit_card_form.fields[4].value = ASCIIToUTF16("123");
+
+ base::HistogramTester histogram_tester;
+ FormSubmitted(credit_card_form);
+
+ // Verify that the correct histogram entries were logged.
+ ExpectCardUploadDecision(
+ histogram_tester,
+ AutofillMetrics::UPLOAD_NOT_OFFERED_INVALID_LEGAL_MESSAGE);
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.cc b/chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.cc
new file mode 100644
index 00000000000..2a1125b55b0
--- /dev/null
+++ b/chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.cc
@@ -0,0 +1,42 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/payments/fido_authentication_strike_database.h"
+
+#include "components/autofill/core/browser/proto/strike_data.pb.h"
+
+namespace autofill {
+
+const int
+ FidoAuthenticationStrikeDatabase::kStrikesToAddWhenOptInOfferDeclined = 1;
+const int FidoAuthenticationStrikeDatabase::
+ kStrikesToAddWhenUserVerificationFailsOnOptInAttempt = 2;
+const int FidoAuthenticationStrikeDatabase::kStrikesToAddWhenUserOptsOut = 3;
+
+FidoAuthenticationStrikeDatabase::FidoAuthenticationStrikeDatabase(
+ StrikeDatabase* strike_database)
+ : StrikeDatabaseIntegratorBase(strike_database) {
+ RemoveExpiredStrikes();
+}
+
+FidoAuthenticationStrikeDatabase::~FidoAuthenticationStrikeDatabase() {}
+
+std::string FidoAuthenticationStrikeDatabase::GetProjectPrefix() {
+ return "FidoAuthentication";
+}
+
+int FidoAuthenticationStrikeDatabase::GetMaxStrikesLimit() {
+ return 3;
+}
+
+long long FidoAuthenticationStrikeDatabase::GetExpiryTimeMicros() {
+ // Expiry time is six months.
+ return 1000000LL * 60 * 60 * 24 * 30 * 6;
+}
+
+bool FidoAuthenticationStrikeDatabase::UniqueIdsRequired() {
+ return false;
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.h b/chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.h
new file mode 100644
index 00000000000..f06f9fc5ebe
--- /dev/null
+++ b/chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.h
@@ -0,0 +1,38 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_FIDO_AUTHENTICATION_STRIKE_DATABASE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_FIDO_AUTHENTICATION_STRIKE_DATABASE_H_
+
+#include <string>
+
+#include "components/autofill/core/browser/payments/strike_database.h"
+#include "components/autofill/core/browser/payments/strike_database_integrator_base.h"
+
+namespace autofill {
+
+// Implementation of StrikeDatabaseIntegratorBase for offering FIDO
+// authentication for card unmasking.
+class FidoAuthenticationStrikeDatabase : public StrikeDatabaseIntegratorBase {
+ public:
+ FidoAuthenticationStrikeDatabase(StrikeDatabase* strike_database);
+ ~FidoAuthenticationStrikeDatabase() override;
+
+ // Strikes to add when user declines opt-in offer.
+ static const int kStrikesToAddWhenOptInOfferDeclined;
+ // Strikes to add when user fails to complete user-verification for an opt-in
+ // attempt.
+ static const int kStrikesToAddWhenUserVerificationFailsOnOptInAttempt;
+ // Strikes to add when user opts-out from settings page.
+ static const int kStrikesToAddWhenUserOptsOut;
+
+ std::string GetProjectPrefix() override;
+ int GetMaxStrikesLimit() override;
+ long long GetExpiryTimeMicros() override;
+ bool UniqueIdsRequired() override;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_FIDO_AUTHENTICATION_STRIKE_DATABASE_H_
diff --git a/chromium/components/autofill/core/browser/payments/full_card_request.cc b/chromium/components/autofill/core/browser/payments/full_card_request.cc
index 2d8be66ebc5..2c87a60b6df 100644
--- a/chromium/components/autofill/core/browser/payments/full_card_request.cc
+++ b/chromium/components/autofill/core/browser/payments/full_card_request.cc
@@ -13,6 +13,8 @@
#include "components/autofill/core/browser/payments/payments_util.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/common/autofill_clock.h"
+#include "components/autofill/core/common/autofill_payments_features.h"
+#include "components/autofill/core/common/autofill_tick_clock.h"
namespace autofill {
namespace payments {
@@ -110,10 +112,6 @@ void FullCardRequest::GetFullCard(const CreditCard& card,
}
}
-bool FullCardRequest::IsGettingFullCard() const {
- return !!request_;
-}
-
void FullCardRequest::OnUnmaskPromptAccepted(
const UserProvidedUnmaskDetails& user_response) {
if (!user_response.exp_month.empty())
@@ -155,12 +153,13 @@ void FullCardRequest::OnUnmaskPromptClosed() {
void FullCardRequest::OnDidGetUnmaskRiskData(const std::string& risk_data) {
request_->risk_data = risk_data;
if (!request_->user_response.cvc.empty() ||
- !request_->fido_assertion_info.is_none())
+ !request_->fido_assertion_info.is_none()) {
SendUnmaskCardRequest();
+ }
}
void FullCardRequest::SendUnmaskCardRequest() {
- real_pan_request_timestamp_ = AutofillClock::Now();
+ real_pan_request_timestamp_ = AutofillTickClock::NowTicks();
payments_client_->UnmaskCard(*request_,
base::BindOnce(&FullCardRequest::OnDidGetRealPan,
weak_ptr_factory_.GetWeakPtr()));
@@ -169,8 +168,18 @@ void FullCardRequest::SendUnmaskCardRequest() {
void FullCardRequest::OnDidGetRealPan(
AutofillClient::PaymentsRpcResult result,
payments::PaymentsClient::UnmaskResponseDetails& response_details) {
- AutofillMetrics::LogRealPanDuration(
- AutofillClock::Now() - real_pan_request_timestamp_, result);
+ // If the CVC field is populated, that means the user performed a CVC check.
+ // If FIDO AssertionInfo is populated, then the user must have performed FIDO
+ // authentication. Exactly one of these fields must be populated.
+ DCHECK_NE(request_->user_response.cvc.empty(),
+ request_->fido_assertion_info.is_none());
+ if (!request_->user_response.cvc.empty()) {
+ AutofillMetrics::LogRealPanDuration(
+ AutofillTickClock::NowTicks() - real_pan_request_timestamp_, result);
+ } else if (!request_->fido_assertion_info.is_none()) {
+ AutofillMetrics::LogCardUnmaskDurationAfterWebauthn(
+ AutofillTickClock::NowTicks() - real_pan_request_timestamp_, result);
+ }
if (ui_delegate_)
ui_delegate_->OnUnmaskVerificationResult(result);
@@ -204,9 +213,16 @@ void FullCardRequest::OnDidGetRealPan(
// |response_details_| if |user_response.fido_opt_in| was not set to true
// to avoid an unwanted registration prompt.
unmask_response_details_ = response_details;
+
+ const base::string16 cvc =
+ base::FeatureList::IsEnabled(
+ features::kAutofillAlwaysReturnCloudTokenizedCard) &&
+ !response_details.dcvv.empty()
+ ? base::UTF8ToUTF16(response_details.dcvv)
+ : request_->user_response.cvc;
if (result_delegate_)
- result_delegate_->OnFullCardRequestSucceeded(
- *this, request_->card, request_->user_response.cvc);
+ result_delegate_->OnFullCardRequestSucceeded(*this, request_->card,
+ cvc);
Reset();
break;
}
diff --git a/chromium/components/autofill/core/browser/payments/full_card_request.h b/chromium/components/autofill/core/browser/payments/full_card_request.h
index 9d5338b3c3d..c8608085877 100644
--- a/chromium/components/autofill/core/browser/payments/full_card_request.h
+++ b/chromium/components/autofill/core/browser/payments/full_card_request.h
@@ -18,6 +18,10 @@
namespace autofill {
+class AutofillManagerTest;
+class AutofillMetricsTest;
+class CreditCardAccessManagerTest;
+class CreditCardCVCAuthenticatorTest;
class CreditCard;
class PersonalDataManager;
@@ -85,9 +89,6 @@ class FullCardRequest final : public CardUnmaskDelegate {
base::WeakPtr<ResultDelegate> result_delegate,
base::Value fido_assertion_info);
- // Returns true if there's a pending request to get the full card.
- bool IsGettingFullCard() const;
-
// Called by the payments client when a card has been unmasked.
void OnDidGetRealPan(
AutofillClient::PaymentsRpcResult result,
@@ -103,6 +104,11 @@ class FullCardRequest final : public CardUnmaskDelegate {
}
private:
+ friend class autofill::AutofillManagerTest;
+ friend class autofill::AutofillMetricsTest;
+ friend class autofill::CreditCardAccessManagerTest;
+ friend class autofill::CreditCardCVCAuthenticatorTest;
+
// Retrieves the pan for |card| and invokes
// Delegate::OnFullCardRequestSucceeded() or
// Delegate::OnFullCardRequestFailed(). Only one request should be active at a
@@ -158,7 +164,7 @@ class FullCardRequest final : public CardUnmaskDelegate {
// The timestamp when the full PAN was requested from a server. For
// histograms.
- base::Time real_pan_request_timestamp_;
+ base::TimeTicks real_pan_request_timestamp_;
// The timestamp when the form is parsed. For histograms.
base::TimeTicks form_parsed_timestamp_;
diff --git a/chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc b/chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc
index f4fb8e536a2..d57e76c31c4 100644
--- a/chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc
@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/stringprintf.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -18,6 +19,8 @@
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
+#include "components/autofill/core/common/autofill_clock.h"
+#include "components/autofill/core/common/autofill_payments_features.h"
#include "net/url_request/url_request_test_util.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
@@ -106,6 +109,17 @@ class FullCardRequestTest : public testing::Test {
request_->OnDidGetRealPan(result, response.with_real_pan(real_pan));
}
+ void OnDidGetRealPanWithDcvv(AutofillClient::PaymentsRpcResult result,
+ const std::string& real_pan,
+ const std::string& dcvv) {
+ payments::PaymentsClient::UnmaskResponseDetails response;
+ request_->OnDidGetRealPan(result,
+ response.with_real_pan(real_pan).with_dcvv(dcvv));
+ }
+
+ protected:
+ base::test::ScopedFeatureList scoped_feature_list_;
+
private:
base::test::SingleThreadTaskEnvironment task_environment_;
MockPersonalDataManager personal_data_;
@@ -159,6 +173,56 @@ TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForMaskedServerCardViaCvc) {
card_unmask_delegate()->OnUnmaskPromptClosed();
}
+// Verify getting the full PAN and the dCVV for a masked server card when cloud
+// tokenization is enabled.
+TEST_F(FullCardRequestTest, GetFullCardPanAndDcvvForMaskedServerCardViaDcvv) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillAlwaysReturnCloudTokenizedCard);
+ EXPECT_CALL(*result_delegate(),
+ OnFullCardRequestSucceeded(
+ testing::Ref(*request()),
+ CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
+ base::ASCIIToUTF16("321")));
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*ui_delegate(),
+ OnUnmaskVerificationResult(AutofillClient::SUCCESS));
+
+ request()->GetFullCard(
+ CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
+ AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
+ OnDidGetRealPanWithDcvv(AutofillClient::SUCCESS, "4111", "321");
+ card_unmask_delegate()->OnUnmaskPromptClosed();
+}
+
+// Verify getting the full PAN for a masked server card when cloud
+// tokenization is enabled but no dCVV is returned.
+TEST_F(FullCardRequestTest, GetFullCardPanForMaskedServerCardWithoutDcvv) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillAlwaysReturnCloudTokenizedCard);
+ EXPECT_CALL(*result_delegate(),
+ OnFullCardRequestSucceeded(
+ testing::Ref(*request()),
+ CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
+ base::ASCIIToUTF16("123")));
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*ui_delegate(),
+ OnUnmaskVerificationResult(AutofillClient::SUCCESS));
+
+ request()->GetFullCard(
+ CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
+ AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
+ OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
+ card_unmask_delegate()->OnUnmaskPromptClosed();
+}
+
// Verify getting the full PAN for a masked server card.
TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForMaskedServerCardViaFido) {
EXPECT_CALL(*result_delegate(),
@@ -263,7 +327,7 @@ TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForExpiredFullServerCard) {
OnUnmaskVerificationResult(AutofillClient::SUCCESS));
base::Time::Exploded today;
- base::Time::Now().LocalExplode(&today);
+ AutofillClock::Now().LocalExplode(&today);
CreditCard full_server_card(CreditCard::FULL_SERVER_CARD, "server_id");
test::SetCreditCardInfo(&full_server_card, nullptr, "4111", "12",
base::StringPrintf("%d", today.year - 1).c_str(),
@@ -493,7 +557,7 @@ TEST_F(FullCardRequestTest, UpdateExpDateForLocalCard) {
OnUnmaskVerificationResult(AutofillClient::SUCCESS));
base::Time::Exploded today;
- base::Time::Now().LocalExplode(&today);
+ AutofillClock::Now().LocalExplode(&today);
CreditCard card;
test::SetCreditCardInfo(&card, nullptr, "4111", "10",
base::StringPrintf("%d", today.year - 1).c_str(),
@@ -559,74 +623,5 @@ TEST_F(FullCardRequestTest, UnmaskForPaymentRequest) {
card_unmask_delegate()->OnUnmaskPromptClosed();
}
-// Verify that FullCardRequest::IsGettingFullCard() is true until the server
-// returns the full PAN for a masked card.
-TEST_F(FullCardRequestTest, IsGettingFullCardForMaskedServerCard) {
- EXPECT_CALL(*result_delegate(),
- OnFullCardRequestSucceeded(
- testing::Ref(*request()),
- CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
- base::ASCIIToUTF16("123")));
- EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
- EXPECT_CALL(*ui_delegate(),
- OnUnmaskVerificationResult(AutofillClient::SUCCESS));
-
- EXPECT_FALSE(request()->IsGettingFullCard());
-
- request()->GetFullCard(
- CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
- AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
- ui_delegate()->AsWeakPtr());
-
- EXPECT_TRUE(request()->IsGettingFullCard());
-
- CardUnmaskDelegate::UserProvidedUnmaskDetails details;
- details.cvc = base::ASCIIToUTF16("123");
- card_unmask_delegate()->OnUnmaskPromptAccepted(details);
-
- EXPECT_TRUE(request()->IsGettingFullCard());
-
- OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
-
- EXPECT_FALSE(request()->IsGettingFullCard());
-
- card_unmask_delegate()->OnUnmaskPromptClosed();
-
- EXPECT_FALSE(request()->IsGettingFullCard());
-}
-
-// Verify that FullCardRequest::IsGettingFullCard() is true until the user types
-// in the CVC for a card that is not masked.
-TEST_F(FullCardRequestTest, IsGettingFullCardForLocalCard) {
- EXPECT_CALL(
- *result_delegate(),
- OnFullCardRequestSucceeded(testing::Ref(*request()),
- CardMatches(CreditCard::LOCAL_CARD, "4111"),
- base::ASCIIToUTF16("123")));
- EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
- EXPECT_CALL(*ui_delegate(),
- OnUnmaskVerificationResult(AutofillClient::SUCCESS));
-
- EXPECT_FALSE(request()->IsGettingFullCard());
-
- CreditCard card;
- test::SetCreditCardInfo(&card, nullptr, "4111", "12", "2050", "1");
- request()->GetFullCard(card, AutofillClient::UNMASK_FOR_AUTOFILL,
- result_delegate()->AsWeakPtr(),
- ui_delegate()->AsWeakPtr());
-
- EXPECT_TRUE(request()->IsGettingFullCard());
-
- CardUnmaskDelegate::UserProvidedUnmaskDetails details;
- details.cvc = base::ASCIIToUTF16("123");
- card_unmask_delegate()->OnUnmaskPromptAccepted(details);
-
- EXPECT_FALSE(request()->IsGettingFullCard());
-
- card_unmask_delegate()->OnUnmaskPromptClosed();
-
- EXPECT_FALSE(request()->IsGettingFullCard());
-}
-
} // namespace payments
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/legal_message_line.cc b/chromium/components/autofill/core/browser/payments/legal_message_line.cc
index b18bc273c41..34baff793d9 100644
--- a/chromium/components/autofill/core/browser/payments/legal_message_line.cc
+++ b/chromium/components/autofill/core/browser/payments/legal_message_line.cc
@@ -113,7 +113,7 @@ bool LegalMessageLine::ParseLine(const base::Value& line,
const base::Value* template_parameters =
line.FindKeyOfType("template_parameter", base::Value::Type::LIST);
if (template_parameters) {
- const base::Value::ListStorage& template_parameters_storage =
+ base::span<const base::Value> template_parameters_storage =
template_parameters->GetList();
display_texts.reserve(template_parameters_storage.size());
links_.reserve(template_parameters_storage.size());
diff --git a/chromium/components/autofill/core/browser/payments/local_card_migration_manager.cc b/chromium/components/autofill/core/browser/payments/local_card_migration_manager.cc
index f3dae8c54d6..85556ad2c5d 100644
--- a/chromium/components/autofill/core/browser/payments/local_card_migration_manager.cc
+++ b/chromium/components/autofill/core/browser/payments/local_card_migration_manager.cc
@@ -5,8 +5,8 @@
#include "components/autofill/core/browser/payments/local_card_migration_manager.h"
#include <stddef.h>
-
#include <algorithm>
+#include <unordered_map>
#include <vector>
#include "base/bind.h"
@@ -228,9 +228,19 @@ void LocalCardMigrationManager::OnDidGetUploadDetails(
observer_for_testing_->OnReceivedGetUploadDetailsResponse();
if (result == AutofillClient::SUCCESS) {
+ LegalMessageLine::Parse(*legal_message, &legal_message_lines_,
+ /*escape_apostrophes=*/true);
+
+ if (legal_message_lines_.empty()) {
+ AutofillMetrics::LogLocalCardMigrationDecisionMetric(
+ AutofillMetrics::LocalCardMigrationDecisionMetric::
+ NOT_OFFERED_INVALID_LEGAL_MESSAGE);
+ return;
+ }
+
migration_request_.context_token = context_token;
- legal_message_ = base::DictionaryValue::From(std::move(legal_message));
migration_request_.risk_data.clear();
+
// If we successfully received the legal docs, trigger the offer-to-migrate
// dialog. If triggered from settings page, we pop-up the main prompt
// directly. If not, we pop up the intermediate bubble.
@@ -274,6 +284,7 @@ void LocalCardMigrationManager::OnDidGetUploadDetails(
local_card_migration_origin_,
AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN);
}
+
// TODO(crbug.com/876895): Clean up the LoadRiskData Bind/BindRepeating
// usages
client_->LoadRiskData(base::BindRepeating(
@@ -330,6 +341,12 @@ void LocalCardMigrationManager::OnDidMigrateLocalCards(
NOTREACHED();
}
}
+
+ // If at least one card was migrated, notifies the |personal_data_manager_|.
+ // PDM uses this information to update the avatar button UI.
+ if (!migrated_cards.empty())
+ personal_data_manager_->OnCreditCardSaved(/*is_local_card=*/false);
+
// Remove cards that were successfully migrated from local storage.
personal_data_manager_->DeleteLocalCreditCards(migrated_cards);
}
@@ -388,7 +405,7 @@ void LocalCardMigrationManager::ShowMainMigrationDialog() {
local_card_migration_origin_, AutofillMetrics::MAIN_DIALOG_SHOWN);
// Pops up a larger, modal dialog showing the local cards to be uploaded.
client_->ConfirmMigrateLocalCardToCloud(
- std::move(legal_message_),
+ legal_message_lines_,
personal_data_manager_->GetAccountInfoForPaymentsServer().email,
migratable_credit_cards_,
base::BindOnce(
diff --git a/chromium/components/autofill/core/browser/payments/local_card_migration_manager.h b/chromium/components/autofill/core/browser/payments/local_card_migration_manager.h
index d717e199bd0..3f2c73c3720 100644
--- a/chromium/components/autofill/core/browser/payments/local_card_migration_manager.h
+++ b/chromium/components/autofill/core/browser/payments/local_card_migration_manager.h
@@ -7,12 +7,14 @@
#include <memory>
#include <string>
+#include <unordered_map>
#include <utility>
#include <vector>
#include "base/strings/string16.h"
#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/payments/legal_message_line.h"
#include "components/autofill/core/browser/payments/local_card_migration_strike_database.h"
#include "components/autofill/core/browser/payments/payments_client.h"
@@ -209,7 +211,8 @@ class LocalCardMigrationManager {
observer_for_testing_ = observer;
}
- std::unique_ptr<base::DictionaryValue> legal_message_;
+ // The parsed lines from the legal message return from GetUploadDetails.
+ LegalMessageLines legal_message_lines_;
std::string app_locale_;
diff --git a/chromium/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc b/chromium/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
index e1441ba421d..2a09894c0e3 100644
--- a/chromium/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
@@ -1541,4 +1541,19 @@ TEST_F(LocalCardMigrationManagerTest,
AutofillMetrics::LocalCardMigrationDecisionMetric::OFFERED);
}
+// Tests that if payment client returns an invalid legal message migration
+// should not be offered.
+TEST_F(LocalCardMigrationManagerTest,
+ InvalidLegalMessageInOnDidGetUploadDetails) {
+ payments_client_->SetUseInvalidLegalMessageInGetUploadDetails(true);
+
+ base::HistogramTester histogram_tester;
+ UseLocalCardWithOtherLocalCardsOnFile();
+
+ // Verify that the correct histogram entries were logged.
+ ExpectUniqueLocalCardMigrationDecision(
+ histogram_tester, AutofillMetrics::LocalCardMigrationDecisionMetric::
+ NOT_OFFERED_INVALID_LEGAL_MESSAGE);
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/payments_client.cc b/chromium/components/autofill/core/browser/payments/payments_client.cc
index b097a05e500..a7e30b9dcd5 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_client.cc
@@ -56,9 +56,11 @@ const char kUnmaskCardRequestPath[] =
const char kUnmaskCardRequestFormat[] =
"requestContentType=application/json; charset=utf-8&request=%s"
"&s7e_13_cvc=%s";
+const char kUnmaskCardRequestFormatWithoutCvc[] =
+ "requestContentType=application/json; charset=utf-8&request=%s";
const char kOptChangeRequestPath[] =
- "payments/apis/chromepaymentsservice/autofillauthoptchange";
+ "payments/apis/chromepaymentsservice/updateautofilluserpreference";
const char kGetUploadDetailsRequestPath[] =
"payments/apis/chromepaymentsservice/getdetailsforsavecard";
@@ -142,7 +144,7 @@ void AppendStringIfNotEmpty(const AutofillProfile& profile,
base::Value& list) {
const base::string16 value = profile.GetInfo(type, app_locale);
if (!value.empty())
- list.GetList().emplace_back(value);
+ list.Append(value);
}
// Returns a dictionary with the structure expected by Payments RPCs, containing
@@ -228,7 +230,7 @@ void SetActiveExperiments(const std::vector<const char*>& active_experiments,
base::Value active_chrome_experiments(base::Value::Type::LIST);
for (const char* it : active_experiments)
- active_chrome_experiments.GetList().emplace_back(it);
+ active_chrome_experiments.Append(it);
request_dict.SetKey("active_chrome_experiments",
std::move(active_chrome_experiments));
@@ -295,7 +297,7 @@ class GetUnmaskDetailsRequest : public PaymentsRequest {
unmask_details_.fido_request_options = dictionary_value->Clone();
const auto* fido_eligible_card_ids = response.FindKeyOfType(
- "fido_eligible_credit_card_id", base::Value::Type::LIST);
+ "fido_eligible_card_id", base::Value::Type::LIST);
if (fido_eligible_card_ids) {
for (const base::Value& result : fido_eligible_card_ids->GetList()) {
unmask_details_.fido_eligible_card_ids.insert(result.GetString());
@@ -347,9 +349,14 @@ class UnmaskCardRequest : public PaymentsRequest {
std::string GetRequestContent() override {
base::Value request_dict(base::Value::Type::DICTIONARY);
- request_dict.SetKey("encrypted_cvc", base::Value("__param:s7e_13_cvc"));
request_dict.SetKey("credit_card_id",
base::Value(request_details_.card.server_id()));
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillAlwaysReturnCloudTokenizedCard)) {
+ // See b/140727361.
+ request_dict.SetKey("instrument_token",
+ base::Value("INSTRUMENT_TOKEN_FOR_TEST"));
+ }
request_dict.SetKey("risk_data_encoded",
BuildRiskDictionary(request_details_.risk_data));
base::Value context(base::Value::Type::DICTIONARY);
@@ -380,19 +387,33 @@ class UnmaskCardRequest : public PaymentsRequest {
"opt_in_fido_auth",
base::Value(request_details_.user_response.enable_fido_auth));
- if (request_details_.fido_assertion_info.is_dict()) {
+ // Either FIDO assertion info is set or CVC is set, never both.
+ bool is_cvc_auth = !request_details_.user_response.cvc.empty();
+ bool is_fido_auth = request_details_.fido_assertion_info.is_dict();
+
+ DCHECK_NE(is_cvc_auth, is_fido_auth);
+ if (is_cvc_auth) {
+ request_dict.SetKey("encrypted_cvc", base::Value("__param:s7e_13_cvc"));
+ } else {
request_dict.SetKey("fido_assertion_info",
std::move(request_details_.fido_assertion_info));
}
std::string json_request;
base::JSONWriter::Write(request_dict, &json_request);
- std::string request_content = base::StringPrintf(
- kUnmaskCardRequestFormat,
- net::EscapeUrlEncodedData(json_request, true).c_str(),
- net::EscapeUrlEncodedData(
- base::UTF16ToASCII(request_details_.user_response.cvc), true)
- .c_str());
+ std::string request_content;
+ if (is_cvc_auth) {
+ request_content = base::StringPrintf(
+ kUnmaskCardRequestFormat,
+ net::EscapeUrlEncodedData(json_request, true).c_str(),
+ net::EscapeUrlEncodedData(
+ base::UTF16ToASCII(request_details_.user_response.cvc), true)
+ .c_str());
+ } else {
+ request_content = base::StringPrintf(
+ kUnmaskCardRequestFormatWithoutCvc,
+ net::EscapeUrlEncodedData(json_request, true).c_str());
+ }
// Payments is reporting receiving blank or non-standard-length CVCs.
// Log CVC length being sent to gauge how often this is happening.
@@ -414,10 +435,21 @@ class UnmaskCardRequest : public PaymentsRequest {
const auto* pan = response.FindStringKey("pan");
response_details_.real_pan = pan ? *pan : std::string();
+ const auto* dcvv = response.FindStringKey("dcvv");
+ response_details_.dcvv = dcvv ? *dcvv : std::string();
+
const auto* creation_options = response.FindKeyOfType(
"fido_creation_options", base::Value::Type::DICTIONARY);
if (creation_options)
response_details_.fido_creation_options = creation_options->Clone();
+
+ const auto* request_options = response.FindKeyOfType(
+ "fido_request_options", base::Value::Type::DICTIONARY);
+ if (request_options)
+ response_details_.fido_request_options = request_options->Clone();
+
+ const auto* token = response.FindStringKey("card_authorization_token");
+ response_details_.card_authorization_token = token ? *token : std::string();
}
bool IsResponseComplete() override {
@@ -443,7 +475,9 @@ class OptChangeRequest : public PaymentsRequest {
public:
OptChangeRequest(
const PaymentsClient::OptChangeRequestDetails& request_details,
- OptChangeCallback callback,
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ PaymentsClient::OptChangeResponseDetails&)>
+ callback,
const bool full_sync_enabled)
: request_details_(request_details),
callback_(std::move(callback)),
@@ -470,46 +504,84 @@ class OptChangeRequest : public PaymentsRequest {
std::move(chrome_user_context));
}
- request_dict.SetKey("opt_in", base::Value(request_details_.opt_in));
+ std::string reason;
+ switch (request_details_.reason) {
+ case PaymentsClient::OptChangeRequestDetails::ENABLE_FIDO_AUTH:
+ reason = "ENABLE_FIDO_AUTH";
+ break;
+ case PaymentsClient::OptChangeRequestDetails::DISABLE_FIDO_AUTH:
+ reason = "DISABLE_FIDO_AUTH";
+ break;
+ case PaymentsClient::OptChangeRequestDetails::ADD_CARD_FOR_FIDO_AUTH:
+ reason = "ADD_CARD_FOR_FIDO_AUTH";
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ request_dict.SetKey("reason", base::Value(reason));
if (request_details_.fido_authenticator_response.is_dict()) {
- request_dict.SetKey(
+ base::Value fido_authentication_info(base::Value::Type::DICTIONARY);
+
+ fido_authentication_info.SetKey(
"fido_authenticator_response",
std::move(request_details_.fido_authenticator_response));
+
+ if (!request_details_.card_authorization_token.empty()) {
+ fido_authentication_info.SetKey(
+ "card_authorization_token",
+ base::Value(request_details_.card_authorization_token));
+ }
+
+ request_dict.SetKey("fido_authentication_info",
+ std::move(fido_authentication_info));
}
std::string request_content;
base::JSONWriter::Write(request_dict, &request_content);
- VLOG(3) << "autofillauthoptchange request body: " << request_content;
+ VLOG(3) << "updateautofilluserpreference request body: " << request_content;
return request_content;
}
void ParseResponse(const base::Value& response) override {
- const auto* user_is_opted_in =
- response.FindKeyOfType("user_is_opted_in", base::Value::Type::BOOLEAN);
- if (user_is_opted_in)
- user_is_opted_in_ = user_is_opted_in->GetBool();
+ const auto* fido_authentication_info = response.FindKeyOfType(
+ "fido_authentication_info", base::Value::Type::DICTIONARY);
+ if (!fido_authentication_info)
+ return;
- const auto* fido_creation_options = response.FindKeyOfType(
+ const auto* user_status =
+ fido_authentication_info->FindStringKey("user_status");
+ if (user_status && *user_status != "UNKNOWN_USER_STATUS")
+ response_details_.user_is_opted_in =
+ (*user_status == "FIDO_AUTH_ENABLED");
+
+ const auto* fido_creation_options = fido_authentication_info->FindKeyOfType(
"fido_creation_options", base::Value::Type::DICTIONARY);
if (fido_creation_options)
- fido_creation_options_ = fido_creation_options->Clone();
+ response_details_.fido_creation_options = fido_creation_options->Clone();
+
+ const auto* fido_request_options = fido_authentication_info->FindKeyOfType(
+ "fido_request_options", base::Value::Type::DICTIONARY);
+ if (fido_request_options)
+ response_details_.fido_request_options = fido_request_options->Clone();
}
- bool IsResponseComplete() override { return user_is_opted_in_.has_value(); }
+ bool IsResponseComplete() override {
+ return response_details_.user_is_opted_in.has_value();
+ }
void RespondToDelegate(AutofillClient::PaymentsRpcResult result) override {
- std::move(callback_).Run(
- result, user_is_opted_in_.value_or(!request_details_.opt_in),
- std::move(fido_creation_options_));
+ std::move(callback_).Run(result, response_details_);
}
private:
PaymentsClient::OptChangeRequestDetails request_details_;
- OptChangeCallback callback_;
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ PaymentsClient::OptChangeResponseDetails&)>
+ callback_;
const bool full_sync_enabled_;
- base::Optional<bool> user_is_opted_in_;
- base::Value fido_creation_options_;
+ PaymentsClient::OptChangeResponseDetails response_details_;
DISALLOW_COPY_AND_ASSIGN(OptChangeRequest);
};
@@ -568,8 +640,7 @@ class GetUploadDetailsRequest : public PaymentsRequest {
// min address is not possible). The final parameter directs
// BuildAddressDictionary to omit names and phone numbers, which aren't
// useful for these purposes.
- addresses.GetList().push_back(
- BuildAddressDictionary(profile, app_locale_, false));
+ addresses.Append(BuildAddressDictionary(profile, app_locale_, false));
}
request_dict.SetKey("address", std::move(addresses));
@@ -740,8 +811,7 @@ class UploadCardRequest : public PaymentsRequest {
base::Value addresses(base::Value::Type::LIST);
for (const AutofillProfile& profile : request_details_.profiles) {
- addresses.GetList().push_back(
- BuildAddressDictionary(profile, app_locale, true));
+ addresses.Append(BuildAddressDictionary(profile, app_locale, true));
}
request_dict.SetKey("address", std::move(addresses));
@@ -859,7 +929,7 @@ class MigrateCardsRequest : public PaymentsRequest {
for (size_t index = 0; index < migratable_credit_cards_.size(); ++index) {
std::string pan_field_name = GetPanFieldName(index);
// Generate credit card dictionary.
- migrate_cards.GetList().push_back(BuildCreditCardDictionary(
+ migrate_cards.Append(BuildCreditCardDictionary(
migratable_credit_cards_[index].credit_card(), app_locale,
pan_field_name));
// Append pan data to the |all_pans_data|.
@@ -968,6 +1038,12 @@ operator=(const PaymentsClient::UnmaskResponseDetails& other) {
} else {
fido_creation_options.reset();
}
+ if (other.fido_request_options.has_value()) {
+ fido_request_options = other.fido_request_options->Clone();
+ } else {
+ fido_request_options.reset();
+ }
+ card_authorization_token = other.card_authorization_token;
return *this;
}
@@ -975,11 +1051,30 @@ PaymentsClient::OptChangeRequestDetails::OptChangeRequestDetails() {}
PaymentsClient::OptChangeRequestDetails::OptChangeRequestDetails(
const OptChangeRequestDetails& other) {
app_locale = other.app_locale;
- opt_in = other.opt_in;
+ reason = other.reason;
fido_authenticator_response = other.fido_authenticator_response.Clone();
+ card_authorization_token = other.card_authorization_token;
}
PaymentsClient::OptChangeRequestDetails::~OptChangeRequestDetails() {}
+PaymentsClient::OptChangeResponseDetails::OptChangeResponseDetails() {}
+PaymentsClient::OptChangeResponseDetails::OptChangeResponseDetails(
+ const OptChangeResponseDetails& other) {
+ user_is_opted_in = other.user_is_opted_in;
+
+ if (other.fido_creation_options.has_value()) {
+ fido_creation_options = other.fido_creation_options->Clone();
+ } else {
+ fido_creation_options.reset();
+ }
+ if (other.fido_request_options.has_value()) {
+ fido_request_options = other.fido_request_options->Clone();
+ } else {
+ fido_request_options.reset();
+ }
+}
+PaymentsClient::OptChangeResponseDetails::~OptChangeResponseDetails() {}
+
PaymentsClient::UploadRequestDetails::UploadRequestDetails() {}
PaymentsClient::UploadRequestDetails::UploadRequestDetails(
const UploadRequestDetails& other) = default;
@@ -1027,8 +1122,11 @@ void PaymentsClient::UnmaskCard(
/*authenticate=*/true);
}
-void PaymentsClient::OptChange(const OptChangeRequestDetails request_details,
- OptChangeCallback callback) {
+void PaymentsClient::OptChange(
+ const OptChangeRequestDetails request_details,
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ PaymentsClient::OptChangeResponseDetails&)>
+ callback) {
IssueRequest(std::make_unique<OptChangeRequest>(
request_details, std::move(callback),
account_info_getter_->IsSyncFeatureEnabled()),
@@ -1231,7 +1329,7 @@ void PaymentsClient::StartTokenFetch(bool invalidate_old) {
identity::ScopeSet payments_scopes;
payments_scopes.insert(kPaymentsOAuth2Scope);
- std::string account_id =
+ CoreAccountId account_id =
account_info_getter_->GetAccountInfoForPaymentsServer().account_id;
if (invalidate_old) {
DCHECK(!access_token_.empty());
diff --git a/chromium/components/autofill/core/browser/payments/payments_client.h b/chromium/components/autofill/core/browser/payments/payments_client.h
index 07523979cc2..9ce00b334e2 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client.h
+++ b/chromium/components/autofill/core/browser/payments/payments_client.h
@@ -53,11 +53,6 @@ typedef base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
AutofillClient::UnmaskDetails&)>
GetUnmaskDetailsCallback;
-// Callback type for OptChange callback.
-typedef base::OnceCallback<
- void(AutofillClient::PaymentsRpcResult, bool, base::Value)>
- OptChangeCallback;
-
// Billable service number is defined in Payments server to distinguish
// different requests.
const int kUnmaskCardBillableServiceNumber = 70154;
@@ -106,8 +101,22 @@ class PaymentsClient {
return *this;
}
+ UnmaskResponseDetails& with_dcvv(std::string d) {
+ dcvv = d;
+ return *this;
+ }
+
std::string real_pan;
- base::Optional<base::Value> fido_creation_options;
+ std::string dcvv;
+ // Challenge required for enrolling user into FIDO authentication for future
+ // card unmasking.
+ base::Optional<base::Value> fido_creation_options = base::nullopt;
+ // Challenge required for authorizing user for FIDO authentication for
+ // future card unmasking.
+ base::Optional<base::Value> fido_request_options = base::nullopt;
+ // An opaque token used to logically chain consecutive UnmaskCard and
+ // OptChange calls together.
+ std::string card_authorization_token = std::string();
};
// Information required to either opt-in or opt-out a user for FIDO
@@ -118,8 +127,45 @@ class PaymentsClient {
~OptChangeRequestDetails();
std::string app_locale;
- bool opt_in;
+
+ // The reason for making the request.
+ enum Reason {
+ // Unknown default.
+ UNKNOWN_REASON = 0,
+ // The user wants to enable FIDO authentication for card unmasking.
+ ENABLE_FIDO_AUTH = 1,
+ // The user wants to disable FIDO authentication for card unmasking.
+ DISABLE_FIDO_AUTH = 2,
+ // The user is authorizing a new card for future FIDO authentication
+ // unmasking.
+ ADD_CARD_FOR_FIDO_AUTH = 3,
+ };
+
+ // Reason for the request.
+ Reason reason;
+ // Signature required for enrolling user into FIDO authentication for future
+ // card unmasking.
base::Value fido_authenticator_response;
+ // An opaque token used to logically chain consecutive UnmaskCard and
+ // OptChange calls together.
+ std::string card_authorization_token = std::string();
+ };
+
+ // Information retrieved from an OptChange request.
+ struct OptChangeResponseDetails {
+ OptChangeResponseDetails();
+ OptChangeResponseDetails(const OptChangeResponseDetails& other);
+ ~OptChangeResponseDetails();
+
+ // Unset if response failed. True if user is opted-in for FIDO
+ // authentication for card unmasking. False otherwise.
+ base::Optional<bool> user_is_opted_in;
+ // Challenge required for enrolling user into FIDO authentication for future
+ // card unmasking.
+ base::Optional<base::Value> fido_creation_options;
+ // Challenge required for authorizing user for FIDO authentication for
+ // future card unmasking.
+ base::Optional<base::Value> fido_request_options;
};
// A collection of the information required to make a credit card upload
@@ -206,8 +252,11 @@ class PaymentsClient {
// Opts-in or opts-out the user to use FIDO authentication for card unmasking
// on this device.
- void OptChange(const OptChangeRequestDetails request_details,
- OptChangeCallback callback);
+ void OptChange(
+ const OptChangeRequestDetails request_details,
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ PaymentsClient::OptChangeResponseDetails&)>
+ callback);
// Determine if the user meets the Payments service's conditions for upload.
// The service uses |addresses| (from which names and phone numbers are
diff --git a/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc b/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc
index 39f0e812a59..10d0dfc4bbd 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc
@@ -24,6 +24,7 @@
#include "components/autofill/core/browser/payments/local_card_migration_manager.h"
#include "components/autofill/core/browser/payments/payments_client.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/autofill/core/common/autofill_switches.h"
@@ -140,13 +141,15 @@ class PaymentsClientTest : public testing::Test {
unmask_response_details_ = &response;
}
- void OnDidGetOptChangeResult(AutofillClient::PaymentsRpcResult result,
- bool user_is_opted_in,
- base::Value fido_creation_options) {
+ void OnDidGetOptChangeResult(
+ AutofillClient::PaymentsRpcResult result,
+ PaymentsClient::OptChangeResponseDetails& response) {
result_ = result;
- user_is_opted_in_ = user_is_opted_in;
- if (fido_creation_options.is_dict())
- fido_creation_options_ = fido_creation_options.Clone();
+ opt_change_response_.user_is_opted_in = response.user_is_opted_in;
+ opt_change_response_.fido_creation_options =
+ std::move(response.fido_creation_options);
+ opt_change_response_.fido_request_options =
+ std::move(response.fido_request_options);
}
void OnDidGetUploadDetails(
@@ -209,9 +212,10 @@ class PaymentsClientTest : public testing::Test {
// If |opt_in| is set to true, then opts the user in to use FIDO
// authentication for card unmasking. Otherwise opts the user out.
- void StartOptChangeRequest(bool opt_in) {
+ void StartOptChangeRequest(
+ PaymentsClient::OptChangeRequestDetails::Reason reason) {
PaymentsClient::OptChangeRequestDetails request_details;
- request_details.opt_in = opt_in;
+ request_details.reason = reason;
client_->OptChange(
request_details,
base::BindOnce(&PaymentsClientTest::OnDidGetOptChangeResult,
@@ -279,7 +283,7 @@ class PaymentsClientTest : public testing::Test {
void IssueOAuthToken() {
identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"totally_real_token",
- base::Time::Now() + base::TimeDelta::FromDays(10));
+ AutofillClock::Now() + base::TimeDelta::FromDays(10));
// Verify the auth header.
std::string auth_header_value;
@@ -299,10 +303,8 @@ class PaymentsClientTest : public testing::Test {
// Server ID of a saved card via credit card upload save.
std::string server_id_;
- // Status of the user's FIDO auth opt-in; returned from an OptChange call.
- base::Optional<bool> user_is_opted_in_;
- // FIDO auth enrollment creation options; returned from an OptChange call.
- base::Value fido_creation_options_;
+ // The OptChangeResponseDetails retrieved from an OptChangeRequest.
+ PaymentsClient::OptChangeResponseDetails opt_change_response_;
// The UnmaskResponseDetails retrieved from an UnmaskRequest. Includes PAN.
PaymentsClient::UnmaskResponseDetails* unmask_response_details_ = nullptr;
// The legal message returned from a GetDetails upload save preflight call.
@@ -428,11 +430,13 @@ TEST_F(PaymentsClientTest, UnmaskSuccessViaFIDO) {
TEST_F(PaymentsClientTest, UnmaskSuccessViaCVCWithCreationOptions) {
StartUnmasking(CardUnmaskOptions().with_use_fido(false));
IssueOAuthToken();
- ReturnResponse(net::HTTP_OK,
- "{ \"pan\": \"1234\", \"fido_creation_options\": "
- "{\"relying_party_id\": \"google.com\"}}");
+ ReturnResponse(
+ net::HTTP_OK,
+ "{ \"pan\": \"1234\", \"dcvv\": \"321\", \"fido_creation_options\": "
+ "{\"relying_party_id\": \"google.com\"}}");
EXPECT_EQ(AutofillClient::SUCCESS, result_);
EXPECT_EQ("1234", unmask_response_details_->real_pan);
+ EXPECT_EQ("321", unmask_response_details_->dcvv);
EXPECT_EQ("google.com",
*unmask_response_details_->fido_creation_options->FindStringKey(
"relying_party_id"));
@@ -514,51 +518,51 @@ TEST_F(PaymentsClientTest, UnmaskLogsCvcLengthForPaymentRequest) {
"Autofill.CardUnmask.CvcLength.ForPaymentRequest", 5, 1);
}
-TEST_F(PaymentsClientTest, UnmaskLogsBlankCvcLength) {
- base::HistogramTester histogram_tester;
- StartUnmasking(CardUnmaskOptions()
- .with_reason(AutofillClient::UNMASK_FOR_AUTOFILL)
- .with_cvc(""));
- IssueOAuthToken();
-
- histogram_tester.ExpectBucketCount(
- "Autofill.CardUnmask.CvcLength.ForAutofill", 0, 1);
-}
-
TEST_F(PaymentsClientTest, OptInSuccess) {
- StartOptChangeRequest(/*opt_in=*/true);
+ StartOptChangeRequest(
+ PaymentsClient::OptChangeRequestDetails::ENABLE_FIDO_AUTH);
IssueOAuthToken();
- ReturnResponse(net::HTTP_OK, "{ \"user_is_opted_in\": true }");
+ ReturnResponse(net::HTTP_OK,
+ "{ \"fido_authentication_info\": { \"user_status\": "
+ "\"FIDO_AUTH_ENABLED\"}}");
EXPECT_EQ(AutofillClient::SUCCESS, result_);
- EXPECT_TRUE(user_is_opted_in_.value());
+ EXPECT_TRUE(opt_change_response_.user_is_opted_in.value());
}
TEST_F(PaymentsClientTest, OptInServerUnresponsive) {
- StartOptChangeRequest(/*opt_in=*/true);
+ StartOptChangeRequest(
+ PaymentsClient::OptChangeRequestDetails::ENABLE_FIDO_AUTH);
IssueOAuthToken();
ReturnResponse(net::HTTP_REQUEST_TIMEOUT, "");
EXPECT_EQ(AutofillClient::NETWORK_ERROR, result_);
- EXPECT_FALSE(user_is_opted_in_.value());
+ EXPECT_FALSE(opt_change_response_.user_is_opted_in.has_value());
}
TEST_F(PaymentsClientTest, OptOutSuccess) {
- StartOptChangeRequest(/*opt_in=*/false);
+ StartOptChangeRequest(
+ PaymentsClient::OptChangeRequestDetails::DISABLE_FIDO_AUTH);
IssueOAuthToken();
- ReturnResponse(net::HTTP_OK, "{ \"user_is_opted_in\": false }");
+ ReturnResponse(net::HTTP_OK,
+ "{ \"fido_authentication_info\": { \"user_status\": "
+ "\"FIDO_AUTH_DISABLED\"}}");
EXPECT_EQ(AutofillClient::SUCCESS, result_);
- EXPECT_FALSE(user_is_opted_in_.value());
+ EXPECT_FALSE(opt_change_response_.user_is_opted_in.value());
}
TEST_F(PaymentsClientTest, EnrollAttemptReturnsCreationOptions) {
- StartOptChangeRequest(/*opt_in=*/true);
+ StartOptChangeRequest(
+ PaymentsClient::OptChangeRequestDetails::ENABLE_FIDO_AUTH);
IssueOAuthToken();
ReturnResponse(net::HTTP_OK,
- "{ \"user_is_opted_in\": false, \"fido_creation_options\": { "
- "\"relying_party_id\": \"google.com\"} }");
+ "{ \"fido_authentication_info\": { \"user_status\": "
+ "\"FIDO_AUTH_DISABLED\","
+ "\"fido_creation_options\": {"
+ "\"relying_party_id\": \"google.com\"}}}");
EXPECT_EQ(AutofillClient::SUCCESS, result_);
- EXPECT_FALSE(user_is_opted_in_.value());
+ EXPECT_FALSE(opt_change_response_.user_is_opted_in.value());
EXPECT_EQ("google.com",
- *fido_creation_options_.FindStringKey("relying_party_id"));
+ *opt_change_response_.fido_creation_options->FindStringKey(
+ "relying_party_id"));
}
TEST_F(PaymentsClientTest, GetDetailsSuccess) {
@@ -806,7 +810,7 @@ TEST_F(PaymentsClientTest, GetUploadAccountFromSyncTest) {
// Issue a token for the secondary account.
identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
secondary_account_info.account_id, "secondary_account_token",
- base::Time::Now() + base::TimeDelta::FromDays(10));
+ AutofillClock::Now() + base::TimeDelta::FromDays(10));
// Verify the auth header.
std::string auth_header_value;
diff --git a/chromium/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.cc b/chromium/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.cc
index e8a556c8081..bce45685589 100644
--- a/chromium/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.cc
+++ b/chromium/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.cc
@@ -22,12 +22,14 @@ TestCreditCardFIDOAuthenticator::~TestCreditCardFIDOAuthenticator() {}
void TestCreditCardFIDOAuthenticator::GetAssertion(
PublicKeyCredentialRequestOptionsPtr request_options) {
- request_options_ = std::move(request_options);
+ request_options_ = request_options->Clone();
+ CreditCardFIDOAuthenticator::GetAssertion(std::move(request_options));
}
void TestCreditCardFIDOAuthenticator::MakeCredential(
PublicKeyCredentialCreationOptionsPtr creation_options) {
- creation_options_ = std::move(creation_options);
+ creation_options_ = creation_options->Clone();
+ CreditCardFIDOAuthenticator::MakeCredential(std::move(creation_options));
}
// static
diff --git a/chromium/components/autofill/core/browser/payments/test_payments_client.cc b/chromium/components/autofill/core/browser/payments/test_payments_client.cc
index 88ba1252ce0..144de6532c2 100644
--- a/chromium/components/autofill/core/browser/payments/test_payments_client.cc
+++ b/chromium/components/autofill/core/browser/payments/test_payments_client.cc
@@ -7,7 +7,9 @@
#include <memory>
#include <unordered_map>
+#include "base/json/json_reader.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -33,7 +35,8 @@ TestPaymentsClient::~TestPaymentsClient() {}
void TestPaymentsClient::GetUnmaskDetails(GetUnmaskDetailsCallback callback,
const std::string& app_locale) {
- std::move(callback).Run(AutofillClient::SUCCESS, unmask_details_);
+ if (should_return_unmask_details_)
+ std::move(callback).Run(AutofillClient::SUCCESS, unmask_details_);
}
void TestPaymentsClient::GetUploadDetails(
@@ -56,7 +59,7 @@ void TestPaymentsClient::GetUploadDetails(
app_locale == "en-US" ? AutofillClient::SUCCESS
: AutofillClient::PERMANENT_FAILURE,
base::ASCIIToUTF16("this is a context token"),
- std::unique_ptr<base::Value>(nullptr), supported_card_bin_ranges_);
+ TestPaymentsClient::LegalMessage(), supported_card_bin_ranges_);
}
void TestPaymentsClient::UploadCard(
@@ -76,13 +79,20 @@ void TestPaymentsClient::MigrateCards(
"this is display text");
}
+void TestPaymentsClient::ShouldReturnUnmaskDetailsImmediately(
+ bool should_return_unmask_details) {
+ should_return_unmask_details_ = should_return_unmask_details;
+}
+
void TestPaymentsClient::AllowFidoRegistration(bool offer_fido_opt_in) {
+ should_return_unmask_details_ = true;
unmask_details_.offer_fido_opt_in = offer_fido_opt_in;
}
void TestPaymentsClient::AddFidoEligibleCard(std::string server_id,
std::string credential_id,
std::string relying_party_id) {
+ should_return_unmask_details_ = true;
unmask_details_.offer_fido_opt_in = false;
unmask_details_.unmask_auth_method = AutofillClient::UnmaskAuthMethod::FIDO;
unmask_details_.fido_eligible_card_ids.insert(server_id);
@@ -136,5 +146,40 @@ void TestPaymentsClient::SetSupportedBINRanges(
supported_card_bin_ranges_ = bin_ranges;
}
+void TestPaymentsClient::SetUseInvalidLegalMessageInGetUploadDetails(
+ bool use_invalid_legal_message) {
+ use_invalid_legal_message_ = use_invalid_legal_message;
+}
+
+std::unique_ptr<base::Value> TestPaymentsClient::LegalMessage() {
+ if (use_invalid_legal_message_) {
+ // Legal message is invalid because it's missing the url.
+ return std::unique_ptr<base::Value>(
+ base::JSONReader::ReadDeprecated("{"
+ " \"line\" : [ {"
+ " \"template\": \"Panda {0}.\","
+ " \"template_parameter\": [ {"
+ " \"display_text\": \"bear\""
+ " } ]"
+ " } ]"
+ "}"));
+ return std::unique_ptr<base::Value>(base::JSONReader::ReadDeprecated("{}"));
+ } else {
+ return std::unique_ptr<base::Value>(base::JSONReader::ReadDeprecated(
+ "{"
+ " \"line\" : [ {"
+ " \"template\": \"The legal documents are: {0} and {1}.\","
+ " \"template_parameter\" : [ {"
+ " \"display_text\" : \"Terms of Service\","
+ " \"url\": \"http://www.example.com/tos\""
+ " }, {"
+ " \"display_text\" : \"Privacy Policy\","
+ " \"url\": \"http://www.example.com/pp\""
+ " } ]"
+ " } ]"
+ "}"));
+ }
+}
+
} // namespace payments
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/test_payments_client.h b/chromium/components/autofill/core/browser/payments/test_payments_client.h
index 01763edd62f..03ffcc0bea3 100644
--- a/chromium/components/autofill/core/browser/payments/test_payments_client.h
+++ b/chromium/components/autofill/core/browser/payments/test_payments_client.h
@@ -56,6 +56,10 @@ class TestPaymentsClient : public payments::PaymentsClient {
const std::vector<MigratableCreditCard>& migratable_credit_cards,
MigrateCardsCallback callback) override;
+ // Some metrics are affected by the latency of GetUnmaskDetails, so it is
+ // useful to control whether or not GetUnmaskDetails() is responded to.
+ void ShouldReturnUnmaskDetailsImmediately(bool should_return_unmask_details);
+
void AllowFidoRegistration(bool offer_fido_opt_in = true);
void AddFidoEligibleCard(std::string server_id,
@@ -70,6 +74,9 @@ class TestPaymentsClient : public payments::PaymentsClient {
void SetSupportedBINRanges(std::vector<std::pair<int, int>> bin_ranges);
+ void SetUseInvalidLegalMessageInGetUploadDetails(
+ bool use_invalid_legal_message);
+
int detected_values_in_upload_details() const { return detected_values_; }
const std::vector<AutofillProfile>& addresses_in_upload_details() const {
return upload_details_addresses_;
@@ -89,6 +96,9 @@ class TestPaymentsClient : public payments::PaymentsClient {
private:
std::string server_id_;
+ // Some metrics are affected by the latency of GetUnmaskDetails, so it is
+ // useful to control whether or not GetUnmaskDetails() is responded to.
+ bool should_return_unmask_details_ = true;
AutofillClient::UnmaskDetails unmask_details_;
std::vector<std::pair<int, int>> supported_card_bin_ranges_;
std::vector<AutofillProfile> upload_details_addresses_;
@@ -99,6 +109,8 @@ class TestPaymentsClient : public payments::PaymentsClient {
int billable_service_number_;
PaymentsClient::UploadCardSource upload_card_source_;
std::unique_ptr<std::unordered_map<std::string, std::string>> save_result_;
+ bool use_invalid_legal_message_ = false;
+ std::unique_ptr<base::Value> LegalMessage();
DISALLOW_COPY_AND_ASSIGN(TestPaymentsClient);
};
diff --git a/chromium/components/autofill/core/browser/payments/test_strike_database.cc b/chromium/components/autofill/core/browser/payments/test_strike_database.cc
index 7b96773e25b..d80df7cbac1 100644
--- a/chromium/components/autofill/core/browser/payments/test_strike_database.cc
+++ b/chromium/components/autofill/core/browser/payments/test_strike_database.cc
@@ -5,6 +5,7 @@
#include "components/autofill/core/browser/payments/test_strike_database.h"
#include "components/autofill/core/browser/proto/strike_data.pb.h"
+#include "components/autofill/core/common/autofill_clock.h"
namespace autofill {
@@ -36,7 +37,7 @@ void TestStrikeDatabase::AddEntryWithNumStrikes(const std::string& key,
StrikeData strike_data;
strike_data.set_num_strikes(num_strikes);
strike_data.set_last_update_timestamp(
- base::Time::Now().ToDeltaSinceWindowsEpoch().InMicroseconds());
+ AutofillClock::Now().ToDeltaSinceWindowsEpoch().InMicroseconds());
db_[key] = strike_data;
}
diff --git a/chromium/components/autofill/core/browser/payments/upi_vpa_save_manager.cc b/chromium/components/autofill/core/browser/payments/upi_vpa_save_manager.cc
new file mode 100644
index 00000000000..324fbfc53bc
--- /dev/null
+++ b/chromium/components/autofill/core/browser/payments/upi_vpa_save_manager.cc
@@ -0,0 +1,21 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/payments/upi_vpa_save_manager.h"
+
+#include "base/logging.h"
+
+namespace autofill {
+
+UpiVpaSaveManager::UpiVpaSaveManager(PersonalDataManager* personal_data_manager)
+ : personal_data_manager_(personal_data_manager) {}
+
+void UpiVpaSaveManager::OfferLocalSave(const std::string& upi_id) {
+ // TODO(crbug.com/986289): Ask user with a prompt before saving.
+
+ if (personal_data_manager_)
+ personal_data_manager_->AddVPA(upi_id);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/upi_vpa_save_manager.h b/chromium/components/autofill/core/browser/payments/upi_vpa_save_manager.h
new file mode 100644
index 00000000000..b97a6330969
--- /dev/null
+++ b/chromium/components/autofill/core/browser/payments/upi_vpa_save_manager.h
@@ -0,0 +1,29 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_UPI_VPA_SAVE_MANAGER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_UPI_VPA_SAVE_MANAGER_H_
+
+#include "base/strings/string16.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+
+namespace autofill {
+
+class UpiVpaSaveManager {
+ public:
+ UpiVpaSaveManager(PersonalDataManager* personal_data_manager);
+ ~UpiVpaSaveManager() = default;
+
+ void OfferLocalSave(const std::string& upi_id);
+
+ private:
+ // The personal data manager, used to save and load personal data to/from the
+ // web database. This is overridden by the AutofillManagerTest.
+ // Weak reference. May be nullptr, which indicates OTR.
+ PersonalDataManager* personal_data_manager_;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_UPI_VPA_SAVE_MANAGER_H_
diff --git a/chromium/components/autofill/core/browser/personal_data_manager.cc b/chromium/components/autofill/core/browser/personal_data_manager.cc
index 41cd4d5bb74..10787c72754 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager.cc
@@ -47,6 +47,7 @@
#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_features.h"
+#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/autofill_util.h"
@@ -641,6 +642,13 @@ void PersonalDataManager::RecordUseOf(const AutofillDataModel& data_model) {
}
}
+void PersonalDataManager::AddVPA(const std::string& vpa_id) {
+ DCHECK(!vpa_id.empty());
+ if (is_off_the_record_ || !database_helper_->GetLocalDatabase())
+ return;
+ database_helper_->GetLocalDatabase()->AddVPA(vpa_id);
+}
+
void PersonalDataManager::AddProfile(const AutofillProfile& profile) {
if (!IsAutofillProfileEnabled())
return;
@@ -1305,7 +1313,7 @@ bool PersonalDataManager::ShouldSuggestServerCards() const {
// seeing them in the dropdown.
if (!prefs::IsUserOptedInWalletSyncTransport(
pref_service_,
- sync_service_->GetAuthenticatedAccountInfo().account_id)) {
+ sync_service_->GetAuthenticatedAccountInfo().account_id.id)) {
return false;
}
}
@@ -1349,7 +1357,6 @@ void PersonalDataManager::ClearProfileNonSettingsOrigins() {
UpdateProfileInDB(*profile, /*enforced=*/true);
}
}
-
}
void PersonalDataManager::ClearCreditCardNonSettingsOrigins() {
@@ -1369,35 +1376,6 @@ void PersonalDataManager::ClearCreditCardNonSettingsOrigins() {
Refresh();
}
-void PersonalDataManager::MoveJapanCityToStreetAddress() {
- if (!database_helper_->GetLocalDatabase())
- return;
-
- // Don't run if the migration has already been performed.
- if (pref_service_->GetBoolean(prefs::kAutofillJapanCityFieldMigrated))
- return;
-
- base::string16 japan_country_code = base::ASCIIToUTF16("JP");
- base::string16 line_separator = base::ASCIIToUTF16("\n");
- for (AutofillProfile* profile : GetProfiles()) {
- base::string16 country_code = profile->GetRawInfo(ADDRESS_HOME_COUNTRY);
- base::string16 city = profile->GetRawInfo(ADDRESS_HOME_CITY);
- if (country_code == japan_country_code && !city.empty()) {
- base::string16 street_address =
- profile->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS);
- street_address = street_address.empty()
- ? city
- : street_address + line_separator + city;
- profile->SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, street_address);
- profile->SetRawInfo(ADDRESS_HOME_CITY, base::string16());
- UpdateProfileInDB(*profile, /*enforced=*/true);
- }
- }
-
- // Set the pref so that this migration is never run again.
- pref_service_->SetBoolean(prefs::kAutofillJapanCityFieldMigrated, true);
-}
-
void PersonalDataManager::OnValidated(const AutofillProfile* profile) {
if (!profile)
return;
@@ -1452,94 +1430,6 @@ const ProfileValidityMap& PersonalDataManager::GetProfileValidityByGUID(
return empty_validity_map;
}
-// static
-std::string PersonalDataManager::MergeProfile(
- const AutofillProfile& new_profile,
- std::vector<std::unique_ptr<AutofillProfile>>* existing_profiles,
- const std::string& app_locale,
- std::vector<AutofillProfile>* merged_profiles) {
- merged_profiles->clear();
-
- // Sort the existing profiles in decreasing order of frecency, so the "best"
- // profiles are checked first. Put the verified profiles last so the non
- // verified profiles get deduped among themselves before reaching the verified
- // profiles.
- // TODO(crbug.com/620521): Remove the check for verified from the sort.
- base::Time comparison_time = AutofillClock::Now();
- std::sort(existing_profiles->begin(), existing_profiles->end(),
- [comparison_time](const std::unique_ptr<AutofillProfile>& a,
- const std::unique_ptr<AutofillProfile>& b) {
- if (a->IsVerified() != b->IsVerified())
- return !a->IsVerified();
- return a->HasGreaterFrecencyThan(b.get(), comparison_time);
- });
-
- // Set to true if |existing_profiles| already contains an equivalent profile.
- bool matching_profile_found = false;
- std::string guid = new_profile.guid();
-
- // If we have already saved this address, merge in any missing values.
- // Only merge with the first match. Merging the new profile into the existing
- // one preserves the validity of credit card's billing address reference.
- AutofillProfileComparator comparator(app_locale);
- for (const auto& existing_profile : *existing_profiles) {
- if (!matching_profile_found &&
- comparator.AreMergeable(new_profile, *existing_profile) &&
- existing_profile->SaveAdditionalInfo(new_profile, app_locale)) {
- // Unverified profiles should always be updated with the newer data,
- // whereas verified profiles should only ever be overwritten by verified
- // data. If an automatically aggregated profile would overwrite a
- // verified profile, just drop it.
- matching_profile_found = true;
- guid = existing_profile->guid();
-
- // We set the modification date so that immediate requests for profiles
- // will properly reflect the fact that this profile has been modified
- // recently. After writing to the database and refreshing the local copies
- // the profile will have a very slightly newer time reflecting what's
- // actually stored in the database.
- existing_profile->set_modification_date(AutofillClock::Now());
- }
- merged_profiles->push_back(*existing_profile);
- }
-
- // If the new profile was not merged with an existing one, add it to the list.
- if (!matching_profile_found) {
- merged_profiles->push_back(new_profile);
- // Similar to updating merged profiles above, set the modification date on
- // new profiles.
- merged_profiles->back().set_modification_date(AutofillClock::Now());
- AutofillMetrics::LogProfileActionOnFormSubmitted(
- AutofillMetrics::NEW_PROFILE_CREATED);
- }
-
- return guid;
-}
-
-bool PersonalDataManager::IsCountryOfInterest(
- const std::string& country_code) const {
- DCHECK_EQ(2U, country_code.size());
-
- const std::vector<AutofillProfile*>& profiles = GetProfiles();
- std::list<std::string> country_codes;
- for (size_t i = 0; i < profiles.size(); ++i) {
- country_codes.push_back(base::ToLowerASCII(
- base::UTF16ToASCII(profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY))));
- }
-
- std::string timezone_country = CountryCodeForCurrentTimezone();
- if (!timezone_country.empty())
- country_codes.push_back(base::ToLowerASCII(timezone_country));
-
- // Only take the locale into consideration if all else fails.
- if (country_codes.empty()) {
- country_codes.push_back(base::ToLowerASCII(
- AutofillCountry::CountryCodeForLocale(app_locale())));
- }
-
- return base::Contains(country_codes, base::ToLowerASCII(country_code));
-}
-
const std::string& PersonalDataManager::GetDefaultCountryCodeForNewAddress()
const {
if (default_country_code_.empty())
@@ -1762,8 +1652,8 @@ std::string PersonalDataManager::SaveImportedProfile(
return std::string();
std::vector<AutofillProfile> profiles;
- std::string guid =
- MergeProfile(imported_profile, &web_profiles_, app_locale_, &profiles);
+ std::string guid = AutofillProfileComparator::MergeProfile(
+ imported_profile, &web_profiles_, app_locale_, &profiles);
SetProfiles(&profiles);
return guid;
}
@@ -1799,6 +1689,10 @@ std::string PersonalDataManager::SaveImportedCreditCard(
credit_cards.push_back(imported_card);
SetCreditCards(&credit_cards);
+
+ // After a card is saved locally, notifies the observers.
+ OnCreditCardSaved(/*is_local_card=*/true);
+
return guid;
}
@@ -1945,7 +1839,8 @@ bool PersonalDataManager::ShouldShowCardsFromAccountOption() const {
features::kAutofillEnableAccountWalletStorage));
bool is_opted_in = prefs::IsUserOptedInWalletSyncTransport(
- pref_service_, sync_service_->GetAuthenticatedAccountInfo().account_id);
+ pref_service_,
+ sync_service_->GetAuthenticatedAccountInfo().account_id.id);
AutofillMetrics::LogWalletSyncTransportCardsOptIn(is_opted_in);
@@ -1957,7 +1852,7 @@ void PersonalDataManager::OnUserAcceptedCardsFromAccountOption() {
DCHECK_EQ(AutofillSyncSigninState::kSignedInAndWalletSyncTransportEnabled,
GetSyncSigninState());
prefs::SetUserOptedInWalletSyncTransport(
- pref_service_, sync_service_->GetAuthenticatedAccountInfo().account_id,
+ pref_service_, sync_service_->GetAuthenticatedAccountInfo().account_id.id,
/*opted_in=*/true);
}
@@ -2014,7 +1909,8 @@ void PersonalDataManager::OnUserAcceptedUpstreamOffer() {
if (GetSyncSigninState() ==
AutofillSyncSigninState::kSignedInAndWalletSyncTransportEnabled) {
prefs::SetUserOptedInWalletSyncTransport(
- pref_service_, sync_service_->GetAuthenticatedAccountInfo().account_id,
+ pref_service_,
+ sync_service_->GetAuthenticatedAccountInfo().account_id.id,
/*opted_in=*/true);
}
}
@@ -2033,6 +1929,16 @@ void PersonalDataManager::NotifyPersonalDataObserver() {
}
}
+void PersonalDataManager::OnCreditCardSaved(bool is_local_card) {
+ if (!base::FeatureList::IsEnabled(
+ features::kAutofillCreditCardUploadFeedback)) {
+ return;
+ }
+ for (PersonalDataManagerObserver& observer : observers_)
+ observer.OnCreditCardSaved(
+ /*should_show_sign_in_promo_if_applicable=*/is_local_card);
+}
+
std::vector<Suggestion> PersonalDataManager::GetSuggestionsForCards(
const AutofillType& type,
const base::string16& field_contents,
@@ -2421,9 +2327,6 @@ void PersonalDataManager::ApplyAddressFixesAndCleanups() {
// Ran everytime it is called.
ClearProfileNonSettingsOrigins();
-
- // One-time fix, otherwise NOP.
- MoveJapanCityToStreetAddress();
}
void PersonalDataManager::ApplyCardFixesAndCleanups() {
diff --git a/chromium/components/autofill/core/browser/personal_data_manager.h b/chromium/components/autofill/core/browser/personal_data_manager.h
index 912b4542d40..0e652553e43 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager.h
+++ b/chromium/components/autofill/core/browser/personal_data_manager.h
@@ -154,6 +154,10 @@ class PersonalDataManager : public KeyedService,
std::string OnAcceptedLocalCreditCardSave(
const CreditCard& imported_credit_card);
+ // Triggered when the user accepts saving a VPA value. Stores the |vpa_id| to
+ // the database.
+ virtual void AddVPA(const std::string& vpa_id);
+
// Adds |profile| to the web database.
virtual void AddProfile(const AutofillProfile& profile);
@@ -264,12 +268,6 @@ class PersonalDataManager : public KeyedService,
// Returns the profiles to suggest to the user, ordered by frecency.
std::vector<AutofillProfile*> GetProfilesToSuggest() const;
- // Remove profiles that whose |type| field is flagged as invalid, if Chrome
- // is configured to not make suggestions based on invalid data.
- static void MaybeRemoveInvalidSuggestions(
- const AutofillType& type,
- std::vector<AutofillProfile*>* profiles);
-
// Returns Suggestions corresponding to the focused field's |type| and
// |field_contents|, i.e. what the user has typed. |field_is_autofilled| is
// true if the field has already been autofilled, and |field_types| stores the
@@ -325,22 +323,6 @@ class PersonalDataManager : public KeyedService,
const std::string& app_locale() const { return app_locale_; }
- // Merges |new_profile| into one of the |existing_profiles| if possible;
- // otherwise appends |new_profile| to the end of that list. Fills
- // |merged_profiles| with the result. Returns the |guid| of the new or updated
- // profile.
- static std::string MergeProfile(
- const AutofillProfile& new_profile,
- std::vector<std::unique_ptr<AutofillProfile>>* existing_profiles,
- const std::string& app_locale,
- std::vector<AutofillProfile>* merged_profiles);
-
- // Returns true if |country_code| is a country that the user is likely to
- // be associated with the user. More concretely, it checks if there are any
- // addresses with this country or if the user's system timezone is in the
- // given country.
- virtual bool IsCountryOfInterest(const std::string& country_code) const;
-
// Returns our best guess for the country a user is likely to use when
// inputting a new address. The value is calculated once and cached, so it
// will only update when Chrome is restarted.
@@ -387,6 +369,10 @@ class PersonalDataManager : public KeyedService,
// Notifies observers that the waiting should be stopped.
void NotifyPersonalDataObserver();
+ // Called when at least one (can be multiple) card was saved. |is_local_card|
+ // indicates if the card is saved to local storage.
+ void OnCreditCardSaved(bool is_local_card);
+
void set_client_profile_validator_for_test(
AutofillProfileValidator* validator) {
client_profile_validator_ = validator;
@@ -466,8 +452,6 @@ class PersonalDataManager : public KeyedService,
FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
ClearCreditCardNonSettingsOrigins);
FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
- MoveJapanCityToStreetAddress);
- FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
RequestProfileServerValidity);
FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
GetProfileSuggestions_Validity);
@@ -555,12 +539,6 @@ class PersonalDataManager : public KeyedService,
void ClearProfileNonSettingsOrigins();
void ClearCreditCardNonSettingsOrigins();
- // Appends the value of the city field of a JP address to its street address
- // field, separated by a newline, and clears the city field.
- // TODO(rouslan): Remove this migration in or after October 2019. See bug:
- // https://crbug.com/871301
- void MoveJapanCityToStreetAddress();
-
// Called when the |profile| is validated by the AutofillProfileValidator,
// updates the profiles on the |ongoing_profile_changes_| and the DB.
virtual void OnValidated(const AutofillProfile* profile);
@@ -703,13 +681,6 @@ class PersonalDataManager : public KeyedService,
void RemoveAutofillProfileByGUIDAndBlankCreditCardReference(
const std::string& guid);
- // Returns true if an address can be deleted in a major version upgrade.
- // An address is deletable if it is unverified, and not used by a valid
- // credit card as billing address, and not used for a long time(13 months).
- bool IsAddressDeletable(
- AutofillProfile* profile,
- const std::unordered_set<std::string>& used_billing_address_guids);
-
// Applies various fixes and cleanups on autofill addresses.
void ApplyAddressFixesAndCleanups();
diff --git a/chromium/components/autofill/core/browser/personal_data_manager_observer.h b/chromium/components/autofill/core/browser/personal_data_manager_observer.h
index d09bc934f9e..4a40dbba366 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager_observer.h
+++ b/chromium/components/autofill/core/browser/personal_data_manager_observer.h
@@ -13,7 +13,7 @@ namespace autofill {
class PersonalDataManagerObserver {
public:
// Notifies the observer that the PersonalDataManager changed in some way.
- virtual void OnPersonalDataChanged() = 0;
+ virtual void OnPersonalDataChanged() {}
// Called when there is insufficient data to fill a form. Used for testing.
virtual void OnInsufficientFormData() {}
@@ -22,6 +22,11 @@ class PersonalDataManagerObserver {
// handle.
virtual void OnPersonalDataFinishedProfileTasks() {}
+ // Notifies the observer whenever at least one (can be multiple) credit card
+ // is suceesfully saved.
+ virtual void OnCreditCardSaved(bool should_show_sign_in_promo_if_applicable) {
+ }
+
protected:
virtual ~PersonalDataManagerObserver() {}
};
diff --git a/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc b/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
index ed12c5048f9..16972154375 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -286,19 +286,8 @@ class PersonalDataManagerTestBase {
return account_info;
}
- void MoveJapanCityToStreetAddress(PersonalDataManager* personal_data,
- int move_times) {
- base::RunLoop run_loop;
- EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
- .WillRepeatedly(QuitMessageLoop(&run_loop));
- EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
- .Times(move_times);
- personal_data->MoveJapanCityToStreetAddress();
- run_loop.Run();
- }
-
- base::test::TaskEnvironment task_environment_{
- base::test::TaskEnvironment::MainThreadType::UI};
+ base::test::SingleThreadTaskEnvironment task_environment_{
+ base::test::SingleThreadTaskEnvironment::MainThreadType::UI};
std::unique_ptr<PrefService> prefs_;
network::TestURLLoaderFactory test_url_loader_factory_;
signin::IdentityTestEnvironment identity_test_env_;
@@ -958,7 +947,7 @@ TEST_F(PersonalDataManagerTest, SaveImportedProfileSetModificationDate) {
SaveImportedProfileToPersonalDataManager(profile);
const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
ASSERT_EQ(1U, profiles.size());
- EXPECT_GT(base::TimeDelta::FromMilliseconds(1000),
+ EXPECT_GT(base::TimeDelta::FromMilliseconds(2000),
AutofillClock::Now() - profiles[0]->modification_date());
}
@@ -1338,7 +1327,6 @@ TEST_F(PersonalDataManagerTest, AddFullCardAsMaskedCard) {
"378282246310005" /* American Express */, "04",
"2999", "1");
-
personal_data_->AddFullServerCreditCard(server_card);
WaitForOnPersonalDataChanged();
@@ -2773,7 +2761,7 @@ TEST_F(PersonalDataManagerTest,
profile2.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(10));
profile2.set_use_count(1);
- EXPECT_TRUE(profile1.HasGreaterFrecencyThan(&profile2, base::Time::Now()));
+ EXPECT_TRUE(profile1.HasGreaterFrecencyThan(&profile2, AutofillClock::Now()));
AddProfileToPersonalDataManager(profile1);
AddProfileToPersonalDataManager(profile2);
@@ -4478,7 +4466,7 @@ TEST_F(PersonalDataManagerTest, MergeProfile_Frecency) {
// Merge the imported profile into the existing profiles.
std::vector<AutofillProfile> profiles;
- std::string guid = personal_data_->MergeProfile(
+ std::string guid = AutofillProfileComparator::MergeProfile(
imported_profile, &existing_profiles, "US-EN", &profiles);
// The new profile should be merged into the "fox" profile.
@@ -4527,7 +4515,7 @@ TEST_F(PersonalDataManagerTest, MAYBE_MergeProfile_UsageStats) {
// Merge the imported profile into the existing profiles.
std::vector<AutofillProfile> profiles;
- std::string guid = personal_data_->MergeProfile(
+ std::string guid = AutofillProfileComparator::MergeProfile(
imported_profile, &existing_profiles, "US-EN", &profiles);
// The new profile should be merged into the existing profile.
@@ -6881,108 +6869,6 @@ TEST_F(PersonalDataManagerTest, ClearCreditCardNonSettingsOrigins) {
personal_data_->GetCreditCardsToSuggest(false)[3]->origin());
}
-// Tests that all city fields in a Japan profile are moved to the street address
-// field.
-TEST_F(PersonalDataManagerTest, MoveJapanCityToStreetAddress) {
- // Turn on sync feature to avoid calling MoveJapanCityToStreetAddress on
- // adding the profiles implicitly.
- ASSERT_TRUE(TurnOnSyncFeature());
- // A US profile with both street address and a city.
- std::string guid0 = base::GenerateGUID();
- {
- AutofillProfile profile0(guid0, test::kEmptyOrigin);
- test::SetProfileInfo(&profile0, "Homer", "J", "Simpson",
- "homer.simpson@abc.com", "", "742. Evergreen Terrace",
- "", "Springfield", "IL", "91601", "US", "");
- AddProfileToPersonalDataManager(profile0);
- }
-
- // A JP profile with both street address and a city.
- std::string guid1 = base::GenerateGUID();
- {
- AutofillProfile profile1(guid1, test::kEmptyOrigin);
- test::SetProfileInfo(&profile1, "Homer", "J", "Simpson",
- "homer.simpson@abc.com", "", "742. Evergreen Terrace",
- "", "Springfield", "IL", "91601", "JP", "");
- AddProfileToPersonalDataManager(profile1);
- }
-
- // A JP profile with only a city.
- std::string guid2 = base::GenerateGUID();
- {
- AutofillProfile profile2(guid2, test::kEmptyOrigin);
- test::SetProfileInfo(&profile2, "Homer", "J", "Simpson",
- "homer.simpson@abc.com", "", "", "", "Springfield",
- "IL", "91601", "JP", "");
- AddProfileToPersonalDataManager(profile2);
- }
-
- // A JP profile with only a street address.
- std::string guid3 = base::GenerateGUID();
- {
- AutofillProfile profile3(guid3, test::kEmptyOrigin);
- test::SetProfileInfo(&profile3, "Homer", "J", "Simpson",
- "homer.simpson@abc.com", "", "742. Evergreen Terrace",
- "", "", "IL", "91601", "JP", "");
- AddProfileToPersonalDataManager(profile3);
- }
-
- // A JP profile with neither a street address nor a city.
- std::string guid4 = base::GenerateGUID();
- {
- AutofillProfile profile4(guid4, test::kEmptyOrigin);
- test::SetProfileInfo(&profile4, "Homer", "J", "Simpson",
- "homer.simpson@abc.com", "", "", "", "", "IL", "91601",
- "JP", "");
- AddProfileToPersonalDataManager(profile4);
- }
- auto profiles = personal_data_->GetProfiles();
- ASSERT_EQ(5U, profiles.size());
-
- MoveJapanCityToStreetAddress(
- personal_data_.get(),
- 2); // For the japan profiles where the city is not empty.
-
- {
- AutofillProfile* profile0 = personal_data_->GetProfileByGUID(guid0);
- EXPECT_EQ(base::ASCIIToUTF16("742. Evergreen Terrace"),
- profile0->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
- EXPECT_EQ(base::ASCIIToUTF16("Springfield"),
- profile0->GetRawInfo(ADDRESS_HOME_CITY));
- }
-
- {
- AutofillProfile* profile1 = personal_data_->GetProfileByGUID(guid1);
- EXPECT_EQ(base::ASCIIToUTF16("742. Evergreen Terrace\nSpringfield"),
- profile1->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
- EXPECT_EQ(base::ASCIIToUTF16("742. Evergreen Terrace"),
- profile1->GetRawInfo(ADDRESS_HOME_LINE1));
- EXPECT_EQ(base::ASCIIToUTF16("Springfield"),
- profile1->GetRawInfo(ADDRESS_HOME_LINE2));
- EXPECT_TRUE(profile1->GetRawInfo(ADDRESS_HOME_CITY).empty());
- }
-
- {
- AutofillProfile* profile2 = personal_data_->GetProfileByGUID(guid2);
- EXPECT_EQ(base::ASCIIToUTF16("Springfield"),
- profile2->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
- EXPECT_TRUE(profile2->GetRawInfo(ADDRESS_HOME_CITY).empty());
- }
-
- {
- AutofillProfile* profile3 = personal_data_->GetProfileByGUID(guid3);
- EXPECT_EQ(base::ASCIIToUTF16("742. Evergreen Terrace"),
- profile3->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
- EXPECT_TRUE(profile3->GetRawInfo(ADDRESS_HOME_CITY).empty());
- }
-
- {
- AutofillProfile* profile4 = personal_data_->GetProfileByGUID(guid4);
- EXPECT_TRUE(profile4->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS).empty());
- EXPECT_TRUE(profile4->GetRawInfo(ADDRESS_HOME_CITY).empty());
- }
-}
-
// Tests that all the non settings origins of autofill profiles are cleared even
// if sync is disabled.
TEST_F(
@@ -7192,7 +7078,7 @@ TEST_F(PersonalDataManagerTest, RequestProfileServerValidity) {
AutofillDataModel::INVALID, AutofillDataModel::VALID,
AutofillDataModel::UNVALIDATED, AutofillDataModel::INVALID};
ASSERT_EQ(types.size(), states.size());
- for (unsigned long i = 0; i < types.size(); ++i) {
+ for (uint64_t i = 0; i < types.size(); ++i) {
(*profile_validity_map
.mutable_field_validity_states())[static_cast<int>(types[i])] =
static_cast<int>(states[i]);
@@ -7231,7 +7117,7 @@ TEST_F(PersonalDataManagerTest, RequestProfileServerValidity) {
auto validities =
personal_data_->GetProfileValidityByGUID(guid).field_validity_states();
ASSERT_EQ(validities.size(), types.size());
- for (unsigned long i = 0; i < types.size(); ++i)
+ for (uint64_t i = 0; i < types.size(); ++i)
EXPECT_EQ(validities.at(types[i]), states[i]);
guid = "00000000-0000-0000-0000-0000000000002";
@@ -7952,7 +7838,7 @@ namespace {
class OneTimeObserver : public PersonalDataManagerObserver {
public:
- OneTimeObserver(PersonalDataManager* manager) : manager_(manager) {}
+ explicit OneTimeObserver(PersonalDataManager* manager) : manager_(manager) {}
~OneTimeObserver() override {
if (manager_)
diff --git a/chromium/components/autofill/core/browser/proto/server.proto b/chromium/components/autofill/core/browser/proto/server.proto
index 67002a10096..72e0e4f60bc 100644
--- a/chromium/components/autofill/core/browser/proto/server.proto
+++ b/chromium/components/autofill/core/browser/proto/server.proto
@@ -337,11 +337,11 @@ message AutofillUploadContents {
// Whether the password has any lowercase letter.
optional bool password_has_lowercase_letter = 25;
- // Whether the password has any uppercase letter.
- optional bool password_has_uppercase_letter = 26;
+ // Deprecated since M80: Whether the password has any uppercase letter.
+ optional bool password_has_uppercase_letter = 26 [deprecated = true];
- // Whether the password has any digit.
- optional bool password_has_numeric = 27;
+ // Deprecated since M80: Whether the password has any digit.
+ optional bool password_has_numeric = 27 [deprecated = true];
// Whether the password has any special symbol.
optional bool password_has_special_symbol = 28;
diff --git a/chromium/components/autofill/core/browser/test_autofill_client.cc b/chromium/components/autofill/core/browser/test_autofill_client.cc
index 89baf299c69..a04561e1fe1 100644
--- a/chromium/components/autofill/core/browser/test_autofill_client.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_client.cc
@@ -88,7 +88,7 @@ void TestAutofillClient::ShowLocalCardMigrationDialog(
}
void TestAutofillClient::ConfirmMigrateLocalCardToCloud(
- std::unique_ptr<base::DictionaryValue> legal_message,
+ const LegalMessageLines& legal_message_lines,
const std::string& user_email,
const std::vector<MigratableCreditCard>& migratable_credit_cards,
LocalCardMigrationCallback start_migrating_cards_callback) {
@@ -107,9 +107,20 @@ void TestAutofillClient::ShowLocalCardMigrationResults(
const std::vector<MigratableCreditCard>& migratable_credit_cards,
MigrationDeleteCardCallback delete_local_card_callback) {}
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+void TestAutofillClient::ShowVerifyPendingDialog(
+ base::OnceClosure cancel_card_verification_callback) {}
+
+void TestAutofillClient::CloseVerifyPendingDialog() {}
+#endif
+
void TestAutofillClient::ShowWebauthnOfferDialog(
WebauthnOfferDialogCallback callback) {}
+bool TestAutofillClient::CloseWebauthnOfferDialog() {
+ return true;
+}
+
void TestAutofillClient::ConfirmSaveAutofillProfile(
const AutofillProfile& profile,
base::OnceClosure callback) {
@@ -128,13 +139,15 @@ void TestAutofillClient::ConfirmSaveCreditCardLocally(
std::move(callback).Run(AutofillClient::ACCEPTED);
}
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_IOS)
void TestAutofillClient::ConfirmAccountNameFixFlow(
base::OnceCallback<void(const base::string16&)> callback) {
credit_card_name_fix_flow_bubble_was_shown_ = true;
std::move(callback).Run(base::string16(base::ASCIIToUTF16("Gaia Name")));
}
+#endif // defined(OS_ANDROID) || defined(OS_IOS)
+#if defined(OS_ANDROID)
void TestAutofillClient::ConfirmExpirationDateFixFlow(
const CreditCard& card,
base::OnceCallback<void(const base::string16&, const base::string16&)>
@@ -148,7 +161,7 @@ void TestAutofillClient::ConfirmExpirationDateFixFlow(
void TestAutofillClient::ConfirmSaveCreditCardToCloud(
const CreditCard& card,
- std::unique_ptr<base::DictionaryValue> legal_message,
+ const LegalMessageLines& legal_message_lines,
SaveCreditCardOptions options,
UploadSaveCardPromptCallback callback) {
offer_to_save_credit_card_bubble_was_shown_ = options.show_prompt;
diff --git a/chromium/components/autofill/core/browser/test_autofill_client.h b/chromium/components/autofill/core/browser/test_autofill_client.h
index 2f8b9bdda12..92b7019d260 100644
--- a/chromium/components/autofill/core/browser/test_autofill_client.h
+++ b/chromium/components/autofill/core/browser/test_autofill_client.h
@@ -16,6 +16,7 @@
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/mock_autocomplete_history_manager.h"
+#include "components/autofill/core/browser/payments/legal_message_line.h"
#include "components/autofill/core/browser/payments/test_payments_client.h"
#include "components/autofill/core/browser/payments/test_strike_database.h"
#include "components/autofill/core/browser/test_address_normalizer.h"
@@ -55,7 +56,7 @@ class TestAutofillClient : public AutofillClient {
void ShowLocalCardMigrationDialog(
base::OnceClosure show_migration_dialog_closure) override;
void ConfirmMigrateLocalCardToCloud(
- std::unique_ptr<base::DictionaryValue> legal_message,
+ const LegalMessageLines& legal_message_lines,
const std::string& user_email,
const std::vector<MigratableCreditCard>& migratable_credit_cards,
LocalCardMigrationCallback start_migrating_cards_callback) override;
@@ -64,16 +65,25 @@ class TestAutofillClient : public AutofillClient {
const base::string16& tip_message,
const std::vector<MigratableCreditCard>& migratable_credit_cards,
MigrationDeleteCardCallback delete_local_card_callback) override;
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+ void ShowVerifyPendingDialog(
+ base::OnceClosure cancel_card_verification_callback) override;
+ void CloseVerifyPendingDialog() override;
+#endif
void ShowWebauthnOfferDialog(WebauthnOfferDialogCallback callback) override;
+ bool CloseWebauthnOfferDialog() override;
void ConfirmSaveAutofillProfile(const AutofillProfile& profile,
base::OnceClosure callback) override;
void ConfirmSaveCreditCardLocally(
const CreditCard& card,
SaveCreditCardOptions options,
LocalSaveCardPromptCallback callback) override;
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_IOS)
void ConfirmAccountNameFixFlow(
base::OnceCallback<void(const base::string16&)> callback) override;
+#endif // defined(OS_ANDROID) || defined(OS_IOS)
+
+#if defined(OS_ANDROID)
void ConfirmExpirationDateFixFlow(
const CreditCard& card,
base::OnceCallback<void(const base::string16&, const base::string16&)>
@@ -81,7 +91,7 @@ class TestAutofillClient : public AutofillClient {
#endif // defined(OS_ANDROID)
void ConfirmSaveCreditCardToCloud(
const CreditCard& card,
- std::unique_ptr<base::DictionaryValue> legal_message,
+ const LegalMessageLines& legal_message_lines,
SaveCreditCardOptions options,
UploadSaveCardPromptCallback callback) override;
void CreditCardUploadCompleted(bool card_saved) override;
diff --git a/chromium/components/autofill/core/browser/test_autofill_clock.h b/chromium/components/autofill/core/browser/test_autofill_clock.h
index 2b973619433..19ea0a8962b 100644
--- a/chromium/components/autofill/core/browser/test_autofill_clock.h
+++ b/chromium/components/autofill/core/browser/test_autofill_clock.h
@@ -19,7 +19,7 @@ namespace autofill {
// Handles the customization of the time in tests. Replaces the clock in
// AutofillClock with a test version that can be manipulated from this class.
// Automatically resets a normal clock to AutofillClock when this gets
-// destroyed,
+// destroyed.
class TestAutofillClock {
public:
TestAutofillClock();
diff --git a/chromium/components/autofill/core/browser/test_autofill_driver.cc b/chromium/components/autofill/core/browser/test_autofill_driver.cc
index dd51b9637b6..e7ce762307b 100644
--- a/chromium/components/autofill/core/browser/test_autofill_driver.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_driver.cc
@@ -79,7 +79,7 @@ void TestAutofillDriver::RendererShouldPreviewFieldWithValue(
}
void TestAutofillDriver::RendererShouldSetSuggestionAvailability(
- bool available) {}
+ const mojom::AutofillState state) {}
void TestAutofillDriver::PopupHidden() {
}
diff --git a/chromium/components/autofill/core/browser/test_autofill_driver.h b/chromium/components/autofill/core/browser/test_autofill_driver.h
index d65c2b23cd8..f524de90b92 100644
--- a/chromium/components/autofill/core/browser/test_autofill_driver.h
+++ b/chromium/components/autofill/core/browser/test_autofill_driver.h
@@ -46,7 +46,8 @@ class TestAutofillDriver : public AutofillDriver {
void RendererShouldFillFieldWithValue(const base::string16& value) override;
void RendererShouldPreviewFieldWithValue(
const base::string16& value) override;
- void RendererShouldSetSuggestionAvailability(bool available) override;
+ void RendererShouldSetSuggestionAvailability(
+ const mojom::AutofillState state) override;
void PopupHidden() override;
gfx::RectF TransformBoundingBoxToViewportCoordinates(
const gfx::RectF& bounding_box) override;
diff --git a/chromium/components/autofill/core/browser/test_autofill_external_delegate.cc b/chromium/components/autofill/core/browser/test_autofill_external_delegate.cc
index f38acc764ca..d97cfccf5c2 100644
--- a/chromium/components/autofill/core/browser/test_autofill_external_delegate.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_external_delegate.cc
@@ -68,8 +68,11 @@ bool TestAutofillExternalDelegate::HasActiveScreenReader() const {
}
void TestAutofillExternalDelegate::OnAutofillAvailabilityEvent(
- bool has_suggestions) {
- has_suggestions_available_on_field_focus_ = has_suggestions;
+ const mojom::AutofillState state) {
+ if (state == mojom::AutofillState::kAutofillAvailable)
+ has_suggestions_available_on_field_focus_ = true;
+ else if (state == mojom::AutofillState::kNoSuggestions)
+ has_suggestions_available_on_field_focus_ = false;
}
void TestAutofillExternalDelegate::WaitForPopupHidden() {
diff --git a/chromium/components/autofill/core/browser/test_autofill_external_delegate.h b/chromium/components/autofill/core/browser/test_autofill_external_delegate.h
index 7757ba9682e..2aa50399df6 100644
--- a/chromium/components/autofill/core/browser/test_autofill_external_delegate.h
+++ b/chromium/components/autofill/core/browser/test_autofill_external_delegate.h
@@ -31,7 +31,7 @@ class TestAutofillExternalDelegate : public AutofillExternalDelegate {
bool autoselect_first_suggestion,
bool is_all_server_suggestions) override;
bool HasActiveScreenReader() const override;
- void OnAutofillAvailabilityEvent(bool has_suggestions) override;
+ void OnAutofillAvailabilityEvent(const mojom::AutofillState state) override;
// Functions unique to TestAutofillExternalDelegate.
diff --git a/chromium/components/autofill/core/browser/test_autofill_tick_clock.cc b/chromium/components/autofill/core/browser/test_autofill_tick_clock.cc
new file mode 100644
index 00000000000..c558ed8b8f6
--- /dev/null
+++ b/chromium/components/autofill/core/browser/test_autofill_tick_clock.cc
@@ -0,0 +1,31 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/test_autofill_tick_clock.h"
+
+#include <utility>
+
+#include "base/test/simple_test_tick_clock.h"
+#include "components/autofill/core/common/autofill_tick_clock.h"
+
+namespace autofill {
+
+TestAutofillTickClock::TestAutofillTickClock() {
+ AutofillTickClock::SetTestTickClock(&test_tick_clock_);
+}
+
+TestAutofillTickClock::~TestAutofillTickClock() {
+ // Destroys the test tick_clock and resets a normal tick_clock.
+ AutofillTickClock::SetTickClock();
+}
+
+void TestAutofillTickClock::SetNowTicks(base::TimeTicks now) {
+ test_tick_clock_.SetNowTicks(now);
+}
+
+void TestAutofillTickClock::Advance(base::TimeDelta delta) {
+ test_tick_clock_.Advance(delta);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/test_autofill_tick_clock.h b/chromium/components/autofill/core/browser/test_autofill_tick_clock.h
new file mode 100644
index 00000000000..481d493725c
--- /dev/null
+++ b/chromium/components/autofill/core/browser/test_autofill_tick_clock.h
@@ -0,0 +1,42 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_TICK_CLOCK_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_TICK_CLOCK_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/test/simple_test_tick_clock.h"
+
+namespace base {
+class TimeTicks;
+} // namespace base
+
+namespace autofill {
+
+// Handles the customization of the time in tests. Replaces the tick_clock in
+// AutofillTickClock with a test version that can be manipulated from this
+// class. Automatically resets a normal tick_clock to AutofillTickClock when
+// this gets destroyed.
+class TestAutofillTickClock {
+ public:
+ TestAutofillTickClock();
+ ~TestAutofillTickClock();
+
+ // Set the time to be returned from AutofillTickClock::Now() calls.
+ void SetNowTicks(base::TimeTicks now);
+
+ // Advances the tick_clock by |delta|.
+ void Advance(base::TimeDelta delta);
+
+ private:
+ base::SimpleTestTickClock test_tick_clock_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestAutofillTickClock);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_TICK_CLOCK_H_
diff --git a/chromium/components/autofill/core/browser/test_personal_data_manager.cc b/chromium/components/autofill/core/browser/test_personal_data_manager.cc
index f1d48c3d9bc..02cdc5f4ebb 100644
--- a/chromium/components/autofill/core/browser/test_personal_data_manager.cc
+++ b/chromium/components/autofill/core/browser/test_personal_data_manager.cc
@@ -46,6 +46,10 @@ std::string TestPersonalDataManager::SaveImportedCreditCard(
return imported_credit_card.guid();
}
+void TestPersonalDataManager::AddVPA(const std::string& profile) {
+ num_times_save_vpa_called_++;
+}
+
void TestPersonalDataManager::AddProfile(const AutofillProfile& profile) {
std::unique_ptr<AutofillProfile> profile_ptr =
std::make_unique<AutofillProfile>(profile);
@@ -222,8 +226,7 @@ bool TestPersonalDataManager::ShouldSuggestServerCards() const {
return IsAutofillCreditCardEnabled() && IsAutofillWalletImportEnabled();
}
-std::string TestPersonalDataManager::CountryCodeForCurrentTimezone()
- const {
+std::string TestPersonalDataManager::CountryCodeForCurrentTimezone() const {
return timezone_country_code_;
}
diff --git a/chromium/components/autofill/core/browser/test_personal_data_manager.h b/chromium/components/autofill/core/browser/test_personal_data_manager.h
index 688fe7fc9b8..a4d9dde9e4e 100644
--- a/chromium/components/autofill/core/browser/test_personal_data_manager.h
+++ b/chromium/components/autofill/core/browser/test_personal_data_manager.h
@@ -34,6 +34,7 @@ class TestPersonalDataManager : public PersonalDataManager {
const AutofillProfile& imported_profile) override;
std::string SaveImportedCreditCard(
const CreditCard& imported_credit_card) override;
+ void AddVPA(const std::string& vpa) override;
void AddProfile(const AutofillProfile& profile) override;
void UpdateProfile(const AutofillProfile& profile) override;
void RemoveByGUID(const std::string& guid) override;
@@ -91,6 +92,8 @@ class TestPersonalDataManager : public PersonalDataManager {
return num_times_save_imported_credit_card_called_;
}
+ int num_times_save_vpa_called() const { return num_times_save_vpa_called_; }
+
bool sync_service_initialized() const { return sync_service_initialized_; }
void SetAutofillEnabled(bool autofill_enabled) {
@@ -129,6 +132,7 @@ class TestPersonalDataManager : public PersonalDataManager {
std::string default_country_code_;
int num_times_save_imported_profile_called_ = 0;
int num_times_save_imported_credit_card_called_ = 0;
+ int num_times_save_vpa_called_ = 0;
base::Optional<bool> autofill_enabled_;
base::Optional<bool> autofill_profile_enabled_;
base::Optional<bool> autofill_credit_card_enabled_;
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller.h b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller.h
new file mode 100644
index 00000000000..96d9faeb47f
--- /dev/null
+++ b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller.h
@@ -0,0 +1,36 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_CARD_NAME_FIX_FLOW_CONTROLLER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_CARD_NAME_FIX_FLOW_CONTROLLER_H_
+
+#include "base/strings/string16.h"
+
+namespace autofill {
+
+// Enables the user to accept or deny cardholder name fix flow prompt.
+// Only used on mobile.
+class CardNameFixFlowController {
+ public:
+ virtual ~CardNameFixFlowController() {}
+
+ // Interaction.
+ virtual void OnConfirmNameDialogClosed() = 0;
+ virtual void OnNameAccepted(const base::string16& name) = 0;
+ virtual void OnDismissed() = 0;
+
+ // State.
+ virtual int GetIconId() const = 0;
+ virtual base::string16 GetCancelButtonLabel() const = 0;
+ virtual base::string16 GetInferredCardholderName() const = 0;
+ virtual base::string16 GetInferredNameTooltipText() const = 0;
+ virtual base::string16 GetInputLabel() const = 0;
+ virtual base::string16 GetInputPlaceholderText() const = 0;
+ virtual base::string16 GetSaveButtonLabel() const = 0;
+ virtual base::string16 GetTitleText() const = 0;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_CARD_NAME_FIX_FLOW_CONTROLLER_H_
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl.cc b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl.cc
new file mode 100644
index 00000000000..ea355c2fbff
--- /dev/null
+++ b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl.cc
@@ -0,0 +1,127 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "build/branding_buildflags.h"
+#include "build/build_config.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/ui/payments/card_name_fix_flow_view.h"
+#include "components/grit/components_scaled_resources.h"
+#include "components/strings/grit/components_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace autofill {
+
+CardNameFixFlowControllerImpl::CardNameFixFlowControllerImpl() {}
+
+CardNameFixFlowControllerImpl::~CardNameFixFlowControllerImpl() {
+ if (card_name_fix_flow_view_)
+ card_name_fix_flow_view_->ControllerGone();
+
+ if (shown_ && !had_user_interaction_) {
+ AutofillMetrics::LogCardholderNameFixFlowPromptEvent(
+ AutofillMetrics::
+ CARDHOLDER_NAME_FIX_FLOW_PROMPT_CLOSED_WITHOUT_INTERACTION);
+ }
+}
+
+void CardNameFixFlowControllerImpl::Show(
+ CardNameFixFlowView* card_name_fix_flow_view,
+ const base::string16& inferred_cardholder_name,
+ base::OnceCallback<void(const base::string16&)> name_accepted_callback) {
+ DCHECK(!name_accepted_callback.is_null());
+ DCHECK(card_name_fix_flow_view);
+
+ if (card_name_fix_flow_view_)
+ card_name_fix_flow_view_->ControllerGone();
+ card_name_fix_flow_view_ = card_name_fix_flow_view;
+
+ name_accepted_callback_ = std::move(name_accepted_callback);
+
+ inferred_cardholder_name_ = inferred_cardholder_name;
+ AutofillMetrics::LogSaveCardCardholderNamePrefilled(
+ !inferred_cardholder_name_.empty());
+
+ card_name_fix_flow_view_->Show();
+ AutofillMetrics::LogCardholderNameFixFlowPromptEvent(
+ AutofillMetrics::CARDHOLDER_NAME_FIX_FLOW_PROMPT_SHOWN);
+ shown_ = true;
+}
+
+void CardNameFixFlowControllerImpl::OnConfirmNameDialogClosed() {
+ card_name_fix_flow_view_ = nullptr;
+}
+
+void CardNameFixFlowControllerImpl::OnNameAccepted(const base::string16& name) {
+ AutofillMetrics::LogCardholderNameFixFlowPromptEvent(
+ AutofillMetrics::CARDHOLDER_NAME_FIX_FLOW_PROMPT_ACCEPTED);
+ had_user_interaction_ = true;
+ AutofillMetrics::LogSaveCardCardholderNameWasEdited(
+ inferred_cardholder_name_ != name);
+ base::string16 trimmed_name;
+ base::TrimWhitespace(name, base::TRIM_ALL, &trimmed_name);
+ std::move(name_accepted_callback_).Run(trimmed_name);
+}
+
+void CardNameFixFlowControllerImpl::OnDismissed() {
+ AutofillMetrics::LogCardholderNameFixFlowPromptEvent(
+ AutofillMetrics::CARDHOLDER_NAME_FIX_FLOW_PROMPT_DISMISSED);
+ had_user_interaction_ = true;
+}
+
+int CardNameFixFlowControllerImpl::GetIconId() const {
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+ return IDR_AUTOFILL_GOOGLE_PAY_WITH_DIVIDER;
+#else
+ return 0;
+#endif
+}
+
+base::string16 CardNameFixFlowControllerImpl::GetCancelButtonLabel() const {
+ return l10n_util::GetStringUTF16(IDS_CANCEL);
+}
+
+base::string16 CardNameFixFlowControllerImpl::GetInferredCardholderName()
+ const {
+ return inferred_cardholder_name_;
+}
+
+base::string16 CardNameFixFlowControllerImpl::GetInferredNameTooltipText()
+ const {
+ return l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_SAVE_CARD_PROMPT_CARDHOLDER_NAME_TOOLTIP);
+}
+
+base::string16 CardNameFixFlowControllerImpl::GetInputLabel() const {
+ return l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_SAVE_CARD_PROMPT_CARDHOLDER_NAME);
+}
+
+base::string16 CardNameFixFlowControllerImpl::GetInputPlaceholderText() const {
+ return l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_SAVE_CARD_PROMPT_CARDHOLDER_NAME);
+}
+
+base::string16 CardNameFixFlowControllerImpl::GetSaveButtonLabel() const {
+#if defined(OS_IOS)
+ return l10n_util::GetStringUTF16(IDS_SAVE);
+#else
+ return l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_FIX_FLOW_PROMPT_SAVE_CARD_LABEL);
+#endif
+}
+
+base::string16 CardNameFixFlowControllerImpl::GetTitleText() const {
+ return l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_SAVE_CARD_CARDHOLDER_NAME_FIX_FLOW_HEADER);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl.h b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl.h
new file mode 100644
index 00000000000..e9f4d9ba72a
--- /dev/null
+++ b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl.h
@@ -0,0 +1,62 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_CARD_NAME_FIX_FLOW_CONTROLLER_IMPL_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_CARD_NAME_FIX_FLOW_CONTROLLER_IMPL_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "components/autofill/core/browser/ui/payments/card_name_fix_flow_controller.h"
+
+namespace autofill {
+
+class CardNameFixFlowView;
+
+class CardNameFixFlowControllerImpl : public CardNameFixFlowController {
+ public:
+ CardNameFixFlowControllerImpl();
+ ~CardNameFixFlowControllerImpl() override;
+
+ void Show(CardNameFixFlowView* card_name_fix_flow_view,
+ const base::string16& inferred_cardholder_name,
+ base::OnceCallback<void(const base::string16&)> name_callback);
+
+ // CardNameFixFlowController implementation.
+ void OnConfirmNameDialogClosed() override;
+ void OnNameAccepted(const base::string16& name) override;
+ void OnDismissed() override;
+ int GetIconId() const override;
+ base::string16 GetCancelButtonLabel() const override;
+ base::string16 GetInferredCardholderName() const override;
+ base::string16 GetInferredNameTooltipText() const override;
+ base::string16 GetInputLabel() const override;
+ base::string16 GetInputPlaceholderText() const override;
+ base::string16 GetSaveButtonLabel() const override;
+ base::string16 GetTitleText() const override;
+
+ private:
+ // Inferred cardholder name from Gaia account.
+ base::string16 inferred_cardholder_name_;
+
+ // View that displays the fix flow prompt.
+ CardNameFixFlowView* card_name_fix_flow_view_ = nullptr;
+
+ // The callback to call once user confirms their name through the fix flow.
+ base::OnceCallback<void(const base::string16&)> name_accepted_callback_;
+
+ // Whether the prompt was shown to the user.
+ bool shown_ = false;
+
+ // Whether the user explicitly accepted or dismissed this prompt.
+ bool had_user_interaction_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(CardNameFixFlowControllerImpl);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_CARD_NAME_FIX_FLOW_CONTROLLER_IMPL_H_
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl_unittest.cc b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl_unittest.cc
new file mode 100644
index 00000000000..c6dc583e35b
--- /dev/null
+++ b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl_unittest.cc
@@ -0,0 +1,147 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl.h"
+
+#include <stddef.h>
+#include <memory>
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/browser/ui/payments/card_name_fix_flow_view.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+
+class TestCardNameFixFlowView : public CardNameFixFlowView {
+ public:
+ void Show() override {}
+ void ControllerGone() override {}
+};
+
+class CardNameFixFlowControllerImplGenericTest {
+ public:
+ CardNameFixFlowControllerImplGenericTest() {}
+
+ void ShowPromptWithInferredName() {
+ inferred_name_ = base::ASCIIToUTF16("John Doe");
+ ShowPrompt();
+ }
+
+ void ShowPromptWithoutInferredName() {
+ inferred_name_ = base::ASCIIToUTF16("");
+ ShowPrompt();
+ }
+
+ void AcceptWithInferredName() { controller_->OnNameAccepted(inferred_name_); }
+
+ void AcceptWithEditedName() {
+ controller_->OnNameAccepted(base::ASCIIToUTF16("Edited Name"));
+ }
+
+ protected:
+ std::unique_ptr<TestCardNameFixFlowView> test_card_name_fix_flow_view_;
+ std::unique_ptr<CardNameFixFlowControllerImpl> controller_;
+ base::string16 inferred_name_;
+ base::string16 accepted_name_;
+ base::WeakPtrFactory<CardNameFixFlowControllerImplGenericTest>
+ weak_ptr_factory_{this};
+
+ private:
+ void OnNameAccepted(const base::string16& name) { accepted_name_ = name; }
+
+ void ShowPrompt() {
+ controller_->Show(
+ test_card_name_fix_flow_view_.get(), inferred_name_,
+ base::BindOnce(
+ &CardNameFixFlowControllerImplGenericTest::OnNameAccepted,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(CardNameFixFlowControllerImplGenericTest);
+};
+
+class CardNameFixFlowControllerImplTest
+ : public CardNameFixFlowControllerImplGenericTest,
+ public testing::Test {
+ public:
+ CardNameFixFlowControllerImplTest() {}
+ ~CardNameFixFlowControllerImplTest() override {}
+
+ void SetUp() override {
+ test_card_name_fix_flow_view_.reset(new TestCardNameFixFlowView());
+ controller_.reset(new CardNameFixFlowControllerImpl());
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CardNameFixFlowControllerImplTest);
+};
+
+TEST_F(CardNameFixFlowControllerImplTest, LogShown) {
+ base::HistogramTester histogram_tester;
+ ShowPromptWithInferredName();
+
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.CardholderNameFixFlowPrompt.Events",
+ AutofillMetrics::CARDHOLDER_NAME_FIX_FLOW_PROMPT_SHOWN, 1);
+}
+
+TEST_F(CardNameFixFlowControllerImplTest, LogPrefilled) {
+ base::HistogramTester histogram_tester;
+ ShowPromptWithInferredName();
+
+ histogram_tester.ExpectBucketCount("Autofill.SaveCardCardholderNamePrefilled",
+ true, 1);
+}
+
+TEST_F(CardNameFixFlowControllerImplTest, LogNotPrefilled) {
+ base::HistogramTester histogram_tester;
+ ShowPromptWithoutInferredName();
+
+ histogram_tester.ExpectBucketCount("Autofill.SaveCardCardholderNamePrefilled",
+ false, 1);
+}
+
+TEST_F(CardNameFixFlowControllerImplTest, LogAccepted) {
+ base::HistogramTester histogram_tester;
+ ShowPromptWithInferredName();
+ AcceptWithInferredName();
+
+ histogram_tester.ExpectBucketCount(
+ "Autofill.CardholderNameFixFlowPrompt.Events",
+ AutofillMetrics::CARDHOLDER_NAME_FIX_FLOW_PROMPT_ACCEPTED, 1);
+}
+
+TEST_F(CardNameFixFlowControllerImplTest, LogUserAcceptedInferredName) {
+ base::HistogramTester histogram_tester;
+ ShowPromptWithInferredName();
+ AcceptWithInferredName();
+
+ histogram_tester.ExpectBucketCount("Autofill.SaveCardCardholderNameWasEdited",
+ false, 1);
+}
+
+TEST_F(CardNameFixFlowControllerImplTest, LogUserAcceptedEditedName) {
+ base::HistogramTester histogram_tester;
+ ShowPromptWithInferredName();
+ AcceptWithEditedName();
+
+ histogram_tester.ExpectBucketCount("Autofill.SaveCardCardholderNameWasEdited",
+ true, 1);
+}
+
+TEST_F(CardNameFixFlowControllerImplTest, LogDismissed) {
+ base::HistogramTester histogram_tester;
+ controller_->OnDismissed();
+
+ histogram_tester.ExpectBucketCount(
+ "Autofill.CardholderNameFixFlowPrompt.Events",
+ AutofillMetrics::CARDHOLDER_NAME_FIX_FLOW_PROMPT_DISMISSED, 1);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view.h b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view.h
new file mode 100644
index 00000000000..f9bf6cea366
--- /dev/null
+++ b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view.h
@@ -0,0 +1,26 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_CARD_NAME_FIX_FLOW_VIEW_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_CARD_NAME_FIX_FLOW_VIEW_H_
+
+#include "base/macros.h"
+#include "base/strings/string16.h"
+
+namespace autofill {
+
+// The cross-platform UI interface which prompts the user to confirm their name.
+// This object is responsible for its own lifetime.
+class CardNameFixFlowView {
+ public:
+ virtual void Show() = 0;
+ virtual void ControllerGone() = 0;
+
+ protected:
+ virtual ~CardNameFixFlowView() = default;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_CARD_NAME_FIX_FLOW_VIEW_H_
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view_delegate_mobile.cc b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view_delegate_mobile.cc
deleted file mode 100644
index 94d6dc8b052..00000000000
--- a/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view_delegate_mobile.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/autofill/core/browser/ui/payments/card_name_fix_flow_view_delegate_mobile.h"
-
-#include <utility>
-
-#include "base/logging.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "build/branding_buildflags.h"
-#include "components/grit/components_scaled_resources.h"
-#include "components/strings/grit/components_strings.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace autofill {
-
-CardNameFixFlowViewDelegateMobile::CardNameFixFlowViewDelegateMobile(
- const base::string16& inferred_cardholder_name,
- base::OnceCallback<void(const base::string16&)> upload_save_card_callback)
- : inferred_cardholder_name_(inferred_cardholder_name),
- upload_save_card_callback_(std::move(upload_save_card_callback)),
- shown_(false),
- had_user_interaction_(false) {
- DCHECK(!upload_save_card_callback_.is_null());
- AutofillMetrics::LogSaveCardCardholderNamePrefilled(
- !inferred_cardholder_name_.empty());
-}
-
-CardNameFixFlowViewDelegateMobile::~CardNameFixFlowViewDelegateMobile() {
- if (shown_ && !had_user_interaction_)
- AutofillMetrics::LogCardholderNameFixFlowPromptEvent(
- AutofillMetrics::
- CARDHOLDER_NAME_FIX_FLOW_PROMPT_CLOSED_WITHOUT_INTERACTION);
-}
-
-int CardNameFixFlowViewDelegateMobile::GetIconId() const {
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
- return IDR_AUTOFILL_GOOGLE_PAY_WITH_DIVIDER;
-#else
- return 0;
-#endif
-}
-
-base::string16 CardNameFixFlowViewDelegateMobile::GetTitleText() const {
- return l10n_util::GetStringUTF16(
- IDS_AUTOFILL_SAVE_CARD_CARDHOLDER_NAME_FIX_FLOW_HEADER);
-}
-
-base::string16 CardNameFixFlowViewDelegateMobile::GetInferredCardHolderName()
- const {
- return inferred_cardholder_name_;
-}
-
-base::string16 CardNameFixFlowViewDelegateMobile::GetSaveButtonLabel() const {
- return l10n_util::GetStringUTF16(
- IDS_AUTOFILL_FIX_FLOW_PROMPT_SAVE_CARD_LABEL);
-}
-
-void CardNameFixFlowViewDelegateMobile::Accept(const base::string16& name) {
- std::move(upload_save_card_callback_).Run(name);
- AutofillMetrics::LogCardholderNameFixFlowPromptEvent(
- AutofillMetrics::CARDHOLDER_NAME_FIX_FLOW_PROMPT_ACCEPTED);
- had_user_interaction_ = true;
- AutofillMetrics::LogSaveCardCardholderNameWasEdited(
- inferred_cardholder_name_ != name);
-}
-
-void CardNameFixFlowViewDelegateMobile::Dismissed() {
- AutofillMetrics::LogCardholderNameFixFlowPromptEvent(
- AutofillMetrics::CARDHOLDER_NAME_FIX_FLOW_PROMPT_DISMISSED);
- had_user_interaction_ = true;
-}
-
-void CardNameFixFlowViewDelegateMobile::Shown() {
- AutofillMetrics::LogCardholderNameFixFlowPromptEvent(
- AutofillMetrics::CARDHOLDER_NAME_FIX_FLOW_PROMPT_SHOWN);
- shown_ = true;
-}
-
-} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view_delegate_mobile.h b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view_delegate_mobile.h
deleted file mode 100644
index 64415a44661..00000000000
--- a/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view_delegate_mobile.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_CARD_NAME_FIX_FLOW_VIEW_DELEGATE_MOBILE_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_CARD_NAME_FIX_FLOW_VIEW_DELEGATE_MOBILE_H_
-
-#include <memory>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "components/autofill/core/browser/autofill_metrics.h"
-
-namespace autofill {
-
-// Enables the user to accept or deny cardholder name fix flow prompt.
-// Only used on mobile.
-class CardNameFixFlowViewDelegateMobile {
- public:
- CardNameFixFlowViewDelegateMobile(
- const base::string16& inferred_cardholder_name,
- base::OnceCallback<void(const base::string16&)>
- upload_save_card_callback);
-
- ~CardNameFixFlowViewDelegateMobile();
-
- int GetIconId() const;
- base::string16 GetTitleText() const;
- base::string16 GetInferredCardHolderName() const;
- base::string16 GetSaveButtonLabel() const;
- void Accept(const base::string16& name);
- void Dismissed();
- void Shown();
-
- private:
- // Inferred cardholder name from Gaia account.
- base::string16 inferred_cardholder_name_;
-
- // The callback to save the credit card to Google Payments once user accepts
- // fix flow.
- base::OnceCallback<void(const base::string16&)> upload_save_card_callback_;
-
- // Whether the prompt was shown to the user.
- bool shown_;
-
- // Did the user ever explicitly accept or dismiss this prompt?
- bool had_user_interaction_;
-
- DISALLOW_COPY_AND_ASSIGN(CardNameFixFlowViewDelegateMobile);
-};
-
-} // namespace autofill
-
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_CARD_NAME_FIX_FLOW_VIEW_DELEGATE_MOBILE_H_
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller.h b/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller.h
index 8a33e40f7dd..e2df819d693 100644
--- a/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller.h
+++ b/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller.h
@@ -33,6 +33,7 @@ class CardUnmaskPromptController {
virtual bool ShouldRequestExpirationDate() const = 0;
virtual bool CanStoreLocally() const = 0;
virtual bool GetStoreLocallyStartState() const = 0;
+ virtual bool GetWebauthnOfferStartState() const = 0;
virtual base::TimeDelta GetSuccessMessageDuration() const = 0;
virtual AutofillClient::PaymentsRpcResult GetVerificationResult() const = 0;
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.cc b/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.cc
index f4918d2ff28..14a43d4a1a5 100644
--- a/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.cc
+++ b/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.cc
@@ -134,6 +134,16 @@ void CardUnmaskPromptControllerImpl::OnUnmaskPromptAccepted(
pending_details_.should_store_pan = false;
}
+ // The FIDO authentication checkbox is only shown when the local storage
+ // checkbox is not shown and the flag is turned on. If it is shown, then
+ // remember the last choice the user made on this device.
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillCreditCardAuthentication) &&
+ !CanStoreLocally()) {
+ pref_service_->SetBoolean(
+ prefs::kAutofillCreditCardFidoAuthOfferCheckboxState, enable_fido_auth);
+ }
+
// There is a chance the delegate has disappeared (i.e. tab closed) before the
// unmask response came in. Avoid a crash.
if (delegate_)
@@ -219,6 +229,11 @@ bool CardUnmaskPromptControllerImpl::GetStoreLocallyStartState() const {
prefs::kAutofillWalletImportStorageCheckboxState);
}
+bool CardUnmaskPromptControllerImpl::GetWebauthnOfferStartState() const {
+ return pref_service_->GetBoolean(
+ prefs::kAutofillCreditCardFidoAuthOfferCheckboxState);
+}
+
bool CardUnmaskPromptControllerImpl::InputCvcIsValid(
const base::string16& input_text) const {
base::string16 trimmed_text;
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.h b/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.h
index dd174d24644..345de4c8d82 100644
--- a/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.h
+++ b/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.h
@@ -48,6 +48,7 @@ class CardUnmaskPromptControllerImpl : public CardUnmaskPromptController {
bool ShouldRequestExpirationDate() const override;
bool CanStoreLocally() const override;
bool GetStoreLocallyStartState() const override;
+ bool GetWebauthnOfferStartState() const override;
bool InputCvcIsValid(const base::string16& input_text) const override;
bool InputExpirationIsValid(const base::string16& month,
const base::string16& year) const override;
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl_unittest.cc b/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl_unittest.cc
index 418ac6c636e..56275f7a2dc 100644
--- a/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl_unittest.cc
+++ b/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl_unittest.cc
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
@@ -105,11 +106,12 @@ class CardUnmaskPromptControllerImplGenericTest {
AutofillClient::UNMASK_FOR_AUTOFILL, delegate_->GetWeakPtr());
}
- void ShowPromptAndSimulateResponse(bool should_store_pan) {
+ void ShowPromptAndSimulateResponse(bool should_store_pan,
+ bool enable_fido_auth) {
ShowPrompt();
controller_->OnUnmaskPromptAccepted(ASCIIToUTF16("444"), ASCIIToUTF16("01"),
ASCIIToUTF16("2050"), should_store_pan,
- /*enable_fido_auth=*/false);
+ enable_fido_auth);
EXPECT_EQ(should_store_pan,
pref_service_->GetBoolean(
prefs::kAutofillWalletImportStorageCheckboxState));
@@ -121,6 +123,7 @@ class CardUnmaskPromptControllerImplGenericTest {
value);
}
+ base::test::ScopedFeatureList scoped_feature_list_;
std::unique_ptr<TestCardUnmaskPromptView> test_unmask_prompt_view_;
std::unique_ptr<TestingPrefServiceSimple> pref_service_;
std::unique_ptr<TestCardUnmaskPromptController> controller_;
@@ -144,6 +147,8 @@ class CardUnmaskPromptControllerImplTest
delegate_.reset(new TestCardUnmaskDelegate());
pref_service_->registry()->RegisterBooleanPref(
prefs::kAutofillWalletImportStorageCheckboxState, false);
+ pref_service_->registry()->RegisterBooleanPref(
+ prefs::kAutofillCreditCardFidoAuthOfferCheckboxState, true);
}
private:
@@ -169,7 +174,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogClosedNoAttempts) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogClosedAbandonUnmasking) {
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
base::HistogramTester histogram_tester;
controller_->OnUnmaskDialogClosed();
@@ -180,7 +186,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogClosedAbandonUnmasking) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogClosedFailedToUnmaskRetriable) {
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
controller_->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE);
base::HistogramTester histogram_tester;
@@ -198,7 +205,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogClosedFailedToUnmaskRetriable) {
TEST_F(CardUnmaskPromptControllerImplTest,
LogClosedFailedToUnmaskNonRetriable) {
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
controller_->OnVerificationResult(AutofillClient::PERMANENT_FAILURE);
base::HistogramTester histogram_tester;
@@ -216,7 +224,8 @@ TEST_F(CardUnmaskPromptControllerImplTest,
}
TEST_F(CardUnmaskPromptControllerImplTest, LogUnmaskedCardFirstAttempt) {
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
base::HistogramTester histogram_tester;
controller_->OnVerificationResult(AutofillClient::SUCCESS);
@@ -232,7 +241,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogUnmaskedCardFirstAttempt) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogUnmaskedCardAfterFailure) {
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
controller_->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE);
controller_->OnUnmaskPromptAccepted(ASCIIToUTF16("444"), ASCIIToUTF16("01"),
ASCIIToUTF16("2050"),
@@ -249,7 +259,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogUnmaskedCardAfterFailure) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogSavedCardLocally) {
- ShowPromptAndSimulateResponse(/*should_store_pan=*/true);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/true,
+ /*enable_fido_auth=*/false);
base::HistogramTester histogram_tester;
controller_->OnVerificationResult(AutofillClient::SUCCESS);
@@ -262,7 +273,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogSavedCardLocally) {
TEST_F(CardUnmaskPromptControllerImplTest, LogDidOptIn) {
SetImportCheckboxState(false);
- ShowPromptAndSimulateResponse(/*should_store_pan=*/true);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/true,
+ /*enable_fido_auth=*/false);
base::HistogramTester histogram_tester;
controller_->OnUnmaskDialogClosed();
@@ -273,7 +285,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogDidOptIn) {
TEST_F(CardUnmaskPromptControllerImplTest, LogDidNotOptIn) {
SetImportCheckboxState(false);
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
base::HistogramTester histogram_tester;
controller_->OnUnmaskDialogClosed();
@@ -284,7 +297,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogDidNotOptIn) {
TEST_F(CardUnmaskPromptControllerImplTest, LogDidOptOut) {
SetImportCheckboxState(true);
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
base::HistogramTester histogram_tester;
controller_->OnUnmaskDialogClosed();
@@ -295,7 +309,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogDidOptOut) {
TEST_F(CardUnmaskPromptControllerImplTest, LogDidNotOptOut) {
SetImportCheckboxState(true);
- ShowPromptAndSimulateResponse(/*should_store_pan=*/true);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/true,
+ /*enable_fido_auth=*/false);
base::HistogramTester histogram_tester;
controller_->OnUnmaskDialogClosed();
@@ -306,7 +321,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogDidNotOptOut) {
TEST_F(CardUnmaskPromptControllerImplTest, DontLogForHiddenCheckbox) {
controller_->set_can_store_locally(false);
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
base::HistogramTester histogram_tester;
controller_->OnUnmaskDialogClosed();
@@ -324,6 +340,22 @@ TEST_F(CardUnmaskPromptControllerImplTest, DontLogForHiddenCheckbox) {
AutofillMetrics::UNMASK_PROMPT_LOCAL_SAVE_DID_NOT_OPT_OUT, 0);
}
+TEST_F(CardUnmaskPromptControllerImplTest,
+ FidoAuthOfferCheckboxStatePersistent) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillCreditCardAuthentication);
+ controller_->set_can_store_locally(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/true);
+ EXPECT_TRUE(pref_service_->GetBoolean(
+ prefs::kAutofillCreditCardFidoAuthOfferCheckboxState));
+
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
+ EXPECT_FALSE(pref_service_->GetBoolean(
+ prefs::kAutofillCreditCardFidoAuthOfferCheckboxState));
+}
+
TEST_F(CardUnmaskPromptControllerImplTest, LogDurationNoAttempts) {
ShowPrompt();
base::HistogramTester histogram_tester;
@@ -336,7 +368,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogDurationNoAttempts) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogDurationAbandonUnmasking) {
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
base::HistogramTester histogram_tester;
controller_->OnUnmaskDialogClosed();
@@ -347,7 +380,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogDurationAbandonUnmasking) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogDurationFailedToUnmaskRetriable) {
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
controller_->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE);
base::HistogramTester histogram_tester;
@@ -360,7 +394,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogDurationFailedToUnmaskRetriable) {
TEST_F(CardUnmaskPromptControllerImplTest,
LogDurationFailedToUnmaskNonRetriable) {
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
controller_->OnVerificationResult(AutofillClient::PERMANENT_FAILURE);
base::HistogramTester histogram_tester;
@@ -372,7 +407,8 @@ TEST_F(CardUnmaskPromptControllerImplTest,
}
TEST_F(CardUnmaskPromptControllerImplTest, LogDurationCardFirstAttempt) {
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
base::HistogramTester histogram_tester;
controller_->OnVerificationResult(AutofillClient::SUCCESS);
@@ -385,7 +421,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogDurationCardFirstAttempt) {
TEST_F(CardUnmaskPromptControllerImplTest,
LogDurationUnmaskedCardAfterFailure) {
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
controller_->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE);
controller_->OnUnmaskPromptAccepted(
base::ASCIIToUTF16("444"), base::ASCIIToUTF16("01"),
@@ -402,7 +439,8 @@ TEST_F(CardUnmaskPromptControllerImplTest,
}
TEST_F(CardUnmaskPromptControllerImplTest, LogTimeBeforeAbandonUnmasking) {
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
base::HistogramTester histogram_tester;
controller_->OnUnmaskDialogClosed();
@@ -412,7 +450,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogTimeBeforeAbandonUnmasking) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogRealPanResultSuccess) {
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
base::HistogramTester histogram_tester;
controller_->OnVerificationResult(AutofillClient::SUCCESS);
@@ -422,7 +461,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogRealPanResultSuccess) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogRealPanTryAgainFailure) {
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
base::HistogramTester histogram_tester;
controller_->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE);
@@ -433,7 +473,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogRealPanTryAgainFailure) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogUnmaskingDurationResultSuccess) {
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
base::HistogramTester histogram_tester;
controller_->OnVerificationResult(AutofillClient::SUCCESS);
@@ -446,7 +487,8 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogUnmaskingDurationResultSuccess) {
TEST_F(CardUnmaskPromptControllerImplTest,
LogUnmaskingDurationTryAgainFailure) {
- ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
base::HistogramTester histogram_tester;
controller_->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE);
diff --git a/chromium/components/autofill/core/browser/ui/popup_item_ids.h b/chromium/components/autofill/core/browser/ui/popup_item_ids.h
index 917f68981fb..52193d51e05 100644
--- a/chromium/components/autofill/core/browser/ui/popup_item_ids.h
+++ b/chromium/components/autofill/core/browser/ui/popup_item_ids.h
@@ -25,9 +25,8 @@ enum PopupItemId {
POPUP_ITEM_ID_USERNAME_ENTRY = -11,
POPUP_ITEM_ID_CREATE_HINT = -12,
POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY = -13,
- POPUP_ITEM_ID_GOOGLE_PAY_BRANDING = -14,
- POPUP_ITEM_ID_GENERATE_PASSWORD_ENTRY = -15,
- POPUP_ITEM_ID_SHOW_ACCOUNT_CARDS = -16,
+ POPUP_ITEM_ID_GENERATE_PASSWORD_ENTRY = -14,
+ POPUP_ITEM_ID_SHOW_ACCOUNT_CARDS = -15,
};
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc
index 7ae1e1cadbc..66e412c2b9f 100644
--- a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc
@@ -23,7 +23,7 @@
#include "components/autofill/core/browser/webdata/autofill_entry.h"
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h"
-#include "components/sync/base/hash_util.h"
+#include "components/sync/base/client_tag_hash.h"
#include "components/sync/model/data_batch.h"
#include "components/sync/model/data_type_activation_request.h"
#include "components/sync/model/metadata_batch.h"
@@ -245,7 +245,7 @@ class AutocompleteSyncBridgeTest : public testing::Test {
const AutofillSpecifics& specifics) {
auto data = std::make_unique<EntityData>();
*data->specifics.mutable_autofill() = specifics;
- data->client_tag_hash = syncer::GenerateSyncableHash(
+ data->client_tag_hash = syncer::ClientTagHash::FromUnhashed(
syncer::AUTOFILL, bridge()->GetClientTag(*data));
return data;
}
@@ -293,7 +293,7 @@ class AutocompleteSyncBridgeTest : public testing::Test {
private:
ScopedTempDir temp_dir_;
- base::test::TaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
testing::NiceMock<MockAutofillWebDataBackend> backend_;
AutofillTable table_;
WebDatabase db_;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.cc b/chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.cc
index eeda7a580d9..d2489486839 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.cc
@@ -14,11 +14,12 @@
namespace browser_sync {
AutofillProfileModelTypeController::AutofillProfileModelTypeController(
- std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk,
+ std::unique_ptr<syncer::ModelTypeControllerDelegate>
+ delegate_for_full_sync_mode,
PrefService* pref_service,
syncer::SyncService* sync_service)
: ModelTypeController(syncer::AUTOFILL_PROFILE,
- std::move(delegate_on_disk)),
+ std::move(delegate_for_full_sync_mode)),
pref_service_(pref_service),
sync_service_(sync_service) {
pref_registrar_.Init(pref_service_);
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.h b/chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.h
index ed684b9e63e..9ff3493d283 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.h
@@ -24,7 +24,8 @@ namespace browser_sync {
class AutofillProfileModelTypeController : public syncer::ModelTypeController {
public:
AutofillProfileModelTypeController(
- std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk,
+ std::unique_ptr<syncer::ModelTypeControllerDelegate>
+ delegate_for_full_sync_mode,
PrefService* pref_service,
syncer::SyncService* sync_service);
~AutofillProfileModelTypeController() override;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc
index e0579be7e08..0ebf17dc2c8 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc
@@ -28,7 +28,7 @@
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h"
#include "components/autofill/core/common/autofill_constants.h"
-#include "components/sync/base/hash_util.h"
+#include "components/sync/base/client_tag_hash.h"
#include "components/sync/model/data_batch.h"
#include "components/sync/model/data_type_activation_request.h"
#include "components/sync/model/entity_data.h"
@@ -296,7 +296,7 @@ class AutofillProfileSyncBridgeTest : public testing::Test {
const AutofillProfileSpecifics& specifics) {
auto data = std::make_unique<EntityData>();
*data->specifics.mutable_autofill_profile() = specifics;
- data->client_tag_hash = syncer::GenerateSyncableHash(
+ data->client_tag_hash = syncer::ClientTagHash::FromUnhashed(
syncer::AUTOFILL_PROFILE, bridge()->GetClientTag(*data));
return data;
}
@@ -321,7 +321,7 @@ class AutofillProfileSyncBridgeTest : public testing::Test {
private:
autofill::TestAutofillClock test_clock_;
ScopedTempDir temp_dir_;
- base::test::TaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
testing::NiceMock<MockAutofillWebDataBackend> backend_;
AutofillTable table_;
WebDatabase db_;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util_unittest.cc
index 0ca087cdd24..997d51b187b 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util_unittest.cc
@@ -14,7 +14,7 @@
#include "components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.h"
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/autofill/core/common/autofill_constants.h"
-#include "components/sync/base/hash_util.h"
+#include "components/sync/base/client_tag_hash.h"
#include "components/sync/model/entity_data.h"
#include "components/sync/protocol/sync.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -50,8 +50,8 @@ std::unique_ptr<EntityData> SpecificsToEntity(
const std::string& client_tag) {
auto data = std::make_unique<syncer::EntityData>();
*data->specifics.mutable_autofill_wallet() = specifics;
- data->client_tag_hash =
- syncer::GenerateSyncableHash(syncer::AUTOFILL_WALLET_DATA, client_tag);
+ data->client_tag_hash = syncer::ClientTagHash::FromUnhashed(
+ syncer::AUTOFILL_WALLET_DATA, client_tag);
return data;
}
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table.cc b/chromium/components/autofill/core/browser/webdata/autofill_table.cc
index df8bf08bddc..c6448b452e4 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table.cc
@@ -410,7 +410,8 @@ bool AutofillTable::CreateTablesIfNecessary() {
InitMaskedCreditCardsTable() && InitUnmaskedCreditCardsTable() &&
InitServerCardMetadataTable() && InitServerAddressesTable() &&
InitServerAddressMetadataTable() && InitAutofillSyncMetadataTable() &&
- InitModelTypeStateTable() && InitPaymentsCustomerDataTable());
+ InitModelTypeStateTable() && InitPaymentsCustomerDataTable() &&
+ InitPaymentsUPIVPATable());
}
bool AutofillTable::IsSyncable() {
@@ -1640,6 +1641,21 @@ bool AutofillTable::GetPaymentsCustomerData(
return s.Succeeded();
}
+bool AutofillTable::InsertVPA(const std::string& vpa) {
+ sql::Transaction transaction(db_);
+ if (!transaction.Begin())
+ return false;
+
+ sql::Statement insert_vpa_statement(
+ db_->GetUniqueStatement("INSERT INTO payments_upi_vpa (vpa) VALUES (?)"));
+ insert_vpa_statement.BindString(0, vpa);
+ insert_vpa_statement.Run();
+
+ transaction.Commit();
+
+ return db_->GetLastChangeCount() > 0;
+}
+
bool AutofillTable::ClearAllServerData() {
sql::Transaction transaction(db_);
if (!transaction.Begin())
@@ -1843,36 +1859,6 @@ bool AutofillTable::RemoveOriginURLsModifiedBetween(
return true;
}
-bool AutofillTable::GetAutofillProfilesInTrash(
- std::vector<std::string>* guids) {
- guids->clear();
-
- sql::Statement s(
- db_->GetUniqueStatement("SELECT guid FROM autofill_profiles_trash"));
-
- while (s.Step()) {
- std::string guid = s.ColumnString(0);
- guids->push_back(guid);
- }
-
- return s.Succeeded();
-}
-
-bool AutofillTable::EmptyAutofillProfilesTrash() {
- sql::Statement s(
- db_->GetUniqueStatement("DELETE FROM autofill_profiles_trash"));
-
- return s.Run();
-}
-
-bool AutofillTable::AddAutofillGUIDToTrash(const std::string& guid) {
- sql::Statement s(db_->GetUniqueStatement(
- "INSERT INTO autofill_profiles_trash (guid) VALUES (?)"));
- s.BindString(0, guid);
-
- return s.Run();
-}
-
bool AutofillTable::ClearAutofillProfiles() {
sql::Statement s1(db_->GetUniqueStatement("DELETE FROM autofill_profiles"));
@@ -2609,11 +2595,12 @@ bool AutofillTable::MigrateToVersion78AddModelTypeColumns() {
"SELECT ?, storage_key, value "
"FROM autofill_sync_metadata"));
// Note: This uses the *wrong* ID for the ModelType - instead of
- // |syncer::ModelTypeToHistogramInt|, this should be |GetKeyValueForModelType|
+ // |syncer::ModelTypeHistogramValue|, this should be |GetKeyValueForModelType|
// aka |syncer::ModelTypeToStableIdentifier|. But at this point, fixing it
// here would just make an even bigger mess. Instead, we clean this up in the
// migration to version 81. See also crbug.com/895826.
- insert_metadata.BindInt(0, syncer::ModelTypeToHistogramInt(syncer::AUTOFILL));
+ insert_metadata.BindInt(
+ 0, static_cast<int>(syncer::ModelTypeHistogramValue(syncer::AUTOFILL)));
// Prior to this migration, the table was a singleton, containing only one
// entry with id being hard-coded to 1.
@@ -2622,7 +2609,8 @@ bool AutofillTable::MigrateToVersion78AddModelTypeColumns() {
"(model_type, value) SELECT ?, value "
"FROM autofill_model_type_state WHERE id=1"));
// Note: Like above, this uses the *wrong* ID for the ModelType.
- insert_state.BindInt(0, syncer::ModelTypeToHistogramInt(syncer::AUTOFILL));
+ insert_state.BindInt(
+ 0, static_cast<int>(syncer::ModelTypeHistogramValue(syncer::AUTOFILL)));
if (!insert_metadata.Run() || !insert_state.Run()) {
return false;
@@ -2655,7 +2643,7 @@ bool AutofillTable::MigrateToVersion81CleanUpWrongModelTypeData() {
// in trying to recover anything, since by now it'll have been redownloaded
// anyway.
const int bad_model_type_id =
- syncer::ModelTypeToHistogramInt(syncer::AUTOFILL);
+ static_cast<int>(syncer::ModelTypeHistogramValue(syncer::AUTOFILL));
DCHECK_NE(bad_model_type_id, GetKeyValueForModelType(syncer::AUTOFILL));
sql::Transaction transaction(db_);
@@ -3139,4 +3127,15 @@ bool AutofillTable::InitPaymentsCustomerDataTable() {
return true;
}
+bool AutofillTable::InitPaymentsUPIVPATable() {
+ if (!db_->DoesTableExist("payments_upi_vpa")) {
+ if (!db_->Execute("CREATE TABLE payments_upi_vpa ("
+ "vpa VARCHAR)")) {
+ NOTREACHED();
+ return false;
+ }
+ }
+ return true;
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table.h b/chromium/components/autofill/core/browser/webdata/autofill_table.h
index 0e212e999ac..ba29c015768 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table.h
@@ -177,6 +177,8 @@ struct PaymentsCustomerData;
// exp_month Expiration month: 1-12
// exp_year Four-digit year: 2017
// bank_name Issuer bank name of the credit card.
+// cloud_token_data Opaque identifier for the cloud token associated with
+// the payment instrument.
//
// unmasked_credit_cards
// When a masked credit credit card is unmasked and the
@@ -273,6 +275,11 @@ struct PaymentsCustomerData;
// Contains Google Payments customer data.
//
// customer_id A string representing the Google Payments customer id.
+//
+// payments_upi_vpa Contains saved UPI/VPA payment data.
+// https://en.wikipedia.org/wiki/Unified_Payments_Interface
+//
+// vpa_id A string representing the VPA value.
class AutofillTable : public WebDatabaseTable,
public syncer::SyncMetadataStore {
@@ -433,6 +440,9 @@ class AutofillTable : public WebDatabaseTable,
bool GetPaymentsCustomerData(
std::unique_ptr<PaymentsCustomerData>* customer_data) const;
+ // Adds |vpa| to the saved VPA ids.
+ bool InsertVPA(const std::string& vpa);
+
// Deletes all data from the server card and profile tables. Returns true if
// any data was deleted, false if not (so false means "commit not needed"
// rather than "error").
@@ -466,17 +476,6 @@ class AutofillTable : public WebDatabaseTable,
const base::Time& delete_end,
std::vector<std::unique_ptr<AutofillProfile>>* profiles);
- // Retrieves all profiles in the database that have been deleted since last
- // "empty" of the trash.
- bool GetAutofillProfilesInTrash(std::vector<std::string>* guids);
-
- // Empties the Autofill profiles "trash can".
- bool EmptyAutofillProfilesTrash();
-
- // Retrieves all profiles in the database that have been deleted since last
- // "empty" of the trash.
- bool AddAutofillGUIDToTrash(const std::string& guid);
-
// Clear all profiles.
bool ClearAutofillProfiles();
@@ -635,6 +634,7 @@ class AutofillTable : public WebDatabaseTable,
bool InitAutofillSyncMetadataTable();
bool InitModelTypeStateTable();
bool InitPaymentsCustomerDataTable();
+ bool InitPaymentsUPIVPATable();
std::unique_ptr<AutofillTableEncryptor> autofill_table_encryptor_;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
index cd9547ff280..54444cbb468 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
@@ -85,14 +85,15 @@ std::ostream& operator<<(std::ostream& os, const AutofillChange& change) {
namespace {
typedef std::set<AutofillEntry,
- bool (*)(const AutofillEntry&, const AutofillEntry&)> AutofillEntrySet;
+ bool (*)(const AutofillEntry&, const AutofillEntry&)>
+ AutofillEntrySet;
typedef AutofillEntrySet::iterator AutofillEntrySetIterator;
bool CompareAutofillEntries(const AutofillEntry& a, const AutofillEntry& b) {
- return std::tie(a.key().name(), a.key().value(),
- a.date_created(), a.date_last_used()) <
- std::tie(b.key().name(), b.key().value(),
- b.date_created(), b.date_last_used());
+ return std::tie(a.key().name(), a.key().value(), a.date_created(),
+ a.date_last_used()) <
+ std::tie(b.key().name(), b.key().value(), b.date_created(),
+ b.date_last_used());
}
AutofillEntry MakeAutofillEntry(const std::string& name,
@@ -160,7 +161,7 @@ class AutofillTableTest : public testing::Test {
};
TEST_F(AutofillTableTest, Autofill) {
- Time t1 = Time::Now();
+ Time t1 = AutofillClock::Now();
// Simulate the submission of a handful of entries in a field called "Name",
// some more often than others.
@@ -168,25 +169,25 @@ TEST_F(AutofillTableTest, Autofill) {
FormFieldData field;
field.name = ASCIIToUTF16("Name");
field.value = ASCIIToUTF16("Superman");
- base::Time now = base::Time::Now();
+ base::Time now = AutofillClock::Now();
base::TimeDelta two_seconds = base::TimeDelta::FromSeconds(2);
EXPECT_TRUE(table_->AddFormFieldValue(field, &changes));
std::vector<AutofillEntry> v;
for (int i = 0; i < 5; ++i) {
field.value = ASCIIToUTF16("Clark Kent");
- EXPECT_TRUE(table_->AddFormFieldValueTime(field, &changes,
- now + i * two_seconds));
+ EXPECT_TRUE(
+ table_->AddFormFieldValueTime(field, &changes, now + i * two_seconds));
}
for (int i = 0; i < 3; ++i) {
field.value = ASCIIToUTF16("Clark Sutter");
- EXPECT_TRUE(table_->AddFormFieldValueTime(field, &changes,
- now + i * two_seconds));
+ EXPECT_TRUE(
+ table_->AddFormFieldValueTime(field, &changes, now + i * two_seconds));
}
for (int i = 0; i < 2; ++i) {
field.name = ASCIIToUTF16("Favorite Color");
field.value = ASCIIToUTF16("Green");
- EXPECT_TRUE(table_->AddFormFieldValueTime(field, &changes,
- now + i * two_seconds));
+ EXPECT_TRUE(
+ table_->AddFormFieldValueTime(field, &changes, now + i * two_seconds));
}
// We have added the name Clark Kent 5 times, so count should be 5.
@@ -205,8 +206,8 @@ TEST_F(AutofillTableTest, Autofill) {
// in the second argument means it should return all suggestions for a name
// no matter what they start with. The order that the names occur in the list
// should be decreasing order by count.
- EXPECT_TRUE(table_->GetFormValuesForElementName(
- ASCIIToUTF16("Name"), base::string16(), &v, 6));
+ EXPECT_TRUE(table_->GetFormValuesForElementName(ASCIIToUTF16("Name"),
+ base::string16(), &v, 6));
EXPECT_EQ(3U, v.size());
if (v.size() == 3) {
EXPECT_EQ(ASCIIToUTF16("Clark Kent"), v[0].key().value());
@@ -216,8 +217,8 @@ TEST_F(AutofillTableTest, Autofill) {
// If we query again limiting the list size to 1, we should only get the most
// frequent entry.
- EXPECT_TRUE(table_->GetFormValuesForElementName(
- ASCIIToUTF16("Name"), base::string16(), &v, 1));
+ EXPECT_TRUE(table_->GetFormValuesForElementName(ASCIIToUTF16("Name"),
+ base::string16(), &v, 1));
EXPECT_EQ(1U, v.size());
if (v.size() == 1) {
EXPECT_EQ(ASCIIToUTF16("Clark Kent"), v[0].key().value());
@@ -225,8 +226,8 @@ TEST_F(AutofillTableTest, Autofill) {
// Querying for suggestions given a prefix is case-insensitive, so the prefix
// "cLa" shoud get suggestions for both Clarks.
- EXPECT_TRUE(table_->GetFormValuesForElementName(
- ASCIIToUTF16("Name"), ASCIIToUTF16("cLa"), &v, 6));
+ EXPECT_TRUE(table_->GetFormValuesForElementName(ASCIIToUTF16("Name"),
+ ASCIIToUTF16("cLa"), &v, 6));
EXPECT_EQ(2U, v.size());
if (v.size() == 2) {
EXPECT_EQ(ASCIIToUTF16("Clark Kent"), v[0].key().value());
@@ -239,18 +240,18 @@ TEST_F(AutofillTableTest, Autofill) {
EXPECT_TRUE(table_->RemoveFormElementsAddedBetween(t1, Time(), &changes));
const AutofillChange kExpectedChanges[] = {
- AutofillChange(AutofillChange::REMOVE,
- AutofillKey(ASCIIToUTF16("Name"),
- ASCIIToUTF16("Superman"))),
- AutofillChange(AutofillChange::REMOVE,
- AutofillKey(ASCIIToUTF16("Name"),
- ASCIIToUTF16("Clark Kent"))),
- AutofillChange(AutofillChange::REMOVE,
- AutofillKey(ASCIIToUTF16("Name"),
- ASCIIToUTF16("Clark Sutter"))),
- AutofillChange(AutofillChange::REMOVE,
- AutofillKey(ASCIIToUTF16("Favorite Color"),
- ASCIIToUTF16("Green"))),
+ AutofillChange(
+ AutofillChange::REMOVE,
+ AutofillKey(ASCIIToUTF16("Name"), ASCIIToUTF16("Superman"))),
+ AutofillChange(
+ AutofillChange::REMOVE,
+ AutofillKey(ASCIIToUTF16("Name"), ASCIIToUTF16("Clark Kent"))),
+ AutofillChange(
+ AutofillChange::REMOVE,
+ AutofillKey(ASCIIToUTF16("Name"), ASCIIToUTF16("Clark Sutter"))),
+ AutofillChange(
+ AutofillChange::REMOVE,
+ AutofillKey(ASCIIToUTF16("Favorite Color"), ASCIIToUTF16("Green"))),
};
EXPECT_EQ(base::size(kExpectedChanges), changes.size());
for (size_t i = 0; i < base::size(kExpectedChanges); ++i) {
@@ -260,8 +261,8 @@ TEST_F(AutofillTableTest, Autofill) {
EXPECT_EQ(0, GetAutofillEntryCount(ASCIIToUTF16("Name"),
ASCIIToUTF16("Clark Kent"), db_.get()));
- EXPECT_TRUE(table_->GetFormValuesForElementName(
- ASCIIToUTF16("Name"), base::string16(), &v, 6));
+ EXPECT_TRUE(table_->GetFormValuesForElementName(ASCIIToUTF16("Name"),
+ base::string16(), &v, 6));
EXPECT_EQ(0U, v.size());
// Now add some values with empty strings.
@@ -282,8 +283,8 @@ TEST_F(AutofillTableTest, Autofill) {
// They should be stored normally as the DB layer does not check for empty
// values.
v.clear();
- EXPECT_TRUE(table_->GetFormValuesForElementName(
- ASCIIToUTF16("blank"), base::string16(), &v, 10));
+ EXPECT_TRUE(table_->GetFormValuesForElementName(ASCIIToUTF16("blank"),
+ base::string16(), &v, 10));
EXPECT_EQ(4U, v.size());
}
@@ -329,21 +330,16 @@ TEST_F(AutofillTableTest, Autofill_GetCountOfValuesContainedBetween) {
// This test makes time comparisons that are precise to a microsecond, but the
// database uses the time_t format which is only precise to a second.
// Make sure we use timestamps rounded to a second.
- Time begin = Time::FromTimeT(Time::Now().ToTimeT());
+ Time begin = Time::FromTimeT(AutofillClock::Now().ToTimeT());
Time now = begin;
TimeDelta second = TimeDelta::FromSeconds(1);
struct Entry {
const char* name;
const char* value;
- } entries[] = {
- { "Alter ego", "Superman" },
- { "Name", "Superman" },
- { "Name", "Clark Kent" },
- { "Name", "Superman" },
- { "Name", "Clark Sutter" },
- { "Nomen", "Clark Kent" }
- };
+ } entries[] = {{"Alter ego", "Superman"}, {"Name", "Superman"},
+ {"Name", "Clark Kent"}, {"Name", "Superman"},
+ {"Name", "Clark Sutter"}, {"Nomen", "Clark Kent"}};
for (Entry entry : entries) {
FormFieldData field;
@@ -356,30 +352,29 @@ TEST_F(AutofillTableTest, Autofill_GetCountOfValuesContainedBetween) {
// While the entry "Alter ego" : "Superman" is entirely contained within
// the first second, the value "Superman" itself appears in another entry,
// so it is not contained.
- EXPECT_EQ(0, table_->GetCountOfValuesContainedBetween(
- begin, begin + second));
+ EXPECT_EQ(0, table_->GetCountOfValuesContainedBetween(begin, begin + second));
// No values are entirely contained within the first three seconds either
// (note that the second time constraint is exclusive).
- EXPECT_EQ(0, table_->GetCountOfValuesContainedBetween(
- begin, begin + 3 * second));
+ EXPECT_EQ(
+ 0, table_->GetCountOfValuesContainedBetween(begin, begin + 3 * second));
// Only "Superman" is entirely contained within the first four seconds.
- EXPECT_EQ(1, table_->GetCountOfValuesContainedBetween(
- begin, begin + 4 * second));
+ EXPECT_EQ(
+ 1, table_->GetCountOfValuesContainedBetween(begin, begin + 4 * second));
// "Clark Kent" and "Clark Sutter" are contained between the first
// and seventh second.
- EXPECT_EQ(2, table_->GetCountOfValuesContainedBetween(
- begin + second, begin + 7 * second));
+ EXPECT_EQ(2, table_->GetCountOfValuesContainedBetween(begin + second,
+ begin + 7 * second));
// Beginning from the third second, "Clark Kent" is not contained.
- EXPECT_EQ(1, table_->GetCountOfValuesContainedBetween(
- begin + 3 * second, begin + 7 * second));
+ EXPECT_EQ(1, table_->GetCountOfValuesContainedBetween(begin + 3 * second,
+ begin + 7 * second));
// We have three distinct values total.
- EXPECT_EQ(3, table_->GetCountOfValuesContainedBetween(
- begin, begin + 7 * second));
+ EXPECT_EQ(
+ 3, table_->GetCountOfValuesContainedBetween(begin, begin + 7 * second));
// And we should get the same result for unlimited time interval.
EXPECT_EQ(3, table_->GetCountOfValuesContainedBetween(Time(), Time::Max()));
@@ -388,8 +383,8 @@ TEST_F(AutofillTableTest, Autofill_GetCountOfValuesContainedBetween) {
EXPECT_EQ(3, table_->GetCountOfValuesContainedBetween(Time(), Time()));
// An interval that does not fully contain any entries returns zero.
- EXPECT_EQ(0, table_->GetCountOfValuesContainedBetween(
- begin + second, begin + 2 * second));
+ EXPECT_EQ(0, table_->GetCountOfValuesContainedBetween(begin + second,
+ begin + 2 * second));
// So does an interval which has no intersection with any entry.
EXPECT_EQ(0, table_->GetCountOfValuesContainedBetween(Time(), begin));
@@ -397,7 +392,7 @@ TEST_F(AutofillTableTest, Autofill_GetCountOfValuesContainedBetween) {
TEST_F(AutofillTableTest, Autofill_RemoveBetweenChanges) {
TimeDelta one_day(TimeDelta::FromDays(1));
- Time t1 = Time::Now();
+ Time t1 = AutofillClock::Now();
Time t2 = t1 + one_day;
AutofillChangeList changes;
@@ -410,24 +405,24 @@ TEST_F(AutofillTableTest, Autofill_RemoveBetweenChanges) {
changes.clear();
EXPECT_TRUE(table_->RemoveFormElementsAddedBetween(t1, t2, &changes));
ASSERT_EQ(1U, changes.size());
- EXPECT_EQ(AutofillChange(AutofillChange::UPDATE,
- AutofillKey(ASCIIToUTF16("Name"),
- ASCIIToUTF16("Superman"))),
+ EXPECT_EQ(AutofillChange(
+ AutofillChange::UPDATE,
+ AutofillKey(ASCIIToUTF16("Name"), ASCIIToUTF16("Superman"))),
changes[0]);
changes.clear();
EXPECT_TRUE(
table_->RemoveFormElementsAddedBetween(t2, t2 + one_day, &changes));
ASSERT_EQ(1U, changes.size());
- EXPECT_EQ(AutofillChange(AutofillChange::REMOVE,
- AutofillKey(ASCIIToUTF16("Name"),
- ASCIIToUTF16("Superman"))),
+ EXPECT_EQ(AutofillChange(
+ AutofillChange::REMOVE,
+ AutofillKey(ASCIIToUTF16("Name"), ASCIIToUTF16("Superman"))),
changes[0]);
}
TEST_F(AutofillTableTest, Autofill_AddChanges) {
TimeDelta one_day(TimeDelta::FromDays(1));
- Time t1 = Time::Now();
+ Time t1 = AutofillClock::Now();
Time t2 = t1 + one_day;
AutofillChangeList changes;
@@ -436,18 +431,17 @@ TEST_F(AutofillTableTest, Autofill_AddChanges) {
field.value = ASCIIToUTF16("Superman");
EXPECT_TRUE(table_->AddFormFieldValueTime(field, &changes, t1));
ASSERT_EQ(1U, changes.size());
- EXPECT_EQ(AutofillChange(AutofillChange::ADD,
- AutofillKey(ASCIIToUTF16("Name"),
- ASCIIToUTF16("Superman"))),
+ EXPECT_EQ(AutofillChange(
+ AutofillChange::ADD,
+ AutofillKey(ASCIIToUTF16("Name"), ASCIIToUTF16("Superman"))),
changes[0]);
changes.clear();
- EXPECT_TRUE(
- table_->AddFormFieldValueTime(field, &changes, t2));
+ EXPECT_TRUE(table_->AddFormFieldValueTime(field, &changes, t2));
ASSERT_EQ(1U, changes.size());
- EXPECT_EQ(AutofillChange(AutofillChange::UPDATE,
- AutofillKey(ASCIIToUTF16("Name"),
- ASCIIToUTF16("Superman"))),
+ EXPECT_EQ(AutofillChange(
+ AutofillChange::UPDATE,
+ AutofillKey(ASCIIToUTF16("Name"), ASCIIToUTF16("Superman"))),
changes[0]);
}
@@ -489,8 +483,7 @@ TEST_F(AutofillTableTest, Autofill_GetAutofillTimestamps) {
Time date_created, date_last_used;
ASSERT_TRUE(table_->GetAutofillTimestamps(ASCIIToUTF16("foo"),
- ASCIIToUTF16("bar"),
- &date_created,
+ ASCIIToUTF16("bar"), &date_created,
&date_last_used));
EXPECT_EQ(Time::FromTimeT(1), date_created);
EXPECT_EQ(Time::FromTimeT(2), date_last_used);
@@ -555,7 +548,7 @@ TEST_F(AutofillTableTest, Autofill_UpdateReplace) {
}
TEST_F(AutofillTableTest, Autofill_UpdateDontReplace) {
- Time t = Time::Now();
+ Time t = AutofillClock::Now();
AutofillEntry existing(
MakeAutofillEntry("Name", "Superman", t.ToTimeT(), -1));
@@ -573,15 +566,14 @@ TEST_F(AutofillTableTest, Autofill_UpdateDontReplace) {
std::vector<AutofillEntry> all_entries;
ASSERT_TRUE(table_->GetAllAutofillEntries(&all_entries));
ASSERT_EQ(2U, all_entries.size());
- AutofillEntrySet expected_entries(all_entries.begin(),
- all_entries.end(),
+ AutofillEntrySet expected_entries(all_entries.begin(), all_entries.end(),
CompareAutofillEntries);
EXPECT_EQ(1U, expected_entries.count(existing));
EXPECT_EQ(1U, expected_entries.count(entry));
}
TEST_F(AutofillTableTest, Autofill_AddFormFieldValues) {
- Time t = Time::Now();
+ Time t = AutofillClock::Now();
// Add multiple values for "firstname" and "lastname" names. Test that only
// first value of each gets added. Related to security issue:
@@ -610,10 +602,10 @@ TEST_F(AutofillTableTest, Autofill_AddFormFieldValues) {
ASSERT_EQ(2U, changes.size());
EXPECT_EQ(changes[0], AutofillChange(AutofillChange::ADD,
AutofillKey(ASCIIToUTF16("firstname"),
- ASCIIToUTF16("Joe"))));
+ ASCIIToUTF16("Joe"))));
EXPECT_EQ(changes[1], AutofillChange(AutofillChange::ADD,
AutofillKey(ASCIIToUTF16("lastname"),
- ASCIIToUTF16("Smith"))));
+ ASCIIToUTF16("Smith"))));
std::vector<AutofillEntry> all_entries;
ASSERT_TRUE(table_->GetAllAutofillEntries(&all_entries));
@@ -641,9 +633,8 @@ TEST_F(AutofillTableTest,
EXPECT_EQ(5, GetAutofillEntryCount(field.name, field.value, db_.get()));
changes.clear();
- EXPECT_TRUE(table_->RemoveFormElementsAddedBetween(base::Time::FromTimeT(51),
- base::Time::FromTimeT(60),
- &changes));
+ EXPECT_TRUE(table_->RemoveFormElementsAddedBetween(
+ base::Time::FromTimeT(51), base::Time::FromTimeT(60), &changes));
EXPECT_TRUE(changes.empty());
EXPECT_EQ(5, GetAutofillEntryCount(field.name, field.value, db_.get()));
}
@@ -669,9 +660,8 @@ TEST_F(AutofillTableTest,
EXPECT_EQ(5, GetAutofillEntryCount(field.name, field.value, db_.get()));
changes.clear();
- EXPECT_TRUE(table_->RemoveFormElementsAddedBetween(base::Time::FromTimeT(40),
- base::Time::FromTimeT(50),
- &changes));
+ EXPECT_TRUE(table_->RemoveFormElementsAddedBetween(
+ base::Time::FromTimeT(40), base::Time::FromTimeT(50), &changes));
EXPECT_TRUE(changes.empty());
EXPECT_EQ(5, GetAutofillEntryCount(field.name, field.value, db_.get()));
}
@@ -697,9 +687,8 @@ TEST_F(AutofillTableTest,
EXPECT_EQ(5, GetAutofillEntryCount(field.name, field.value, db_.get()));
changes.clear();
- EXPECT_TRUE(table_->RemoveFormElementsAddedBetween(base::Time::FromTimeT(10),
- base::Time::FromTimeT(51),
- &changes));
+ EXPECT_TRUE(table_->RemoveFormElementsAddedBetween(
+ base::Time::FromTimeT(10), base::Time::FromTimeT(51), &changes));
ASSERT_EQ(1U, changes.size());
EXPECT_EQ(AutofillChange(AutofillChange::REMOVE,
AutofillKey(field.name, field.value)),
@@ -728,18 +717,16 @@ TEST_F(AutofillTableTest,
EXPECT_EQ(5, GetAutofillEntryCount(field.name, field.value, db_.get()));
changes.clear();
- EXPECT_TRUE(table_->RemoveFormElementsAddedBetween(base::Time::FromTimeT(40),
- base::Time::FromTimeT(60),
- &changes));
+ EXPECT_TRUE(table_->RemoveFormElementsAddedBetween(
+ base::Time::FromTimeT(40), base::Time::FromTimeT(60), &changes));
ASSERT_EQ(1U, changes.size());
EXPECT_EQ(AutofillChange(AutofillChange::UPDATE,
AutofillKey(field.name, field.value)),
changes[0]);
EXPECT_EQ(4, GetAutofillEntryCount(field.name, field.value, db_.get()));
base::Time date_created, date_last_used;
- EXPECT_TRUE(
- table_->GetAutofillTimestamps(field.name, field.value,
- &date_created, &date_last_used));
+ EXPECT_TRUE(table_->GetAutofillTimestamps(field.name, field.value,
+ &date_created, &date_last_used));
EXPECT_EQ(base::Time::FromTimeT(10), date_created);
EXPECT_EQ(base::Time::FromTimeT(39), date_last_used);
}
@@ -765,25 +752,23 @@ TEST_F(AutofillTableTest,
EXPECT_EQ(5, GetAutofillEntryCount(field.name, field.value, db_.get()));
changes.clear();
- EXPECT_TRUE(table_->RemoveFormElementsAddedBetween(base::Time::FromTimeT(40),
- base::Time::FromTimeT(80),
- &changes));
+ EXPECT_TRUE(table_->RemoveFormElementsAddedBetween(
+ base::Time::FromTimeT(40), base::Time::FromTimeT(80), &changes));
ASSERT_EQ(1U, changes.size());
EXPECT_EQ(AutofillChange(AutofillChange::UPDATE,
AutofillKey(field.name, field.value)),
changes[0]);
EXPECT_EQ(2, GetAutofillEntryCount(field.name, field.value, db_.get()));
base::Time date_created, date_last_used;
- EXPECT_TRUE(
- table_->GetAutofillTimestamps(field.name, field.value,
- &date_created, &date_last_used));
+ EXPECT_TRUE(table_->GetAutofillTimestamps(field.name, field.value,
+ &date_created, &date_last_used));
EXPECT_EQ(base::Time::FromTimeT(80), date_created);
EXPECT_EQ(base::Time::FromTimeT(90), date_last_used);
}
TEST_F(AutofillTableTest,
Autofill_RemoveFormElementsAddedBetween_OlderThan30Days) {
- const base::Time kNow = base::Time::Now();
+ const base::Time kNow = AutofillClock::Now();
const base::Time k29DaysOld = kNow - base::TimeDelta::FromDays(29);
const base::Time k30DaysOld = kNow - base::TimeDelta::FromDays(30);
const base::Time k31DaysOld = kNow - base::TimeDelta::FromDays(31);
@@ -880,9 +865,9 @@ TEST_F(AutofillTableTest, AutofillProfile) {
home_profile.SetClientValidityFromBitfieldValue(6);
home_profile.set_is_client_validity_states_updated(true);
- Time pre_creation_time = Time::Now();
+ Time pre_creation_time = AutofillClock::Now();
EXPECT_TRUE(table_->AddAutofillProfile(home_profile));
- Time post_creation_time = Time::Now();
+ Time post_creation_time = AutofillClock::Now();
// Get the 'Home' profile.
std::unique_ptr<AutofillProfile> db_profile =
@@ -907,9 +892,9 @@ TEST_F(AutofillTableTest, AutofillProfile) {
ASCIIToUTF16("5678 Bottom Street"));
billing_profile.SetRawInfo(ADDRESS_HOME_LINE2, ASCIIToUTF16("suite 3"));
- pre_creation_time = Time::Now();
+ pre_creation_time = AutofillClock::Now();
EXPECT_TRUE(table_->AddAutofillProfile(billing_profile));
- post_creation_time = Time::Now();
+ post_creation_time = AutofillClock::Now();
// Get the 'Billing' profile.
db_profile = table_->GetAutofillProfile(billing_profile.guid());
@@ -926,9 +911,9 @@ TEST_F(AutofillTableTest, AutofillProfile) {
// Update the 'Billing' profile, name only.
billing_profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
- Time pre_modification_time = Time::Now();
+ Time pre_modification_time = AutofillClock::Now();
EXPECT_TRUE(table_->UpdateAutofillProfile(billing_profile));
- Time post_modification_time = Time::Now();
+ Time post_modification_time = AutofillClock::Now();
db_profile = table_->GetAutofillProfile(billing_profile.guid());
ASSERT_TRUE(db_profile);
EXPECT_EQ(billing_profile, *db_profile);
@@ -937,10 +922,8 @@ TEST_F(AutofillTableTest, AutofillProfile) {
s_billing_updated.BindString(0, billing_profile.guid());
ASSERT_TRUE(s_billing_updated.is_valid());
ASSERT_TRUE(s_billing_updated.Step());
- EXPECT_GE(s_billing_updated.ColumnInt64(0),
- pre_modification_time.ToTimeT());
- EXPECT_LE(s_billing_updated.ColumnInt64(0),
- post_modification_time.ToTimeT());
+ EXPECT_GE(s_billing_updated.ColumnInt64(0), pre_modification_time.ToTimeT());
+ EXPECT_LE(s_billing_updated.ColumnInt64(0), post_modification_time.ToTimeT());
EXPECT_FALSE(s_billing_updated.Step());
// Update the 'Billing' profile with non-default data. The specific values are
@@ -965,9 +948,9 @@ TEST_F(AutofillTableTest, AutofillProfile) {
billing_profile.SetClientValidityFromBitfieldValue(54);
billing_profile.set_is_client_validity_states_updated(true);
- Time pre_modification_time_2 = Time::Now();
+ Time pre_modification_time_2 = AutofillClock::Now();
EXPECT_TRUE(table_->UpdateAutofillProfile(billing_profile));
- Time post_modification_time_2 = Time::Now();
+ Time post_modification_time_2 = AutofillClock::Now();
db_profile = table_->GetAutofillProfile(billing_profile.guid());
ASSERT_TRUE(db_profile);
EXPECT_EQ(billing_profile, *db_profile);
@@ -989,87 +972,6 @@ TEST_F(AutofillTableTest, AutofillProfile) {
EXPECT_FALSE(db_profile);
}
-TEST_F(AutofillTableTest, AutofillProfileTrash) {
- std::vector<std::string> guids;
- table_->GetAutofillProfilesInTrash(&guids);
- EXPECT_TRUE(guids.empty());
-
- ASSERT_TRUE(table_->AddAutofillGUIDToTrash(
- "00000000-0000-0000-0000-000000000000"));
- ASSERT_TRUE(table_->AddAutofillGUIDToTrash(
- "00000000-0000-0000-0000-000000000001"));
- ASSERT_TRUE(table_->GetAutofillProfilesInTrash(&guids));
- EXPECT_EQ(2UL, guids.size());
- EXPECT_EQ("00000000-0000-0000-0000-000000000000", guids[0]);
- EXPECT_EQ("00000000-0000-0000-0000-000000000001", guids[1]);
-
- ASSERT_TRUE(table_->EmptyAutofillProfilesTrash());
- ASSERT_TRUE(table_->GetAutofillProfilesInTrash(&guids));
- EXPECT_TRUE(guids.empty());
-}
-
-TEST_F(AutofillTableTest, AutofillProfileTrashInteraction) {
- std::vector<std::string> guids;
- table_->GetAutofillProfilesInTrash(&guids);
- EXPECT_TRUE(guids.empty());
-
- AutofillProfile profile;
- profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
- profile.SetRawInfo(NAME_MIDDLE, ASCIIToUTF16("Q."));
- profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Smith"));
- profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16("js@smith.xyz"));
- profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1 Main St"));
- profile.SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("Los Angeles"));
- profile.SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("CA"));
- profile.SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("90025"));
- profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("US"));
-
- // Mark this profile as in the trash. This stops |AddAutofillProfile| from
- // adding it.
- EXPECT_TRUE(table_->AddAutofillGUIDToTrash(profile.guid()));
- EXPECT_TRUE(table_->AddAutofillProfile(profile));
- std::unique_ptr<AutofillProfile> added_profile =
- table_->GetAutofillProfile(profile.guid());
- EXPECT_FALSE(added_profile);
-
- // Add the profile for real this time.
- EXPECT_TRUE(table_->EmptyAutofillProfilesTrash());
- EXPECT_TRUE(table_->GetAutofillProfilesInTrash(&guids));
- EXPECT_TRUE(guids.empty());
- EXPECT_TRUE(table_->AddAutofillProfile(profile));
- added_profile = table_->GetAutofillProfile(profile.guid());
- EXPECT_TRUE(added_profile);
-
- // Mark this profile as in the trash. This stops |UpdateAutofillProfileMulti|
- // from updating it. In normal operation a profile should not be both in the
- // trash and in the profiles table simultaneously.
- EXPECT_TRUE(table_->AddAutofillGUIDToTrash(profile.guid()));
- profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
- EXPECT_TRUE(table_->UpdateAutofillProfile(profile));
- std::unique_ptr<AutofillProfile> updated_profile =
- table_->GetAutofillProfile(profile.guid());
- EXPECT_TRUE(updated_profile);
- EXPECT_EQ(ASCIIToUTF16("John"), updated_profile->GetRawInfo(NAME_FIRST));
-
- // Try to delete the trashed profile. This stops |RemoveAutofillProfile| from
- // deleting it. In normal operation deletion is done by migration step, and
- // removal from trash is done by |WebDataService|. |RemoveAutofillProfile|
- // does remove the item from the trash if it is found however, so that if
- // other clients remove it (via Sync say) then it is gone and doesn't need to
- // be processed further by |WebDataService|.
- EXPECT_TRUE(table_->RemoveAutofillProfile(profile.guid()));
- std::unique_ptr<AutofillProfile> removed_profile =
- table_->GetAutofillProfile(profile.guid());
- EXPECT_TRUE(removed_profile);
- EXPECT_FALSE(table_->IsAutofillGUIDInTrash(profile.guid()));
-
- // Check that emptying the trash now allows removal to occur.
- EXPECT_TRUE(table_->EmptyAutofillProfilesTrash());
- EXPECT_TRUE(table_->RemoveAutofillProfile(profile.guid()));
- removed_profile = table_->GetAutofillProfile(profile.guid());
- EXPECT_FALSE(removed_profile);
-}
-
TEST_F(AutofillTableTest, CreditCard) {
// Add a 'Work' credit card.
CreditCard work_creditcard;
@@ -1082,9 +984,9 @@ TEST_F(AutofillTableTest, CreditCard) {
work_creditcard.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR,
ASCIIToUTF16("2013"));
- Time pre_creation_time = Time::Now();
+ Time pre_creation_time = AutofillClock::Now();
EXPECT_TRUE(table_->AddCreditCard(work_creditcard));
- Time post_creation_time = Time::Now();
+ Time post_creation_time = AutofillClock::Now();
// Get the 'Work' credit card.
std::unique_ptr<CreditCard> db_creditcard =
@@ -1113,9 +1015,9 @@ TEST_F(AutofillTableTest, CreditCard) {
target_creditcard.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR,
ASCIIToUTF16("2012"));
- pre_creation_time = Time::Now();
+ pre_creation_time = AutofillClock::Now();
EXPECT_TRUE(table_->AddCreditCard(target_creditcard));
- post_creation_time = Time::Now();
+ post_creation_time = AutofillClock::Now();
db_creditcard = table_->GetCreditCard(target_creditcard.guid());
ASSERT_TRUE(db_creditcard);
EXPECT_EQ(target_creditcard, *db_creditcard);
@@ -1134,9 +1036,9 @@ TEST_F(AutofillTableTest, CreditCard) {
target_creditcard.set_origin("Interactive Autofill dialog");
target_creditcard.SetRawInfo(CREDIT_CARD_NAME_FULL,
ASCIIToUTF16("Charles Grady"));
- Time pre_modification_time = Time::Now();
+ Time pre_modification_time = AutofillClock::Now();
EXPECT_TRUE(table_->UpdateCreditCard(target_creditcard));
- Time post_modification_time = Time::Now();
+ Time post_modification_time = AutofillClock::Now();
db_creditcard = table_->GetCreditCard(target_creditcard.guid());
ASSERT_TRUE(db_creditcard);
EXPECT_EQ(target_creditcard, *db_creditcard);
@@ -1194,7 +1096,7 @@ TEST_F(AutofillTableTest, UpdateAutofillProfile) {
table_->AddAutofillProfile(profile);
// Set a mocked value for the profile's creation time.
- const time_t kMockCreationDate = Time::Now().ToTimeT() - 13;
+ const time_t kMockCreationDate = AutofillClock::Now().ToTimeT() - 13;
sql::Statement s_mock_creation_date(
db_->GetSQLConnection()->GetUniqueStatement(
"UPDATE autofill_profiles SET date_modified = ?"));
@@ -1231,7 +1133,7 @@ TEST_F(AutofillTableTest, UpdateAutofillProfile) {
EXPECT_FALSE(s_updated.Step());
// Set a mocked value for the profile's modification time.
- const time_t mock_modification_date = Time::Now().ToTimeT() - 7;
+ const time_t mock_modification_date = AutofillClock::Now().ToTimeT() - 7;
sql::Statement s_mock_modification_date(
db_->GetSQLConnection()->GetUniqueStatement(
"UPDATE autofill_profiles SET date_modified = ?"));
@@ -1265,7 +1167,7 @@ TEST_F(AutofillTableTest, UpdateCreditCard) {
table_->AddCreditCard(credit_card);
// Set a mocked value for the credit card's creation time.
- const time_t kMockCreationDate = Time::Now().ToTimeT() - 13;
+ const time_t kMockCreationDate = AutofillClock::Now().ToTimeT() - 13;
sql::Statement s_mock_creation_date(
db_->GetSQLConnection()->GetUniqueStatement(
"UPDATE credit_cards SET date_modified = ?"));
@@ -1302,7 +1204,7 @@ TEST_F(AutofillTableTest, UpdateCreditCard) {
EXPECT_FALSE(s_updated.Step());
// Set a mocked value for the credit card's modification time.
- const time_t mock_modification_date = Time::Now().ToTimeT() - 7;
+ const time_t mock_modification_date = AutofillClock::Now().ToTimeT() - 7;
sql::Statement s_mock_modification_date(
db_->GetSQLConnection()->GetUniqueStatement(
"UPDATE credit_cards SET date_modified = ?"));
@@ -1344,7 +1246,7 @@ TEST_F(AutofillTableTest, UpdateProfileOriginOnly) {
table_->AddAutofillProfile(profile);
// Set a mocked value for the profile's creation time.
- const time_t kMockCreationDate = Time::Now().ToTimeT() - 13;
+ const time_t kMockCreationDate = AutofillClock::Now().ToTimeT() - 13;
sql::Statement s_mock_creation_date(
db_->GetSQLConnection()->GetUniqueStatement(
"UPDATE autofill_profiles SET date_modified = ?"));
@@ -1391,7 +1293,7 @@ TEST_F(AutofillTableTest, UpdateCreditCardOriginOnly) {
table_->AddCreditCard(credit_card);
// Set a mocked value for the credit card's creation time.
- const time_t kMockCreationDate = Time::Now().ToTimeT() - 13;
+ const time_t kMockCreationDate = AutofillClock::Now().ToTimeT() - 13;
sql::Statement s_mock_creation_date(
db_->GetSQLConnection()->GetUniqueStatement(
"UPDATE credit_cards SET date_modified = ?"));
@@ -1725,8 +1627,8 @@ TEST_F(AutofillTableTest, RemoveOriginURLsModifiedBetween) {
// Remove all origin URLs set in the bounded time range [21,27).
std::vector<std::unique_ptr<AutofillProfile>> profiles;
- table_->RemoveOriginURLsModifiedBetween(
- Time::FromTimeT(21), Time::FromTimeT(27), &profiles);
+ table_->RemoveOriginURLsModifiedBetween(Time::FromTimeT(21),
+ Time::FromTimeT(27), &profiles);
ASSERT_EQ(1UL, profiles.size());
EXPECT_EQ("00000000-0000-0000-0000-000000000001", profiles[0]->guid());
sql::Statement s_autofill_profiles_bounded(
@@ -1751,8 +1653,7 @@ TEST_F(AutofillTableTest, RemoveOriginURLsModifiedBetween) {
EXPECT_EQ(std::string(), s_credit_cards_bounded.ColumnString(1));
ASSERT_TRUE(s_credit_cards_bounded.Step());
EXPECT_EQ(27, s_credit_cards_bounded.ColumnInt64(0));
- EXPECT_EQ("https://www.example.com/",
- s_credit_cards_bounded.ColumnString(1));
+ EXPECT_EQ("https://www.example.com/", s_credit_cards_bounded.ColumnString(1));
ASSERT_TRUE(s_credit_cards_bounded.Step());
EXPECT_EQ(37, s_credit_cards_bounded.ColumnInt64(0));
EXPECT_EQ(kSettingsOrigin, s_credit_cards_bounded.ColumnString(1));
@@ -1774,9 +1675,8 @@ TEST_F(AutofillTableTest, RemoveOriginURLsModifiedBetween) {
ASSERT_TRUE(s_autofill_profiles_all.Step());
EXPECT_EQ(31, s_autofill_profiles_all.ColumnInt64(0));
EXPECT_EQ(kSettingsOrigin, s_autofill_profiles_all.ColumnString(1));
- sql::Statement s_credit_cards_all(
- db_->GetSQLConnection()->GetUniqueStatement(
- "SELECT date_modified, origin FROM credit_cards"));
+ sql::Statement s_credit_cards_all(db_->GetSQLConnection()->GetUniqueStatement(
+ "SELECT date_modified, origin FROM credit_cards"));
ASSERT_TRUE(s_credit_cards_all.is_valid());
ASSERT_TRUE(s_credit_cards_all.Step());
EXPECT_EQ(17, s_credit_cards_all.ColumnInt64(0));
@@ -1798,19 +1698,19 @@ TEST_F(AutofillTableTest, Autofill_GetAllAutofillEntries_NoResults) {
TEST_F(AutofillTableTest, Autofill_GetAllAutofillEntries_OneResult) {
AutofillChangeList changes;
- std::map<std::string, std::vector<Time> > name_value_times_map;
+ std::map<std::string, std::vector<Time>> name_value_times_map;
time_t start = 0;
std::vector<Time> timestamps1;
FormFieldData field;
field.name = ASCIIToUTF16("Name");
field.value = ASCIIToUTF16("Superman");
- EXPECT_TRUE(table_->AddFormFieldValueTime(field, &changes,
- Time::FromTimeT(start)));
+ EXPECT_TRUE(
+ table_->AddFormFieldValueTime(field, &changes, Time::FromTimeT(start)));
timestamps1.push_back(Time::FromTimeT(start));
std::string key1("NameSuperman");
name_value_times_map.insert(
- std::pair<std::string, std::vector<Time> >(key1, timestamps1));
+ std::pair<std::string, std::vector<Time>>(key1, timestamps1));
AutofillEntrySet expected_entries(CompareAutofillEntries);
AutofillKey ak1(ASCIIToUTF16("Name"), ASCIIToUTF16("Superman"));
@@ -1828,30 +1728,30 @@ TEST_F(AutofillTableTest, Autofill_GetAllAutofillEntries_OneResult) {
TEST_F(AutofillTableTest, Autofill_GetAllAutofillEntries_TwoDistinct) {
AutofillChangeList changes;
- std::map<std::string, std::vector<Time> > name_value_times_map;
+ std::map<std::string, std::vector<Time>> name_value_times_map;
time_t start = 0;
std::vector<Time> timestamps1;
FormFieldData field;
field.name = ASCIIToUTF16("Name");
field.value = ASCIIToUTF16("Superman");
- EXPECT_TRUE(table_->AddFormFieldValueTime(field, &changes,
- Time::FromTimeT(start)));
+ EXPECT_TRUE(
+ table_->AddFormFieldValueTime(field, &changes, Time::FromTimeT(start)));
timestamps1.push_back(Time::FromTimeT(start));
std::string key1("NameSuperman");
name_value_times_map.insert(
- std::pair<std::string, std::vector<Time> >(key1, timestamps1));
+ std::pair<std::string, std::vector<Time>>(key1, timestamps1));
++start;
std::vector<Time> timestamps2;
field.name = ASCIIToUTF16("Name");
field.value = ASCIIToUTF16("Clark Kent");
- EXPECT_TRUE(table_->AddFormFieldValueTime(field, &changes,
- Time::FromTimeT(start)));
+ EXPECT_TRUE(
+ table_->AddFormFieldValueTime(field, &changes, Time::FromTimeT(start)));
timestamps2.push_back(Time::FromTimeT(start));
std::string key2("NameClark Kent");
name_value_times_map.insert(
- std::pair<std::string, std::vector<Time> >(key2, timestamps2));
+ std::pair<std::string, std::vector<Time>>(key2, timestamps2));
AutofillEntrySet expected_entries(CompareAutofillEntries);
AutofillKey ak1(ASCIIToUTF16("Name"), ASCIIToUTF16("Superman"));
@@ -1872,7 +1772,7 @@ TEST_F(AutofillTableTest, Autofill_GetAllAutofillEntries_TwoDistinct) {
TEST_F(AutofillTableTest, Autofill_GetAllAutofillEntries_TwoSame) {
AutofillChangeList changes;
- std::map<std::string, std::vector<Time> > name_value_times_map;
+ std::map<std::string, std::vector<Time>> name_value_times_map;
std::vector<Time> timestamps;
time_t start = 0;
@@ -1880,14 +1780,14 @@ TEST_F(AutofillTableTest, Autofill_GetAllAutofillEntries_TwoSame) {
FormFieldData field;
field.name = ASCIIToUTF16("Name");
field.value = ASCIIToUTF16("Superman");
- EXPECT_TRUE(table_->AddFormFieldValueTime(field, &changes,
- Time::FromTimeT(start)));
+ EXPECT_TRUE(
+ table_->AddFormFieldValueTime(field, &changes, Time::FromTimeT(start)));
timestamps.push_back(Time::FromTimeT(start));
}
std::string key("NameSuperman");
name_value_times_map.insert(
- std::pair<std::string, std::vector<Time> >(key, timestamps));
+ std::pair<std::string, std::vector<Time>>(key, timestamps));
AutofillEntrySet expected_entries(CompareAutofillEntries);
AutofillKey ak1(ASCIIToUTF16("Name"), ASCIIToUTF16("Superman"));
@@ -1980,8 +1880,7 @@ TEST_F(AutofillTableTest, SetGetServerCards) {
inputs[0].SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2020"));
inputs[0].SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111"));
- inputs.push_back(
- CreditCard(CreditCard::MASKED_SERVER_CARD, "b456"));
+ inputs.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b456"));
inputs[1].SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("Rick Roman"));
inputs[1].SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("12"));
inputs[1].SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("1997"));
@@ -2019,7 +1918,7 @@ TEST_F(AutofillTableTest, SetGetRemoveServerCardMetadata) {
AutofillMetadata input;
input.id = "server id";
input.use_count = 50;
- input.use_date = Time::Now();
+ input.use_date = AutofillClock::Now();
input.billing_address_id = "billing id";
EXPECT_TRUE(table_->AddServerCardMetadata(input));
@@ -2042,7 +1941,7 @@ TEST_F(AutofillTableTest, SetGetRemoveServerAddressMetadata) {
AutofillMetadata input;
input.id = "server id";
input.use_count = 50;
- input.use_date = Time::Now();
+ input.use_date = AutofillClock::Now();
input.has_converted = true;
table_->AddServerAddressMetadata(input);
@@ -2065,7 +1964,7 @@ TEST_F(AutofillTableTest, AddUpdateServerAddressMetadata) {
AutofillMetadata input;
input.id = "server id";
input.use_count = 50;
- input.use_date = Time::Now();
+ input.use_date = AutofillClock::Now();
input.has_converted = true;
ASSERT_TRUE(table_->AddServerAddressMetadata(input));
@@ -2096,7 +1995,7 @@ TEST_F(AutofillTableTest, AddUpdateServerCardMetadata) {
AutofillMetadata input;
input.id = "server id";
input.use_count = 50;
- input.use_date = Time::Now();
+ input.use_date = AutofillClock::Now();
input.billing_address_id = "billing id";
ASSERT_TRUE(table_->AddServerCardMetadata(input));
@@ -2192,7 +2091,7 @@ TEST_F(AutofillTableTest, RemoveWrongServerCardMetadata) {
AutofillMetadata input;
input.id = "server id";
input.use_count = 50;
- input.use_date = Time::Now();
+ input.use_date = AutofillClock::Now();
input.billing_address_id = "billing id";
table_->AddServerCardMetadata(input);
@@ -2261,7 +2160,7 @@ TEST_F(AutofillTableTest, SetServerCardsData_ExistingMetadata) {
AutofillMetadata input;
input.id = "server id";
input.use_count = 50;
- input.use_date = Time::Now();
+ input.use_date = AutofillClock::Now();
input.billing_address_id = "billing id";
table_->AddServerCardMetadata(input);
@@ -2318,7 +2217,7 @@ TEST_F(AutofillTableTest, SetServerAddressesData_ExistingMetadata) {
AutofillMetadata input;
input.id = "server id";
input.use_count = 50;
- input.use_date = Time::Now();
+ input.use_date = AutofillClock::Now();
input.has_converted = true;
table_->AddServerAddressMetadata(input);
@@ -2340,7 +2239,7 @@ TEST_F(AutofillTableTest, RemoveWrongServerAddressMetadata) {
AutofillMetadata input;
input.id = "server id";
input.use_count = 50;
- input.use_date = Time::Now();
+ input.use_date = AutofillClock::Now();
input.has_converted = true;
table_->AddServerAddressMetadata(input);
@@ -2371,8 +2270,7 @@ TEST_F(AutofillTableTest, MaskUnmaskServerCards) {
// Unmask the number. The full number should be available.
base::string16 full_number(ASCIIToUTF16("4111111111111111"));
- ASSERT_TRUE(table_->UnmaskServerCreditCard(inputs[0],
- full_number));
+ ASSERT_TRUE(table_->UnmaskServerCreditCard(inputs[0], full_number));
std::vector<std::unique_ptr<CreditCard>> outputs;
table_->GetServerCreditCards(&outputs);
@@ -2601,7 +2499,7 @@ TEST_F(AutofillTableTest, SetServerProfileUpdateUsageStats) {
// Update the usage stats; make sure they're reflected in GetServerProfiles.
inputs.back().set_use_count(4U);
- inputs.back().set_use_date(base::Time::Now());
+ inputs.back().set_use_date(AutofillClock::Now());
table_->UpdateServerAddressMetadata(inputs.back());
table_->GetServerProfiles(&outputs);
ASSERT_EQ(1u, outputs.size());
@@ -2627,7 +2525,7 @@ TEST_F(AutofillTableTest, SetServerProfileUpdateUsageStats) {
TEST_F(AutofillTableTest, DeleteUnmaskedCard) {
// This isn't the exact unmasked time, since the database will use the
// current time that it is called. The code below has to be approximate.
- base::Time unmasked_time = base::Time::Now();
+ base::Time unmasked_time = AutofillClock::Now();
// Add a masked card.
base::string16 masked_number = ASCIIToUTF16("1111");
@@ -2666,7 +2564,7 @@ TEST_F(AutofillTableTest, DeleteUnmaskedCard) {
// Delete data in the range of the last 24 hours.
// Fudge |now| to make sure it's strictly greater than the |now| that
// the database uses.
- base::Time now = base::Time::Now() + base::TimeDelta::FromSeconds(1);
+ base::Time now = AutofillClock::Now() + base::TimeDelta::FromSeconds(1);
ASSERT_TRUE(table_->RemoveAutofillDataModifiedBetween(
now - base::TimeDelta::FromDays(1), now, &profiles, &credit_cards));
@@ -2775,7 +2673,7 @@ TEST_P(GetFormValuesTest, GetFormValuesForElementName_SubstringMatchEnabled) {
<< "suggestion = " << test_case.field_suggestion[0]
<< ", contents = " << test_case.field_contents);
- Time t1 = Time::Now();
+ Time t1 = AutofillClock::Now();
// Simulate the submission of a handful of entries in a field called "Name".
AutofillChangeList changes;
@@ -3102,4 +3000,16 @@ TEST_F(AutofillTableTest, RemoveOrphanAutofillTableRows) {
EXPECT_FALSE(s_autofill_profile_phones.Step());
}
+TEST_F(AutofillTableTest, VPA) {
+ EXPECT_TRUE(table_->InsertVPA("name@indianbank"));
+
+ sql::Statement s_inspect(db_->GetSQLConnection()->GetUniqueStatement(
+ "SELECT vpa FROM payments_upi_vpa"));
+
+ ASSERT_TRUE(s_inspect.is_valid());
+ ASSERT_TRUE(s_inspect.Step());
+ EXPECT_GE(s_inspect.ColumnString(0), "name@indianbank");
+ EXPECT_FALSE(s_inspect.Step());
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc
index eeae78ff20d..0f78f82f872 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc
@@ -29,7 +29,7 @@
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h"
#include "components/autofill/core/common/autofill_constants.h"
-#include "components/sync/base/hash_util.h"
+#include "components/sync/base/client_tag_hash.h"
#include "components/sync/model/data_batch.h"
#include "components/sync/model/entity_data.h"
#include "components/sync/model/mock_model_type_change_processor.h"
@@ -353,7 +353,7 @@ class AutofillWalletMetadataSyncBridgeTest : public testing::Test {
bool is_deleted = false) {
auto data = std::make_unique<EntityData>();
*data->specifics.mutable_wallet_metadata() = specifics;
- data->client_tag_hash = syncer::GenerateSyncableHash(
+ data->client_tag_hash = syncer::ClientTagHash::FromUnhashed(
syncer::AUTOFILL_WALLET_METADATA, bridge()->GetClientTag(*data));
if (is_deleted) {
// Specifics had to be set in order to generate the client tag. Since
@@ -451,7 +451,7 @@ class AutofillWalletMetadataSyncBridgeTest : public testing::Test {
int response_version = 0;
autofill::TestAutofillClock test_clock_;
ScopedTempDir temp_dir_;
- base::test::TaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
testing::NiceMock<MockAutofillWebDataBackend> backend_;
AutofillTable table_;
WebDatabase db_;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
index 50741416fb7..12e7e536098 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
@@ -31,7 +31,7 @@
#include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
#include "components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h"
#include "components/autofill/core/common/autofill_constants.h"
-#include "components/sync/base/hash_util.h"
+#include "components/sync/base/client_tag_hash.h"
#include "components/sync/driver/sync_driver_switches.h"
#include "components/sync/model/entity_data.h"
#include "components/sync/model/mock_model_type_change_processor.h"
@@ -269,7 +269,7 @@ class AutofillWalletSyncBridgeTest : public testing::Test {
const AutofillWalletSpecifics& specifics) {
auto data = std::make_unique<EntityData>();
*data->specifics.mutable_autofill_wallet() = specifics;
- data->client_tag_hash = syncer::GenerateSyncableHash(
+ data->client_tag_hash = syncer::ClientTagHash::FromUnhashed(
syncer::AUTOFILL_WALLET_DATA, bridge()->GetClientTag(*data));
return data;
}
@@ -307,7 +307,7 @@ class AutofillWalletSyncBridgeTest : public testing::Test {
private:
autofill::TestAutofillClock test_clock_;
ScopedTempDir temp_dir_;
- base::test::TaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
NiceMock<MockAutofillWebDataBackend> backend_;
AutofillTable table_;
WebDatabase db_;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc b/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
index 3573e2a2fc1..f7f343a4b7c 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
@@ -117,10 +117,6 @@ void AutofillWebDataBackendImpl::NotifyOfCreditCardChanged(
void AutofillWebDataBackendImpl::NotifyOfMultipleAutofillChanges() {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
- // DB sequence notification.
- for (auto& db_observer : db_observer_list_)
- db_observer.AutofillMultipleChangedBySync();
-
// UI sequence notification.
ui_task_runner_->PostTask(FROM_HERE, on_changed_callback_);
}
@@ -157,11 +153,12 @@ void AutofillWebDataBackendImpl::ResetUserData() {
}
WebDatabase::State AutofillWebDataBackendImpl::AddFormElements(
- const std::vector<FormFieldData>& fields, WebDatabase* db) {
+ const std::vector<FormFieldData>& fields,
+ WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
AutofillChangeList changes;
- if (!AutofillTable::FromWebDatabase(db)->AddFormFieldValues(
- fields, &changes)) {
+ if (!AutofillTable::FromWebDatabase(db)->AddFormFieldValues(fields,
+ &changes)) {
NOTREACHED();
return WebDatabase::COMMIT_NOT_NEEDED;
}
@@ -211,7 +208,9 @@ WebDatabase::State AutofillWebDataBackendImpl::RemoveFormElementsAddedBetween(
}
WebDatabase::State AutofillWebDataBackendImpl::RemoveFormValueForElementName(
- const base::string16& name, const base::string16& value, WebDatabase* db) {
+ const base::string16& name,
+ const base::string16& value,
+ WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
if (AutofillTable::FromWebDatabase(db)->RemoveFormElement(name, value)) {
@@ -229,7 +228,8 @@ WebDatabase::State AutofillWebDataBackendImpl::RemoveFormValueForElementName(
}
WebDatabase::State AutofillWebDataBackendImpl::AddAutofillProfile(
- const AutofillProfile& profile, WebDatabase* db) {
+ const AutofillProfile& profile,
+ WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
if (!AutofillTable::FromWebDatabase(db)->AddAutofillProfile(profile)) {
NOTREACHED();
@@ -237,8 +237,8 @@ WebDatabase::State AutofillWebDataBackendImpl::AddAutofillProfile(
}
// Send GUID-based notification.
- AutofillProfileChange change(
- AutofillProfileChange::ADD, profile.guid(), &profile);
+ AutofillProfileChange change(AutofillProfileChange::ADD, profile.guid(),
+ &profile);
for (auto& db_observer : db_observer_list_)
db_observer.AutofillProfileChanged(change);
@@ -253,7 +253,8 @@ WebDatabase::State AutofillWebDataBackendImpl::AddAutofillProfile(
}
WebDatabase::State AutofillWebDataBackendImpl::UpdateAutofillProfile(
- const AutofillProfile& profile, WebDatabase* db) {
+ const AutofillProfile& profile,
+ WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
// Only perform the update if the profile exists. It is currently
// valid to try to update a missing profile. We simply drop the write and
@@ -269,8 +270,8 @@ WebDatabase::State AutofillWebDataBackendImpl::UpdateAutofillProfile(
}
// Send GUID-based notification.
- AutofillProfileChange change(
- AutofillProfileChange::UPDATE, profile.guid(), &profile);
+ AutofillProfileChange change(AutofillProfileChange::UPDATE, profile.guid(),
+ &profile);
for (auto& db_observer : db_observer_list_)
db_observer.AutofillProfileChanged(change);
@@ -285,7 +286,8 @@ WebDatabase::State AutofillWebDataBackendImpl::UpdateAutofillProfile(
}
WebDatabase::State AutofillWebDataBackendImpl::RemoveAutofillProfile(
- const std::string& guid, WebDatabase* db) {
+ const std::string& guid,
+ WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
std::unique_ptr<AutofillProfile> profile =
AutofillTable::FromWebDatabase(db)->GetAutofillProfile(guid);
@@ -352,8 +354,9 @@ AutofillWebDataBackendImpl::GetCountOfValuesContainedBetween(
const base::Time& end,
WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
- int value = AutofillTable::FromWebDatabase(db)
- ->GetCountOfValuesContainedBetween(begin, end);
+ int value =
+ AutofillTable::FromWebDatabase(db)->GetCountOfValuesContainedBetween(
+ begin, end);
return std::unique_ptr<WDTypedResult>(
new WDResult<int>(AUTOFILL_VALUE_RESULT, value));
}
@@ -362,15 +365,16 @@ WebDatabase::State AutofillWebDataBackendImpl::UpdateAutofillEntries(
const std::vector<AutofillEntry>& autofill_entries,
WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
- if (!AutofillTable::FromWebDatabase(db)
- ->UpdateAutofillEntries(autofill_entries))
+ if (!AutofillTable::FromWebDatabase(db)->UpdateAutofillEntries(
+ autofill_entries))
return WebDatabase::COMMIT_NOT_NEEDED;
return WebDatabase::COMMIT_NEEDED;
}
WebDatabase::State AutofillWebDataBackendImpl::AddCreditCard(
- const CreditCard& credit_card, WebDatabase* db) {
+ const CreditCard& credit_card,
+ WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
if (!AutofillTable::FromWebDatabase(db)->AddCreditCard(credit_card)) {
NOTREACHED();
@@ -385,7 +389,8 @@ WebDatabase::State AutofillWebDataBackendImpl::AddCreditCard(
}
WebDatabase::State AutofillWebDataBackendImpl::UpdateCreditCard(
- const CreditCard& credit_card, WebDatabase* db) {
+ const CreditCard& credit_card,
+ WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
// It is currently valid to try to update a missing profile. We simply drop
// the write and the caller will detect this on the next refresh.
@@ -407,7 +412,8 @@ WebDatabase::State AutofillWebDataBackendImpl::UpdateCreditCard(
}
WebDatabase::State AutofillWebDataBackendImpl::RemoveCreditCard(
- const std::string& guid, WebDatabase* db) {
+ const std::string& guid,
+ WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
std::unique_ptr<CreditCard> card =
AutofillTable::FromWebDatabase(db)->GetCreditCard(guid);
@@ -470,16 +476,15 @@ WebDatabase::State AutofillWebDataBackendImpl::UnmaskServerCreditCard(
const base::string16& full_number,
WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
- if (AutofillTable::FromWebDatabase(db)->UnmaskServerCreditCard(
- card, full_number))
+ if (AutofillTable::FromWebDatabase(db)->UnmaskServerCreditCard(card,
+ full_number))
return WebDatabase::COMMIT_NEEDED;
return WebDatabase::COMMIT_NOT_NEEDED;
}
-WebDatabase::State
- AutofillWebDataBackendImpl::MaskServerCreditCard(
- const std::string& id,
- WebDatabase* db) {
+WebDatabase::State AutofillWebDataBackendImpl::MaskServerCreditCard(
+ const std::string& id,
+ WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
if (AutofillTable::FromWebDatabase(db)->MaskServerCreditCard(id))
return WebDatabase::COMMIT_NEEDED;
@@ -520,6 +525,15 @@ WebDatabase::State AutofillWebDataBackendImpl::UpdateServerAddressMetadata(
return WebDatabase::COMMIT_NEEDED;
}
+WebDatabase::State AutofillWebDataBackendImpl::AddVPA(const std::string& vpa_id,
+ WebDatabase* db) {
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
+
+ if (!AutofillTable::FromWebDatabase(db)->InsertVPA(vpa_id))
+ return WebDatabase::COMMIT_NOT_NEEDED;
+ return WebDatabase::COMMIT_NEEDED;
+}
+
std::unique_ptr<WDTypedResult>
AutofillWebDataBackendImpl::GetPaymentsCustomerData(WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
@@ -550,10 +564,10 @@ WebDatabase::State AutofillWebDataBackendImpl::ClearAllLocalData(
}
WebDatabase::State
- AutofillWebDataBackendImpl::RemoveAutofillDataModifiedBetween(
- const base::Time& delete_begin,
- const base::Time& delete_end,
- WebDatabase* db) {
+AutofillWebDataBackendImpl::RemoveAutofillDataModifiedBetween(
+ const base::Time& delete_begin,
+ const base::Time& delete_end,
+ WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
std::vector<std::unique_ptr<AutofillProfile>> profiles;
std::vector<std::unique_ptr<CreditCard>> credit_cards;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h b/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
index 16a0151ff85..0dbb45d2404 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
@@ -161,8 +161,7 @@ class AutofillWebDataBackendImpl
WebDatabase* db);
// Removes a credit card from the web database. Valid only for local cards.
- WebDatabase::State RemoveCreditCard(const std::string& guid,
- WebDatabase* db);
+ WebDatabase::State RemoveCreditCard(const std::string& guid, WebDatabase* db);
// Adds a full server credit card to the web database.
WebDatabase::State AddFullServerCreditCard(const CreditCard& credit_card,
@@ -186,6 +185,8 @@ class AutofillWebDataBackendImpl
WebDatabase::State UpdateServerAddressMetadata(const AutofillProfile& profile,
WebDatabase* db);
+ WebDatabase::State AddVPA(const std::string& vpa_id, WebDatabase* db);
+
// Returns the PaymentsCustomerData from the database.
std::unique_ptr<WDTypedResult> GetPaymentsCustomerData(WebDatabase* db);
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc
index 90f3917982b..6f9d4604f78 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc
@@ -231,6 +231,11 @@ void AutofillWebDataService::MaskServerCreditCard(const std::string& id) {
autofill_backend_, id));
}
+void AutofillWebDataService::AddVPA(const std::string& vpa_id) {
+ wdbs_->ScheduleDBTask(FROM_HERE, Bind(&AutofillWebDataBackendImpl::AddVPA,
+ autofill_backend_, vpa_id));
+}
+
WebDataServiceBase::Handle AutofillWebDataService::GetPaymentsCustomerData(
WebDataServiceConsumer* consumer) {
return wdbs_->ScheduleDBTaskWithResult(
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h
index 43184406221..a12c516e8cf 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h
@@ -139,6 +139,9 @@ class AutofillWebDataService : public WebDataServiceBase {
const base::string16& full_number);
void MaskServerCreditCard(const std::string& id);
+ // Store a UPI/VPA value.
+ void AddVPA(const std::string& vpa_id);
+
// Initiates the request for Payments customer data. The method
// OnWebDataServiceRequestDone of |consumer| gets called when the request is
// finished, with the customer data included in the argument |result|. The
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service_observer.h b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service_observer.h
index 7fd955e98cc..60820bb1a51 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service_observer.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service_observer.h
@@ -23,13 +23,6 @@ class AutofillWebDataServiceObserverOnDBSequence {
// the WebDatabase.
virtual void CreditCardChanged(const CreditCardChange& change) {}
- // Called on DB sequence when multiple Autofill entries have been modified by
- // Sync.
- // TODO(crbug.com/900607): Remove AutofillMultipleChangedBySync() from
- // AutofillWebDataServiceObserverOnDBSequence once USS for wallet_metadata
- // launches.
- virtual void AutofillMultipleChangedBySync() {}
-
protected:
virtual ~AutofillWebDataServiceObserverOnDBSequence() {}
};
diff --git a/chromium/components/autofill/core/browser/webdata/web_data_service_unittest.cc b/chromium/components/autofill/core/browser/webdata/web_data_service_unittest.cc
index 8a3d73167f7..fbdec05751a 100644
--- a/chromium/components/autofill/core/browser/webdata/web_data_service_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/web_data_service_unittest.cc
@@ -28,6 +28,7 @@
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/webdata/common/web_data_results.h"
#include "components/webdata/common/web_data_service_base.h"
@@ -48,7 +49,7 @@ using testing::ElementsAreArray;
namespace {
template <class T>
-class AutofillWebDataServiceConsumer: public WebDataServiceConsumer {
+class AutofillWebDataServiceConsumer : public WebDataServiceConsumer {
public:
AutofillWebDataServiceConsumer() : handle_(0) {}
virtual ~AutofillWebDataServiceConsumer() {}
@@ -82,8 +83,7 @@ ACTION_P(SignalEvent, event) {
class MockAutofillWebDataServiceObserver
: public AutofillWebDataServiceObserverOnDBSequence {
public:
- MOCK_METHOD1(AutofillEntriesChanged,
- void(const AutofillChangeList& changes));
+ MOCK_METHOD1(AutofillEntriesChanged, void(const AutofillChangeList& changes));
MOCK_METHOD1(AutofillProfileChanged,
void(const AutofillProfileChange& change));
};
@@ -183,9 +183,8 @@ class WebDataServiceAutofillTest : public WebDataServiceTest {
TEST_F(WebDataServiceAutofillTest, FormFillAdd) {
const AutofillChange expected_changes[] = {
- AutofillChange(AutofillChange::ADD, AutofillKey(name1_, value1_)),
- AutofillChange(AutofillChange::ADD, AutofillKey(name2_, value2_))
- };
+ AutofillChange(AutofillChange::ADD, AutofillKey(name1_, value1_)),
+ AutofillChange(AutofillChange::ADD, AutofillKey(name2_, value2_))};
// This will verify that the correct notification is triggered,
// passing the correct list of autofill keys in the details.
@@ -204,8 +203,8 @@ TEST_F(WebDataServiceAutofillTest, FormFillAdd) {
AutofillWebDataServiceConsumer<std::vector<AutofillEntry>> consumer;
WebDataServiceBase::Handle handle;
static const int limit = 10;
- handle = wds_->GetFormValuesForElementName(
- name1_, base::string16(), limit, &consumer);
+ handle = wds_->GetFormValuesForElementName(name1_, base::string16(), limit,
+ &consumer);
task_environment_.RunUntilIdle();
EXPECT_EQ(handle, consumer.handle());
ASSERT_EQ(1U, consumer.result().size());
@@ -226,8 +225,7 @@ TEST_F(WebDataServiceAutofillTest, FormFillRemoveOne) {
// This will verify that the correct notification is triggered,
// passing the correct list of autofill keys in the details.
const AutofillChange expected_changes[] = {
- AutofillChange(AutofillChange::REMOVE, AutofillKey(name1_, value1_))
- };
+ AutofillChange(AutofillChange::REMOVE, AutofillKey(name1_, value1_))};
EXPECT_CALL(observer_,
AutofillEntriesChanged(ElementsAreArray(expected_changes)))
.WillOnce(SignalEvent(&done_event_));
@@ -239,7 +237,7 @@ TEST_F(WebDataServiceAutofillTest, FormFillRemoveOne) {
TEST_F(WebDataServiceAutofillTest, FormFillRemoveMany) {
TimeDelta one_day(TimeDelta::FromDays(1));
- Time t = Time::Now();
+ Time t = AutofillClock::Now();
EXPECT_CALL(observer_, AutofillEntriesChanged(_))
.WillOnce(SignalEvent(&done_event_));
@@ -255,9 +253,8 @@ TEST_F(WebDataServiceAutofillTest, FormFillRemoveMany) {
// This will verify that the correct notification is triggered,
// passing the correct list of autofill keys in the details.
const AutofillChange expected_changes[] = {
- AutofillChange(AutofillChange::REMOVE, AutofillKey(name1_, value1_)),
- AutofillChange(AutofillChange::REMOVE, AutofillKey(name2_, value2_))
- };
+ AutofillChange(AutofillChange::REMOVE, AutofillKey(name1_, value1_)),
+ AutofillChange(AutofillChange::REMOVE, AutofillKey(name2_, value2_))};
EXPECT_CALL(observer_,
AutofillEntriesChanged(ElementsAreArray(expected_changes)))
.WillOnce(SignalEvent(&done_event_));
@@ -271,8 +268,8 @@ TEST_F(WebDataServiceAutofillTest, ProfileAdd) {
AutofillProfile profile;
// Check that GUID-based notification was sent.
- const AutofillProfileChange expected_change(
- AutofillProfileChange::ADD, profile.guid(), &profile);
+ const AutofillProfileChange expected_change(AutofillProfileChange::ADD,
+ profile.guid(), &profile);
EXPECT_CALL(observer_, AutofillProfileChanged(expected_change))
.WillOnce(SignalEvent(&done_event_));
diff --git a/chromium/components/autofill/core/common/BUILD.gn b/chromium/components/autofill/core/common/BUILD.gn
index 0bb58c919d6..2f096cab5d5 100644
--- a/chromium/components/autofill/core/common/BUILD.gn
+++ b/chromium/components/autofill/core/common/BUILD.gn
@@ -29,6 +29,8 @@ jumbo_static_library("common") {
"autofill_regexes.h",
"autofill_switches.cc",
"autofill_switches.h",
+ "autofill_tick_clock.cc",
+ "autofill_tick_clock.h",
"autofill_util.cc",
"autofill_util.h",
"form_data.cc",
@@ -39,9 +41,10 @@ jumbo_static_library("common") {
"form_field_data.h",
"form_field_data_predictions.cc",
"form_field_data_predictions.h",
+ "logging/log_buffer.cc",
+ "logging/log_buffer.h",
"password_form.cc",
"password_form.h",
- "password_form_field_prediction_map.h",
"password_form_fill_data.cc",
"password_form_fill_data.h",
"password_form_generation_data.cc",
@@ -75,12 +78,15 @@ jumbo_static_library("common") {
source_set("unit_tests") {
testonly = true
sources = [
+ "autofill_internals/log_message_unittest.cc",
+ "autofill_internals/logging_scope_unittest.cc",
"autofill_l10n_util_unittest.cc",
"autofill_prefs_unittest.cc",
"autofill_regexes_unittest.cc",
"autofill_util_unittest.cc",
"form_data_unittest.cc",
"form_field_data_unittest.cc",
+ "logging/log_buffer_unittest.cc",
"password_form_fill_data_unittest.cc",
"save_password_progress_logger_unittest.cc",
]
diff --git a/chromium/components/autofill/core/common/autofill_clock.cc b/chromium/components/autofill/core/common/autofill_clock.cc
index 0336eb95132..60169c8c7fb 100644
--- a/chromium/components/autofill/core/common/autofill_clock.cc
+++ b/chromium/components/autofill/core/common/autofill_clock.cc
@@ -9,7 +9,7 @@
namespace autofill {
namespace {
-base::Clock* g_autofill_clock = nullptr;
+const base::Clock* g_autofill_clock = nullptr;
} // namespace
// static
@@ -25,7 +25,7 @@ void AutofillClock::SetClock() {
}
// static
-void AutofillClock::SetTestClock(base::Clock* clock) {
+void AutofillClock::SetTestClock(const base::Clock* clock) {
DCHECK(clock);
g_autofill_clock = clock;
}
diff --git a/chromium/components/autofill/core/common/autofill_clock.h b/chromium/components/autofill/core/common/autofill_clock.h
index 651d9cdf496..2280d16851c 100644
--- a/chromium/components/autofill/core/common/autofill_clock.h
+++ b/chromium/components/autofill/core/common/autofill_clock.h
@@ -16,7 +16,7 @@ namespace autofill {
// with a customizable clock to facilitate testing.
class AutofillClock {
public:
- // Returns the current time based on |clock_|.
+ // Returns the current time based last set clock.
static base::Time Now();
private:
@@ -26,7 +26,7 @@ class AutofillClock {
static void SetClock();
// Sets the clock to be used for tests.
- static void SetTestClock(base::Clock* clock);
+ static void SetTestClock(const base::Clock* clock);
AutofillClock() = delete;
~AutofillClock() = delete;
diff --git a/chromium/components/autofill/core/common/autofill_features.cc b/chromium/components/autofill/core/common/autofill_features.cc
index d7a0b6e4957..7f4ca82a5bf 100644
--- a/chromium/components/autofill/core/common/autofill_features.cc
+++ b/chromium/components/autofill/core/common/autofill_features.cc
@@ -112,6 +112,11 @@ const base::Feature kAutofillProfileServerValidation{
const base::Feature kAutofillRejectCompanyBirthyear{
"AutofillRejectCompanyBirthyear", base::FEATURE_DISABLED_BY_DEFAULT};
+// Controls whether autofill rejects using non-verified company names that are
+// social titles (e.g., "Mrs.") in some languages.
+const base::Feature kAutofillRejectCompanySocialTitle{
+ "AutofillRejectCompanySocialTitle", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Controls whether or not a group of fields not enclosed in a form can be
// considered a form. If this is enabled, unowned fields will only constitute
// a form if there are signals to suggest that this might a checkout page.
@@ -126,6 +131,10 @@ const base::Feature kAutofillRestrictUnownedFieldsToFormlessCheckout{
const base::Feature kAutofillRichMetadataQueries{
"AutofillRichMetadataQueries", base::FEATURE_DISABLED_BY_DEFAULT};
+// Controls whether UPI/VPA values will be saved and filled into payment forms.
+const base::Feature kAutofillSaveAndFillVPA{"AutofillSaveAndFillVPA",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
const base::Feature kAutofillSaveOnProbablySubmitted{
"AutofillSaveOnProbablySubmitted", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -165,6 +174,10 @@ const base::Feature kAutofillSkipComparingInferredLabels{
const base::Feature kAutofillTokenPrefixMatching{
"AutofillTokenPrefixMatching", base::FEATURE_DISABLED_BY_DEFAULT};
+// Enables the touch to fill feature for Android.
+const base::Feature kAutofillTouchToFill = {"TouchToFillAndroid",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
const base::Feature kAutofillUploadThrottling{"AutofillUploadThrottling",
base::FEATURE_ENABLED_BY_DEFAULT};
@@ -178,6 +191,10 @@ const base::Feature kAutofillUseImprovedLabelDisambiguation{
"AutofillUseImprovedLabelDisambiguation",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Server predictions for CVC fields are used if the feature is enabled.
+const base::Feature kAutofillUseServerCVCPrediction{
+ "AutofillUseServerCVCPrediction", base::FEATURE_ENABLED_BY_DEFAULT};
+
#if defined(OS_ANDROID)
// Controls whether the Autofill manual fallback for Addresses and Payments is
// present on Android.
@@ -188,10 +205,6 @@ const base::Feature kAutofillManualFallbackAndroid{
const base::Feature kAutofillRefreshStyleAndroid{
"AutofillRefreshStyleAndroid", base::FEATURE_DISABLED_BY_DEFAULT};
-// Enables the touch to fill feature for Android.
-const base::Feature kTouchToFillAndroid = {"TouchToFillAndroid",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
#endif // OS_ANDROID
#if defined(OS_ANDROID) || defined(OS_IOS)
diff --git a/chromium/components/autofill/core/common/autofill_features.h b/chromium/components/autofill/core/common/autofill_features.h
index 8e6937f5447..78a8bfcbbbc 100644
--- a/chromium/components/autofill/core/common/autofill_features.h
+++ b/chromium/components/autofill/core/common/autofill_features.h
@@ -42,8 +42,10 @@ extern const base::Feature kAutofillPreferServerNamePredictions;
extern const base::Feature kAutofillProfileClientValidation;
extern const base::Feature kAutofillProfileServerValidation;
extern const base::Feature kAutofillRejectCompanyBirthyear;
+extern const base::Feature kAutofillRejectCompanySocialTitle;
extern const base::Feature kAutofillRestrictUnownedFieldsToFormlessCheckout;
extern const base::Feature kAutofillRichMetadataQueries;
+extern const base::Feature kAutofillSaveAndFillVPA;
extern const base::Feature kAutofillSaveOnProbablySubmitted;
extern const base::Feature kAutofillServerCommunication;
extern const base::Feature kAutofillShowAllSuggestionsOnPrefilledForms;
@@ -51,14 +53,14 @@ extern const base::Feature kAutofillShowAutocompleteConsoleWarnings;
extern const base::Feature kAutofillShowTypePredictions;
extern const base::Feature kAutofillSkipComparingInferredLabels;
extern const base::Feature kAutofillTokenPrefixMatching;
+extern const base::Feature kAutofillTouchToFill;
extern const base::Feature kAutofillUploadThrottling;
extern const base::Feature kAutofillUseApi;
extern const base::Feature kAutofillUseImprovedLabelDisambiguation;
-
+extern const base::Feature kAutofillUseServerCVCPrediction;
#if defined(OS_ANDROID)
extern const base::Feature kAutofillManualFallbackAndroid;
extern const base::Feature kAutofillRefreshStyleAndroid;
-extern const base::Feature kTouchToFillAndroid;
#endif // OS_ANDROID
#if defined(OS_ANDROID) || defined(OS_IOS)
diff --git a/chromium/components/autofill/core/common/autofill_internals/log_message.cc b/chromium/components/autofill/core/common/autofill_internals/log_message.cc
index 450258c661c..60da13de84e 100644
--- a/chromium/components/autofill/core/common/autofill_internals/log_message.cc
+++ b/chromium/components/autofill/core/common/autofill_internals/log_message.cc
@@ -5,6 +5,7 @@
#include "components/autofill/core/common/autofill_internals/log_message.h"
#include "base/logging.h"
+#include "components/autofill/core/common/logging/log_buffer.h"
namespace autofill {
@@ -50,4 +51,11 @@ const char* LogMessageValue(LogMessage message) {
return "";
}
+LogBuffer& operator<<(LogBuffer& buf, LogMessage message) {
+ if (!buf.active())
+ return buf;
+ return buf << Tag{"div"} << Attrib{"message", LogMessageToString(message)}
+ << Attrib{"class", "log-message"} << LogMessageValue(message);
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/autofill_internals/log_message.h b/chromium/components/autofill/core/common/autofill_internals/log_message.h
index 4862e5e448e..a7232ce6cbb 100644
--- a/chromium/components/autofill/core/common/autofill_internals/log_message.h
+++ b/chromium/components/autofill/core/common/autofill_internals/log_message.h
@@ -7,15 +7,28 @@
namespace autofill {
+class LogBuffer;
+
/////////////// Log Messages /////////////
// Generator for log message. If you need to find the call site for a log
// message, take the first parameter (e.g. ParsedForms) and search for
// that name prefixed with a k (e.g. kParsedForms) in code search.
-#define AUTOFILL_LOG_MESSAGE_TEMPLATES(T) \
- T(ParsedForms, "Parsed forms:") \
- T(SendAutofillUpload, "Sending Autofill Upload Request:") \
- T(LocalHeuristicRegExMatched, "RegEx of local heuristic matched:")
+#define AUTOFILL_LOG_MESSAGE_TEMPLATES(T) \
+ T(ParsedForms, "Parsed forms:") \
+ T(SendAutofillUpload, "Sending Autofill Upload Request:") \
+ T(LocalHeuristicRegExMatched, "RegEx of local heuristic matched:") \
+ T(AbortParsingTooManyForms, "Abort parsing form: Too many forms in cache: ") \
+ T(AbortParsingNotAllowedScheme, \
+ "Abort parsing form: Ignoring form because the source url has no allowed " \
+ "scheme") \
+ T(AbortParsingNotEnoughFields, \
+ "Abort parsing form: Not enough fields in form: ") \
+ T(AbortParsingUrlMatchesSearchRegex, \
+ "Abort parsing form: Action URL matches kUrlSearchActionRe, indicating " \
+ "that the form may lead to a search.") \
+ T(AbortParsingFormHasNoTextfield, \
+ "Abort parsing form: Form has no text field.")
// Log messages for chrome://autofill-internals.
#define AUTOFILL_TEMPLATE(NAME, MESSAGE) k##NAME,
@@ -29,6 +42,8 @@ const char* LogMessageToString(LogMessage message);
// Returns the actual string to be presented to the user for |message|.
const char* LogMessageValue(LogMessage message);
+LogBuffer& operator<<(LogBuffer& buf, LogMessage message);
+
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_INTERNALS_LOG_MESSAGE_H_
diff --git a/chromium/components/autofill/core/browser/autofill_internals_service_unittest.cc b/chromium/components/autofill/core/common/autofill_internals/log_message_unittest.cc
index 2baaee02348..2d4f225cb99 100644
--- a/chromium/components/autofill/core/browser/autofill_internals_service_unittest.cc
+++ b/chromium/components/autofill/core/common/autofill_internals/log_message_unittest.cc
@@ -2,26 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/autofill/core/browser/autofill_internals_service.h"
+#include "components/autofill/core/common/autofill_internals/log_message.h"
#include "base/json/json_writer.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest-death-test.h"
+#include "components/autofill/core/common/logging/log_buffer.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace autofill {
-TEST(AutofillInternalsService, Scope) {
- LogBuffer buffer;
- buffer << LoggingScope::kContext;
- std::string json;
- EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
- EXPECT_EQ(R"({"attributes":{"class":"log-entry","scope":"Context"},)"
- R"("type":"element","value":"div"})",
- json);
-}
-
-TEST(AutofillInternalsService, Message) {
+TEST(LogMessage, Serialization) {
LogBuffer buffer;
buffer << LogMessage::kParsedForms;
std::string json;
diff --git a/chromium/components/autofill/core/common/autofill_internals/logging_scope.cc b/chromium/components/autofill/core/common/autofill_internals/logging_scope.cc
index ab962d5eaf3..2e1597b07bf 100644
--- a/chromium/components/autofill/core/common/autofill_internals/logging_scope.cc
+++ b/chromium/components/autofill/core/common/autofill_internals/logging_scope.cc
@@ -5,6 +5,7 @@
#include "components/autofill/core/common/autofill_internals/logging_scope.h"
#include "base/logging.h"
+#include "components/autofill/core/common/logging/log_buffer.h"
namespace autofill {
@@ -29,4 +30,11 @@ const char* LoggingScopeToString(LoggingScope scope) {
return "";
}
+LogBuffer& operator<<(LogBuffer& buf, LoggingScope scope) {
+ if (!buf.active())
+ return buf;
+ return buf << Tag{"div"} << Attrib{"scope", LoggingScopeToString(scope)}
+ << Attrib{"class", "log-entry"};
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/autofill_internals/logging_scope.h b/chromium/components/autofill/core/common/autofill_internals/logging_scope.h
index ac719ca73dd..5684511f84e 100644
--- a/chromium/components/autofill/core/common/autofill_internals/logging_scope.h
+++ b/chromium/components/autofill/core/common/autofill_internals/logging_scope.h
@@ -7,6 +7,8 @@
namespace autofill {
+class LogBuffer;
+
/////////////// Logging Scopes /////////////
// Generator for source code related to logging scopes. Pass a template T which
@@ -16,6 +18,8 @@ namespace autofill {
T(Context) \
/* Log messages related to the discovery and parsing of forms. */ \
T(Parsing) \
+ /* Log messages related to reasons to stop parsing a form. */ \
+ T(AbortParsing) \
/* Log messages related to filling of forms. */ \
T(Filling) \
/* Log messages related to the submission of forms. */ \
@@ -33,6 +37,8 @@ enum class LoggingScope {
// Returns the enum value of |scope| as a string (without the leading k).
const char* LoggingScopeToString(LoggingScope scope);
+LogBuffer& operator<<(LogBuffer& buf, LoggingScope scope);
+
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_INTERNALS_LOGGING_SCOPE_H_
diff --git a/chromium/components/autofill/core/common/autofill_internals/logging_scope_unittest.cc b/chromium/components/autofill/core/common/autofill_internals/logging_scope_unittest.cc
new file mode 100644
index 00000000000..16ffe96f22c
--- /dev/null
+++ b/chromium/components/autofill/core/common/autofill_internals/logging_scope_unittest.cc
@@ -0,0 +1,23 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/common/autofill_internals/logging_scope.h"
+
+#include "base/json/json_writer.h"
+#include "components/autofill/core/common/logging/log_buffer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+
+TEST(LoggingScope, Serialization) {
+ LogBuffer buffer;
+ buffer << LoggingScope::kContext;
+ std::string json;
+ EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
+ EXPECT_EQ(R"({"attributes":{"class":"log-entry","scope":"Context"},)"
+ R"("type":"element","value":"div"})",
+ json);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/common/autofill_payments_features.cc b/chromium/components/autofill/core/common/autofill_payments_features.cc
index 6fd64901fe7..d5a33bdaa85 100644
--- a/chromium/components/autofill/core/common/autofill_payments_features.cc
+++ b/chromium/components/autofill/core/common/autofill_payments_features.cc
@@ -34,6 +34,14 @@ const char
kAutofillSaveCreditCardUsesImprovedMessagingParamValueConfirmAndSaveCard[] =
"Confirm & Save Card";
+// Features
+
+// Controls whether or not Autofill client will populate form with CPAN and
+// dCVV, rather than FPAN.
+const base::Feature kAutofillAlwaysReturnCloudTokenizedCard{
+ "AutofillAlwaysReturnCloudTokenizedCard",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
const base::Feature kAutofillCreditCardAblationExperiment{
"AutofillCreditCardAblationExperiment", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -52,12 +60,6 @@ const base::Feature kAutofillDoNotMigrateUnsupportedLocalCards{
"AutofillDoNotMigrateUnsupportedLocalCards",
base::FEATURE_ENABLED_BY_DEFAULT};
-// Controls whether the credit card downstream keyboard accessory shows
-// the Google Pay logo animation on iOS.
-const base::Feature kAutofillDownstreamUseGooglePayBrandingOniOS{
- "AutofillDownstreamUseGooglePayBrandingOniOS",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
// When enabled, enable local card migration flow for user who has signed in but
// has not turned on sync.
const base::Feature kAutofillEnableLocalCardMigrationForNonSyncUser{
@@ -69,15 +71,11 @@ const base::Feature kAutofillEnableLocalCardMigrationForNonSyncUser{
const base::Feature kAutofillEnableToolbarStatusChip{
"AutofillEnableToolbarStatusChip", base::FEATURE_DISABLED_BY_DEFAULT};
-// When enabled, autofill can import credit cards from dynamic change form.
-const base::Feature kAutofillImportDynamicForms{
- "AutofillImportDynamicForms", base::FEATURE_ENABLED_BY_DEFAULT};
-
// Controls whether offering to migrate cards will consider data from the
// Autofill strike database (new version).
const base::Feature kAutofillLocalCardMigrationUsesStrikeSystemV2{
"AutofillLocalCardMigrationUsesStrikeSystemV2",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
// When enabled, will remove the option to save unmasked server cards as
// FULL_SERVER_CARDs upon successful unmask.
@@ -89,12 +87,17 @@ const base::Feature kAutofillNoLocalSaveOnUnmaskSuccess{
const base::Feature kAutofillNoLocalSaveOnUploadSuccess{
"AutofillNoLocalSaveOnUploadSuccess", base::FEATURE_DISABLED_BY_DEFAULT};
+// When enabled, the Save Card infobar will be dismissed by a user initiated
+// navigation other than one caused by submitted form.
+const base::Feature kAutofillSaveCardDismissOnNavigation{
+ "AutofillSaveCardDismissOnNavigation", base::FEATURE_ENABLED_BY_DEFAULT};
+
// When enabled, local and upload credit card save dialogs will add a
// [No thanks] cancel button option. This is intended to bring the
// AutofillSaveCardImprovedUserConsent functionality to Chrome OS, Android, and
// iOS without bringing the extended title string change with it.
const base::Feature kAutofillSaveCardShowNoThanks{
- "AutofillSaveCardShowNoThanks", base::FEATURE_DISABLED_BY_DEFAULT};
+ "AutofillSaveCardShowNoThanks", base::FEATURE_ENABLED_BY_DEFAULT};
// Controls what title and bubble label for the credit card upload bubble are
// shown to users.
diff --git a/chromium/components/autofill/core/common/autofill_payments_features.h b/chromium/components/autofill/core/common/autofill_payments_features.h
index b0f0e2827e5..6dc8e2faa2d 100644
--- a/chromium/components/autofill/core/common/autofill_payments_features.h
+++ b/chromium/components/autofill/core/common/autofill_payments_features.h
@@ -19,17 +19,17 @@ namespace autofill {
namespace features {
// All features in alphabetical order.
+extern const base::Feature kAutofillAlwaysReturnCloudTokenizedCard;
extern const base::Feature kAutofillCreditCardAblationExperiment;
extern const base::Feature kAutofillCreditCardAuthentication;
extern const base::Feature kAutofillCreditCardUploadFeedback;
extern const base::Feature kAutofillDoNotMigrateUnsupportedLocalCards;
-extern const base::Feature kAutofillDownstreamUseGooglePayBrandingOniOS;
extern const base::Feature kAutofillEnableLocalCardMigrationForNonSyncUser;
extern const base::Feature kAutofillEnableToolbarStatusChip;
-extern const base::Feature kAutofillImportDynamicForms;
extern const base::Feature kAutofillLocalCardMigrationUsesStrikeSystemV2;
extern const base::Feature kAutofillNoLocalSaveOnUnmaskSuccess;
extern const base::Feature kAutofillNoLocalSaveOnUploadSuccess;
+extern const base::Feature kAutofillSaveCardDismissOnNavigation;
extern const base::Feature kAutofillSaveCardShowNoThanks;
extern const base::Feature kAutofillSaveCreditCardUsesImprovedMessaging;
extern const base::Feature kAutofillUpdatedCardUnmaskPromptUi;
diff --git a/chromium/components/autofill/core/common/autofill_prefs.cc b/chromium/components/autofill/core/common/autofill_prefs.cc
index 7801f45ada6..1607b0d7274 100644
--- a/chromium/components/autofill/core/common/autofill_prefs.cc
+++ b/chromium/components/autofill/core/common/autofill_prefs.cc
@@ -18,7 +18,6 @@ namespace {
// was found.
int GetSyncTransportOptInBitFieldForAccount(const PrefService* prefs,
const std::string& account_hash) {
-
auto* dictionary = prefs->GetDictionary(prefs::kAutofillSyncTransportOptIn);
// If there is no dictionary it means the account didn't opt-in. Use 0 because
@@ -43,14 +42,18 @@ int GetSyncTransportOptInBitFieldForAccount(const PrefService* prefs,
const char kAutofillAcceptSaveCreditCardPromptState[] =
"autofill.accept_save_credit_card_prompt_state";
-// Boolean that is true if FIDO Authentication is enabled for card unmasking.
-const char kAutofillCreditCardFIDOAuthEnabled[] =
- "autofill.credit_card_fido_auth_enabled";
-
// Boolean that is true if Autofill is enabled and allowed to save credit card
// data.
const char kAutofillCreditCardEnabled[] = "autofill.credit_card_enabled";
+// Boolean that is true if FIDO Authentication is enabled for card unmasking.
+const char kAutofillCreditCardFidoAuthEnabled[] =
+ "autofill.credit_card_fido_auth_enabled";
+
+// Boolean that is true if FIDO Authentication is enabled for card unmasking.
+const char kAutofillCreditCardFidoAuthOfferCheckboxState[] =
+ "autofill.credit_card_fido_auth_offer_checkbox_state";
+
// Number of times the credit card signin promo has been shown.
const char kAutofillCreditCardSigninPromoImpressionCount[] =
"autofill.credit_card_signin_promo_impression_count";
@@ -58,9 +61,8 @@ const char kAutofillCreditCardSigninPromoImpressionCount[] =
// Boolean that is true if Autofill is enabled and allowed to save data.
const char kAutofillEnabledDeprecated[] = "autofill.enabled";
-// Boolean that is true if Japan address city field has been migrated to be a
-// part of the street field.
-const char kAutofillJapanCityFieldMigrated[] =
+// Deprecated 10/2019.
+const char kAutofillJapanCityFieldMigratedDeprecated[] =
"autofill.japan_city_field_migrated_to_street_address";
// Integer that is set to the last version where the profile deduping routine
@@ -157,11 +159,12 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
// Non-synced prefs. Used for per-device choices, e.g., signin promo.
- registry->RegisterBooleanPref(prefs::kAutofillCreditCardFIDOAuthEnabled,
+ registry->RegisterBooleanPref(prefs::kAutofillCreditCardFidoAuthEnabled,
false);
+ registry->RegisterBooleanPref(
+ prefs::kAutofillCreditCardFidoAuthOfferCheckboxState, true);
registry->RegisterIntegerPref(
prefs::kAutofillCreditCardSigninPromoImpressionCount, 0);
- registry->RegisterBooleanPref(prefs::kAutofillJapanCityFieldMigrated, false);
registry->RegisterBooleanPref(prefs::kAutofillWalletImportEnabled, true);
registry->RegisterBooleanPref(
prefs::kAutofillWalletImportStorageCheckboxState, true);
@@ -180,6 +183,10 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterTimePref(prefs::kAutofillUploadEventsLastResetTimestamp,
base::Time());
registry->RegisterDictionaryPref(prefs::kAutofillSyncTransportOptIn);
+
+ // Deprecated prefs registered for migration.
+ registry->RegisterBooleanPref(kAutofillJapanCityFieldMigratedDeprecated,
+ false);
}
void MigrateDeprecatedAutofillPrefs(PrefService* prefs) {
@@ -210,6 +217,9 @@ void MigrateDeprecatedAutofillPrefs(PrefService* prefs) {
prefs->SetBoolean(kAutofillProfileEnabled,
prefs->GetBoolean(kAutofillEnabledDeprecated));
}
+
+ // Added 10/2019.
+ prefs->ClearPref(kAutofillJapanCityFieldMigratedDeprecated);
}
bool IsAutocompleteEnabled(const PrefService* prefs) {
@@ -226,11 +236,11 @@ void SetAutofillEnabled(PrefService* prefs, bool enabled) {
}
bool IsCreditCardFIDOAuthEnabled(PrefService* prefs) {
- return prefs->GetBoolean(kAutofillCreditCardFIDOAuthEnabled);
+ return prefs->GetBoolean(kAutofillCreditCardFidoAuthEnabled);
}
void SetCreditCardFIDOAuthEnabled(PrefService* prefs, bool enabled) {
- prefs->SetBoolean(kAutofillCreditCardFIDOAuthEnabled, enabled);
+ prefs->SetBoolean(kAutofillCreditCardFidoAuthEnabled, enabled);
}
bool IsCreditCardAutofillEnabled(const PrefService* prefs) {
diff --git a/chromium/components/autofill/core/common/autofill_prefs.h b/chromium/components/autofill/core/common/autofill_prefs.h
index f807434285e..7558441a2ac 100644
--- a/chromium/components/autofill/core/common/autofill_prefs.h
+++ b/chromium/components/autofill/core/common/autofill_prefs.h
@@ -20,12 +20,13 @@ namespace prefs {
// component. Keep alphabetized, and document each in the .cc file.
extern const char kAutofillAcceptSaveCreditCardPromptState[];
// Do not get/set the value of this pref directly. Use provided getter/setter.
-extern const char kAutofillCreditCardFIDOAuthEnabled[];
extern const char kAutofillCreditCardEnabled[];
+extern const char kAutofillCreditCardFidoAuthEnabled[];
+extern const char kAutofillCreditCardFidoAuthOfferCheckboxState[];
extern const char kAutofillCreditCardSigninPromoImpressionCount[];
// Please use kAutofillCreditCardEnabled and kAutofillProfileEnabled instead.
extern const char kAutofillEnabledDeprecated[];
-extern const char kAutofillJapanCityFieldMigrated[];
+extern const char kAutofillJapanCityFieldMigratedDeprecated[];
extern const char kAutofillLastVersionDeduped[];
extern const char kAutofillLastVersionValidated[];
extern const char kAutofillLastVersionDisusedAddressesDeleted[];
diff --git a/chromium/components/autofill/core/common/autofill_regex_constants.cc b/chromium/components/autofill/core/common/autofill_regex_constants.cc
index 7cb75718ae4..daacd27d66a 100644
--- a/chromium/components/autofill/core/common/autofill_regex_constants.cc
+++ b/chromium/components/autofill/core/common/autofill_regex_constants.cc
@@ -176,13 +176,14 @@ const char kNameOnCardRe[] =
const char kNameOnCardContextualRe[] = "name";
const char kCardNumberRe[] =
"(add)?(?:card|cc|acct).?(?:number|#|no|num|field)"
- "|(?<!telefon|haus)nummer" // de-DE
- "|カード番号" // ja-JP
- "|Номер.*карты" // ru
- "|信用卡号|信用卡号码" // zh-CN
- "|信用卡卡號" // zh-TW
- "|카드" // ko-KR
- "|(numero|número|numéro)(?!.*(document|fono|phone))"; // es/pt/fr
+ "|(?<!telefon|haus)nummer" // de-DE
+ "|カード番号" // ja-JP
+ "|Номер.*карты" // ru
+ "|信用卡号|信用卡号码" // zh-CN
+ "|信用卡卡號" // zh-TW
+ "|카드" // ko-KR
+ // es/pt/fr
+ "|(numero|número|numéro)(?!.*(document|fono|phone|réservation))";
const char kCardCvcRe[] =
"verification|card.?identification|security.?code|card.?code"
diff --git a/chromium/components/autofill/core/common/autofill_tick_clock.cc b/chromium/components/autofill/core/common/autofill_tick_clock.cc
new file mode 100644
index 00000000000..594916e5c6f
--- /dev/null
+++ b/chromium/components/autofill/core/common/autofill_tick_clock.cc
@@ -0,0 +1,33 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/common/autofill_tick_clock.h"
+
+#include "base/time/default_tick_clock.h"
+#include "base/time/tick_clock.h"
+
+namespace autofill {
+namespace {
+const base::TickClock* g_autofill_tick_clock = nullptr;
+} // namespace
+
+// static
+base::TimeTicks AutofillTickClock::NowTicks() {
+ if (!g_autofill_tick_clock)
+ SetTickClock();
+ return g_autofill_tick_clock->NowTicks();
+}
+
+// static
+void AutofillTickClock::SetTickClock() {
+ g_autofill_tick_clock = base::DefaultTickClock::GetInstance();
+}
+
+// static
+void AutofillTickClock::SetTestTickClock(const base::TickClock* tick_clock) {
+ DCHECK(tick_clock);
+ g_autofill_tick_clock = tick_clock;
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/common/autofill_tick_clock.h b/chromium/components/autofill/core/common/autofill_tick_clock.h
new file mode 100644
index 00000000000..a438604ffed
--- /dev/null
+++ b/chromium/components/autofill/core/common/autofill_tick_clock.h
@@ -0,0 +1,37 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_TICK_CLOCK_H_
+#define COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_TICK_CLOCK_H_
+
+namespace base {
+class TickClock;
+class TimeTicks;
+} // namespace base
+
+namespace autofill {
+
+// Handles getting the current time for the Autofill feature. Can be injected
+// with a customizable tick clock to facilitate testing.
+class AutofillTickClock {
+ public:
+ // Returns the current time based last set tick clock.
+ static base::TimeTicks NowTicks();
+
+ private:
+ friend class TestAutofillTickClock;
+
+ // Resets a normal tick clock.
+ static void SetTickClock();
+
+ // Sets the tick clock to be used for tests.
+ static void SetTestTickClock(const base::TickClock* tick_clock);
+
+ AutofillTickClock() = delete;
+ ~AutofillTickClock() = delete;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_TICK_CLOCK_H_
diff --git a/chromium/components/autofill/core/common/autofill_util.cc b/chromium/components/autofill/core/common/autofill_util.cc
index 19ec7815437..36c3a17d912 100644
--- a/chromium/components/autofill/core/common/autofill_util.cc
+++ b/chromium/components/autofill/core/common/autofill_util.cc
@@ -72,7 +72,7 @@ bool IsKeyboardAccessoryEnabled() {
bool IsTouchToFillEnabled() {
#if defined(OS_ANDROID)
- return base::FeatureList::IsEnabled(features::kTouchToFillAndroid);
+ return base::FeatureList::IsEnabled(features::kAutofillTouchToFill);
#else // !defined(OS_ANDROID)
return false;
#endif
diff --git a/chromium/components/autofill/core/common/form_data.cc b/chromium/components/autofill/core/common/form_data.cc
index 5f2f9c95122..e69ae3a8a28 100644
--- a/chromium/components/autofill/core/common/form_data.cc
+++ b/chromium/components/autofill/core/common/form_data.cc
@@ -12,6 +12,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/common/form_field_data.h"
+#include "components/autofill/core/common/logging/log_buffer.h"
namespace autofill {
@@ -68,29 +69,22 @@ void LogDeserializationError(int version) {
} // namespace
-FormData::FormData() : is_form_tag(true), is_formless_checkout(false) {}
-
-FormData::FormData(const FormData& data)
- : name(data.name),
- button_titles(data.button_titles),
- url(data.url),
- action(data.action),
- main_frame_origin(data.main_frame_origin),
- is_form_tag(data.is_form_tag),
- is_formless_checkout(data.is_formless_checkout),
- unique_renderer_id(data.unique_renderer_id),
- submission_event(data.submission_event),
- fields(data.fields),
- username_predictions(data.username_predictions),
- is_gaia_with_skip_save_password_form(
- data.is_gaia_with_skip_save_password_form) {}
-
-FormData::~FormData() {
-}
+FormData::FormData() = default;
+
+FormData::FormData(const FormData&) = default;
+
+FormData& FormData::operator=(const FormData&) = default;
+
+FormData::FormData(FormData&&) = default;
+
+FormData& FormData::operator=(FormData&&) = default;
+
+FormData::~FormData() = default;
bool FormData::SameFormAs(const FormData& form) const {
- if (name != form.name || url != form.url || action != form.action ||
- is_form_tag != form.is_form_tag ||
+ if (name != form.name || id_attribute != form.id_attribute ||
+ name_attribute != form.name_attribute || url != form.url ||
+ action != form.action || is_form_tag != form.is_form_tag ||
is_formless_checkout != form.is_formless_checkout ||
fields.size() != form.fields.size())
return false;
@@ -102,11 +96,14 @@ bool FormData::SameFormAs(const FormData& form) const {
}
bool FormData::SimilarFormAs(const FormData& form) const {
- if (name != form.name || url != form.url || action != form.action ||
+ if (name != form.name || id_attribute != form.id_attribute ||
+ name_attribute != form.name_attribute || url != form.url ||
+ action != form.action || is_action_empty != form.is_action_empty ||
is_form_tag != form.is_form_tag ||
is_formless_checkout != form.is_formless_checkout ||
- fields.size() != form.fields.size())
+ fields.size() != form.fields.size()) {
return false;
+ }
for (size_t i = 0; i < fields.size(); ++i) {
if (!fields[i].SimilarFieldAs(form.fields[i]))
return false;
@@ -115,7 +112,9 @@ bool FormData::SimilarFormAs(const FormData& form) const {
}
bool FormData::DynamicallySameFormAs(const FormData& form) const {
- if (name != form.name || fields.size() != form.fields.size())
+ if (name != form.name || id_attribute != form.id_attribute ||
+ name_attribute != form.name_attribute ||
+ fields.size() != form.fields.size())
return false;
for (size_t i = 0; i < fields.size(); ++i) {
if (!fields[i].DynamicallySameFieldAs(form.fields[i]))
@@ -125,7 +124,9 @@ bool FormData::DynamicallySameFormAs(const FormData& form) const {
}
bool FormData::operator==(const FormData& form) const {
- return name == form.name && url == form.url && action == form.action &&
+ return name == form.name && id_attribute == form.id_attribute &&
+ name_attribute == form.name_attribute && url == form.url &&
+ action == form.action && is_action_empty == form.is_action_empty &&
unique_renderer_id == form.unique_renderer_id &&
submission_event == form.submission_event &&
is_form_tag == form.is_form_tag &&
@@ -139,10 +140,11 @@ bool FormData::operator!=(const FormData& form) const {
}
bool FormData::operator<(const FormData& form) const {
- return std::tie(name, url, action, is_form_tag, is_formless_checkout,
- fields) < std::tie(form.name, form.url, form.action,
- form.is_form_tag,
- form.is_formless_checkout, form.fields);
+ return std::tie(name, id_attribute, name_attribute, url, action, is_form_tag,
+ is_formless_checkout, fields) <
+ std::tie(form.name, form.id_attribute, form.name_attribute, form.url,
+ form.action, form.is_form_tag, form.is_formless_checkout,
+ form.fields);
}
std::ostream& operator<<(std::ostream& os, const FormData& form) {
@@ -167,15 +169,6 @@ void SerializeFormData(const FormData& form_data, base::Pickle* pickle) {
pickle->WriteString(form_data.main_frame_origin.Serialize());
}
-void SerializeFormDataToBase64String(const FormData& form_data,
- std::string* output) {
- base::Pickle pickle;
- SerializeFormData(form_data, &pickle);
- Base64Encode(
- base::StringPiece(static_cast<const char*>(pickle.data()), pickle.size()),
- output);
-}
-
bool DeserializeFormData(base::PickleIterator* iter, FormData* form_data) {
int version;
FormData temp_form_data;
@@ -239,15 +232,26 @@ bool DeserializeFormData(base::PickleIterator* iter, FormData* form_data) {
return true;
}
-bool DeserializeFormDataFromBase64String(const base::StringPiece& input,
- FormData* form_data) {
- if (input.empty())
- return false;
- std::string pickle_data;
- Base64Decode(input, &pickle_data);
- base::Pickle pickle(pickle_data.data(), static_cast<int>(pickle_data.size()));
- base::PickleIterator iter(pickle);
- return DeserializeFormData(&iter, form_data);
+LogBuffer& operator<<(LogBuffer& buffer, const FormData& form) {
+ buffer << Tag{"div"} << Attrib{"class", "form"};
+ buffer << Tag{"table"};
+ buffer << Tr{} << "Form name:" << form.name;
+ buffer << Tr{} << "Unique renderer Id:" << form.unique_renderer_id;
+ buffer << Tr{} << "URL:" << form.url;
+ buffer << Tr{} << "Action:" << form.action;
+ buffer << Tr{} << "Is action empty:" << form.is_action_empty;
+ buffer << Tr{} << "Is <form> tag:" << form.is_form_tag;
+ for (size_t i = 0; i < form.fields.size(); ++i) {
+ buffer << Tag{"tr"};
+ buffer << Tag{"td"} << "Field " << i << ": " << CTag{};
+ buffer << Tag{"td"};
+ buffer << Tag{"table"} << form.fields.at(i) << CTag{"table"};
+ buffer << CTag{"td"};
+ buffer << CTag{"tr"};
+ }
+ buffer << CTag{"table"};
+ buffer << CTag{"div"};
+ return buffer;
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/form_data.h b/chromium/components/autofill/core/common/form_data.h
index 639135adbb2..932394bc09e 100644
--- a/chromium/components/autofill/core/common/form_data.h
+++ b/chromium/components/autofill/core/common/form_data.h
@@ -18,6 +18,8 @@
namespace autofill {
+class LogBuffer;
+
// Pair of a button title (e.g. "Register") and its type (e.g.
// INPUT_ELEMENT_SUBMIT_TYPE).
using ButtonTitleInfo = std::pair<base::string16, mojom::ButtonTitleType>;
@@ -27,11 +29,16 @@ using ButtonTitleList = std::vector<ButtonTitleInfo>;
// Holds information about a form to be filled and/or submitted.
struct FormData {
+ // TODO(https://crbug.com/875768): Rename this const to kNotSetRendererId, and
+ // use it also for not set renderer ids in FormFieldData.
static constexpr uint32_t kNotSetFormRendererId =
std::numeric_limits<uint32_t>::max();
FormData();
- FormData(const FormData& data);
+ FormData(const FormData&);
+ FormData& operator=(const FormData&);
+ FormData(FormData&&);
+ FormData& operator=(FormData&&);
~FormData();
// Returns true if two forms are the same, not counting the values of the
@@ -71,15 +78,19 @@ struct FormData {
GURL url;
// The action target of the form.
GURL action;
+ // If the form in the DOM has an empty action attribute, the |action| field in
+ // the FormData is set to the frame URL of the embedding document. This field
+ // indicates whether the action attribute is empty in the form in the DOM.
+ bool is_action_empty = false;
// The URL of main frame containing this form.
url::Origin main_frame_origin;
// True if this form is a form tag.
- bool is_form_tag;
+ bool is_form_tag = true;
// True if the form is made of unowned fields (i.e., not within a <form> tag)
// in what appears to be a checkout flow. This attribute is only calculated
// and used if features::kAutofillRestrictUnownedFieldsToFormlessCheckout is
// enabled, to prevent heuristics from running on formless non-checkout.
- bool is_formless_checkout;
+ bool is_formless_checkout = false;
// Unique renderer id which is returned by function
// WebFormElement::UniqueRendererFormId(). It is not persistant between page
// loads, so it is not saved and not used in comparison in SameFormAs().
@@ -111,14 +122,7 @@ void SerializeFormData(const FormData& form_data, base::Pickle* pickle);
// the part of a pickle created by SerializeFormData. Returns true on success.
bool DeserializeFormData(base::PickleIterator* iter, FormData* form_data);
-// Serialize FormData. Used by the PasswordManager to persist FormData
-// pertaining to password forms in base64 string. It is useful since in some
-// cases we need to store C strings without embedded '\0' symbols.
-void SerializeFormDataToBase64String(const FormData& form_data,
- std::string* output);
-// Deserialize FormData. Returns true on success.
-bool DeserializeFormDataFromBase64String(const base::StringPiece& input,
- FormData* form_data);
+LogBuffer& operator<<(LogBuffer& buffer, const FormData& form);
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/form_data_predictions.cc b/chromium/components/autofill/core/common/form_data_predictions.cc
index 9c71a970b98..bc97e87e381 100644
--- a/chromium/components/autofill/core/common/form_data_predictions.cc
+++ b/chromium/components/autofill/core/common/form_data_predictions.cc
@@ -6,23 +6,24 @@
namespace autofill {
-FormDataPredictions::FormDataPredictions() {
-}
+FormDataPredictions::FormDataPredictions() = default;
-FormDataPredictions::FormDataPredictions(const FormDataPredictions& other)
- : data(other.data),
- signature(other.signature),
- fields(other.fields) {
-}
+FormDataPredictions::FormDataPredictions(const FormDataPredictions&) = default;
-FormDataPredictions::~FormDataPredictions() {
-}
+FormDataPredictions& FormDataPredictions::operator=(
+ const FormDataPredictions&) = default;
+
+FormDataPredictions::FormDataPredictions(FormDataPredictions&&) = default;
+
+FormDataPredictions& FormDataPredictions::operator=(FormDataPredictions&&) =
+ default;
+
+FormDataPredictions::~FormDataPredictions() = default;
bool FormDataPredictions::operator==(
const FormDataPredictions& predictions) const {
return (data.SameFormAs(predictions.data) &&
- signature == predictions.signature &&
- fields == predictions.fields);
+ signature == predictions.signature && fields == predictions.fields);
}
bool FormDataPredictions::operator!=(
diff --git a/chromium/components/autofill/core/common/form_data_predictions.h b/chromium/components/autofill/core/common/form_data_predictions.h
index 164778a5b22..cc5f9cf9185 100644
--- a/chromium/components/autofill/core/common/form_data_predictions.h
+++ b/chromium/components/autofill/core/common/form_data_predictions.h
@@ -23,7 +23,10 @@ struct FormDataPredictions {
std::vector<FormFieldDataPredictions> fields;
FormDataPredictions();
- FormDataPredictions(const FormDataPredictions& other);
+ FormDataPredictions(const FormDataPredictions&);
+ FormDataPredictions& operator=(const FormDataPredictions&);
+ FormDataPredictions(FormDataPredictions&&);
+ FormDataPredictions& operator=(FormDataPredictions&&);
~FormDataPredictions();
// Added for the sake of testing.
diff --git a/chromium/components/autofill/core/common/form_data_unittest.cc b/chromium/components/autofill/core/common/form_data_unittest.cc
index ff36cae9cfb..eae97e5c202 100644
--- a/chromium/components/autofill/core/common/form_data_unittest.cc
+++ b/chromium/components/autofill/core/common/form_data_unittest.cc
@@ -121,7 +121,7 @@ void FillInDummyFormData(FormData* data) {
data->action = GURL("https://example.com/action");
data->main_frame_origin =
url::Origin::Create(GURL("https://origin-example.com"));
- data->is_form_tag = true; // Default value.
+ data->is_form_tag = true; // Default value.
data->is_formless_checkout = false; // Default value.
FormFieldData field_data;
@@ -166,20 +166,6 @@ TEST(FormDataTest, SerializeAndDeserialize) {
EXPECT_TRUE(actual.SameFormAs(data));
}
-TEST(FormDataTest, SerializeAndDeserializeInStrings) {
- FormData data;
- FillInDummyFormData(&data);
- data.is_form_tag = false;
-
- std::string serialized_data;
- SerializeFormDataToBase64String(data, &serialized_data);
-
- FormData actual;
- EXPECT_TRUE(DeserializeFormDataFromBase64String(serialized_data, &actual));
-
- EXPECT_TRUE(actual.SameFormAs(data));
-}
-
TEST(FormDataTest, Serialize_v1_Deserialize_vCurrent) {
FormData data;
FillInDummyFormData(&data);
diff --git a/chromium/components/autofill/core/common/form_field_data.cc b/chromium/components/autofill/core/common/form_field_data.cc
index b8c0f13cb30..1a804330c6c 100644
--- a/chromium/components/autofill/core/common/form_field_data.cc
+++ b/chromium/components/autofill/core/common/form_field_data.cc
@@ -8,6 +8,7 @@
#include "base/strings/string_util.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_util.h"
+#include "components/autofill/core/common/logging/log_buffer.h"
// TODO(crbug/897756): Clean up the (de)serialization code.
@@ -143,9 +144,15 @@ bool HaveSameLabel(const FormFieldData& field1, const FormFieldData& field2) {
FormFieldData::FormFieldData() = default;
-FormFieldData::FormFieldData(const FormFieldData& other) = default;
+FormFieldData::FormFieldData(const FormFieldData&) = default;
-FormFieldData::~FormFieldData() {}
+FormFieldData& FormFieldData::operator=(const FormFieldData&) = default;
+
+FormFieldData::FormFieldData(FormFieldData&&) = default;
+
+FormFieldData& FormFieldData::operator=(FormFieldData&&) = default;
+
+FormFieldData::~FormFieldData() = default;
bool FormFieldData::SameFieldAs(const FormFieldData& field) const {
// TODO(crbug.com/896689): On iOS the unique_id member uniquely addresses
@@ -205,6 +212,22 @@ bool FormFieldData::IsTextInputElement() const {
form_control_type == "url" || form_control_type == "email";
}
+bool FormFieldData::IsPasswordInputElement() const {
+ return form_control_type == "password";
+}
+
+bool FormFieldData::DidUserType() const {
+ return properties_mask & USER_TYPED;
+}
+
+bool FormFieldData::HadFocus() const {
+ return properties_mask & HAD_FOCUS;
+}
+
+bool FormFieldData::WasAutofilled() const {
+ return properties_mask & AUTOFILLED;
+}
+
bool FormFieldData::operator==(const FormFieldData& field) const {
return SameFieldAs(field) && unique_renderer_id == field.unique_renderer_id &&
form_control_ax_id == field.form_control_ax_id &&
@@ -468,4 +491,26 @@ std::ostream& operator<<(std::ostream& os, const FormFieldData& field) {
<< "label_source=" << field.label_source;
}
+LogBuffer& operator<<(LogBuffer& buffer, const FormFieldData& field) {
+ buffer << Tag{"table"};
+ buffer << Tr{} << "Name:" << field.name;
+ buffer << Tr{} << "Unique renderer Id:" << field.unique_renderer_id;
+ buffer << Tr{} << "Name attribute:" << field.name_attribute;
+ buffer << Tr{} << "Id attribute:" << field.id_attribute;
+ constexpr size_t kMaxLabelSize = 100;
+ const base::string16 truncated_label =
+ field.label.substr(0, std::min(field.label.length(), kMaxLabelSize));
+ buffer << Tr{} << "Label:" << truncated_label;
+ buffer << Tr{} << "Form control type:" << field.form_control_type;
+ buffer << Tr{} << "Autocomplete attribute:" << field.autocomplete_attribute;
+ buffer << Tr{} << "Aria label:" << field.aria_label;
+ buffer << Tr{} << "Aria description:" << field.aria_description;
+ buffer << Tr{} << "Section:" << field.section;
+ buffer << Tr{} << "Is focusable:" << field.is_focusable;
+ buffer << Tr{} << "Is enabled:" << field.is_enabled;
+ buffer << Tr{} << "Is readonly:" << field.is_readonly;
+ buffer << CTag{"table"};
+ return buffer;
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/form_field_data.h b/chromium/components/autofill/core/common/form_field_data.h
index b9d4f9d6013..605f9e0baad 100644
--- a/chromium/components/autofill/core/common/form_field_data.h
+++ b/chromium/components/autofill/core/common/form_field_data.h
@@ -18,10 +18,12 @@
namespace base {
class Pickle;
class PickleIterator;
-}
+} // namespace base
namespace autofill {
+class LogBuffer;
+
// The flags describing form field properties.
enum FieldPropertiesFlags {
NO_FLAGS = 0u,
@@ -59,7 +61,10 @@ struct FormFieldData {
std::numeric_limits<uint32_t>::max();
FormFieldData();
- FormFieldData(const FormFieldData& other);
+ FormFieldData(const FormFieldData&);
+ FormFieldData& operator=(const FormFieldData&);
+ FormFieldData(FormFieldData&&);
+ FormFieldData& operator=(FormFieldData&&);
~FormFieldData();
// Returns true if two form fields are the same, not counting the value.
@@ -81,11 +86,19 @@ struct FormFieldData {
// a textarea.
bool IsTextInputElement() const;
+ bool IsPasswordInputElement() const;
+
// Returns true if the field is visible to the user.
bool IsVisible() const {
return is_focusable && role != RoleAttribute::kPresentation;
}
+ // These functions do not work for Autofill code.
+ // TODO(https://crbug.com/1006745): Fix this.
+ bool DidUserType() const;
+ bool HadFocus() const;
+ bool WasAutofilled() const;
+
// Note: operator==() performs a full-field-comparison(byte by byte), this is
// different from SameFieldAs(), which ignores comparison for those "values"
// not regarded as part of identity of the field, such as is_autofilled and
@@ -202,6 +215,9 @@ std::ostream& operator<<(std::ostream& os, const FormFieldData& field);
EXPECT_EQ(expected.name_attribute, actual.name_attribute); \
} while (0)
+// Produces a <table> element with information about the form.
+LogBuffer& operator<<(LogBuffer& buffer, const FormFieldData& form);
+
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_COMMON_FORM_FIELD_DATA_H_
diff --git a/chromium/components/autofill/core/common/form_field_data_predictions.cc b/chromium/components/autofill/core/common/form_field_data_predictions.cc
index 9109fcfd537..46e8bd2b6e0 100644
--- a/chromium/components/autofill/core/common/form_field_data_predictions.cc
+++ b/chromium/components/autofill/core/common/form_field_data_predictions.cc
@@ -6,21 +6,21 @@
namespace autofill {
-FormFieldDataPredictions::FormFieldDataPredictions() {
-}
+FormFieldDataPredictions::FormFieldDataPredictions() = default;
FormFieldDataPredictions::FormFieldDataPredictions(
- const FormFieldDataPredictions& other)
- : field(other.field),
- signature(other.signature),
- heuristic_type(other.heuristic_type),
- server_type(other.server_type),
- overall_type(other.overall_type),
- parseable_name(other.parseable_name),
- section(other.section) {}
-
-FormFieldDataPredictions::~FormFieldDataPredictions() {
-}
+ const FormFieldDataPredictions&) = default;
+
+FormFieldDataPredictions& FormFieldDataPredictions::operator=(
+ const FormFieldDataPredictions&) = default;
+
+FormFieldDataPredictions::FormFieldDataPredictions(FormFieldDataPredictions&&) =
+ default;
+
+FormFieldDataPredictions& FormFieldDataPredictions::operator=(
+ FormFieldDataPredictions&&) = default;
+
+FormFieldDataPredictions::~FormFieldDataPredictions() = default;
bool FormFieldDataPredictions::operator==(
const FormFieldDataPredictions& predictions) const {
diff --git a/chromium/components/autofill/core/common/form_field_data_predictions.h b/chromium/components/autofill/core/common/form_field_data_predictions.h
index baeb68bfba8..1792ddc512e 100644
--- a/chromium/components/autofill/core/common/form_field_data_predictions.h
+++ b/chromium/components/autofill/core/common/form_field_data_predictions.h
@@ -15,7 +15,10 @@ namespace autofill {
// Stores information about a field in a form.
struct FormFieldDataPredictions {
FormFieldDataPredictions();
- FormFieldDataPredictions(const FormFieldDataPredictions& other);
+ FormFieldDataPredictions(const FormFieldDataPredictions&);
+ FormFieldDataPredictions& operator=(const FormFieldDataPredictions&);
+ FormFieldDataPredictions(FormFieldDataPredictions&&);
+ FormFieldDataPredictions& operator=(FormFieldDataPredictions&&);
~FormFieldDataPredictions();
FormFieldData field;
diff --git a/chromium/components/autofill/core/browser/logging/log_buffer.cc b/chromium/components/autofill/core/common/logging/log_buffer.cc
index 8bbd7a9df7b..5abd4daa207 100644
--- a/chromium/components/autofill/core/browser/logging/log_buffer.cc
+++ b/chromium/components/autofill/core/common/logging/log_buffer.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/autofill/core/browser/logging/log_buffer.h"
+#include "components/autofill/core/common/logging/log_buffer.h"
#include <string>
@@ -40,7 +40,7 @@ void AppendChildToLastNode(std::vector<base::Value>* buffer,
DCHECK(!IsTextNode(parent));
if (auto* children = parent.FindListKey("children")) {
- children->GetList().push_back(std::move(new_child));
+ children->Append(std::move(new_child));
return;
}
diff --git a/chromium/components/autofill/core/browser/logging/log_buffer.h b/chromium/components/autofill/core/common/logging/log_buffer.h
index 2dd9c4c74b4..fc782f4f93d 100644
--- a/chromium/components/autofill/core/browser/logging/log_buffer.h
+++ b/chromium/components/autofill/core/common/logging/log_buffer.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_LOGGING_LOG_BUFFER_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_LOGGING_LOG_BUFFER_H_
+#ifndef COMPONENTS_AUTOFILL_CORE_COMMON_LOGGING_LOG_BUFFER_H_
+#define COMPONENTS_AUTOFILL_CORE_COMMON_LOGGING_LOG_BUFFER_H_
#include <string>
#include <type_traits>
@@ -14,7 +14,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/values.h"
-#include "third_party/protobuf/src/google/protobuf/repeated_field.h"
#include "url/gurl.h"
// The desired pattern to generate log messages is to pass a scope, a log
@@ -154,19 +153,6 @@ LogBuffer& operator<<(LogBuffer& buf, LogBuffer&& buffer);
LogBuffer& operator<<(LogBuffer& buf, const GURL& url);
template <typename T>
-LogBuffer& operator<<(LogBuffer& buf,
- const ::google::protobuf::RepeatedField<T>& values) {
- buf << "[";
- for (int i = 0; i < values.size(); ++i) {
- if (i)
- buf << ", ";
- buf << values.Get(i);
- }
- buf << "]";
- return buf;
-}
-
-template <typename T>
LogBuffer& operator<<(LogBuffer& buf, const std::vector<T>& values) {
buf << "[";
for (size_t i = 0; i < values.size(); ++i) {
@@ -219,4 +205,4 @@ LogBuffer HighlightValue(base::StringPiece16 haystack,
} // namespace autofill
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_LOGGING_LOG_BUFFER_H_
+#endif // COMPONENTS_AUTOFILL_CORE_COMMON_LOGGING_LOG_BUFFER_H_
diff --git a/chromium/components/autofill/core/browser/logging/log_buffer_unittest.cc b/chromium/components/autofill/core/common/logging/log_buffer_unittest.cc
index 3b4b6c94ab6..de9126e263b 100644
--- a/chromium/components/autofill/core/browser/logging/log_buffer_unittest.cc
+++ b/chromium/components/autofill/core/common/logging/log_buffer_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/autofill/core/browser/logging/log_buffer.h"
+#include "components/autofill/core/common/logging/log_buffer.h"
#include "base/json/json_writer.h"
#include "base/strings/string_piece.h"
diff --git a/chromium/components/autofill/core/common/mojom/autofill_types.mojom b/chromium/components/autofill/core/common/mojom/autofill_types.mojom
index 8e8a3c3c44d..0879248916c 100644
--- a/chromium/components/autofill/core/common/mojom/autofill_types.mojom
+++ b/chromium/components/autofill/core/common/mojom/autofill_types.mojom
@@ -153,6 +153,7 @@ struct FormData {
array<ButtonTitleInfo> button_titles;
url.mojom.Url url;
url.mojom.Url action;
+ bool is_action_empty;
url.mojom.Origin main_frame_origin;
bool is_form_tag;
bool is_formless_checkout;
@@ -213,6 +214,7 @@ struct PasswordGenerationUIData {
int32 max_length;
mojo_base.mojom.String16 generation_element;
uint32 generation_element_id;
+ bool is_generation_element_password_type;
mojo_base.mojom.TextDirection text_direction;
PasswordForm password_form;
};
@@ -295,16 +297,23 @@ struct PasswordForm {
bool only_for_fallback;
};
-// Note: Even though https://crbug.com/628104 is solved, we still can not use a
-// map directly as long as https://crbug.com/914074 is not fixed.
-struct PasswordFormFieldPredictionMap {
- array<FormFieldData> keys;
- array<PasswordFormFieldPredictionType> values;
+// autofill::ParsingResult
+struct ParsingResult {
+ uint32 username_renderer_id;
+ uint32 password_renderer_id;
+ uint32 new_password_renderer_id;
+ uint32 confirm_password_renderer_id;
};
-// Note: Even though https://crbug.com/628104 is solved, we still can not use a
-// map directly as long as https://crbug.com/914074 is not fixed.
-struct FormsPredictionsMap {
- array<FormData> keys;
- array<PasswordFormFieldPredictionMap> values;
+// Represents the autofill state.
+enum AutofillState {
+ // There are no available suggestions, neither autofill nor autocomplete, for
+ // the input.
+ kNoSuggestions,
+ // There are available autofill suggestions for the input. Autofill fills in
+ // an entire form.
+ kAutofillAvailable,
+ // There are available autocomplete suggestions for the input. Autocomplete
+ // only fills in a single input.
+ kAutocompleteAvailable,
};
diff --git a/chromium/components/autofill/core/common/mojom/autofill_types.typemap b/chromium/components/autofill/core/common/mojom/autofill_types.typemap
index 6b444c359f4..1531e37fb14 100644
--- a/chromium/components/autofill/core/common/mojom/autofill_types.typemap
+++ b/chromium/components/autofill/core/common/mojom/autofill_types.typemap
@@ -9,7 +9,6 @@ public_headers = [
"//components/autofill/core/common/form_field_data.h",
"//components/autofill/core/common/form_field_data_predictions.h",
"//components/autofill/core/common/password_form.h",
- "//components/autofill/core/common/password_form_field_prediction_map.h",
"//components/autofill/core/common/password_form_fill_data.h",
"//components/autofill/core/common/password_form_generation_data.h",
"//components/autofill/core/common/password_generation_util.h",
@@ -32,6 +31,7 @@ type_mappings = [
"autofill.mojom.FormFieldData=::autofill::FormFieldData",
"autofill.mojom.FormFieldDataPredictions=::autofill::FormFieldDataPredictions",
"autofill.mojom.FormsPredictionsMap=::autofill::FormsPredictionsMap",
+ "autofill.mojom.ParsingResult=::autofill::ParsingResult",
"autofill.mojom.PasswordAndRealm=::autofill::PasswordAndRealm",
"autofill.mojom.PasswordForm=::autofill::PasswordForm",
"autofill.mojom.PasswordFormFieldPredictionMap=::autofill::PasswordFormFieldPredictionMap",
diff --git a/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc b/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc
index 9128a8523fc..3962a512072 100644
--- a/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc
+++ b/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc
@@ -107,6 +107,7 @@ bool StructTraits<autofill::mojom::FormDataDataView, autofill::FormData>::Read(
return false;
if (!data.ReadAction(&out->action))
return false;
+ out->is_action_empty = data.is_action_empty();
if (!data.ReadMainFrameOrigin(&out->main_frame_origin))
return false;
@@ -222,6 +223,8 @@ bool StructTraits<autofill::mojom::PasswordGenerationUIDataDataView,
out->max_length = data.max_length();
out->generation_element_id = data.generation_element_id();
+ out->is_generation_element_password_type =
+ data.is_generation_element_password_type();
if (!data.ReadGenerationElement(&out->generation_element) ||
!data.ReadTextDirection(&out->text_direction) ||
@@ -298,92 +301,6 @@ bool StructTraits<
}
// static
-std::vector<autofill::FormFieldData>
-StructTraits<autofill::mojom::PasswordFormFieldPredictionMapDataView,
- autofill::PasswordFormFieldPredictionMap>::
- keys(const autofill::PasswordFormFieldPredictionMap& r) {
- std::vector<autofill::FormFieldData> data;
- for (const auto& i : r)
- data.push_back(i.first);
- return data;
-}
-
-// static
-std::vector<autofill::mojom::PasswordFormFieldPredictionType>
-StructTraits<autofill::mojom::PasswordFormFieldPredictionMapDataView,
- autofill::PasswordFormFieldPredictionMap>::
- values(const autofill::PasswordFormFieldPredictionMap& r) {
- std::vector<autofill::mojom::PasswordFormFieldPredictionType> types;
- for (const auto& i : r)
- types.push_back(i.second);
- return types;
-}
-
-// static
-bool StructTraits<autofill::mojom::PasswordFormFieldPredictionMapDataView,
- autofill::PasswordFormFieldPredictionMap>::
- Read(autofill::mojom::PasswordFormFieldPredictionMapDataView data,
- autofill::PasswordFormFieldPredictionMap* out) {
- // Combines keys vector and values vector to the map.
- std::vector<autofill::FormFieldData> keys;
- if (!data.ReadKeys(&keys))
- return false;
- std::vector<autofill::mojom::PasswordFormFieldPredictionType> values;
- if (!data.ReadValues(&values))
- return false;
- if (keys.size() != values.size())
- return false;
- out->clear();
- for (size_t i = 0; i < keys.size(); ++i)
- out->insert({keys[i], values[i]});
-
- return true;
-}
-
-// static
-std::vector<autofill::FormData> StructTraits<
- autofill::mojom::FormsPredictionsMapDataView,
- autofill::FormsPredictionsMap>::keys(const autofill::FormsPredictionsMap&
- r) {
- std::vector<autofill::FormData> data;
- for (const auto& i : r)
- data.push_back(i.first);
- return data;
-}
-
-// static
-std::vector<autofill::PasswordFormFieldPredictionMap> StructTraits<
- autofill::mojom::FormsPredictionsMapDataView,
- autofill::FormsPredictionsMap>::values(const autofill::FormsPredictionsMap&
- r) {
- std::vector<autofill::PasswordFormFieldPredictionMap> maps;
- for (const auto& i : r)
- maps.push_back(i.second);
- return maps;
-}
-
-// static
-bool StructTraits<autofill::mojom::FormsPredictionsMapDataView,
- autofill::FormsPredictionsMap>::
- Read(autofill::mojom::FormsPredictionsMapDataView data,
- autofill::FormsPredictionsMap* out) {
- // Combines keys vector and values vector to the map.
- std::vector<autofill::FormData> keys;
- if (!data.ReadKeys(&keys))
- return false;
- std::vector<autofill::PasswordFormFieldPredictionMap> values;
- if (!data.ReadValues(&values))
- return false;
- if (keys.size() != values.size())
- return false;
- out->clear();
- for (size_t i = 0; i < keys.size(); ++i)
- out->insert({keys[i], values[i]});
-
- return true;
-}
-
-// static
bool StructTraits<autofill::mojom::ValueElementPairDataView,
autofill::ValueElementPair>::
Read(autofill::mojom::ValueElementPairDataView data,
@@ -394,4 +311,16 @@ bool StructTraits<autofill::mojom::ValueElementPairDataView,
return true;
}
+bool StructTraits<
+ autofill::mojom::ParsingResultDataView,
+ autofill::ParsingResult>::Read(autofill::mojom::ParsingResultDataView data,
+ autofill::ParsingResult* out) {
+ out->username_renderer_id = data.username_renderer_id();
+ out->password_renderer_id = data.password_renderer_id();
+ out->new_password_renderer_id = data.new_password_renderer_id();
+ out->confirm_password_renderer_id = data.confirm_password_renderer_id();
+
+ return true;
+}
+
} // namespace mojo
diff --git a/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits.h b/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits.h
index 6a1ca29db05..a26fbd21849 100644
--- a/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits.h
+++ b/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits.h
@@ -18,7 +18,6 @@
#include "components/autofill/core/common/form_field_data_predictions.h"
#include "components/autofill/core/common/mojom/autofill_types.mojom.h"
#include "components/autofill/core/common/password_form.h"
-#include "components/autofill/core/common/password_form_field_prediction_map.h"
#include "components/autofill/core/common/password_form_fill_data.h"
#include "components/autofill/core/common/password_form_generation_data.h"
#include "components/autofill/core/common/password_generation_util.h"
@@ -197,6 +196,10 @@ struct StructTraits<autofill::mojom::FormDataDataView, autofill::FormData> {
static const GURL& action(const autofill::FormData& r) { return r.action; }
+ static bool is_action_empty(const autofill::FormData& r) {
+ return r.is_action_empty;
+ }
+
static const url::Origin& main_frame_origin(const autofill::FormData& r) {
return r.main_frame_origin;
}
@@ -405,6 +408,11 @@ struct StructTraits<autofill::mojom::PasswordGenerationUIDataDataView,
return r.generation_element_id;
}
+ static bool is_generation_element_password_type(
+ const autofill::password_generation::PasswordGenerationUIData& r) {
+ return r.is_generation_element_password_type;
+ }
+
static base::i18n::TextDirection text_direction(
const autofill::password_generation::PasswordGenerationUIData& r) {
return r.text_direction;
@@ -578,32 +586,6 @@ struct StructTraits<autofill::mojom::PasswordFormDataView,
};
template <>
-struct StructTraits<autofill::mojom::PasswordFormFieldPredictionMapDataView,
- autofill::PasswordFormFieldPredictionMap> {
- static std::vector<autofill::FormFieldData> keys(
- const autofill::PasswordFormFieldPredictionMap& r);
-
- static std::vector<autofill::mojom::PasswordFormFieldPredictionType> values(
- const autofill::PasswordFormFieldPredictionMap& r);
-
- static bool Read(autofill::mojom::PasswordFormFieldPredictionMapDataView data,
- autofill::PasswordFormFieldPredictionMap* out);
-};
-
-template <>
-struct StructTraits<autofill::mojom::FormsPredictionsMapDataView,
- autofill::FormsPredictionsMap> {
- static std::vector<autofill::FormData> keys(
- const autofill::FormsPredictionsMap& r);
-
- static std::vector<autofill::PasswordFormFieldPredictionMap> values(
- const autofill::FormsPredictionsMap& r);
-
- static bool Read(autofill::mojom::FormsPredictionsMapDataView data,
- autofill::FormsPredictionsMap* out);
-};
-
-template <>
struct StructTraits<autofill::mojom::ValueElementPairDataView,
autofill::ValueElementPair> {
static base::string16 value(const autofill::ValueElementPair& r) {
@@ -618,6 +600,30 @@ struct StructTraits<autofill::mojom::ValueElementPairDataView,
autofill::ValueElementPair* out);
};
+template <>
+struct StructTraits<autofill::mojom::ParsingResultDataView,
+ autofill::ParsingResult> {
+ static uint32_t username_renderer_id(const autofill::ParsingResult& r) {
+ return r.username_renderer_id;
+ }
+
+ static uint32_t password_renderer_id(const autofill::ParsingResult& r) {
+ return r.password_renderer_id;
+ }
+
+ static uint32_t new_password_renderer_id(const autofill::ParsingResult& r) {
+ return r.new_password_renderer_id;
+ }
+
+ static uint32_t confirm_password_renderer_id(
+ const autofill::ParsingResult& r) {
+ return r.confirm_password_renderer_id;
+ }
+
+ static bool Read(autofill::mojom::ParsingResultDataView data,
+ autofill::ParsingResult* out);
+};
+
} // namespace mojo
#endif // COMPONENTS_AUTOFILL_CORE_COMMON_MOJOM_AUTOFILL_TYPES_MOJOM_TRAITS_H_
diff --git a/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc b/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc
index 37c68ad829a..1fd64be2cfc 100644
--- a/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc
+++ b/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc
@@ -9,13 +9,15 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/task_environment.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/mojom/test_autofill_types.mojom.h"
#include "components/autofill/core/common/password_generation_util.h"
#include "components/autofill/core/common/signatures_util.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace autofill {
@@ -90,8 +92,8 @@ void CreateTestPasswordForm(PasswordForm* form) {
form->new_password_marked_by_site = false;
form->new_password_element = base::ASCIIToUTF16("confirmation_password");
form->preferred = false;
- form->date_created = base::Time::Now();
- form->date_synced = base::Time::Now();
+ form->date_created = AutofillClock::Now();
+ form->date_synced = AutofillClock::Now();
form->blacklisted_by_user = false;
form->type = PasswordForm::Type::kGenerated;
form->times_used = 999;
@@ -109,45 +111,13 @@ void CreateTestPasswordForm(PasswordForm* form) {
mojom::SubmissionIndicatorEvent::SAME_DOCUMENT_NAVIGATION;
}
-void CreateTestFormsPredictionsMap(FormsPredictionsMap* predictions) {
- FormsPredictionsMap& result_map = *predictions;
- // 1st element.
- FormData form_data;
- test::CreateTestAddressFormData(&form_data);
- ASSERT_TRUE(form_data.fields.size() >= 4);
- result_map[form_data][form_data.fields[0]] =
- PasswordFormFieldPredictionType::kUsername;
- result_map[form_data][form_data.fields[1]] =
- PasswordFormFieldPredictionType::kCurrentPassword;
- result_map[form_data][form_data.fields[2]] =
- PasswordFormFieldPredictionType::kNewPassword;
- result_map[form_data][form_data.fields[3]] =
- PasswordFormFieldPredictionType::kNotPassword;
-
- // 2nd element.
- form_data.fields.clear();
- result_map[form_data] = {};
-
- // 3rd element.
- FormFieldData field_data;
- test::CreateTestSelectField("TestLabel1", "TestName1", "TestValue1", kOptions,
- kOptions, 4, &field_data);
- form_data.fields.push_back(field_data);
- test::CreateTestSelectField("TestLabel2", "TestName2", "TestValue2", kOptions,
- kOptions, 4, &field_data);
- form_data.fields.push_back(field_data);
- result_map[form_data][form_data.fields[0]] =
- PasswordFormFieldPredictionType::kNewPassword;
- result_map[form_data][form_data.fields[1]] =
- PasswordFormFieldPredictionType::kCurrentPassword;
-}
-
void CreatePasswordGenerationUIData(
password_generation::PasswordGenerationUIData* data) {
data->bounds = gfx::RectF(1, 1, 200, 100);
data->max_length = 20;
data->generation_element = base::ASCIIToUTF16("generation_element");
data->text_direction = base::i18n::RIGHT_TO_LEFT;
+ data->is_generation_element_password_type = false;
CreateTestPasswordForm(&data->password_form);
}
@@ -185,6 +155,8 @@ void CheckEqualPassPasswordGenerationUIData(
EXPECT_EQ(expected.bounds, actual.bounds);
EXPECT_EQ(expected.max_length, actual.max_length);
EXPECT_EQ(expected.generation_element, actual.generation_element);
+ EXPECT_EQ(expected.is_generation_element_password_type,
+ actual.is_generation_element_password_type);
EXPECT_EQ(expected.text_direction, actual.text_direction);
EXPECT_EQ(expected.password_form, actual.password_form);
}
@@ -196,10 +168,10 @@ class AutofillTypeTraitsTestImpl : public testing::Test,
public:
AutofillTypeTraitsTestImpl() {}
- mojom::TypeTraitsTestPtr GetTypeTraitsTestProxy() {
- mojom::TypeTraitsTestPtr proxy;
- bindings_.AddBinding(this, mojo::MakeRequest(&proxy));
- return proxy;
+ mojo::PendingRemote<mojom::TypeTraitsTest> GetTypeTraitsTestRemote() {
+ mojo::PendingRemote<mojom::TypeTraitsTest> remote;
+ receivers_.Add(this, remote.InitWithNewPipeAndPassReceiver());
+ return remote;
}
// mojom::TypeTraitsTest:
@@ -247,16 +219,10 @@ class AutofillTypeTraitsTestImpl : public testing::Test,
std::move(callback).Run(s);
}
- void PassFormsPredictionsMap(
- const FormsPredictionsMap& s,
- PassFormsPredictionsMapCallback callback) override {
- std::move(callback).Run(s);
- }
-
private:
base::test::TaskEnvironment task_environment_;
- mojo::BindingSet<TypeTraitsTest> bindings_;
+ mojo::ReceiverSet<TypeTraitsTest> receivers_;
};
void ExpectFormFieldData(const FormFieldData& expected,
@@ -321,13 +287,6 @@ void ExpectPasswordForm(const PasswordForm& expected,
std::move(closure).Run();
}
-void ExpectFormsPredictionsMap(const FormsPredictionsMap& expected,
- base::OnceClosure closure,
- const FormsPredictionsMap& passed) {
- EXPECT_EQ(expected, passed);
- std::move(closure).Run();
-}
-
TEST_F(AutofillTypeTraitsTestImpl, PassFormFieldData) {
FormFieldData input;
test::CreateTestSelectField("TestLabel", "TestName", "TestValue", kOptions,
@@ -350,8 +309,8 @@ TEST_F(AutofillTypeTraitsTestImpl, PassFormFieldData) {
input.typed_value = base::ASCIIToUTF16("TestTypedValue");
base::RunLoop loop;
- mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
- proxy->PassFormFieldData(
+ mojo::Remote<mojom::TypeTraitsTest> remote(GetTypeTraitsTestRemote());
+ remote->PassFormFieldData(
input, base::BindOnce(&ExpectFormFieldData, input, loop.QuitClosure()));
loop.Run();
}
@@ -365,8 +324,8 @@ TEST_F(AutofillTypeTraitsTestImpl, PassFormData) {
mojom::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE));
base::RunLoop loop;
- mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
- proxy->PassFormData(
+ mojo::Remote<mojom::TypeTraitsTest> remote(GetTypeTraitsTestRemote());
+ remote->PassFormData(
input, base::BindOnce(&ExpectFormData, input, loop.QuitClosure()));
loop.Run();
}
@@ -376,8 +335,8 @@ TEST_F(AutofillTypeTraitsTestImpl, PassFormFieldDataPredictions) {
CreateTestFieldDataPredictions("TestSignature", &input);
base::RunLoop loop;
- mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
- proxy->PassFormFieldDataPredictions(
+ mojo::Remote<mojom::TypeTraitsTest> remote(GetTypeTraitsTestRemote());
+ remote->PassFormFieldDataPredictions(
input, base::BindOnce(&ExpectFormFieldDataPredictions, input,
loop.QuitClosure()));
loop.Run();
@@ -397,8 +356,8 @@ TEST_F(AutofillTypeTraitsTestImpl, PassFormDataPredictions) {
input.fields.push_back(field_predict);
base::RunLoop loop;
- mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
- proxy->PassFormDataPredictions(
+ mojo::Remote<mojom::TypeTraitsTest> remote(GetTypeTraitsTestRemote());
+ remote->PassFormDataPredictions(
input,
base::BindOnce(&ExpectFormDataPredictions, input, loop.QuitClosure()));
loop.Run();
@@ -409,8 +368,8 @@ TEST_F(AutofillTypeTraitsTestImpl, PassPasswordFormFillData) {
CreateTestPasswordFormFillData(&input);
base::RunLoop loop;
- mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
- proxy->PassPasswordFormFillData(
+ mojo::Remote<mojom::TypeTraitsTest> remote(GetTypeTraitsTestRemote());
+ remote->PassPasswordFormFillData(
input,
base::BindOnce(&ExpectPasswordFormFillData, input, loop.QuitClosure()));
loop.Run();
@@ -422,8 +381,8 @@ TEST_F(AutofillTypeTraitsTestImpl, PasswordFormGenerationData) {
input.confirmation_password_renderer_id = 5789u;
base::RunLoop loop;
- mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
- proxy->PassPasswordFormGenerationData(
+ mojo::Remote<mojom::TypeTraitsTest> remote(GetTypeTraitsTestRemote());
+ remote->PassPasswordFormGenerationData(
input, base::BindOnce(&ExpectPasswordFormGenerationData, input,
loop.QuitClosure()));
loop.Run();
@@ -434,8 +393,8 @@ TEST_F(AutofillTypeTraitsTestImpl, PassPasswordGenerationUIData) {
CreatePasswordGenerationUIData(&input);
base::RunLoop loop;
- mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
- proxy->PassPasswordGenerationUIData(
+ mojo::Remote<mojom::TypeTraitsTest> remote(GetTypeTraitsTestRemote());
+ remote->PassPasswordGenerationUIData(
input, base::BindOnce(&ExpectPasswordGenerationUIData, input,
loop.QuitClosure()));
loop.Run();
@@ -446,22 +405,10 @@ TEST_F(AutofillTypeTraitsTestImpl, PassPasswordForm) {
CreateTestPasswordForm(&input);
base::RunLoop loop;
- mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
- proxy->PassPasswordForm(
+ mojo::Remote<mojom::TypeTraitsTest> remote(GetTypeTraitsTestRemote());
+ remote->PassPasswordForm(
input, base::BindOnce(&ExpectPasswordForm, input, loop.QuitClosure()));
loop.Run();
}
-TEST_F(AutofillTypeTraitsTestImpl, PassFormsPredictionsMap) {
- FormsPredictionsMap input;
- CreateTestFormsPredictionsMap(&input);
-
- base::RunLoop loop;
- mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
- proxy->PassFormsPredictionsMap(
- input,
- base::BindOnce(&ExpectFormsPredictionsMap, input, loop.QuitClosure()));
- loop.Run();
-}
-
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/mojom/test_autofill_types.mojom b/chromium/components/autofill/core/common/mojom/test_autofill_types.mojom
index 9f5be9e3b81..dd1392662f1 100644
--- a/chromium/components/autofill/core/common/mojom/test_autofill_types.mojom
+++ b/chromium/components/autofill/core/common/mojom/test_autofill_types.mojom
@@ -16,8 +16,6 @@ interface TypeTraitsTest {
PassPasswordForm(PasswordForm s) => (PasswordForm passed);
PassPasswordFormFillData(PasswordFormFillData s) =>
(PasswordFormFillData passed);
- PassFormsPredictionsMap(FormsPredictionsMap s) =>
- (FormsPredictionsMap passed);
PassPasswordFormGenerationData(PasswordFormGenerationData s) =>
(PasswordFormGenerationData passed);
PassPasswordGenerationUIData(PasswordGenerationUIData s) =>
diff --git a/chromium/components/autofill/core/common/password_form.cc b/chromium/components/autofill/core/common/password_form.cc
index fc34f742b52..d6f0044c8ea 100644
--- a/chromium/components/autofill/core/common/password_form.cc
+++ b/chromium/components/autofill/core/common/password_form.cc
@@ -26,6 +26,17 @@ std::string ToString(const T& obj) {
return ostream.str();
}
+std::string StoreToString(PasswordForm::Store from_store) {
+ switch (from_store) {
+ case PasswordForm::Store::kNotSet:
+ return "Not Set";
+ case PasswordForm::Store::kProfileStore:
+ return "Profile Store";
+ case PasswordForm::Store::kAccountStore:
+ return "Account Store";
+ }
+}
+
// Serializes a PasswordForm to a JSON object. Used only for logging in tests.
void PasswordFormToJSON(const PasswordForm& form,
base::DictionaryValue* target) {
@@ -85,6 +96,7 @@ void PasswordFormToJSON(const PasswordForm& form,
target->SetBoolean("is_gaia_with_skip_save_password_form",
form.form_data.is_gaia_with_skip_save_password_form);
target->SetBoolean("is_new_password_reliable", form.is_new_password_reliable);
+ target->SetString("from_store", StoreToString(form.from_store));
}
} // namespace
@@ -136,6 +148,10 @@ bool PasswordForm::IsSingleUsername() const {
!HasNewPasswordElement();
}
+bool PasswordForm::IsUsingAccountStore() const {
+ return from_store == Store::kAccountStore;
+}
+
bool PasswordForm::operator==(const PasswordForm& form) const {
return scheme == form.scheme && signon_realm == form.signon_realm &&
origin == form.origin && action == form.action &&
@@ -180,7 +196,8 @@ bool PasswordForm::operator==(const PasswordForm& form) const {
app_icon_url == form.app_icon_url &&
submission_event == form.submission_event &&
only_for_fallback == form.only_for_fallback &&
- is_new_password_reliable == form.is_new_password_reliable;
+ is_new_password_reliable == form.is_new_password_reliable &&
+ from_store == form.from_store;
}
bool PasswordForm::operator!=(const PasswordForm& form) const {
@@ -196,28 +213,6 @@ bool ArePasswordFormUniqueKeysEqual(const PasswordForm& left,
left.password_element == right.password_element);
}
-bool LessThanUniqueKey::operator()(
- const std::unique_ptr<PasswordForm>& left,
- const std::unique_ptr<PasswordForm>& right) const {
- int result = left->signon_realm.compare(right->signon_realm);
- if (result)
- return result < 0;
-
- result = left->username_element.compare(right->username_element);
- if (result)
- return result < 0;
-
- result = left->username_value.compare(right->username_value);
- if (result)
- return result < 0;
-
- result = left->password_element.compare(right->password_element);
- if (result)
- return result < 0;
-
- return left->origin < right->origin;
-}
-
base::string16 ValueElementVectorToString(
const ValueElementVector& value_element_pairs) {
std::vector<base::string16> pairs(value_element_pairs.size());
@@ -228,12 +223,6 @@ base::string16 ValueElementVectorToString(
return base::JoinString(pairs, base::ASCIIToUTF16(", "));
}
-bool IsHttpAuthScheme(PasswordForm::Scheme scheme) {
- return scheme == PasswordForm::Scheme::kBasic ||
- scheme == PasswordForm::Scheme::kDigest ||
- scheme == PasswordForm::Scheme::kOther;
-}
-
std::ostream& operator<<(std::ostream& os, const PasswordForm& form) {
base::DictionaryValue form_json;
PasswordFormToJSON(form, &form_json);
diff --git a/chromium/components/autofill/core/common/password_form.h b/chromium/components/autofill/core/common/password_form.h
index 348900b8212..48e63390f8b 100644
--- a/chromium/components/autofill/core/common/password_form.h
+++ b/chromium/components/autofill/core/common/password_form.h
@@ -303,6 +303,16 @@ struct PasswordForm {
// as signal for password generation eligibility.
bool is_new_password_reliable = false;
+ enum class Store {
+ // Default value.
+ kNotSet,
+ // Credential came from the profile (i.e. local) storage.
+ kProfileStore,
+ // Credential came from the Gaia-account-scoped storage.
+ kAccountStore
+ };
+ Store from_store = Store::kNotSet;
+
// Return true if we consider this form to be a change password form.
// We use only client heuristics, so it could include signup forms.
bool IsPossibleChangePasswordForm() const;
@@ -328,6 +338,10 @@ struct PasswordForm {
// not set.
bool IsSingleUsername() const;
+ // Returns whether this form is stored in the account-scoped store, i.e.
+ // whether |from_store == Store::kAccountStore|.
+ bool IsUsingAccountStore() const;
+
// Equality operators for testing.
bool operator==(const PasswordForm& form) const;
bool operator!=(const PasswordForm& form) const;
@@ -346,19 +360,10 @@ struct PasswordForm {
bool ArePasswordFormUniqueKeysEqual(const PasswordForm& left,
const PasswordForm& right);
-// A comparator for the unique key.
-struct LessThanUniqueKey {
- bool operator()(const std::unique_ptr<PasswordForm>& left,
- const std::unique_ptr<PasswordForm>& right) const;
-};
-
// Converts a vector of ValueElementPair to string.
base::string16 ValueElementVectorToString(
const ValueElementVector& value_element_pairs);
-// Returns true if |scheme| corresponds to http auth scheme.
-bool IsHttpAuthScheme(PasswordForm::Scheme scheme);
-
// For testing.
std::ostream& operator<<(std::ostream& os, const PasswordForm& form);
std::ostream& operator<<(std::ostream& os, PasswordForm* form);
diff --git a/chromium/components/autofill/core/common/password_form_field_prediction_map.h b/chromium/components/autofill/core/common/password_form_field_prediction_map.h
deleted file mode 100644
index b0d149c092c..00000000000
--- a/chromium/components/autofill/core/common/password_form_field_prediction_map.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PASSWORD_FORM_FIELD_PREDICTION_MAP_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_PASSWORD_FORM_FIELD_PREDICTION_MAP_H_
-
-#include "base/containers/flat_map.h"
-#include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/form_field_data.h"
-#include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h"
-
-namespace autofill {
-
-using PasswordFormFieldPredictionMap =
- base::flat_map<FormFieldData, mojom::PasswordFormFieldPredictionType>;
-using FormsPredictionsMap =
- base::flat_map<FormData, PasswordFormFieldPredictionMap>;
-
-} // namespace autofill
-
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PASSWORD_FORM_FIELD_PREDICTION_MAP_H_
diff --git a/chromium/components/autofill/core/common/password_form_fill_data.cc b/chromium/components/autofill/core/common/password_form_fill_data.cc
index db08ce036bb..06b7eb4de26 100644
--- a/chromium/components/autofill/core/common/password_form_fill_data.cc
+++ b/chromium/components/autofill/core/common/password_form_fill_data.cc
@@ -24,7 +24,7 @@ PasswordFormFillData::PasswordFormFillData() = default;
PasswordFormFillData::PasswordFormFillData(
const PasswordForm& form_on_page,
- const std::map<base::string16, const PasswordForm*>& matches,
+ const std::vector<const PasswordForm*>& matches,
const PasswordForm& preferred_match,
bool wait_for_username)
: form_renderer_id(form_on_page.form_data.unique_renderer_id),
@@ -65,17 +65,25 @@ PasswordFormFillData::PasswordFormFillData(
preferred_realm = preferred_match.signon_realm;
// Copy additional username/value pairs.
- for (const auto& it : matches) {
- if (it.second != &preferred_match) {
- PasswordAndRealm& value = additional_logins[it.first];
- value.password = it.second->password_value;
- if (IsPublicSuffixMatchOrAffiliationBasedMatch(*it.second))
- value.realm = it.second->signon_realm;
- }
+ for (const PasswordForm* match : matches) {
+ if (match == &preferred_match)
+ continue;
+ PasswordAndRealm& value = additional_logins[match->username_value];
+ value.password = match->password_value;
+ if (IsPublicSuffixMatchOrAffiliationBasedMatch(*match))
+ value.realm = match->signon_realm;
}
}
-PasswordFormFillData::PasswordFormFillData(const PasswordFormFillData& other) =
+PasswordFormFillData::PasswordFormFillData(const PasswordFormFillData&) =
+ default;
+
+PasswordFormFillData& PasswordFormFillData::operator=(
+ const PasswordFormFillData&) = default;
+
+PasswordFormFillData::PasswordFormFillData(PasswordFormFillData&&) = default;
+
+PasswordFormFillData& PasswordFormFillData::operator=(PasswordFormFillData&&) =
default;
PasswordFormFillData::~PasswordFormFillData() = default;
diff --git a/chromium/components/autofill/core/common/password_form_fill_data.h b/chromium/components/autofill/core/common/password_form_fill_data.h
index dfe6586ffbb..a94a1aeeb28 100644
--- a/chromium/components/autofill/core/common/password_form_fill_data.h
+++ b/chromium/components/autofill/core/common/password_form_fill_data.h
@@ -6,12 +6,21 @@
#define COMPONENTS_AUTOFILL_CORE_COMMON_PASSWORD_FORM_FILL_DATA_H_
#include <map>
+#include <vector>
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/password_form.h"
namespace autofill {
+// Contains renderer ids of password related elements found by the form parser.
+struct ParsingResult {
+ uint32_t username_renderer_id;
+ uint32_t password_renderer_id;
+ uint32_t new_password_renderer_id;
+ uint32_t confirm_password_renderer_id;
+};
+
struct PasswordAndRealm {
base::string16 password;
std::string realm;
@@ -32,14 +41,15 @@ struct PasswordFormFillData {
// not autofill anything until the user typed in a valid username and blurred
// the field. If |enable_possible_usernames| is true, we will populate
// possible_usernames.
- PasswordFormFillData(
- const PasswordForm& form_on_page,
- const std::map<base::string16, const PasswordForm*>& matches,
- const PasswordForm& preferred_match,
- bool wait_for_username);
-
- PasswordFormFillData(const PasswordFormFillData& other);
-
+ PasswordFormFillData(const PasswordForm& form_on_page,
+ const std::vector<const PasswordForm*>& matches,
+ const PasswordForm& preferred_match,
+ bool wait_for_username);
+
+ PasswordFormFillData(const PasswordFormFillData&);
+ PasswordFormFillData& operator=(const PasswordFormFillData&);
+ PasswordFormFillData(PasswordFormFillData&&);
+ PasswordFormFillData& operator=(PasswordFormFillData&&);
~PasswordFormFillData();
// If |has_renderer_ids| == true then |form_renderer_id| contains the unique
@@ -89,7 +99,6 @@ struct PasswordFormFillData {
// TODO(https://crbug.com/831123): Remove this field when old parsing is
// removed and filling by renderer ids is by default.
bool has_renderer_ids = false;
-
};
// If |data.wait_for_username| is set, the renderer does not need to receive
diff --git a/chromium/components/autofill/core/common/password_form_fill_data_unittest.cc b/chromium/components/autofill/core/common/password_form_fill_data_unittest.cc
index b794cc1115f..2c863d433dd 100644
--- a/chromium/components/autofill/core/common/password_form_fill_data_unittest.cc
+++ b/chromium/components/autofill/core/common/password_form_fill_data_unittest.cc
@@ -47,7 +47,7 @@ TEST(PasswordFormFillDataTest, TestSinglePreferredMatch) {
preferred_match.preferred = true;
preferred_match.scheme = PasswordForm::Scheme::kHtml;
- std::map<base::string16, const PasswordForm*> matches;
+ std::vector<const PasswordForm*> matches;
PasswordFormFillData result(form_on_page, matches, preferred_match, true);
@@ -127,10 +127,8 @@ TEST(PasswordFormFillDataTest, TestPublicSuffixDomainMatching) {
public_suffix_match.scheme = PasswordForm::Scheme::kHtml;
// Add one exact match and one public suffix match.
- std::map<base::string16, const PasswordForm*> matches;
- matches.insert(std::make_pair(exact_match.username_value, &exact_match));
- matches.insert(
- std::make_pair(public_suffix_match.username_value, &public_suffix_match));
+ std::vector<const PasswordForm*> matches = {&exact_match,
+ &public_suffix_match};
PasswordFormFillData result(form_on_page, matches, preferred_match, true);
EXPECT_TRUE(result.wait_for_username);
@@ -202,10 +200,7 @@ TEST(PasswordFormFillDataTest, TestAffiliationMatch) {
affiliated_match.scheme = PasswordForm::Scheme::kHtml;
// Add one exact match and one affiliation based match.
- std::map<base::string16, const PasswordForm*> matches;
- matches.insert(std::make_pair(exact_match.username_value, &exact_match));
- matches.insert(
- std::make_pair(affiliated_match.username_value, &affiliated_match));
+ std::vector<const PasswordForm*> matches = {&exact_match, &affiliated_match};
PasswordFormFillData result(form_on_page, matches, preferred_match, false);
EXPECT_FALSE(result.wait_for_username);
@@ -249,9 +244,7 @@ TEST(PasswordFormFillDataTest, RendererIDs) {
form_on_page.username_element_renderer_id = 123;
form_on_page.password_element_renderer_id = 456;
- std::map<base::string16, const PasswordForm*> matches;
-
- PasswordFormFillData result(form_on_page, matches, preferred_match, true);
+ PasswordFormFillData result(form_on_page, {}, preferred_match, true);
EXPECT_EQ(form_data.unique_renderer_id, result.form_renderer_id);
EXPECT_EQ(form_on_page.has_renderer_ids, result.has_renderer_ids);
diff --git a/chromium/components/autofill/core/common/password_generation_util.cc b/chromium/components/autofill/core/common/password_generation_util.cc
index 8bab183bf31..6f89ed2622d 100644
--- a/chromium/components/autofill/core/common/password_generation_util.cc
+++ b/chromium/components/autofill/core/common/password_generation_util.cc
@@ -17,12 +17,14 @@ PasswordGenerationUIData::PasswordGenerationUIData(
int max_length,
const base::string16& generation_element,
uint32_t generation_element_id,
+ bool is_generation_element_password_type,
base::i18n::TextDirection text_direction,
const autofill::PasswordForm& password_form)
: bounds(bounds),
max_length(max_length),
generation_element(generation_element),
generation_element_id(generation_element_id),
+ is_generation_element_password_type(is_generation_element_password_type),
text_direction(text_direction),
password_form(password_form) {}
diff --git a/chromium/components/autofill/core/common/password_generation_util.h b/chromium/components/autofill/core/common/password_generation_util.h
index e3da088110b..c2143d13476 100644
--- a/chromium/components/autofill/core/common/password_generation_util.h
+++ b/chromium/components/autofill/core/common/password_generation_util.h
@@ -109,6 +109,7 @@ struct PasswordGenerationUIData {
int max_length,
const base::string16& generation_element,
uint32_t generation_element_id,
+ bool is_generation_element_password_type,
base::i18n::TextDirection text_direction,
const autofill::PasswordForm& password_form);
PasswordGenerationUIData();
@@ -132,6 +133,9 @@ struct PasswordGenerationUIData {
// Renderer ID of the generation element.
uint32_t generation_element_id;
+ // Is the generation element |type=password|.
+ bool is_generation_element_password_type;
+
// Direction of the text for |generation_element|.
base::i18n::TextDirection text_direction;
@@ -141,10 +145,6 @@ struct PasswordGenerationUIData {
void LogPasswordGenerationEvent(PasswordGenerationEvent event);
-// Returns true if Password Generation is enabled according to the field
-// trial result and the flags.
-bool IsPasswordGenerationEnabled();
-
} // namespace password_generation
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/save_password_progress_logger.cc b/chromium/components/autofill/core/common/save_password_progress_logger.cc
index 91807e55dce..b4bd692a753 100644
--- a/chromium/components/autofill/core/common/save_password_progress_logger.cc
+++ b/chromium/components/autofill/core/common/save_password_progress_logger.cc
@@ -275,16 +275,8 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "provisionally_saved_forms_[form_frame]";
case SavePasswordProgressLogger::STRING_PROVISIONALLY_SAVE_FORM_METHOD:
return "PasswordManager::ProvisionallySaveForm";
- case SavePasswordProgressLogger::STRING_IS_SAVING_ENABLED:
- return "IsSavingAndFillingEnabled";
case SavePasswordProgressLogger::STRING_EMPTY_PASSWORD:
return "Empty password";
- case SavePasswordProgressLogger::STRING_EXACT_MATCH:
- return "Form manager found, exact match";
- case SavePasswordProgressLogger::STRING_MATCH_WITHOUT_ACTION:
- return "Form manager found, match except for action";
- case SavePasswordProgressLogger::STRING_ORIGINS_MATCH:
- return "Form manager found, only origins match";
case SavePasswordProgressLogger::STRING_MATCHING_NOT_COMPLETE:
return "No form manager has completed matching";
case SavePasswordProgressLogger::STRING_FORM_BLACKLISTED:
@@ -295,8 +287,6 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "Credential is used for syncing passwords";
case STRING_BLOCK_PASSWORD_SAME_ORIGIN_INSECURE_SCHEME:
return "Blocked password due to same origin but insecure scheme";
- case SavePasswordProgressLogger::STRING_PROVISIONALLY_SAVED_FORM:
- return "provisionally_saved_form";
case SavePasswordProgressLogger::STRING_ON_PASSWORD_FORMS_RENDERED_METHOD:
return "PasswordManager::OnPasswordFormsRendered";
case SavePasswordProgressLogger::STRING_ON_SAME_DOCUMENT_NAVIGATION:
@@ -323,8 +313,6 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "Show password prompt";
case SavePasswordProgressLogger::STRING_PASSWORDMANAGER_AUTOFILL:
return "PasswordManager::Autofill";
- case SavePasswordProgressLogger::STRING_PASSWORDMANAGER_AUTOFILLHTTPAUTH:
- return "PasswordManager::AutofillHttpAuth";
case SavePasswordProgressLogger::
STRING_PASSWORDMANAGER_SHOW_INITIAL_PASSWORD_ACCOUNT_SUGGESTIONS:
return "PasswordManager::ShowInitialPasswordAccountSuggestions";
@@ -338,10 +326,6 @@ std::string SavePasswordProgressLogger::GetStringFromID(
case SavePasswordProgressLogger::
STRING_PROVISIONALLY_SAVED_FORM_IS_NOT_HTML:
return "Provisionally saved form is not HTML";
- case SavePasswordProgressLogger::STRING_ON_FETCH_COMPLETED_METHOD:
- return "PasswordFormManager::OnFetchCompleted";
- case SavePasswordProgressLogger::STRING_BEST_SCORE:
- return "best_score";
case SavePasswordProgressLogger::STRING_ON_GET_STORE_RESULTS_METHOD:
return "FormFetcherImpl::OnGetPasswordStoreResults";
case SavePasswordProgressLogger::STRING_NUMBER_RESULTS:
@@ -352,8 +336,6 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "PasswordStore is not available";
case SavePasswordProgressLogger::STRING_CREATE_LOGIN_MANAGERS_METHOD:
return "PasswordManager::CreatePendingLoginManagers";
- case SavePasswordProgressLogger::STRING_NEW_NUMBER_LOGIN_MANAGERS:
- return "Number of pending login managers (after)";
case SavePasswordProgressLogger::
STRING_PASSWORD_MANAGEMENT_ENABLED_FOR_CURRENT_PAGE:
return "IsPasswordManagementEnabledForCurrentPage";
@@ -361,12 +343,6 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "ShowLoginPrompt";
case SavePasswordProgressLogger::STRING_NEW_UI_STATE:
return "The new state of the UI";
- case SavePasswordProgressLogger::STRING_FORM_NOT_AUTOFILLED:
- return "The observed form will not be autofilled";
- case SavePasswordProgressLogger::STRING_CHANGE_PASSWORD_FORM:
- return "Not saving password for a change password form";
- case SavePasswordProgressLogger::STRING_PROCESS_FRAME_METHOD:
- return "PasswordFormManager::ProcessFrame";
case SavePasswordProgressLogger::STRING_FORM_SIGNATURE:
return "Signature of form";
case SavePasswordProgressLogger::STRING_FORM_FETCHER_STATE:
@@ -405,8 +381,6 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "Form name";
case SavePasswordProgressLogger::STRING_FIELDS:
return "Form fields";
- case SavePasswordProgressLogger::STRING_FORM_VOTES:
- return "Form votes";
case SavePasswordProgressLogger::STRING_FIRSTUSE_FORM_VOTE:
return "FirstUse vote";
case SavePasswordProgressLogger::STRING_PASSWORD_FORM_VOTE:
@@ -417,26 +391,6 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "Generation disabled: saving disabled";
case SavePasswordProgressLogger::STRING_GENERATION_DISABLED_NO_SYNC:
return "Generation disabled: no sync";
- case STRING_GENERATION_RENDERER_INVALID_PASSWORD_FORM:
- return "Generation invalid PasswordForm";
- case STRING_GENERATION_RENDERER_POSSIBLE_ACCOUNT_CREATION_FORMS:
- return "Generation possible account creation forms";
- case STRING_GENERATION_RENDERER_NO_PASSWORD_MANAGER_ACCESS:
- return "Generation: no PasswordManager access";
- case STRING_GENERATION_RENDERER_FORM_ALREADY_FOUND:
- return "Generation: account creation form already found";
- case STRING_GENERATION_RENDERER_NO_POSSIBLE_CREATION_FORMS:
- return "Generation: no possible account creation forms";
- case STRING_GENERATION_RENDERER_NOT_BLACKLISTED:
- return "Generation: no non-blacklisted confirmation";
- case STRING_GENERATION_RENDERER_AUTOCOMPLETE_ATTRIBUTE:
- return "Generation: autocomplete attributes found";
- case STRING_GENERATION_RENDERER_NO_SERVER_SIGNAL:
- return "Generation: no server signal";
- case STRING_GENERATION_RENDERER_ELIGIBLE_FORM_FOUND:
- return "Generation: eligible form found";
- case STRING_GENERATION_RENDERER_NO_FIELD_FOUND:
- return "Generation: fields for generation are not found";
case STRING_GENERATION_RENDERER_AUTOMATIC_GENERATION_AVAILABLE:
return "Generation: automatic generation is available";
case STRING_GENERATION_RENDERER_SHOW_MANUAL_GENERATION_POPUP:
@@ -463,8 +417,6 @@ std::string SavePasswordProgressLogger::GetStringFromID(
"exists whose username matches the prefilled value";
case STRING_FAILED_TO_FILL_FOUND_NO_PASSWORD_FOR_USERNAME:
return "Failed to fill: No credential matching found";
- case SavePasswordProgressLogger::STRING_HTTPAUTH_OBSERVER_PRESENT:
- return "Instances of HttpAuthObserver are present";
case SavePasswordProgressLogger::
STRING_HTTPAUTH_ON_ASK_USER_OR_SAVE_PASSWORD:
return "HttpAuthManager::AskUserOrSavePassword";
@@ -476,26 +428,22 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "HttpAuthManager::DetachObserver";
case SavePasswordProgressLogger::STRING_SHOW_ONBOARDING:
return "Show onboarding experience and offer to save password";
+ case STRING_LEAK_DETECTION_DISABLED_FEATURE:
+ return "Leak detection disabled in settings";
+ case STRING_LEAK_DETECTION_DISABLED_SAFE_BROWSING:
+ return "Leak detection is off as the safe browsing is disabled";
case STRING_LEAK_DETECTION_FINISHED:
return "Leak detection finished with result";
case STRING_LEAK_DETECTION_SIGNED_OUT_ERROR:
return "Leak detection failed: signed out";
case STRING_LEAK_DETECTION_TOKEN_REQUEST_ERROR:
return "Leak detection failed: can't get a token";
- case STRING_LEAK_DETECTION_ENCRYPTION_ERROR:
- return "Leak detection failed: encryption";
case STRING_LEAK_DETECTION_INVALID_SERVER_RESPONSE_ERROR:
return "Leak detection failed: invalid server response";
case SavePasswordProgressLogger::
STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_LOWERCASE:
return "Uploading password requirements vote for using lowercase letters";
case SavePasswordProgressLogger::
- STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_UPPERCASE:
- return "Uploading password requirements vote for using lowercase letters";
- case SavePasswordProgressLogger::
- STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_NUMERICS:
- return "Uploading password requirements vote for using numbers";
- case SavePasswordProgressLogger::
STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_SPECIAL_SYMBOL:
return "Uploading password requirements vote for using special symbols";
case SavePasswordProgressLogger::
@@ -504,9 +452,6 @@ std::string SavePasswordProgressLogger::GetStringFromID(
case SavePasswordProgressLogger::
STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_PASSWORD_LENGTH:
return "Uploading password requirements vote for password length";
- case SavePasswordProgressLogger::
- STRING_PASSWORD_REQUIREMENTS_VOTE_NO_PASSWORD_ATTRIBUTES:
- return "No password requirements attributed set";
case STRING_SAVE_PASSWORD_HASH:
return "Password hash is saved";
case STRING_DID_NAVIGATE_MAIN_FRAME:
@@ -515,6 +460,8 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "Navigation to New Tab page";
case STRING_SERVER_PREDICTIONS:
return "Server predictions";
+ case STRING_USERNAME_FIRST_FLOW_VOTE:
+ return "Username first flow vote";
case SavePasswordProgressLogger::STRING_INVALID:
return "INVALID";
// Intentionally no default: clause here -- all IDs need to get covered.
diff --git a/chromium/components/autofill/core/common/save_password_progress_logger.h b/chromium/components/autofill/core/common/save_password_progress_logger.h
index f1899def840..f6f4a681b76 100644
--- a/chromium/components/autofill/core/common/save_password_progress_logger.h
+++ b/chromium/components/autofill/core/common/save_password_progress_logger.h
@@ -78,17 +78,12 @@ class SavePasswordProgressLogger {
STRING_FRAME_NOT_MAIN_FRAME,
STRING_PROVISIONALLY_SAVED_FORM_FOR_FRAME,
STRING_PROVISIONALLY_SAVE_FORM_METHOD,
- STRING_IS_SAVING_ENABLED,
STRING_EMPTY_PASSWORD,
- STRING_EXACT_MATCH,
- STRING_MATCH_WITHOUT_ACTION,
- STRING_ORIGINS_MATCH,
STRING_MATCHING_NOT_COMPLETE,
STRING_FORM_BLACKLISTED,
STRING_INVALID_FORM,
STRING_SYNC_CREDENTIAL,
STRING_BLOCK_PASSWORD_SAME_ORIGIN_INSECURE_SCHEME,
- STRING_PROVISIONALLY_SAVED_FORM,
STRING_ON_PASSWORD_FORMS_RENDERED_METHOD,
STRING_ON_SAME_DOCUMENT_NAVIGATION,
STRING_ON_ASK_USER_OR_SAVE_PASSWORD,
@@ -102,26 +97,19 @@ class SavePasswordProgressLogger {
STRING_ONLY_VISIBLE,
STRING_SHOW_PASSWORD_PROMPT,
STRING_PASSWORDMANAGER_AUTOFILL,
- STRING_PASSWORDMANAGER_AUTOFILLHTTPAUTH,
STRING_PASSWORDMANAGER_SHOW_INITIAL_PASSWORD_ACCOUNT_SUGGESTIONS,
STRING_WAIT_FOR_USERNAME,
STRING_WAS_LAST_NAVIGATION_HTTP_ERROR_METHOD,
STRING_HTTP_STATUS_CODE,
STRING_PROVISIONALLY_SAVED_FORM_IS_NOT_HTML,
- STRING_ON_FETCH_COMPLETED_METHOD,
- STRING_BEST_SCORE,
STRING_ON_GET_STORE_RESULTS_METHOD,
STRING_NUMBER_RESULTS,
STRING_FETCH_METHOD,
STRING_NO_STORE,
STRING_CREATE_LOGIN_MANAGERS_METHOD,
- STRING_NEW_NUMBER_LOGIN_MANAGERS,
STRING_PASSWORD_MANAGEMENT_ENABLED_FOR_CURRENT_PAGE,
STRING_SHOW_LOGIN_PROMPT_METHOD,
STRING_NEW_UI_STATE,
- STRING_FORM_NOT_AUTOFILLED,
- STRING_CHANGE_PASSWORD_FORM,
- STRING_PROCESS_FRAME_METHOD,
STRING_FORM_SIGNATURE,
STRING_FORM_FETCHER_STATE,
STRING_UNOWNED_INPUTS_VISIBLE,
@@ -140,22 +128,11 @@ class SavePasswordProgressLogger {
STRING_PASSWORD_FILLED,
STRING_FORM_NAME,
STRING_FIELDS,
- STRING_FORM_VOTES,
STRING_FIRSTUSE_FORM_VOTE,
STRING_PASSWORD_FORM_VOTE,
STRING_REUSE_FOUND,
STRING_GENERATION_DISABLED_SAVING_DISABLED,
STRING_GENERATION_DISABLED_NO_SYNC,
- STRING_GENERATION_RENDERER_INVALID_PASSWORD_FORM,
- STRING_GENERATION_RENDERER_POSSIBLE_ACCOUNT_CREATION_FORMS,
- STRING_GENERATION_RENDERER_NO_PASSWORD_MANAGER_ACCESS,
- STRING_GENERATION_RENDERER_FORM_ALREADY_FOUND,
- STRING_GENERATION_RENDERER_NO_POSSIBLE_CREATION_FORMS,
- STRING_GENERATION_RENDERER_NOT_BLACKLISTED,
- STRING_GENERATION_RENDERER_AUTOCOMPLETE_ATTRIBUTE,
- STRING_GENERATION_RENDERER_NO_SERVER_SIGNAL,
- STRING_GENERATION_RENDERER_ELIGIBLE_FORM_FOUND,
- STRING_GENERATION_RENDERER_NO_FIELD_FOUND,
STRING_GENERATION_RENDERER_AUTOMATIC_GENERATION_AVAILABLE,
STRING_GENERATION_RENDERER_SHOW_MANUAL_GENERATION_POPUP,
STRING_GENERATION_RENDERER_GENERATED_PASSWORD_ACCEPTED,
@@ -168,28 +145,26 @@ class SavePasswordProgressLogger {
STRING_FAILED_TO_FILL_NO_AUTOCOMPLETEABLE_ELEMENT,
STRING_FAILED_TO_FILL_PREFILLED_USERNAME,
STRING_FAILED_TO_FILL_FOUND_NO_PASSWORD_FOR_USERNAME,
- STRING_HTTPAUTH_OBSERVER_PRESENT,
STRING_HTTPAUTH_ON_ASK_USER_OR_SAVE_PASSWORD,
STRING_HTTPAUTH_ON_PROMPT_USER,
STRING_HTTPAUTH_ON_SET_OBSERVER,
STRING_HTTPAUTH_ON_DETACH_OBSERVER,
STRING_SHOW_ONBOARDING,
+ STRING_LEAK_DETECTION_DISABLED_FEATURE,
+ STRING_LEAK_DETECTION_DISABLED_SAFE_BROWSING,
STRING_LEAK_DETECTION_FINISHED,
STRING_LEAK_DETECTION_SIGNED_OUT_ERROR,
STRING_LEAK_DETECTION_TOKEN_REQUEST_ERROR,
- STRING_LEAK_DETECTION_ENCRYPTION_ERROR,
STRING_LEAK_DETECTION_INVALID_SERVER_RESPONSE_ERROR,
STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_LOWERCASE,
- STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_UPPERCASE,
- STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_NUMERICS,
STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_SPECIAL_SYMBOL,
STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_SPECIFIC_SPECIAL_SYMBOL,
STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_PASSWORD_LENGTH,
- STRING_PASSWORD_REQUIREMENTS_VOTE_NO_PASSWORD_ATTRIBUTES,
STRING_SAVE_PASSWORD_HASH,
STRING_DID_NAVIGATE_MAIN_FRAME,
STRING_NAVIGATION_NTP,
STRING_SERVER_PREDICTIONS,
+ STRING_USERNAME_FIRST_FLOW_VOTE,
STRING_INVALID, // Represents a string returned in a case of an error.
STRING_MAX = STRING_INVALID
};
diff --git a/chromium/components/autofill/ios/browser/autofill_agent.mm b/chromium/components/autofill/ios/browser/autofill_agent.mm
index 092c7847147..c10e6115cbf 100644
--- a/chromium/components/autofill/ios/browser/autofill_agent.mm
+++ b/chromium/components/autofill/ios/browser/autofill_agent.mm
@@ -53,7 +53,7 @@
#import "ios/web/public/js_messaging/web_frames_manager.h"
#import "ios/web/public/navigation/navigation_context.h"
#import "ios/web/public/web_state.h"
-#import "ios/web/public/web_state/web_state_observer_bridge.h"
+#import "ios/web/public/web_state_observer_bridge.h"
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"
@@ -503,7 +503,6 @@ autofillManagerFromWebState:(web::WebState*)webState
popupDelegate:
(const base::WeakPtr<autofill::AutofillPopupDelegate>&)
delegate {
- bool has_gpay_branding = false;
// Convert the suggestions into an NSArray for the keyboard.
NSMutableArray<FormSuggestion*>* suggestions = [[NSMutableArray alloc] init];
for (auto popup_suggestion : popup_suggestions) {
@@ -514,8 +513,7 @@ autofillManagerFromWebState:(web::WebState*)webState
// fortunately almost all the entries we are interested in (profile or
// autofill entries) are zero or positive. Negative entries we are
// interested in is autofill::POPUP_ITEM_ID_CLEAR_FORM, used to show the
- // "clear form" button and autofill::POPUP_ITEM_ID_GOOGLE_PAY_BRANDING, used
- // to show the "Google Pay" branding.
+ // "clear form" button.
NSString* value = nil;
NSString* displayDescription = nil;
if (popup_suggestion.frontend_id >= 0) {
@@ -535,11 +533,6 @@ autofillManagerFromWebState:(web::WebState*)webState
// Show the "clear form" button.
value = base::SysUTF16ToNSString(popup_suggestion.value);
} else if (popup_suggestion.frontend_id ==
- autofill::POPUP_ITEM_ID_GOOGLE_PAY_BRANDING) {
- // Show "GPay branding" icon
- value = base::SysUTF16ToNSString(popup_suggestion.value);
- has_gpay_branding = true;
- } else if (popup_suggestion.frontend_id ==
autofill::POPUP_ITEM_ID_SHOW_ACCOUNT_CARDS) {
// Show opt-in for showing cards from account.
value = base::SysUTF16ToNSString(popup_suggestion.value);
@@ -554,10 +547,9 @@ autofillManagerFromWebState:(web::WebState*)webState
icon:base::SysUTF8ToNSString(popup_suggestion.icon)
identifier:popup_suggestion.frontend_id];
- // Put "clear form" entry at the front of the suggestions. If
- // "GPay branding" icon is present, it remains as the first suggestion.
+ // Put "clear form" entry at the front of the suggestions.
if (popup_suggestion.frontend_id == autofill::POPUP_ITEM_ID_CLEAR_FORM) {
- [suggestions insertObject:suggestion atIndex:has_gpay_branding ? 1 : 0];
+ [suggestions insertObject:suggestion atIndex:0];
} else {
[suggestions addObject:suggestion];
}
diff --git a/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm b/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm
index 7a83d99dfce..aee0fe52e81 100644
--- a/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm
+++ b/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm
@@ -36,7 +36,6 @@
#endif
using autofill::POPUP_ITEM_ID_CLEAR_FORM;
-using autofill::POPUP_ITEM_ID_GOOGLE_PAY_BRANDING;
using autofill::POPUP_ITEM_ID_SHOW_ACCOUNT_CARDS;
using base::test::ios::WaitUntilCondition;
@@ -379,8 +378,6 @@ TEST_F(AutofillAgentTests, onSuggestionsReady_ClearFormWithGPay) {
// Make the suggestions available to AutofillAgent.
std::vector<autofill::Suggestion> suggestions;
- suggestions.push_back(
- autofill::Suggestion("", "", "", POPUP_ITEM_ID_GOOGLE_PAY_BRANDING));
suggestions.push_back(autofill::Suggestion("", "", "", 123));
suggestions.push_back(autofill::Suggestion("", "", "", 321));
suggestions.push_back(
@@ -410,15 +407,11 @@ TEST_F(AutofillAgentTests, onSuggestionsReady_ClearFormWithGPay) {
return completion_handler_called;
});
- // GPay icon should appear as the first suggestion followed by "Clear Form".
- // Otherwise, the order of suggestions should not change.
- EXPECT_EQ(4U, completion_handler_suggestions.count);
- EXPECT_EQ(POPUP_ITEM_ID_GOOGLE_PAY_BRANDING,
- completion_handler_suggestions[0].identifier);
+ EXPECT_EQ(3U, completion_handler_suggestions.count);
EXPECT_EQ(POPUP_ITEM_ID_CLEAR_FORM,
- completion_handler_suggestions[1].identifier);
- EXPECT_EQ(123, completion_handler_suggestions[2].identifier);
- EXPECT_EQ(321, completion_handler_suggestions[3].identifier);
+ completion_handler_suggestions[0].identifier);
+ EXPECT_EQ(123, completion_handler_suggestions[1].identifier);
+ EXPECT_EQ(321, completion_handler_suggestions[2].identifier);
}
// Test that every frames are processed whatever is the order of pageloading
diff --git a/chromium/components/autofill/ios/browser/autofill_driver_ios.h b/chromium/components/autofill/ios/browser/autofill_driver_ios.h
index 9783f364b46..08226a74a59 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios.h
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios.h
@@ -60,7 +60,8 @@ class AutofillDriverIOS : public AutofillDriver {
void RendererShouldFillFieldWithValue(const base::string16& value) override;
void RendererShouldPreviewFieldWithValue(
const base::string16& value) override;
- void RendererShouldSetSuggestionAvailability(bool available) override;
+ void RendererShouldSetSuggestionAvailability(
+ const mojom::AutofillState state) override;
void PopupHidden() override;
gfx::RectF TransformBoundingBoxToViewportCoordinates(
const gfx::RectF& bounding_box) override;
diff --git a/chromium/components/autofill/ios/browser/autofill_driver_ios.mm b/chromium/components/autofill/ios/browser/autofill_driver_ios.mm
index 7c18d5f3b6d..c9bce04f629 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios.mm
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios.mm
@@ -131,7 +131,7 @@ void AutofillDriverIOS::RendererShouldPreviewFieldWithValue(
}
void AutofillDriverIOS::RendererShouldSetSuggestionAvailability(
- bool available) {}
+ const mojom::AutofillState state) {}
void AutofillDriverIOS::PopupHidden() {
}
diff --git a/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.h b/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.h
index 6e1c543769b..99e6f83f7bc 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.h
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.h
@@ -7,7 +7,7 @@
#include "components/autofill/ios/browser/autofill_driver_ios.h"
#include "ios/web/public/js_messaging/web_frame_user_data.h"
-#include "ios/web/public/web_state/web_state_user_data.h"
+#import "ios/web/public/web_state_user_data.h"
namespace web {
class WebFrame;
diff --git a/chromium/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.h b/chromium/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.h
index 6c8f2d6ec8a..85a66449c0f 100644
--- a/chromium/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.h
+++ b/chromium/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.h
@@ -38,7 +38,7 @@ class CreditCardSaveManagerTestObserverBridge
explicit CreditCardSaveManagerTestObserverBridge(
CreditCardSaveManager* credit_card_save_manager,
id<CreditCardSaveManagerTestObserver> observer);
- virtual ~CreditCardSaveManagerTestObserverBridge() = default;
+ ~CreditCardSaveManagerTestObserverBridge() override = default;
// CreditCardSaveManager::ObserverForTest:
void OnOfferLocalSave() override;
diff --git a/chromium/components/autofill/ios/browser/js_autofill_manager.mm b/chromium/components/autofill/ios/browser/js_autofill_manager.mm
index c81f80ff95a..2b134fcfc73 100644
--- a/chromium/components/autofill/ios/browser/js_autofill_manager.mm
+++ b/chromium/components/autofill/ios/browser/js_autofill_manager.mm
@@ -28,7 +28,7 @@
@implementation JsAutofillManager {
// The injection receiver used to evaluate JavaScript.
- CRWJSInjectionReceiver* _receiver;
+ __weak CRWJSInjectionReceiver* _receiver;
}
- (instancetype)initWithReceiver:(CRWJSInjectionReceiver*)receiver {
diff --git a/chromium/components/autofill/ios/browser/js_suggestion_manager.mm b/chromium/components/autofill/ios/browser/js_suggestion_manager.mm
index 07a81ca2d42..d7fd9a123e6 100644
--- a/chromium/components/autofill/ios/browser/js_suggestion_manager.mm
+++ b/chromium/components/autofill/ios/browser/js_suggestion_manager.mm
@@ -24,7 +24,7 @@
@implementation JsSuggestionManager {
// The injection receiver used to evaluate JavaScript.
- CRWJSInjectionReceiver* _receiver;
+ __weak CRWJSInjectionReceiver* _receiver;
web::WebFramesManager* _webFramesManager;
}
diff --git a/chromium/components/autofill/ios/form_util/form_activity_tab_helper.h b/chromium/components/autofill/ios/form_util/form_activity_tab_helper.h
index dc40fa6199f..976a4634857 100644
--- a/chromium/components/autofill/ios/form_util/form_activity_tab_helper.h
+++ b/chromium/components/autofill/ios/form_util/form_activity_tab_helper.h
@@ -8,8 +8,8 @@
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/values.h"
-#include "ios/web/public/web_state/web_state_observer.h"
-#import "ios/web/public/web_state/web_state_user_data.h"
+#include "ios/web/public/web_state_observer.h"
+#import "ios/web/public/web_state_user_data.h"
namespace autofill {