summaryrefslogtreecommitdiff
path: root/chromium/components/autofill
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-13 16:23:34 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-14 10:37:21 +0000
commit38a9a29f4f9436cace7f0e7abf9c586057df8a4e (patch)
treec4e8c458dc595bc0ddb435708fa2229edfd00bd4 /chromium/components/autofill
parente684a3455bcc29a6e3e66a004e352dea4e1141e7 (diff)
downloadqtwebengine-chromium-38a9a29f4f9436cace7f0e7abf9c586057df8a4e.tar.gz
BASELINE: Update Chromium to 73.0.3683.37
Change-Id: I08c9af2948b645f671e5d933aca1f7a90ea372f2 Reviewed-by: Michael Brüning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/components/autofill')
-rw-r--r--chromium/components/autofill/OWNERS1
-rw-r--r--chromium/components/autofill/android/autofill_provider_android.cc3
-rw-r--r--chromium/components/autofill/android/autofill_provider_android.h3
-rw-r--r--chromium/components/autofill/android/java/res/layout/autofill_dropdown_footer_item_refresh.xml2
-rw-r--r--chromium/components/autofill/android/java/res/layout/autofill_dropdown_item.xml4
-rw-r--r--chromium/components/autofill/android/java/res/layout/autofill_dropdown_item_refresh.xml4
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver.cc18
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver.h4
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver_factory.cc4
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver_factory.h14
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc44
-rw-r--r--chromium/components/autofill/content/common/BUILD.gn1
-rw-r--r--chromium/components/autofill/content/common/autofill_agent.mojom12
-rw-r--r--chromium/components/autofill/content/common/autofill_driver.mojom22
-rw-r--r--chromium/components/autofill/content/common/autofill_types.mojom27
-rw-r--r--chromium/components/autofill/content/common/autofill_types.typemap1
-rw-r--r--chromium/components/autofill/content/common/autofill_types_struct_traits.cc85
-rw-r--r--chromium/components/autofill/content/common/autofill_types_struct_traits.h50
-rw-r--r--chromium/components/autofill/content/common/autofill_types_struct_traits_unittest.cc40
-rw-r--r--chromium/components/autofill/content/common/test_autofill_types.mojom1
-rw-r--r--chromium/components/autofill/content/renderer/BUILD.gn3
-rw-r--r--chromium/components/autofill/content/renderer/OWNERS2
-rw-r--r--chromium/components/autofill/content/renderer/autofill_agent.cc22
-rw-r--r--chromium/components/autofill/content/renderer/form_autofill_util.cc217
-rw-r--r--chromium/components/autofill/content/renderer/form_autofill_util.h10
-rw-r--r--chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc145
-rw-r--r--chromium/components/autofill/content/renderer/form_cache.cc2
-rw-r--r--chromium/components/autofill/content/renderer/html_based_username_detector_vocabulary.cc18
-rw-r--r--chromium/components/autofill/content/renderer/page_form_analyser_logger.h10
-rw-r--r--chromium/components/autofill/content/renderer/password_autofill_agent.cc200
-rw-r--r--chromium/components/autofill/content/renderer/password_autofill_agent.h68
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils.cc4
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc183
-rw-r--r--chromium/components/autofill/content/renderer/password_generation_agent.cc211
-rw-r--r--chromium/components/autofill/content/renderer/password_generation_agent.h29
-rw-r--r--chromium/components/autofill/content/renderer/prefilled_values_detector.cc107
-rw-r--r--chromium/components/autofill/content/renderer/prefilled_values_detector.h37
-rw-r--r--chromium/components/autofill/content/renderer/prefilled_values_detector_unittest.cc37
-rw-r--r--chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc6
-rw-r--r--chromium/components/autofill/core/browser/BUILD.gn23
-rw-r--r--chromium/components/autofill/core/browser/DEPS7
-rw-r--r--chromium/components/autofill/core/browser/OWNERS1
-rw-r--r--chromium/components/autofill/core/browser/address_field_unittest.cc3
-rw-r--r--chromium/components/autofill/core/browser/address_normalizer_impl.cc6
-rw-r--r--chromium/components/autofill/core/browser/autocomplete_history_manager.cc295
-rw-r--r--chromium/components/autofill/core/browser/autocomplete_history_manager.h206
-rw-r--r--chromium/components/autofill/core/browser/autocomplete_history_manager_unittest.cc924
-rw-r--r--chromium/components/autofill/core/browser/autofill_address_util.cc2
-rw-r--r--chromium/components/autofill/core/browser/autofill_assistant_unittest.cc19
-rw-r--r--chromium/components/autofill/core/browser/autofill_client.h75
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_model.cc21
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_model.h15
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_model_unittest.cc14
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_util.cc11
-rw-r--r--chromium/components/autofill/core/browser/autofill_download_manager.cc6
-rw-r--r--chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc3
-rw-r--r--chromium/components/autofill/core/browser/autofill_driver.h4
-rw-r--r--chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc5
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments.cc51
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments.h23
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate.cc30
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc54
-rw-r--r--chromium/components/autofill/core/browser/autofill_handler.cc5
-rw-r--r--chromium/components/autofill/core/browser/autofill_handler.h6
-rw-r--r--chromium/components/autofill/core/browser/autofill_handler_proxy.cc5
-rw-r--r--chromium/components/autofill/core/browser/autofill_handler_proxy.h3
-rw-r--r--chromium/components/autofill/core/browser/autofill_ie_toolbar_import_win_unittest.cc8
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager.cc78
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager.h20
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager_unittest.cc916
-rw-r--r--chromium/components/autofill/core/browser/autofill_metadata.cc10
-rw-r--r--chromium/components/autofill/core/browser/autofill_metadata.h4
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.cc132
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.h14
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics_unittest.cc387
-rw-r--r--chromium/components/autofill/core/browser/autofill_observer.cc16
-rw-r--r--chromium/components/autofill/core/browser/autofill_observer.h38
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile.cc49
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile.h8
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_unittest.cc55
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_validator.cc5
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_validator.h4
-rw-r--r--chromium/components/autofill/core/browser/autofill_provider.h3
-rw-r--r--chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc72
-rw-r--r--chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h35
-rw-r--r--chromium/components/autofill/core/browser/autofill_subject.cc54
-rw-r--r--chromium/components/autofill/core/browser/autofill_subject.h38
-rw-r--r--chromium/components/autofill/core/browser/autofill_subject_unittest.cc140
-rw-r--r--chromium/components/autofill/core/browser/autofill_test_utils.cc12
-rw-r--r--chromium/components/autofill/core/browser/autofill_test_utils.h3
-rw-r--r--chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.cc19
-rw-r--r--chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.h6
-rw-r--r--chromium/components/autofill/core/browser/autofill_wallet_data_type_controller_unittest.cc8
-rw-r--r--chromium/components/autofill/core/browser/autofill_wallet_model_type_controller.cc25
-rw-r--r--chromium/components/autofill/core/browser/autofill_wallet_model_type_controller.h13
-rw-r--r--chromium/components/autofill/core/browser/country_data.cc3
-rw-r--r--chromium/components/autofill/core/browser/credit_card.cc41
-rw-r--r--chromium/components/autofill/core/browser/credit_card.h10
-rw-r--r--chromium/components/autofill/core/browser/credit_card_field.cc3
-rw-r--r--chromium/components/autofill/core/browser/credit_card_field.h3
-rw-r--r--chromium/components/autofill/core/browser/credit_card_field_unittest.cc6
-rw-r--r--chromium/components/autofill/core/browser/credit_card_save_manager.cc228
-rw-r--r--chromium/components/autofill/core/browser/credit_card_save_manager.h57
-rw-r--r--chromium/components/autofill/core/browser/credit_card_save_manager_unittest.cc647
-rw-r--r--chromium/components/autofill/core/browser/credit_card_save_strike_database.cc15
-rw-r--r--chromium/components/autofill/core/browser/credit_card_save_strike_database.h11
-rw-r--r--chromium/components/autofill/core/browser/credit_card_save_strike_database_unittest.cc35
-rw-r--r--chromium/components/autofill/core/browser/credit_card_unittest.cc50
-rw-r--r--chromium/components/autofill/core/browser/email_field.cc3
-rw-r--r--chromium/components/autofill/core/browser/email_field.h3
-rw-r--r--chromium/components/autofill/core/browser/field_filler_unittest.cc10
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer.cc13
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer.h15
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer_unittest.cc244
-rw-r--r--chromium/components/autofill/core/browser/form_structure.cc54
-rw-r--r--chromium/components/autofill/core/browser/form_structure.h4
-rw-r--r--chromium/components/autofill/core/browser/form_structure_unittest.cc275
-rw-r--r--chromium/components/autofill/core/browser/legacy_strike_database.cc4
-rw-r--r--chromium/components/autofill/core/browser/legacy_strike_database.h2
-rw-r--r--chromium/components/autofill/core/browser/local_card_migration_manager.cc15
-rw-r--r--chromium/components/autofill/core/browser/local_card_migration_manager.h2
-rw-r--r--chromium/components/autofill/core/browser/local_card_migration_manager_unittest.cc102
-rw-r--r--chromium/components/autofill/core/browser/local_card_migration_strike_database.cc36
-rw-r--r--chromium/components/autofill/core/browser/local_card_migration_strike_database.h29
-rw-r--r--chromium/components/autofill/core/browser/local_card_migration_strike_database_unittest.cc111
-rw-r--r--chromium/components/autofill/core/browser/mock_autocomplete_history_manager.cc14
-rw-r--r--chromium/components/autofill/core/browser/mock_autocomplete_history_manager.h44
-rw-r--r--chromium/components/autofill/core/browser/name_field.cc6
-rw-r--r--chromium/components/autofill/core/browser/name_field_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc4
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client.cc372
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client.h37
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client_unittest.cc72
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_request.h3
-rw-r--r--chromium/components/autofill/core/browser/payments/test_payments_client.cc9
-rw-r--r--chromium/components/autofill/core/browser/payments/test_payments_client.h15
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager.cc640
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager.h94
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager_observer.h4
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager_unittest.cc686
-rw-r--r--chromium/components/autofill/core/browser/phone_field.cc12
-rw-r--r--chromium/components/autofill/core/browser/phone_field_unittest.cc3
-rw-r--r--chromium/components/autofill/core/browser/phone_number_i18n.cc2
-rw-r--r--chromium/components/autofill/core/browser/proto/server.proto28
-rw-r--r--chromium/components/autofill/core/browser/randomized_encoder_unittest.cc170
-rw-r--r--chromium/components/autofill/core/browser/search_field_unittest.cc3
-rw-r--r--chromium/components/autofill/core/browser/strike_database.cc54
-rw-r--r--chromium/components/autofill/core/browser/strike_database.h37
-rw-r--r--chromium/components/autofill/core/browser/strike_database_integrator_base.cc92
-rw-r--r--chromium/components/autofill/core/browser/strike_database_integrator_base.h102
-rw-r--r--chromium/components/autofill/core/browser/strike_database_unittest.cc14
-rw-r--r--chromium/components/autofill/core/browser/suggestion_selection.cc6
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_async_observer.cc28
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_async_observer.h42
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_client.cc42
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_client.h41
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_driver.cc12
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_driver.h6
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_manager.cc19
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_manager.h10
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_provider.h3
-rw-r--r--chromium/components/autofill/core/browser/test_credit_card_save_manager.cc9
-rw-r--r--chromium/components/autofill/core/browser/test_credit_card_save_manager.h10
-rw-r--r--chromium/components/autofill/core/browser/test_credit_card_save_strike_database.cc6
-rw-r--r--chromium/components/autofill/core/browser/test_credit_card_save_strike_database.h2
-rw-r--r--chromium/components/autofill/core/browser/test_data_creator.cc204
-rw-r--r--chromium/components/autofill/core/browser/test_data_creator.h52
-rw-r--r--chromium/components/autofill/core/browser/test_local_card_migration_manager.cc2
-rw-r--r--chromium/components/autofill/core/browser/test_local_card_migration_manager.h2
-rw-r--r--chromium/components/autofill/core/browser/test_local_card_migration_strike_database.cc13
-rw-r--r--chromium/components/autofill/core/browser/test_local_card_migration_strike_database.h20
-rw-r--r--chromium/components/autofill/core/browser/test_personal_data_manager.cc5
-rw-r--r--chromium/components/autofill/core/browser/test_personal_data_manager.h5
-rw-r--r--chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl.cc2
-rw-r--r--chromium/components/autofill/core/browser/ui/local_card_migration_dialog_controller.h1
-rw-r--r--chromium/components/autofill/core/browser/validation.cc7
-rw-r--r--chromium/components/autofill/core/browser/validation.h4
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc33
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc57
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_change.h35
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.cc18
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h9
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.cc14
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.h10
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc4
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc4
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h6
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc10
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc248
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.h65
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table.cc109
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table.h11
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc264
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc483
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h34
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc225
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc15
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h8
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc190
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h6
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc178
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc34
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h11
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc63
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h22
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc15
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h10
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_service_observer.h2
-rw-r--r--chromium/components/autofill/core/browser/webdata/web_data_service_unittest.cc7
-rw-r--r--chromium/components/autofill/core/common/BUILD.gn1
-rw-r--r--chromium/components/autofill/core/common/OWNERS1
-rw-r--r--chromium/components/autofill/core/common/autofill_constants.cc7
-rw-r--r--chromium/components/autofill/core/common/autofill_constants.h17
-rw-r--r--chromium/components/autofill/core/common/autofill_features.cc67
-rw-r--r--chromium/components/autofill/core/common/autofill_features.h14
-rw-r--r--chromium/components/autofill/core/common/autofill_l10n_util.cc2
-rw-r--r--chromium/components/autofill/core/common/autofill_prefs.cc7
-rw-r--r--chromium/components/autofill/core/common/autofill_prefs.h1
-rw-r--r--chromium/components/autofill/core/common/autofill_prefs_unittest.cc24
-rw-r--r--chromium/components/autofill/core/common/autofill_switches.cc2
-rw-r--r--chromium/components/autofill/core/common/button_title_type.h26
-rw-r--r--chromium/components/autofill/core/common/form_data.cc2
-rw-r--r--chromium/components/autofill/core/common/form_data.h12
-rw-r--r--chromium/components/autofill/core/common/password_form.cc25
-rw-r--r--chromium/components/autofill/core/common/password_form.h25
-rw-r--r--chromium/components/autofill/core/common/password_form_fill_data.cc36
-rw-r--r--chromium/components/autofill/core/common/password_form_fill_data.h6
-rw-r--r--chromium/components/autofill/core/common/password_form_generation_data.h19
-rw-r--r--chromium/components/autofill/core/common/save_password_progress_logger.cc26
-rw-r--r--chromium/components/autofill/core/common/save_password_progress_logger.h6
-rw-r--r--chromium/components/autofill/ios/browser/BUILD.gn1
-rw-r--r--chromium/components/autofill/ios/browser/autofill_agent.mm3
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios.h1
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios.mm6
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.h14
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.mm8
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios_webstate.h1
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios_webstate.mm4
-rw-r--r--chromium/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.h4
-rw-r--r--chromium/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.mm4
-rw-r--r--chromium/components/autofill/ios/form_util/form_activity_tab_helper.mm2
-rw-r--r--chromium/components/autofill/ios/form_util/resources/form_handlers.js12
243 files changed, 9243 insertions, 4088 deletions
diff --git a/chromium/components/autofill/OWNERS b/chromium/components/autofill/OWNERS
index 04b0d2f9b7b..f1fa6a5c923 100644
--- a/chromium/components/autofill/OWNERS
+++ b/chromium/components/autofill/OWNERS
@@ -4,6 +4,5 @@ ftirelo@chromium.org
mahmadi@chromium.org
rogerm@chromium.org
sebsg@chromium.org
-vabr@chromium.org
# COMPONENT: UI>Browser>Autofill
diff --git a/chromium/components/autofill/android/autofill_provider_android.cc b/chromium/components/autofill/android/autofill_provider_android.cc
index a930d663e0e..a08b4a3688f 100644
--- a/chromium/components/autofill/android/autofill_provider_android.cc
+++ b/chromium/components/autofill/android/autofill_provider_android.cc
@@ -174,8 +174,7 @@ void AutofillProviderAndroid::FireSuccessfulSubmission(
void AutofillProviderAndroid::OnFormSubmitted(AutofillHandlerProxy* handler,
const FormData& form,
bool known_success,
- SubmissionSource source,
- base::TimeTicks timestamp) {
+ SubmissionSource source) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!IsCurrentlyLinkedHandler(handler) || !IsCurrentlyLinkedForm(form))
return;
diff --git a/chromium/components/autofill/android/autofill_provider_android.h b/chromium/components/autofill/android/autofill_provider_android.h
index 0cc29ac8c5a..457be941ebc 100644
--- a/chromium/components/autofill/android/autofill_provider_android.h
+++ b/chromium/components/autofill/android/autofill_provider_android.h
@@ -49,8 +49,7 @@ class AutofillProviderAndroid : public AutofillProvider {
void OnFormSubmitted(AutofillHandlerProxy* handler,
const FormData& form,
bool known_success,
- SubmissionSource source,
- base::TimeTicks timestamp) override;
+ SubmissionSource source) override;
void OnFocusNoLongerOnForm(AutofillHandlerProxy* handler) override;
void OnFocusOnFormField(AutofillHandlerProxy* handler,
const FormData& form,
diff --git a/chromium/components/autofill/android/java/res/layout/autofill_dropdown_footer_item_refresh.xml b/chromium/components/autofill/android/java/res/layout/autofill_dropdown_footer_item_refresh.xml
index b97c548e22d..c36837ee342 100644
--- a/chromium/components/autofill/android/java/res/layout/autofill_dropdown_footer_item_refresh.xml
+++ b/chromium/components/autofill/android/java/res/layout/autofill_dropdown_footer_item_refresh.xml
@@ -26,7 +26,7 @@
android:includeFontPadding="false"
android:singleLine="true"
android:textAlignment="viewStart"
- android:textAppearance="@style/BlackHint2" />
+ android:textAppearance="@style/TextAppearance.BlackHint2" />
<ImageView
android:id="@+id/dropdown_icon"
diff --git a/chromium/components/autofill/android/java/res/layout/autofill_dropdown_item.xml b/chromium/components/autofill/android/java/res/layout/autofill_dropdown_item.xml
index 93512e2012a..5b0c93116dd 100644
--- a/chromium/components/autofill/android/java/res/layout/autofill_dropdown_item.xml
+++ b/chromium/components/autofill/android/java/res/layout/autofill_dropdown_item.xml
@@ -39,7 +39,7 @@
android:includeFontPadding="false"
android:singleLine="true"
android:textAlignment="viewStart"
- android:textAppearance="@style/BlackTitle1" />
+ android:textAppearance="@style/TextAppearance.BlackTitle1" />
<TextView
android:id="@+id/dropdown_sublabel"
@@ -51,7 +51,7 @@
android:includeFontPadding="false"
android:singleLine="true"
android:textAlignment="viewStart"
- android:textAppearance="@style/BlackCaption" />
+ android:textAppearance="@style/TextAppearance.BlackCaption" />
</LinearLayout>
<ImageView
diff --git a/chromium/components/autofill/android/java/res/layout/autofill_dropdown_item_refresh.xml b/chromium/components/autofill/android/java/res/layout/autofill_dropdown_item_refresh.xml
index 3760277d326..0c77e09b4b6 100644
--- a/chromium/components/autofill/android/java/res/layout/autofill_dropdown_item_refresh.xml
+++ b/chromium/components/autofill/android/java/res/layout/autofill_dropdown_item_refresh.xml
@@ -34,7 +34,7 @@
android:ellipsize="end"
android:includeFontPadding="false"
android:singleLine="true"
- android:textAppearance="@style/BlackBodyDefault" />
+ android:textAppearance="@style/TextAppearance.BlackBodyDefault" />
<TextView
android:id="@+id/dropdown_sublabel"
@@ -44,7 +44,7 @@
android:includeFontPadding="false"
android:singleLine="true"
android:textAlignment="viewStart"
- android:textAppearance="@style/BlackCaption" />
+ android:textAppearance="@style/TextAppearance.BlackCaption" />
</LinearLayout>
<ImageView
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver.cc b/chromium/components/autofill/content/browser/content_autofill_driver.cc
index 7bde728205a..48bc282528a 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver.cc
@@ -182,19 +182,6 @@ gfx::RectF ContentAutofillDriver::TransformBoundingBoxToViewportCoordinates(
bounding_box.width(), bounding_box.height());
}
-void ContentAutofillDriver::DidInteractWithCreditCardForm() {
- // If there is an autofill manager, notify its client about credit card
- // inputs on non-secure pages.
- if (!autofill_manager_)
- return;
- if (content::IsOriginSecure(
- content::WebContents::FromRenderFrameHost(render_frame_host_)
- ->GetVisibleURL())) {
- return;
- }
- autofill_manager_->client()->DidInteractWithNonsecureCreditCardInput();
-}
-
void ContentAutofillDriver::FormsSeen(const std::vector<FormData>& forms,
base::TimeTicks timestamp) {
autofill_handler_->OnFormsSeen(forms, timestamp);
@@ -202,9 +189,8 @@ void ContentAutofillDriver::FormsSeen(const std::vector<FormData>& forms,
void ContentAutofillDriver::FormSubmitted(const FormData& form,
bool known_success,
- SubmissionSource source,
- base::TimeTicks timestamp) {
- autofill_handler_->OnFormSubmitted(form, known_success, source, timestamp);
+ SubmissionSource source) {
+ autofill_handler_->OnFormSubmitted(form, known_success, source);
}
void ContentAutofillDriver::TextFieldDidChange(const FormData& form,
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver.h b/chromium/components/autofill/content/browser/content_autofill_driver.h
index 4668b0313df..bb605784fbb 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver.h
+++ b/chromium/components/autofill/content/browser/content_autofill_driver.h
@@ -71,15 +71,13 @@ class ContentAutofillDriver : public AutofillDriver,
void PopupHidden() override;
gfx::RectF TransformBoundingBoxToViewportCoordinates(
const gfx::RectF& bounding_box) override;
- void DidInteractWithCreditCardForm() override;
// mojom::AutofillDriver:
void FormsSeen(const std::vector<FormData>& forms,
base::TimeTicks timestamp) override;
void FormSubmitted(const FormData& form,
bool known_success,
- SubmissionSource source,
- base::TimeTicks timestamp) override;
+ SubmissionSource source) override;
void TextFieldDidChange(const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box,
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 6825bcf6749..6c85d18ee0e 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver_factory.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver_factory.cc
@@ -57,8 +57,8 @@ void ContentAutofillDriverFactory::CreateForWebContentsAndDelegate(
if (FromWebContents(contents))
return;
- auto new_factory = base::WrapUnique(new ContentAutofillDriverFactory(
- contents, client, app_locale, enable_download_manager, provider));
+ 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) {
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 2ff9b3352ab..3d503f477c4 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver_factory.h
+++ b/chromium/components/autofill/content/browser/content_autofill_driver_factory.h
@@ -28,6 +28,13 @@ class ContentAutofillDriverFactory : public AutofillDriverFactory,
public content::WebContentsObserver,
public base::SupportsUserData::Data {
public:
+ ContentAutofillDriverFactory(
+ content::WebContents* web_contents,
+ AutofillClient* client,
+ const std::string& app_locale,
+ AutofillManager::AutofillDownloadManagerState enable_download_manager,
+ AutofillProvider* provider);
+
~ContentAutofillDriverFactory() override;
static void CreateForWebContentsAndDelegate(
@@ -63,13 +70,6 @@ class ContentAutofillDriverFactory : public AutofillDriverFactory,
static const char kContentAutofillDriverFactoryWebContentsUserDataKey[];
private:
- ContentAutofillDriverFactory(
- content::WebContents* web_contents,
- AutofillClient* client,
- const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager,
- AutofillProvider* provider);
-
std::string app_locale_;
AutofillManager::AutofillDownloadManagerState enable_download_manager_;
AutofillProvider* provider_;
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 fd830d0ebf5..1a08f64bb43 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc
@@ -21,12 +21,11 @@
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/form_data_predictions.h"
#include "content/public/browser/browser_context.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/frame_navigate_params.h"
+#include "content/public/test/mock_navigation_handle.h"
#include "content/public/test/test_renderer_host.h"
#include "mojo/public/cpp/bindings/associated_binding_set.h"
#include "net/base/net_errors.h"
@@ -252,7 +251,6 @@ class MockAutofillManager : public AutofillManager {
class MockAutofillClient : public TestAutofillClient {
public:
MOCK_METHOD0(OnFirstUserGestureObserved, void());
- MOCK_METHOD0(DidInteractWithNonsecureCreditCardInput, void());
};
class TestContentAutofillDriver : public ContentAutofillDriver {
@@ -305,10 +303,10 @@ class ContentAutofillDriverTest : public content::RenderViewHostTestHarness {
}
void Navigate(bool same_document) {
- std::unique_ptr<content::NavigationHandle> navigation_handle =
- content::NavigationHandle::CreateNavigationHandleForTesting(
- GURL(), main_rfh(), /*committed=*/true, net::OK, same_document);
- driver_->DidNavigateMainFrame(navigation_handle.get());
+ content::MockNavigationHandle navigation_handle(GURL(), main_rfh());
+ navigation_handle.set_has_committed(true);
+ navigation_handle.set_is_same_document(same_document);
+ driver_->DidNavigateMainFrame(&navigation_handle);
}
protected:
@@ -458,36 +456,4 @@ TEST_F(ContentAutofillDriverTest, PreviewFieldWithValue) {
EXPECT_EQ(input_value, output_value);
}
-// Tests that credit card form interactions trigger a call to the client's
-// |DidInteractWithNonsecureCreditCardInput| function if the page is HTTP.
-TEST_F(ContentAutofillDriverTest, CreditCardFormInteraction) {
- GURL url("http://example.test");
- NavigateAndCommit(url);
- content::NavigationEntry* entry =
- web_contents()->GetController().GetVisibleEntry();
- ASSERT_TRUE(entry);
- EXPECT_EQ(url, entry->GetURL());
-
- EXPECT_CALL(*test_autofill_client_,
- DidInteractWithNonsecureCreditCardInput());
- driver_->DidInteractWithCreditCardForm();
-}
-
-// Tests that credit card form interactions do NOT trigger a call to the
-// client's |DidInteractWithNonsecureCreditCardInput| function if the page
-// is HTTPS.
-TEST_F(ContentAutofillDriverTest, CreditCardFormInteractionOnHTTPS) {
- EXPECT_CALL(*test_autofill_client_, DidInteractWithNonsecureCreditCardInput())
- .Times(0);
-
- GURL url("https://example.test");
- NavigateAndCommit(url);
- content::NavigationEntry* entry =
- web_contents()->GetController().GetVisibleEntry();
- ASSERT_TRUE(entry);
- EXPECT_EQ(url, entry->GetURL());
-
- driver_->DidInteractWithCreditCardForm();
-}
-
} // namespace autofill
diff --git a/chromium/components/autofill/content/common/BUILD.gn b/chromium/components/autofill/content/common/BUILD.gn
index 04379f467a7..3fb742d14b8 100644
--- a/chromium/components/autofill/content/common/BUILD.gn
+++ b/chromium/components/autofill/content/common/BUILD.gn
@@ -53,6 +53,7 @@ source_set("unit_tests") {
deps = [
"//base",
+ "//base/test:test_support",
"//components/autofill/core/browser:test_support",
"//components/password_manager/core/common",
"//mojo/public/cpp/bindings",
diff --git a/chromium/components/autofill/content/common/autofill_agent.mojom b/chromium/components/autofill/content/common/autofill_agent.mojom
index 34995958f01..6138f4bf336 100644
--- a/chromium/components/autofill/content/common/autofill_agent.mojom
+++ b/chromium/components/autofill/content/common/autofill_agent.mojom
@@ -107,9 +107,9 @@ interface PasswordGenerationAgent {
GeneratedPasswordAccepted(mojo_base.mojom.String16 generated_password);
// Tells the renderer to find a focused element, and if it is a password field
- // eligible for generation then to trigger generation by responding to the
- // browser with the message |ShowPasswordGenerationPopup|.
- UserTriggeredGeneratePassword();
+ // eligible for generation then to trigger generation by returning
+ // non-empty PasswordGenerationUIData.
+ UserTriggeredGeneratePassword() => (PasswordGenerationUIData? data);
// Tells the renderer that this password form is not blacklisted. A form can
// be blacklisted if a user chooses "never save passwords for this site".
@@ -117,5 +117,11 @@ interface PasswordGenerationAgent {
// Sent when Autofill manager gets the query response from the Autofill server
// and there are fields classified for password generation in the response.
+ // TODO(https://crbug.com/866444): Remove this when PasswordGenerationAgent
+ // refactoring is finished.
FoundFormsEligibleForGeneration(array<PasswordFormGenerationData> forms);
+
+ // Tells the renderer that a password can be generated on the fields
+ // identified by |form|.
+ FoundFormEligibleForGeneration(NewPasswordFormGenerationData form);
};
diff --git a/chromium/components/autofill/content/common/autofill_driver.mojom b/chromium/components/autofill/content/common/autofill_driver.mojom
index 34068b109cc..1235cd0b238 100644
--- a/chromium/components/autofill/content/common/autofill_driver.mojom
+++ b/chromium/components/autofill/content/common/autofill_driver.mojom
@@ -23,8 +23,7 @@ interface AutofillDriver {
// succeeds if the form is removed.
FormSubmitted(FormData form,
bool known_success,
- SubmissionSource source,
- mojo_base.mojom.TimeTicks timestamp);
+ SubmissionSource source);
// Notification that a form field's value has changed.
TextFieldDidChange(FormData form,
@@ -80,7 +79,7 @@ interface AutofillDriver {
// There is one instance of this interface per web contents in the browser
// process that handles all the frames. The motivation was to make the interface
-// associated with PasswordManagerClient.
+// associated with PasswordGenerationDriver.
interface PasswordManagerDriver {
// Notification that password forms have been seen that are candidates for
// filling/submitting by the password manager.
@@ -131,11 +130,18 @@ interface PasswordManagerDriver {
// The focus changed to a different input in the same frame (e.g. tabbed from
// email to password field).
FocusedInputChanged(bool is_fillable, bool is_password_field);
+
+ // Sends the success state of filling credentials into a form. This happens
+ // only if the form being filled has a renderer_id. |result| is an
+ // integer serialization of autofill::FillingResult. It is passed as an
+ // integer as no further interpretation of the value is necessary in the
+ // browser.
+ LogFirstFillingResult(uint32 form_renderer_id, int32 result);
};
// There is one instance of this interface per web contents in the browser
// process.
-interface PasswordManagerClient {
+interface PasswordGenerationDriver {
// Instructs the browser that generation is available for this particular
// form. This is used for UMA stats.
GenerationAvailableForForm(PasswordForm password_form);
@@ -145,14 +151,6 @@ interface PasswordManagerClient {
AutomaticGenerationStatusChanged(
bool available, PasswordGenerationUIData? password_generation_ui_data);
- // Instructs the browser to show the password generation popup for manual
- // generation and provides the data necessary to display it.
- // TODO(crbug.com/845458): Replace this with a method called from the browser
- // when user triggers generation manually which returns a boolean signaling
- // whether the state for generation could be saved or not.
- ShowManualPasswordGenerationPopup(
- PasswordGenerationUIData password_generation_ui_data);
-
// Instructs the browser to show the popup for editing a generated password.
// The location should be specified in the renderers coordinate system. Form
// is the form associated with the password field.
diff --git a/chromium/components/autofill/content/common/autofill_types.mojom b/chromium/components/autofill/content/common/autofill_types.mojom
index 8e62015abef..2428dd1e4ea 100644
--- a/chromium/components/autofill/content/common/autofill_types.mojom
+++ b/chromium/components/autofill/content/common/autofill_types.mojom
@@ -102,6 +102,18 @@ enum FillingStatus {
ERROR_NOT_ALLOWED,
};
+// autofill::ButtonTitleType
+enum ButtonTitleType {
+ NONE,
+ BUTTON_ELEMENT_SUBMIT_TYPE,
+ BUTTON_ELEMENT_BUTTON_TYPE,
+ INPUT_ELEMENT_SUBMIT_TYPE,
+ INPUT_ELEMENT_BUTTON_TYPE,
+ HYPERLINK,
+ DIV,
+ SPAN
+};
+
// autofill::FormFieldData
struct FormFieldData {
mojo_base.mojom.String16 label;
@@ -136,12 +148,17 @@ struct FormFieldData {
LabelSource label_source;
};
+struct ButtonTitleInfo {
+ mojo_base.mojom.String16 title;
+ ButtonTitleType type;
+};
+
// autofill::FormData
struct FormData {
mojo_base.mojom.String16 id_attribute;
mojo_base.mojom.String16 name_attribute;
mojo_base.mojom.String16 name;
- mojo_base.mojom.String16 button_title;
+ array<ButtonTitleInfo> button_titles;
// TODO(crbug.com/788181): Either change type to Origin or rename to URL.
url.mojom.Url origin;
url.mojom.Url action;
@@ -200,6 +217,12 @@ struct PasswordFormGenerationData {
uint32 confirmation_field_signature;
};
+// autofill::NewPasswordFormGenerationData
+struct NewPasswordFormGenerationData {
+ uint32 new_password_renderer_id;
+ uint32 confirmation_password_renderer_id;
+};
+
// autofill::password_generation::PasswordGenerationUIData
struct PasswordGenerationUIData {
gfx.mojom.RectF bounds;
@@ -251,7 +274,7 @@ struct PasswordForm {
bool is_public_suffix_match;
bool is_affiliation_based_match;
SubmissionIndicatorEvent submission_event;
- bool only_for_fallback_saving;
+ bool only_for_fallback;
bool is_gaia_with_skip_save_password_form;
};
diff --git a/chromium/components/autofill/content/common/autofill_types.typemap b/chromium/components/autofill/content/common/autofill_types.typemap
index 8aab6a3bdcc..90333460722 100644
--- a/chromium/components/autofill/content/common/autofill_types.typemap
+++ b/chromium/components/autofill/content/common/autofill_types.typemap
@@ -37,6 +37,7 @@ type_mappings = [
"autofill.mojom.FormFieldDataPredictions=autofill::FormFieldDataPredictions",
"autofill.mojom.FormsPredictionsMap=autofill::FormsPredictionsMap",
"autofill.mojom.GenerationUploadStatus=autofill::PasswordForm::GenerationUploadStatus",
+ "autofill.mojom.NewPasswordFormGenerationData=autofill::NewPasswordFormGenerationData",
"autofill.mojom.PasswordAndRealm=autofill::PasswordAndRealm",
"autofill.mojom.PasswordForm=autofill::PasswordForm",
"autofill.mojom.PasswordFormFieldPredictionMap=autofill::PasswordFormFieldPredictionMap",
diff --git a/chromium/components/autofill/content/common/autofill_types_struct_traits.cc b/chromium/components/autofill/content/common/autofill_types_struct_traits.cc
index 5f762c736be..bd2c31e1f01 100644
--- a/chromium/components/autofill/content/common/autofill_types_struct_traits.cc
+++ b/chromium/components/autofill/content/common/autofill_types_struct_traits.cc
@@ -527,6 +527,66 @@ bool EnumTraits<autofill::mojom::FillingStatus, autofill::FillingStatus>::
}
// static
+autofill::mojom::ButtonTitleType EnumTraits<
+ autofill::mojom::ButtonTitleType,
+ autofill::ButtonTitleType>::ToMojom(autofill::ButtonTitleType input) {
+ switch (input) {
+ case autofill::ButtonTitleType::NONE:
+ return autofill::mojom::ButtonTitleType::NONE;
+ case autofill::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE:
+ return autofill::mojom::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE;
+ case autofill::ButtonTitleType::BUTTON_ELEMENT_BUTTON_TYPE:
+ return autofill::mojom::ButtonTitleType::BUTTON_ELEMENT_BUTTON_TYPE;
+ case autofill::ButtonTitleType::INPUT_ELEMENT_SUBMIT_TYPE:
+ return autofill::mojom::ButtonTitleType::INPUT_ELEMENT_SUBMIT_TYPE;
+ case autofill::ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE:
+ return autofill::mojom::ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE;
+ case autofill::ButtonTitleType::HYPERLINK:
+ return autofill::mojom::ButtonTitleType::HYPERLINK;
+ case autofill::ButtonTitleType::DIV:
+ return autofill::mojom::ButtonTitleType::DIV;
+ case autofill::ButtonTitleType::SPAN:
+ return autofill::mojom::ButtonTitleType::SPAN;
+ }
+ NOTREACHED();
+ return autofill::mojom::ButtonTitleType::NONE;
+}
+
+// static
+bool EnumTraits<autofill::mojom::ButtonTitleType, autofill::ButtonTitleType>::
+ FromMojom(autofill::mojom::ButtonTitleType input,
+ autofill::ButtonTitleType* output) {
+ switch (input) {
+ case autofill::mojom::ButtonTitleType::NONE:
+ *output = autofill::ButtonTitleType::NONE;
+ return true;
+ case autofill::mojom::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE:
+ *output = autofill::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE;
+ return true;
+ case autofill::mojom::ButtonTitleType::BUTTON_ELEMENT_BUTTON_TYPE:
+ *output = autofill::ButtonTitleType::BUTTON_ELEMENT_BUTTON_TYPE;
+ return true;
+ case autofill::mojom::ButtonTitleType::INPUT_ELEMENT_SUBMIT_TYPE:
+ *output = autofill::ButtonTitleType::INPUT_ELEMENT_SUBMIT_TYPE;
+ return true;
+ case autofill::mojom::ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE:
+ *output = autofill::ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE;
+ return true;
+ case autofill::mojom::ButtonTitleType::HYPERLINK:
+ *output = autofill::ButtonTitleType::HYPERLINK;
+ return true;
+ case autofill::mojom::ButtonTitleType::DIV:
+ *output = autofill::ButtonTitleType::DIV;
+ return true;
+ case autofill::mojom::ButtonTitleType::SPAN:
+ *output = autofill::ButtonTitleType::SPAN;
+ return true;
+ }
+ NOTREACHED();
+ return false;
+}
+
+// static
bool StructTraits<
autofill::mojom::FormFieldDataDataView,
autofill::FormFieldData>::Read(autofill::mojom::FormFieldDataDataView data,
@@ -581,7 +641,7 @@ bool StructTraits<
out->is_enabled = data.is_enabled();
out->is_readonly = data.is_readonly();
- if (!data.ReadValue(&out->typed_value))
+ if (!data.ReadTypedValue(&out->typed_value))
return false;
if (!data.ReadOptionValues(&out->option_values))
@@ -596,6 +656,14 @@ bool StructTraits<
}
// static
+bool StructTraits<autofill::mojom::ButtonTitleInfoDataView,
+ autofill::ButtonTitleInfo>::
+ Read(autofill::mojom::ButtonTitleInfoDataView data,
+ autofill::ButtonTitleInfo* out) {
+ return data.ReadTitle(&out->first) && data.ReadType(&out->second);
+}
+
+// static
bool StructTraits<autofill::mojom::FormDataDataView, autofill::FormData>::Read(
autofill::mojom::FormDataDataView data,
autofill::FormData* out) {
@@ -605,7 +673,7 @@ bool StructTraits<autofill::mojom::FormDataDataView, autofill::FormData>::Read(
return false;
if (!data.ReadName(&out->name))
return false;
- if (!data.ReadButtonTitle(&out->button_title))
+ if (!data.ReadButtonTitles(&out->button_titles))
return false;
if (!data.ReadOrigin(&out->origin))
return false;
@@ -719,6 +787,17 @@ bool StructTraits<autofill::mojom::PasswordFormGenerationDataDataView,
}
// static
+bool StructTraits<autofill::mojom::NewPasswordFormGenerationDataDataView,
+ autofill::NewPasswordFormGenerationData>::
+ Read(autofill::mojom::NewPasswordFormGenerationDataDataView data,
+ autofill::NewPasswordFormGenerationData* out) {
+ out->new_password_renderer_id = data.new_password_renderer_id();
+ out->confirmation_password_renderer_id =
+ data.confirmation_password_renderer_id();
+ return true;
+}
+
+// static
bool StructTraits<autofill::mojom::PasswordGenerationUIDataDataView,
autofill::password_generation::PasswordGenerationUIData>::
Read(autofill::mojom::PasswordGenerationUIDataDataView data,
@@ -798,7 +877,7 @@ bool StructTraits<
data.was_parsed_using_autofill_predictions();
out->is_public_suffix_match = data.is_public_suffix_match();
out->is_affiliation_based_match = data.is_affiliation_based_match();
- out->only_for_fallback_saving = data.only_for_fallback_saving();
+ out->only_for_fallback = data.only_for_fallback();
out->is_gaia_with_skip_save_password_form =
data.is_gaia_with_skip_save_password_form();
diff --git a/chromium/components/autofill/content/common/autofill_types_struct_traits.h b/chromium/components/autofill/content/common/autofill_types_struct_traits.h
index 97c683e443a..957bc222b97 100644
--- a/chromium/components/autofill/content/common/autofill_types_struct_traits.h
+++ b/chromium/components/autofill/content/common/autofill_types_struct_traits.h
@@ -119,6 +119,14 @@ struct EnumTraits<autofill::mojom::FillingStatus, autofill::FillingStatus> {
};
template <>
+struct EnumTraits<autofill::mojom::ButtonTitleType, autofill::ButtonTitleType> {
+ static autofill::mojom::ButtonTitleType ToMojom(
+ autofill::ButtonTitleType input);
+ static bool FromMojom(autofill::mojom::ButtonTitleType input,
+ autofill::ButtonTitleType* output);
+};
+
+template <>
struct StructTraits<autofill::mojom::FormFieldDataDataView,
autofill::FormFieldData> {
static const base::string16& label(const autofill::FormFieldData& r) {
@@ -244,6 +252,22 @@ struct StructTraits<autofill::mojom::FormFieldDataDataView,
};
template <>
+struct StructTraits<autofill::mojom::ButtonTitleInfoDataView,
+ autofill::ButtonTitleInfo> {
+ static const base::string16& title(const autofill::ButtonTitleInfo& r) {
+ return r.first;
+ }
+
+ static const autofill::ButtonTitleType& type(
+ const autofill::ButtonTitleInfo& r) {
+ return r.second;
+ }
+
+ static bool Read(autofill::mojom::ButtonTitleInfoDataView data,
+ autofill::ButtonTitleInfo* out);
+};
+
+template <>
struct StructTraits<autofill::mojom::FormDataDataView, autofill::FormData> {
static const base::string16& id_attribute(const autofill::FormData& r) {
return r.id_attribute;
@@ -257,8 +281,9 @@ struct StructTraits<autofill::mojom::FormDataDataView, autofill::FormData> {
return r.name;
}
- static const base::string16& button_title(const autofill::FormData& r) {
- return r.button_title;
+ static const autofill::ButtonTitleList& button_titles(
+ const autofill::FormData& r) {
+ return r.button_titles;
}
static const GURL& origin(const autofill::FormData& r) { return r.origin; }
@@ -456,6 +481,23 @@ struct StructTraits<autofill::mojom::PasswordFormGenerationDataDataView,
};
template <>
+struct StructTraits<autofill::mojom::NewPasswordFormGenerationDataDataView,
+ autofill::NewPasswordFormGenerationData> {
+ static uint32_t new_password_renderer_id(
+ const autofill::NewPasswordFormGenerationData& r) {
+ return r.new_password_renderer_id;
+ }
+
+ static uint32_t confirmation_password_renderer_id(
+ const autofill::NewPasswordFormGenerationData& r) {
+ return r.confirmation_password_renderer_id;
+ }
+
+ static bool Read(autofill::mojom::NewPasswordFormGenerationDataDataView data,
+ autofill::NewPasswordFormGenerationData* out);
+};
+
+template <>
struct StructTraits<autofill::mojom::PasswordGenerationUIDataDataView,
autofill::password_generation::PasswordGenerationUIData> {
static const gfx::RectF& bounds(
@@ -637,8 +679,8 @@ struct StructTraits<autofill::mojom::PasswordFormDataView,
return r.submission_event;
}
- static bool only_for_fallback_saving(const autofill::PasswordForm& r) {
- return r.only_for_fallback_saving;
+ static bool only_for_fallback(const autofill::PasswordForm& r) {
+ return r.only_for_fallback;
}
static bool is_gaia_with_skip_save_password_form(
diff --git a/chromium/components/autofill/content/common/autofill_types_struct_traits_unittest.cc b/chromium/components/autofill/content/common/autofill_types_struct_traits_unittest.cc
index df9c8152d49..2d2534c264f 100644
--- a/chromium/components/autofill/content/common/autofill_types_struct_traits_unittest.cc
+++ b/chromium/components/autofill/content/common/autofill_types_struct_traits_unittest.cc
@@ -4,11 +4,12 @@
#include <utility>
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_task_environment.h"
#include "components/autofill/content/common/test_autofill_types.mojom.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/common/button_title_type.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/password_generation_util.h"
@@ -244,6 +245,12 @@ class AutofillTypeTraitsTestImpl : public testing::Test,
std::move(callback).Run(s);
}
+ void PassNewPasswordFormGenerationData(
+ const NewPasswordFormGenerationData& s,
+ PassNewPasswordFormGenerationDataCallback callback) override {
+ std::move(callback).Run(s);
+ }
+
void PassPasswordGenerationUIData(
const password_generation::PasswordGenerationUIData& s,
PassPasswordGenerationUIDataCallback callback) override {
@@ -262,7 +269,7 @@ class AutofillTypeTraitsTestImpl : public testing::Test,
}
private:
- base::MessageLoop loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
mojo::BindingSet<TypeTraitsTest> bindings_;
};
@@ -271,6 +278,8 @@ void ExpectFormFieldData(const FormFieldData& expected,
const base::Closure& closure,
const FormFieldData& passed) {
EXPECT_EQ(expected, passed);
+ EXPECT_EQ(expected.value, passed.value);
+ EXPECT_EQ(expected.typed_value, passed.typed_value);
closure.Run();
}
@@ -310,6 +319,16 @@ void ExpectPasswordFormGenerationData(
closure.Run();
}
+void ExpectNewPasswordFormGenerationData(
+ const NewPasswordFormGenerationData& expected,
+ const base::Closure& closure,
+ const NewPasswordFormGenerationData& passed) {
+ EXPECT_EQ(expected.new_password_renderer_id, passed.new_password_renderer_id);
+ EXPECT_EQ(expected.confirmation_password_renderer_id,
+ passed.confirmation_password_renderer_id);
+ closure.Run();
+}
+
void ExpectPasswordGenerationUIData(
const password_generation::PasswordGenerationUIData& expected,
base::OnceClosure closure,
@@ -351,6 +370,7 @@ TEST_F(AutofillTypeTraitsTestImpl, PassFormFieldData) {
input.role = FormFieldData::ROLE_ATTRIBUTE_PRESENTATION;
input.text_direction = base::i18n::RIGHT_TO_LEFT;
input.properties_mask = FieldPropertiesFlags::HAD_FOCUS;
+ input.typed_value = base::ASCIIToUTF16("TestTypedValue");
base::RunLoop loop;
mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
@@ -363,6 +383,9 @@ TEST_F(AutofillTypeTraitsTestImpl, PassFormData) {
FormData input;
test::CreateTestAddressFormData(&input);
input.username_predictions = {1, 13, 2};
+ input.button_titles.push_back(
+ std::make_pair(base::ASCIIToUTF16("Sign-up"),
+ autofill::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE));
base::RunLoop loop;
mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
@@ -433,6 +456,19 @@ TEST_F(AutofillTypeTraitsTestImpl, PassPasswordFormGenerationData) {
loop.Run();
}
+TEST_F(AutofillTypeTraitsTestImpl, NewPasswordFormGenerationData) {
+ NewPasswordFormGenerationData input = {
+ .new_password_renderer_id = 1234u,
+ .confirmation_password_renderer_id = 5789u};
+
+ base::RunLoop loop;
+ mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
+ proxy->PassNewPasswordFormGenerationData(
+ input, base::BindOnce(&ExpectNewPasswordFormGenerationData, input,
+ loop.QuitClosure()));
+ loop.Run();
+}
+
TEST_F(AutofillTypeTraitsTestImpl, PassPasswordGenerationUIData) {
password_generation::PasswordGenerationUIData input;
CreatePasswordGenerationUIData(&input);
diff --git a/chromium/components/autofill/content/common/test_autofill_types.mojom b/chromium/components/autofill/content/common/test_autofill_types.mojom
index a0a0234d217..c24e36bcc7e 100644
--- a/chromium/components/autofill/content/common/test_autofill_types.mojom
+++ b/chromium/components/autofill/content/common/test_autofill_types.mojom
@@ -15,5 +15,6 @@ interface TypeTraitsTest {
PassPasswordFormFillData(PasswordFormFillData s) => (PasswordFormFillData passed);
PassFormsPredictionsMap(FormsPredictionsMap s) => (FormsPredictionsMap passed);
PassPasswordFormGenerationData(PasswordFormGenerationData s) => (PasswordFormGenerationData passed);
+ PassNewPasswordFormGenerationData(NewPasswordFormGenerationData s) => (NewPasswordFormGenerationData passed);
PassPasswordGenerationUIData(PasswordGenerationUIData s) => (PasswordGenerationUIData passed);
};
diff --git a/chromium/components/autofill/content/renderer/BUILD.gn b/chromium/components/autofill/content/renderer/BUILD.gn
index f0b3b85b830..6849329db91 100644
--- a/chromium/components/autofill/content/renderer/BUILD.gn
+++ b/chromium/components/autofill/content/renderer/BUILD.gn
@@ -30,6 +30,8 @@ jumbo_static_library("renderer") {
"password_form_conversion_utils.h",
"password_generation_agent.cc",
"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",
@@ -92,6 +94,7 @@ source_set("unit_tests") {
testonly = true
sources = [
"form_cache_unittest.cc",
+ "prefilled_values_detector_unittest.cc",
"renderer_save_password_progress_logger_unittest.cc",
]
diff --git a/chromium/components/autofill/content/renderer/OWNERS b/chromium/components/autofill/content/renderer/OWNERS
index d1737e7f0e1..15f8279c885 100644
--- a/chromium/components/autofill/content/renderer/OWNERS
+++ b/chromium/components/autofill/content/renderer/OWNERS
@@ -1,9 +1,7 @@
per-file *password*=dvadym@chromium.org
per-file *password*=kolos@chromium.org
-per-file *password*=vabr@chromium.org
per-file *password*=vasilii@chromium.org
per-file *username*=dvadym@chromium.org
per-file *username*=kolos@chromium.org
-per-file *username*=vabr@chromium.org
per-file *username*=vasilii@chromium.org
diff --git a/chromium/components/autofill/content/renderer/autofill_agent.cc b/chromium/components/autofill/content/renderer/autofill_agent.cc
index f5bed4ccbc6..1e4ee613d2a 100644
--- a/chromium/components/autofill/content/renderer/autofill_agent.cc
+++ b/chromium/components/autofill/content/renderer/autofill_agent.cc
@@ -87,12 +87,6 @@ namespace {
// upon, instead of multiple in close succession (debounce time).
size_t kWaitTimeForSelectOptionsChangesMs = 50;
-// Whether the "single click" autofill feature is enabled, through command-line
-// or field trial.
-bool IsSingleClickEnabled() {
- return base::FeatureList::IsEnabled(features::kSingleClickAutofill);
-}
-
// Gets all the data list values (with corresponding label) for the given
// element.
void GetDataListSuggestions(const WebInputElement& element,
@@ -301,8 +295,7 @@ void AutofillAgent::FireHostSubmitEvents(const FormData& form_data,
if (!submitted_forms_.insert(form_data).second)
return;
- GetAutofillDriver()->FormSubmitted(form_data, known_success, source,
- base::TimeTicks::Now());
+ GetAutofillDriver()->FormSubmitted(form_data, known_success, source);
}
void AutofillAgent::Shutdown() {
@@ -660,7 +653,14 @@ void AutofillAgent::ShowSuggestions(const WebFormControlElement& element,
// Password field elements should only have suggestions shown by the password
// autofill agent.
- if (input_element && input_element->IsPasswordFieldForAutofill() &&
+ // The /*disable presubmit*/ comment below is used to disable a presubmit
+ // script that ensures that only IsPasswordFieldForAutofill() is used in this
+ // code (it has to appear between the function name and the parentesis to not
+ // match a regex). In this specific case we are actually interested in whether
+ // the field is currently a password field, not whether it has ever been a
+ // password field.
+ if (input_element &&
+ input_element->IsPasswordField /*disable presubmit*/ () &&
!query_password_suggestion_) {
return;
}
@@ -926,10 +926,6 @@ void AutofillAgent::FormControlElementClicked(
// Show full suggestions when clicking on an already-focused form field.
options.show_full_suggestion_list = element.IsAutofilled() || was_focused;
- if (!IsSingleClickEnabled()) {
- // On the initial click (not focused yet), only show password suggestions.
- options.show_password_suggestions_only = !was_focused;
- }
ShowSuggestions(element, options);
}
diff --git a/chromium/components/autofill/content/renderer/form_autofill_util.cc b/chromium/components/autofill/content/renderer/form_autofill_util.cc
index ee74da2318f..c446763ff7a 100644
--- a/chromium/components/autofill/content/renderer/form_autofill_util.cc
+++ b/chromium/components/autofill/content/renderer/form_autofill_util.cc
@@ -9,6 +9,7 @@
#include <map>
#include <memory>
#include <set>
+#include <string>
#include <utility>
#include <vector>
@@ -29,6 +30,7 @@
#include "components/autofill/core/common/autofill_regexes.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/autofill_util.h"
+#include "components/autofill/core/common/button_title_type.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
#include "third_party/blink/public/platform/url_conversion.h"
@@ -69,6 +71,18 @@ const size_t kMaxParseableFields = 200;
namespace {
+// Maximal length of a button's title.
+const int kMaxLengthForSingleButtonTitle = 30;
+// Maximal length of all button titles.
+const int kMaxLengthForAllButtonTitles = 200;
+
+// Text features to detect form submission buttons. Features are selected based
+// on analysis of real forms and their buttons.
+// TODO(crbug.com/910546): Consider to add more features (e.g. non-English
+// features).
+const char* const kButtonFeatures[] = {"button", "btn", "submit",
+ "boton" /* "button" in Spanish */};
+
// A bit field mask for FillForm functions to not fill some fields.
enum FieldFilterMask {
FILTER_NONE = 0,
@@ -118,7 +132,8 @@ bool IsElementInControlElementSet(
return base::ContainsValue(control_elements, form_control_element);
}
-bool IsElementInsideFormOrFieldSet(const WebElement& element) {
+bool IsElementInsideFormOrFieldSet(const WebElement& element,
+ bool consider_fieldset_tags) {
for (WebNode parent_node = element.ParentNode(); !parent_node.IsNull();
parent_node = parent_node.ParentNode()) {
if (!parent_node.IsElementNode())
@@ -126,7 +141,7 @@ bool IsElementInsideFormOrFieldSet(const WebElement& element) {
WebElement cur_element = parent_node.To<WebElement>();
if (cur_element.HasHTMLTagName("form") ||
- cur_element.HasHTMLTagName("fieldset")) {
+ (consider_fieldset_tags && cur_element.HasHTMLTagName("fieldset"))) {
return true;
}
}
@@ -357,6 +372,68 @@ bool InferLabelFromSibling(const WebFormControlElement& element,
return false;
}
+// Helper function to add a button's |title| to the |list|.
+void AddButtonTitleToList(base::string16 title,
+ ButtonTitleType button_type,
+ ButtonTitleList* list) {
+ title = base::CollapseWhitespace(std::move(title), false);
+ if (title.empty())
+ return;
+ TruncateString(&title, kMaxLengthForSingleButtonTitle);
+ list->push_back(std::make_pair(std::move(title), button_type));
+}
+
+// Returns true iff |attribute| contains one of |kButtonFeatures|.
+bool AttributeHasButtonFeature(const WebString& attribute) {
+ if (attribute.IsNull())
+ return false;
+ std::string value = attribute.Utf8();
+ std::transform(value.begin(), value.end(), value.begin(), ::tolower);
+ for (const char* const button_feature : kButtonFeatures) {
+ if (value.find(button_feature, 0) != std::string::npos)
+ return true;
+ }
+ return false;
+}
+
+// Returns true if |element|'s id, name or css class contain |kButtonFeatures|.
+bool ElementAttributesHasButtonFeature(const WebElement& element) {
+ return AttributeHasButtonFeature(element.GetAttribute("id")) ||
+ AttributeHasButtonFeature(element.GetAttribute("name")) ||
+ AttributeHasButtonFeature(element.GetAttribute("class"));
+}
+
+// Finds elements from |elements| that contains |kButtonFeatures|, adds them to
+// |list| and updates the |total_length| of the |list|'s items.
+// If |extract_value_attribute|, the "value" attribute is extracted as a button
+// title. Otherwise, |WebElement::TextContent| (aka innerText in Javascript) is
+// extracted as a title.
+void FindElementsWithButtonFeatures(const WebElementCollection& elements,
+ bool only_formless_elements,
+ ButtonTitleType button_type,
+ bool extract_value_attribute,
+ ButtonTitleList* list) {
+ static base::NoDestructor<WebString> kValue("value");
+ for (WebElement item = elements.FirstItem(); !item.IsNull();
+ item = elements.NextItem()) {
+ if (!ElementAttributesHasButtonFeature(item))
+ continue;
+ if (only_formless_elements &&
+ IsElementInsideFormOrFieldSet(item,
+ false /* consider_fieldset_tags */)) {
+ continue;
+ }
+ base::string16 title =
+ extract_value_attribute
+ ? (item.HasAttribute(*kValue) ? item.GetAttribute(*kValue).Utf16()
+ : base::string16())
+ : item.TextContent().Utf16();
+ if (extract_value_attribute && title.empty())
+ title = item.TextContent().Utf16();
+ AddButtonTitleToList(std::move(title), button_type, list);
+ }
+}
+
// Helper for |InferLabelForElement()| that infers a label, if possible, from
// a previous sibling of |element|,
// e.g. Some Text <input ...>
@@ -780,40 +857,107 @@ bool InferLabelForElement(const WebFormControlElement& element,
return false;
}
-base::string16 InferButtonTitleForForm(const WebFormElement& form_element) {
- static base::NoDestructor<WebString> kSubmit("submit");
+// Removes the duplicate titles and limits totals length. The order of the list
+// is preserved as first elements are more reliable features than following
+// ones.
+void RemoveDuplicatesAndLimitTotalLength(ButtonTitleList* result) {
+ std::set<ButtonTitleInfo> already_added;
+ ButtonTitleList unique_titles;
+ int total_length = 0;
+ for (auto title : *result) {
+ if (already_added.find(title) != already_added.end())
+ continue;
+ already_added.insert(title);
+
+ total_length += title.first.length();
+ if (total_length > kMaxLengthForAllButtonTitles) {
+ int new_length =
+ title.first.length() - (total_length - kMaxLengthForAllButtonTitles);
+ TruncateString(&title.first, new_length);
+ }
+ unique_titles.push_back(std::move(title));
+
+ if (total_length >= kMaxLengthForAllButtonTitles)
+ break;
+ }
+ *result = std::move(unique_titles);
+}
+
+// Infer button titles enclosed by |root_element|. |root_element| may be a
+// <form> or a <body> if there are <input>s that are not enclosed in a <form>
+// element.
+ButtonTitleList InferButtonTitlesForForm(const WebElement& root_element) {
+ static base::NoDestructor<WebString> kA("a");
static base::NoDestructor<WebString> kButton("button");
+ static base::NoDestructor<WebString> kDiv("div");
+ static base::NoDestructor<WebString> kForm("form");
+ static base::NoDestructor<WebString> kInput("input");
+ static base::NoDestructor<WebString> kSpan("span");
+ static base::NoDestructor<WebString> kSubmit("submit");
- base::string16 title;
- WebVector<WebFormControlElement> control_elements;
- form_element.GetFormControlElements(control_elements);
- for (const WebFormControlElement& control_element : control_elements) {
+ // If the |root_element| is not a <form>, ignore the elements inclosed in a
+ // <form>.
+ bool only_formless_elements = !root_element.HasHTMLTagName(*kForm);
+
+ ButtonTitleList result;
+ WebElementCollection input_elements =
+ root_element.GetElementsByHTMLTagName(*kInput);
+ int total_length = 0;
+ for (WebElement item = input_elements.FirstItem();
+ !item.IsNull() && total_length < kMaxLengthForAllButtonTitles;
+ item = input_elements.NextItem()) {
+ DCHECK(item.IsFormControlElement());
+ WebFormControlElement control_element =
+ item.ToConst<WebFormControlElement>();
+ if (only_formless_elements && !control_element.Form().IsNull())
+ continue;
bool is_submit_input =
control_element.FormControlTypeForAutofill() == *kSubmit;
bool is_button_input =
control_element.FormControlTypeForAutofill() == *kButton;
if (!is_submit_input && !is_button_input)
continue;
- if (!control_element.Value().IsEmpty())
- title = control_element.Value().Utf16() +
- base::ASCIIToUTF16(is_submit_input ? "$" : "#") + title;
- if (title.length() >= kMaxDataLength)
- break;
+ base::string16 title = control_element.Value().Utf16();
+ AddButtonTitleToList(std::move(title),
+ is_submit_input
+ ? ButtonTitleType::INPUT_ELEMENT_SUBMIT_TYPE
+ : ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE,
+ &result);
}
WebElementCollection buttons =
- form_element.GetElementsByHTMLTagName(*kButton);
- for (WebElement item = buttons.FirstItem();
- !item.IsNull() && title.length() <= kMaxDataLength;
+ root_element.GetElementsByHTMLTagName(*kButton);
+ for (WebElement item = buttons.FirstItem(); !item.IsNull();
item = buttons.NextItem()) {
- if (!item.TextContent().IsEmpty()) {
- bool is_submit_button =
- item.HasAttribute("type") && item.GetAttribute("type") == *kSubmit;
- title = item.TextContent().Utf16() +
- base::ASCIIToUTF16(is_submit_button ? "&" : "%") + title;
+ WebString type_attribute = item.GetAttribute("type");
+ if (!type_attribute.IsNull() && type_attribute != *kButton &&
+ type_attribute != *kSubmit) {
+ // Neither type='submit' nor type='button'. Skip this button.
+ continue;
}
- }
- TruncateString(&title, kMaxDataLength);
- return title;
+ if (only_formless_elements &&
+ IsElementInsideFormOrFieldSet(item,
+ false /* consider_fieldset_tags */)) {
+ continue;
+ }
+ bool is_submit_type = type_attribute.IsNull() || type_attribute == *kSubmit;
+ base::string16 title = item.TextContent().Utf16();
+ AddButtonTitleToList(std::move(title),
+ is_submit_type
+ ? ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE
+ : ButtonTitleType::BUTTON_ELEMENT_BUTTON_TYPE,
+ &result);
+ }
+ FindElementsWithButtonFeatures(
+ root_element.GetElementsByHTMLTagName(*kA), only_formless_elements,
+ ButtonTitleType::HYPERLINK, true /* extract_value_attribute */, &result);
+ FindElementsWithButtonFeatures(root_element.GetElementsByHTMLTagName(*kDiv),
+ only_formless_elements, ButtonTitleType::DIV,
+ false /* extract_value_attribute */, &result);
+ FindElementsWithButtonFeatures(root_element.GetElementsByHTMLTagName(*kSpan),
+ only_formless_elements, ButtonTitleType::SPAN,
+ false /* extract_value_attribute */, &result);
+ RemoveDuplicatesAndLimitTotalLength(&result);
+ return result;
}
// Fills |option_strings| with the values of the <option> elements present in
@@ -1647,7 +1791,6 @@ bool WebFormElementToFormData(
form->unique_renderer_id = form_element.UniqueRendererFormId();
form->origin = GetCanonicalOriginForDocument(frame->GetDocument());
form->action = GetCanonicalActionForForm(form_element);
- form->button_title = InferButtonTitleForForm(form_element);
if (frame->Top()) {
form->main_frame_origin = frame->Top()->GetSecurityOrigin();
} else {
@@ -1681,7 +1824,8 @@ std::vector<WebFormControlElement> GetUnownedFormFieldElements(
}
if (fieldsets && element.HasHTMLTagName("fieldset") &&
- !IsElementInsideFormOrFieldSet(element)) {
+ !IsElementInsideFormOrFieldSet(element,
+ true /* consider_fieldset_tags */)) {
fieldsets->push_back(element);
}
}
@@ -2017,8 +2161,8 @@ bool InferLabelForElementForTesting(const WebFormControlElement& element,
return InferLabelForElement(element, stop_words, label, label_source);
}
-base::string16 InferButtonTitleForTesting(const WebFormElement& form_element) {
- return InferButtonTitleForForm(form_element);
+ButtonTitleList InferButtonTitlesForTesting(const WebElement& form_element) {
+ return InferButtonTitlesForForm(form_element);
}
WebFormElement FindFormByUniqueRendererId(WebDocument doc,
@@ -2033,6 +2177,23 @@ WebFormElement FindFormByUniqueRendererId(WebDocument doc,
return WebFormElement();
}
+WebFormControlElement FindFormControlElementsByUniqueRendererId(
+ WebDocument doc,
+ uint32_t form_control_renderer_id) {
+ WebElementCollection elements = doc.All();
+
+ for (WebElement element = elements.FirstItem(); !element.IsNull();
+ element = elements.NextItem()) {
+ if (!element.IsFormControlElement())
+ continue;
+ WebFormControlElement control = element.To<WebFormControlElement>();
+ if (form_control_renderer_id == control.UniqueRendererFormControlId())
+ return control;
+ }
+
+ return WebFormControlElement();
+}
+
std::vector<WebFormControlElement> FindFormControlElementsByUniqueRendererId(
WebDocument doc,
const std::vector<uint32_t>& form_control_renderer_ids) {
diff --git a/chromium/components/autofill/content/renderer/form_autofill_util.h b/chromium/components/autofill/content/renderer/form_autofill_util.h
index 3cfb4186c7b..bb64fb7fe73 100644
--- a/chromium/components/autofill/content/renderer/form_autofill_util.h
+++ b/chromium/components/autofill/content/renderer/form_autofill_util.h
@@ -278,14 +278,20 @@ bool InferLabelForElementForTesting(const blink::WebFormControlElement& element,
const std::vector<base::char16>& stop_words,
base::string16* label,
FormFieldData::LabelSource* label_source);
-base::string16 InferButtonTitleForTesting(
- const blink::WebFormElement& form_element);
+ButtonTitleList InferButtonTitlesForTesting(
+ const blink::WebElement& form_element);
// Returns form by unique renderer id. Return null element if there is no form
// with given form renderer id.
blink::WebFormElement FindFormByUniqueRendererId(blink::WebDocument doc,
uint32_t form_renderer_id);
+// Returns form control element by unique renderer id. Return null element if
+// there is no element with given renderer id.
+blink::WebFormControlElement FindFormControlElementsByUniqueRendererId(
+ blink::WebDocument doc,
+ uint32_t form_control_renderer_id);
+
// Note: The vector-based API of the following two functions is a tax for limiting
// the frequency and duration of retrieving a lot of DOM elements. Alternative
// solutions have been discussed on https://crrev.com/c/1108201.
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 136bb92ab41..48ce8bb59a6 100644
--- a/chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc
+++ b/chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc
@@ -4,6 +4,8 @@
#include "components/autofill/content/renderer/form_autofill_util.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/test/render_view_test.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -267,31 +269,107 @@ TEST_F(FormAutofillUtilsTest, InferLabelSourceTest) {
}
TEST_F(FormAutofillUtilsTest, InferButtonTitleForFormTest) {
- static const AutofillFieldUtilCase test_cases[] = {
- {"<button>", "<form id='target'><button>Sign Up</button></form>",
- "Sign Up%"},
- {"<input type='submit'>",
- "<form id='target'><input type='submit' value='Sign In'></form>",
- "Sign In$"},
- {"several labels",
- "<form id='target'><button type='button'>Show "
- "password</button><button type='submit'>Register</button></form>",
- "Register&Show password%"}};
- for (const auto& test_case : test_cases) {
- SCOPED_TRACE(test_case.description);
- LoadHTML(test_case.html);
- WebLocalFrame* web_frame = GetMainFrame();
- ASSERT_NE(nullptr, web_frame);
- const WebElement& target =
- web_frame->GetDocument().GetElementById("target");
- ASSERT_FALSE(target.IsNull());
- const WebFormElement& form_target = target.ToConst<WebFormElement>();
- ASSERT_FALSE(form_target.IsNull());
+ const char kHtml[] =
+ "<form id='target'>"
+ " <input type='button' value='Clear field'>"
+ " <input type='button' value='Clear field'>"
+ " <input type='button' value='Clear field'>"
+ " <input type='button' value='\n Show\t password '>"
+ " <button>Sign Up</button>"
+ " <button type='button'>Register</button>"
+ " <a id='Submit' value='Create account'>"
+ " <div name='BTN'> Join </div>"
+ " <span class='button'> Start </span>"
+ " <a class='empty button' value=' \t \n'>"
+ "</form>";
+
+ LoadHTML(kHtml);
+ WebLocalFrame* web_frame = GetMainFrame();
+ ASSERT_NE(nullptr, web_frame);
+ const WebElement& target = web_frame->GetDocument().GetElementById("target");
+ ASSERT_FALSE(target.IsNull());
+ const WebFormElement& form_target = target.ToConst<WebFormElement>();
+ ASSERT_FALSE(form_target.IsNull());
+
+ autofill::ButtonTitleList actual =
+ autofill::form_util::InferButtonTitlesForTesting(form_target);
+ autofill::ButtonTitleList expected = {
+ {base::UTF8ToUTF16("Clear field"),
+ autofill::ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE},
+ {base::UTF8ToUTF16("Show password"),
+ autofill::ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE},
+ {base::UTF8ToUTF16("Sign Up"),
+ autofill::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE},
+ {base::UTF8ToUTF16("Register"),
+ autofill::ButtonTitleType::BUTTON_ELEMENT_BUTTON_TYPE},
+ {base::UTF8ToUTF16("Create account"),
+ autofill::ButtonTitleType::HYPERLINK},
+ {base::UTF8ToUTF16("Join"), autofill::ButtonTitleType::DIV},
+ {base::UTF8ToUTF16("Start"), autofill::ButtonTitleType::SPAN}};
+ EXPECT_EQ(expected, actual);
+}
- base::string16 button_title =
- autofill::form_util::InferButtonTitleForTesting(form_target);
- EXPECT_EQ(base::UTF8ToUTF16(test_case.expected_label), button_title);
+TEST_F(FormAutofillUtilsTest, InferButtonTitleForFormTest_TooLongTitle) {
+ std::string title;
+ for (int i = 0; i < 300; ++i)
+ title += "a";
+ std::string kFormHtml = "<form id='target'>";
+ for (int i = 0; i < 10; i++) {
+ std::string kFieldHtml =
+ "<input type='button' value='" + base::IntToString(i) + title + "'>";
+ kFormHtml += kFieldHtml;
}
+ kFormHtml += "</form>";
+
+ LoadHTML(kFormHtml.c_str());
+ WebLocalFrame* web_frame = GetMainFrame();
+ ASSERT_NE(nullptr, web_frame);
+ const WebElement& target = web_frame->GetDocument().GetElementById("target");
+ ASSERT_FALSE(target.IsNull());
+ const WebFormElement& form_target = target.ToConst<WebFormElement>();
+ ASSERT_FALSE(form_target.IsNull());
+
+ autofill::ButtonTitleList actual =
+ autofill::form_util::InferButtonTitlesForTesting(form_target);
+
+ int total_length = 0;
+ for (auto title : actual) {
+ EXPECT_GE(30u, title.first.length());
+ total_length += title.first.length();
+ }
+ EXPECT_EQ(200, total_length);
+}
+
+TEST_F(FormAutofillUtilsTest, InferButtonTitle_Formless) {
+ const char kNoFormHtml[] =
+ "<div class='reg-form'>"
+ " <input type='button' value='\n Show\t password '>"
+ " <button>Sign Up</button>"
+ " <button type='button'>Register</button>"
+ "</div>"
+ "<form id='ignored-form'>"
+ " <input type='button' value='Ignore this'>"
+ " <button>Ignore this</button>"
+ " <a id='Submit' value='Ignore this'>"
+ " <div name='BTN'>Ignore this</div>"
+ "</form>";
+
+ LoadHTML(kNoFormHtml);
+ WebLocalFrame* web_frame = GetMainFrame();
+ ASSERT_NE(nullptr, web_frame);
+ const WebElement& body = web_frame->GetDocument().Body();
+ ASSERT_FALSE(body.IsNull());
+
+ autofill::ButtonTitleList actual =
+ autofill::form_util::InferButtonTitlesForTesting(body);
+ autofill::ButtonTitleList expected = {
+ {base::UTF8ToUTF16("Show password"),
+ autofill::ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE},
+ {base::UTF8ToUTF16("Sign Up"),
+ autofill::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE},
+ {base::UTF8ToUTF16("Register"),
+ autofill::ButtonTitleType::BUTTON_ELEMENT_BUTTON_TYPE}};
+ EXPECT_EQ(expected, actual);
}
TEST_F(FormAutofillUtilsTest, IsEnabled) {
@@ -324,7 +402,7 @@ TEST_F(FormAutofillUtilsTest, IsEnabled) {
} kExpectedFields[] = {
{"name1", true}, {"name2", false}, {"name3", true}, {"name4", false},
};
- const size_t number_of_cases = arraysize(kExpectedFields);
+ const size_t number_of_cases = base::size(kExpectedFields);
ASSERT_EQ(number_of_cases, target.fields.size());
for (size_t i = 0; i < number_of_cases; ++i) {
EXPECT_EQ(base::UTF8ToUTF16(kExpectedFields[i].name),
@@ -363,7 +441,7 @@ TEST_F(FormAutofillUtilsTest, IsReadonly) {
} kExpectedFields[] = {
{"name1", false}, {"name2", true}, {"name3", false}, {"name4", true},
};
- const size_t number_of_cases = arraysize(kExpectedFields);
+ const size_t number_of_cases = base::size(kExpectedFields);
ASSERT_EQ(number_of_cases, target.fields.size());
for (size_t i = 0; i < number_of_cases; ++i) {
EXPECT_EQ(base::UTF8ToUTF16(kExpectedFields[i].name),
@@ -423,6 +501,23 @@ TEST_F(FormAutofillUtilsTest, FindFormByUniqueId) {
.IsNull());
}
+TEST_F(FormAutofillUtilsTest, FindFormControlByUniqueId) {
+ LoadHTML(
+ "<body><form id='form1'><input id='i1'></form><input id='i2'></body>");
+ WebDocument doc = GetMainFrame()->GetDocument();
+ 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()));
+ EXPECT_EQ(input2, FindFormControlElementsByUniqueRendererId(
+ doc, input2.UniqueRendererFormControlId()));
+ EXPECT_TRUE(
+ FindFormControlElementsByUniqueRendererId(doc, non_existing_id).IsNull());
+}
+
TEST_F(FormAutofillUtilsTest, FindFormControlElementsByUniqueIdNoForm) {
LoadHTML("<body><input id='i1'><input id='i2'><input id='i3'></body>");
WebDocument doc = GetMainFrame()->GetDocument();
diff --git a/chromium/components/autofill/content/renderer/form_cache.cc b/chromium/components/autofill/content/renderer/form_cache.cc
index cdb343ce5d9..982cf44b0e1 100644
--- a/chromium/components/autofill/content/renderer/form_cache.cc
+++ b/chromium/components/autofill/content/renderer/form_cache.cc
@@ -164,7 +164,7 @@ void LogDeprecationMessages(const WebFormControlElement& element) {
std::string msg = std::string("autocomplete='") + str +
"' is deprecated and will soon be ignored. See http://goo.gl/YjeSsW";
WebConsoleMessage console_message = WebConsoleMessage(
- WebConsoleMessage::kLevelWarning, WebString::FromASCII(msg));
+ blink::mojom::ConsoleMessageLevel::kWarning, WebString::FromASCII(msg));
element.GetDocument().GetFrame()->AddMessageToConsole(console_message);
}
}
diff --git a/chromium/components/autofill/content/renderer/html_based_username_detector_vocabulary.cc b/chromium/components/autofill/content/renderer/html_based_username_detector_vocabulary.cc
index abf4e4bf888..58b653dbc11 100644
--- a/chromium/components/autofill/content/renderer/html_based_username_detector_vocabulary.cc
+++ b/chromium/components/autofill/content/renderer/html_based_username_detector_vocabulary.cc
@@ -4,7 +4,7 @@
#include "components/autofill/content/renderer/html_based_username_detector_vocabulary.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
namespace autofill {
@@ -23,7 +23,7 @@ const char* const kNegativeLatin[] = {
"second", "passwort", "middlename", "paroladordine",
"codice", "pasvorto", "familyname", "inomboloyokuvula",
"modpas", "salasana", "motdepasse", "numeraeleiloaesesi"};
-const int kNegativeLatinSize = arraysize(kNegativeLatin);
+const int kNegativeLatinSize = base::size(kNegativeLatin);
const char* const kNegativeNonLatin[] = {"fjalëkalim",
"የይለፍቃል",
@@ -74,7 +74,7 @@ const char* const kNegativeNonLatin[] = {"fjalëkalim",
"mậtkhẩu",
"פּאַראָל",
"ọrọigbaniwọle"};
-const int kNegativeNonLatinSize = arraysize(kNegativeNonLatin);
+const int kNegativeNonLatinSize = base::size(kNegativeNonLatin);
const char* const kUsernameLatin[] = {
"gatti", "uzantonomo", "solonanarana", "nombredeusuario",
@@ -86,7 +86,7 @@ const char* const kUsernameLatin[] = {
"mosebedisi", "kasutajanimi", "ainmcleachdaidh", "igamalomsebenzisi",
"nomdusuari", "lomsebenzisi", "jenengpanganggo", "ingoakaiwhakamahi",
"nomeutente", "namapengguna"};
-const int kUsernameLatinSize = arraysize(kUsernameLatin);
+const int kUsernameLatinSize = base::size(kUsernameLatin);
const char* const kUsernameNonLatin[] = {"用户名",
"کاتيجونالو",
@@ -146,7 +146,7 @@ const char* const kUsernameNonLatin[] = {"用户名",
"ব্যবহারকারীরনাম",
"užívateľskémeno",
"ឈ្មោះអ្នកប្រើប្រាស់"};
-const int kUsernameNonLatinSize = arraysize(kUsernameNonLatin);
+const int kUsernameNonLatinSize = base::size(kUsernameNonLatin);
const char* const kUserLatin[] = {
"user", "wosuta", "gebruiker", "utilizator",
@@ -159,7 +159,7 @@ const char* const kUserLatin[] = {
"usuari", "kasutaja", "defnyddiwr", "kaiwhakamahi",
"utente", "korisnik", "mosebedisi", "foydalanuvchi",
"uzanto", "pengguna", "mushandisi"};
-const int kUserLatinSize = arraysize(kUserLatin);
+const int kUserLatinSize = base::size(kUserLatin);
const char* const kUserNonLatin[] = {"用户",
"użytkownik",
@@ -218,7 +218,7 @@ const char* const kUserNonLatin[] = {"用户",
"пайдаланушы",
"အသုံးပြုသူကို",
"käyttäjä"};
-const int kUserNonLatinSize = arraysize(kUserNonLatin);
+const int kUserNonLatinSize = base::size(kUserNonLatin);
const char* const kTechnicalWords[] = {
"uid", "newtel", "uaccount", "regaccount", "ureg",
@@ -226,9 +226,9 @@ const char* const kTechnicalWords[] = {
"loginname", "membername", "uname", "ucreate", "loginmail",
"accountname", "umail", "loginreg", "accountid", "loginaccount",
"ulogin", "regemail", "newmobile", "accountlogin"};
-const int kTechnicalWordsSize = arraysize(kTechnicalWords);
+const int kTechnicalWordsSize = base::size(kTechnicalWords);
const char* const kWeakWords[] = {"id", "login", "mail"};
-const int kWeakWordsSize = arraysize(kWeakWords);
+const int kWeakWordsSize = base::size(kWeakWords);
} // namespace autofill
diff --git a/chromium/components/autofill/content/renderer/page_form_analyser_logger.h b/chromium/components/autofill/content/renderer/page_form_analyser_logger.h
index 8b9ee53c050..eade038f446 100644
--- a/chromium/components/autofill/content/renderer/page_form_analyser_logger.h
+++ b/chromium/components/autofill/content/renderer/page_form_analyser_logger.h
@@ -14,7 +14,7 @@
namespace autofill {
-using ConsoleLevel = blink::WebConsoleMessage::Level;
+using ConsoleLevel = blink::mojom::ConsoleMessageLevel;
// ConsoleLogger provides a convenient interface for logging messages to the
// DevTools console, both in terms of wrapping and formatting console messages
@@ -22,9 +22,11 @@ using ConsoleLevel = blink::WebConsoleMessage::Level;
// warnings are displayed first.
class PageFormAnalyserLogger {
public:
- static const ConsoleLevel kError = blink::WebConsoleMessage::kLevelError;
- static const ConsoleLevel kWarning = blink::WebConsoleMessage::kLevelWarning;
- static const ConsoleLevel kVerbose = blink::WebConsoleMessage::kLevelVerbose;
+ static const ConsoleLevel kError = blink::mojom::ConsoleMessageLevel::kError;
+ static const ConsoleLevel kWarning =
+ blink::mojom::ConsoleMessageLevel::kWarning;
+ static const ConsoleLevel kVerbose =
+ blink::mojom::ConsoleMessageLevel::kVerbose;
explicit PageFormAnalyserLogger(blink::WebLocalFrame* frame);
~PageFormAnalyserLogger();
diff --git a/chromium/components/autofill/content/renderer/password_autofill_agent.cc b/chromium/components/autofill/content/renderer/password_autofill_agent.cc
index 76068b40eb5..ed933f790ea 100644
--- a/chromium/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/chromium/components/autofill/content/renderer/password_autofill_agent.cc
@@ -13,11 +13,10 @@
#include <vector>
#include "base/bind.h"
-#include "base/containers/flat_set.h"
#include "base/i18n/case_conversion.h"
-#include "base/memory/linked_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
+#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -26,6 +25,7 @@
#include "components/autofill/content/renderer/form_autofill_util.h"
#include "components/autofill/content/renderer/password_form_conversion_utils.h"
#include "components/autofill/content/renderer/password_generation_agent.h"
+#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_util.h"
@@ -99,66 +99,6 @@ bool FillDataContainsFillableUsername(const PasswordFormFillData& fill_data) {
!fill_data.username_field.value.empty());
}
-// Checks if the prefilled value of the username element is one of the known
-// values possibly used as placeholders. The list of possible placeholder
-// values comes from popular sites exhibiting this issue.
-// TODO(crbug.com/832622): Remove this once a stable solution is in place.
-bool PossiblePrefilledUsernameValue(const std::string& username_value) {
- // Explicitly create a |StringFlatSet| when constructing
- // kPrefilledUsernameValues to work around GCC bug 84849, which causes the
- // initializer list not to be properly forwarded to base::flat_set's
- // constructor.
- using StringFlatSet = base::flat_set<std::string, std::less<>>;
- static base::NoDestructor<StringFlatSet> kPrefilledUsernameValues(
- StringFlatSet({"3~15个字符,中文字符7个以内",
- "Benutzername",
- "Digite seu CPF ou e-mail",
- "DS Logon Username",
- "Email Address",
- "email address",
- "Email masih kosong",
- "Email/手機號碼",
- "Enter User Name",
- "Identifiant",
- "Kullanıcı Adı",
- "Kunden-ID",
- "Nick",
- "Nom Utilisateur",
- "Rut",
- "Siret",
- "this is usually your email address",
- "UID/用戶名/Email",
- "User Id",
- "User Name",
- "Username",
- "username",
- "username or email",
- "Username or email:",
- "Username/Email",
- "Usuario",
- "Your email address",
- "Имя",
- "Логин",
- "Логин...",
- "כתובת דוא''ל",
- "اسم العضو",
- "اسم المستخدم",
- "الاسم",
- "نام کاربری",
- "メールアドレス",
- "用户名",
- "用户名/Email",
- "請輸入身份證字號",
- "请用微博帐号登录",
- "请输入手机号或邮箱",
- "请输入邮箱或手机号",
- "邮箱/手机/展位号"}));
-
- return kPrefilledUsernameValues->find(
- base::TrimWhitespaceASCII(username_value, base::TRIM_ALL)) !=
- kPrefilledUsernameValues->end();
-}
-
// Returns true if password form has username and password fields with either
// same or no name and id attributes supplied.
bool DoesFormContainAmbiguousOrEmptyNames(
@@ -628,6 +568,11 @@ WebInputElement ConvertToWebInput(const WebFormControlElement& element) {
return input ? *input : WebInputElement();
}
+void LogSendPasswordForm(SendPasswordFormToBrowserProcess value) {
+ UMA_HISTOGRAM_ENUMERATION("PasswordManager.SendPasswordFormToBrowserProcess",
+ value);
+}
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -644,6 +589,7 @@ PasswordAutofillAgent::PasswordAutofillAgent(
sent_request_to_store_(false),
checked_safe_browsing_reputation_(false),
focus_state_notifier_(this),
+ password_generation_agent_(nullptr),
binding_(this) {
registry->AddInterface(
base::Bind(&PasswordAutofillAgent::BindRequest, base::Unretained(this)));
@@ -1200,6 +1146,11 @@ void PasswordAutofillAgent::SendPasswordForms(bool only_visible) {
FormStructureInfo form_structure_info =
ExtractFormStructureInfo(password_form->form_data);
if (only_visible || WasFormStructureChanged(form_structure_info)) {
+ if (only_visible) {
+ LogSendPasswordForm(
+ SendPasswordFormToBrowserProcess::kPasswordFormSentByOnlyVisible);
+ }
+
forms_structure_cache_[form_structure_info.unique_renderer_id] =
std::move(form_structure_info);
@@ -1207,6 +1158,9 @@ void PasswordAutofillAgent::SendPasswordForms(bool only_visible) {
continue;
}
+ LogSendPasswordForm(
+ SendPasswordFormToBrowserProcess::kPasswordFormWasNotSent);
+
WebVector<WebFormControlElement> control_elements_vector;
form.GetFormControlElements(control_elements_vector);
@@ -1242,7 +1196,10 @@ void PasswordAutofillAgent::SendPasswordForms(bool only_visible) {
logger->LogPasswordForm(Logger::STRING_FORM_IS_PASSWORD,
*password_form);
}
+
password_forms.push_back(std::move(*password_form));
+ LogSendPasswordForm(
+ SendPasswordFormToBrowserProcess::kPasswordFormSentByNoFormTag);
}
}
@@ -1267,6 +1224,9 @@ void PasswordAutofillAgent::SendPasswordForms(bool only_visible) {
form_util::GetCanonicalOriginForDocument(frame->GetDocument());
password_forms.back().signon_realm =
GetSignOnRealm(password_forms.back().origin);
+ password_forms.back().form_data.origin = password_forms.back().origin;
+ LogSendPasswordForm(
+ SendPasswordFormToBrowserProcess::kPasswordFormSentByNoFormTag);
}
if (!password_forms.empty()) {
sent_request_to_store_ = true;
@@ -1304,6 +1264,7 @@ void PasswordAutofillAgent::DidCommitProvisionalLoad(
ui::PageTransition transition) {
if (!is_same_document_navigation) {
checked_safe_browsing_reputation_ = false;
+ recorded_first_filling_result_ = false;
}
}
@@ -1454,11 +1415,27 @@ void PasswordAutofillAgent::FillUsingRendererIDs(
FindUsernamePasswordElements(form_data);
if (password_element.IsNull()) {
MaybeStoreFallbackData(form_data);
+ if (form_data.password_field.unique_renderer_id ==
+ FormFieldData::kNotSetFormControlRendererId) {
+ // If the password_field.unique_renderer_id was not set, this was never
+ // meant as an honest attempt to fill the form. Therefore, don't log it as
+ // such.
+ return;
+ }
+ LogFirstFillingResult(form_data, FillingResult::kNoPasswordElement);
return;
}
StoreDataForFillOnAccountSelect(form_data, username_element,
password_element);
+
+ // 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);
+ return;
+ }
+
FillFormOnPasswordReceived(form_data, username_element, password_element,
&field_data_manager_, logger.get());
}
@@ -1482,8 +1459,13 @@ void PasswordAutofillAgent::FillPasswordForm(
// 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)
+ if (form_data.wait_for_username) {
+ LogFirstFillingResult(form_data, FillingResult::kWaitForUsername);
return;
+ }
+
+ if (elements.empty())
+ LogFirstFillingResult(form_data, FillingResult::kNoFillableElementsFound);
for (auto element : elements) {
WebInputElement username_element = !element.IsPasswordFieldForAutofill()
@@ -1755,8 +1737,15 @@ bool PasswordAutofillAgent::FillUserNameAndPassword(
logger->LogMessage(Logger::STRING_FILL_USERNAME_AND_PASSWORD_METHOD);
// Don't fill username if password can't be set.
- if (!IsElementAutocompletable(*password_element))
+ if (!IsElementAutocompletable(*password_element)) {
+ if (logger) {
+ logger->LogMessage(
+ Logger::STRING_FAILED_TO_FILL_NO_AUTOCOMPLETEABLE_ELEMENT);
+ }
+ LogFirstFillingResult(fill_data,
+ FillingResult::kPasswordElementIsNotAutocompleteable);
return false;
+ }
// |current_username| is the username for credentials that are going to be
// autofilled. It is selected according to the algorithm:
@@ -1775,9 +1764,15 @@ bool PasswordAutofillAgent::FillUserNameAndPassword(
bool prefilled_placeholder_username = false;
if (!username_element->IsNull()) {
+ // This is a heuristic guess. If the credential is stored for
+ // www.example.com, the username may be prefilled with "@example.com".
+ std::string possible_email_domain =
+ GetRegistryControlledDomain(fill_data.origin);
+
prefilled_placeholder_username =
!username_element->Value().IsEmpty() &&
- (PossiblePrefilledUsernameValue(username_element->Value().Utf8()) ||
+ (PossiblePrefilledUsernameValue(username_element->Value().Utf8(),
+ possible_email_domain) ||
username_may_use_prefilled_placeholder);
if (!username_element->Value().IsEmpty() &&
!prefilled_placeholder_username) {
@@ -1802,7 +1797,18 @@ bool PasswordAutofillAgent::FillUserNameAndPassword(
!prefilled_placeholder_username) {
LogPrefilledUsernameFillOutcome(
PrefilledUsernameFillOutcome::kPrefilledUsernameNotOverridden);
+ if (logger)
+ logger->LogMessage(Logger::STRING_FAILED_TO_FILL_PREFILLED_USERNAME);
+ LogFirstFillingResult(
+ fill_data, FillingResult::kUsernamePrefilledWithIncompatibleValue);
+ return false;
+ }
+ if (logger) {
+ logger->LogMessage(
+ Logger::STRING_FAILED_TO_FILL_FOUND_NO_PASSWORD_FOR_USERNAME);
}
+ LogFirstFillingResult(fill_data,
+ FillingResult::kFoundNoPasswordForUsername);
return false;
}
@@ -1840,8 +1846,6 @@ bool PasswordAutofillAgent::FillUserNameAndPassword(
field_data_manager->UpdateFieldDataMap(
*password_element, password,
FieldPropertiesFlags::AUTOFILLED_ON_PAGELOAD);
- ProvisionallySavePassword(password_element->Form(), *password_element,
- RESTRICTION_NONE);
gatekeeper_.RegisterElement(password_element);
password_element->SetAutofillState(WebAutofillState::kAutofilled);
@@ -1856,6 +1860,7 @@ bool PasswordAutofillAgent::FillUserNameAndPassword(
autofilled_elements_cache_.emplace(
password_element->UniqueRendererFormControlId(),
WebString::FromUTF16(password));
+ LogFirstFillingResult(fill_data, FillingResult::kSuccess);
return true;
}
@@ -1885,13 +1890,24 @@ bool PasswordAutofillAgent::FillFormOnPasswordReceived(
cur_frame = cur_frame->Parent();
if (!IsPublicSuffixDomainMatch(
bottom_frame_origin.Utf8(),
- cur_frame->GetSecurityOrigin().ToString().Utf8()))
+ cur_frame->GetSecurityOrigin().ToString().Utf8())) {
+ if (logger)
+ logger->LogMessage(Logger::STRING_FAILED_TO_FILL_INTO_IFRAME);
+ LogFirstFillingResult(fill_data, FillingResult::kBlockedByFrameHierarchy);
return false;
+ }
}
// If we can't modify the password, don't try to set the username
- if (!IsElementAutocompletable(password_element))
+ if (!IsElementAutocompletable(password_element)) {
+ if (logger) {
+ logger->LogMessage(
+ Logger::STRING_FAILED_TO_FILL_NO_AUTOCOMPLETEABLE_ELEMENT);
+ }
+ LogFirstFillingResult(fill_data,
+ FillingResult::kPasswordElementIsNotAutocompleteable);
return false;
+ }
bool exact_username_match =
username_element.IsNull() || IsElementEditable(username_element);
@@ -2046,6 +2062,20 @@ void PasswordAutofillAgent::MaybeStoreFallbackData(
last_supplied_password_info_iter_ = web_input_to_password_info_.begin();
}
+void PasswordAutofillAgent::LogFirstFillingResult(
+ const PasswordFormFillData& form_data,
+ FillingResult result) {
+ if (recorded_first_filling_result_)
+ 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));
+ }
+ recorded_first_filling_result_ = true;
+}
+
PasswordAutofillAgent::FormStructureInfo
PasswordAutofillAgent::ExtractFormStructureInfo(const FormData& form_data) {
FormStructureInfo result;
@@ -2067,33 +2097,53 @@ PasswordAutofillAgent::ExtractFormStructureInfo(const FormData& form_data) {
bool PasswordAutofillAgent::WasFormStructureChanged(
const FormStructureInfo& form_info) const {
- if (form_info.unique_renderer_id == FormData::kNotSetFormRendererId)
+ if (form_info.unique_renderer_id == FormData::kNotSetFormRendererId) {
+ LogSendPasswordForm(
+ SendPasswordFormToBrowserProcess::kPasswordFormWithoutId);
return true;
+ }
auto cached_form = forms_structure_cache_.find(form_info.unique_renderer_id);
- if (cached_form == forms_structure_cache_.end())
+ if (cached_form == forms_structure_cache_.end()) {
+ LogSendPasswordForm(
+ SendPasswordFormToBrowserProcess::kPasswordFormSentAsNewlyAdded);
return true;
+ }
const FormStructureInfo& cached_form_info = cached_form->second;
- if (form_info.fields.size() != cached_form_info.fields.size())
+ if (form_info.fields.size() != cached_form_info.fields.size()) {
+ LogSendPasswordForm(
+ SendPasswordFormToBrowserProcess::kPasswordFormSentByStructureChange);
return true;
+ }
for (size_t i = 0; i < form_info.fields.size(); ++i) {
const FormFieldInfo& form_field = form_info.fields[i];
const FormFieldInfo& cached_form_field = cached_form_info.fields[i];
- if (form_field.unique_renderer_id != cached_form_field.unique_renderer_id)
+ if (form_field.unique_renderer_id != cached_form_field.unique_renderer_id) {
+ LogSendPasswordForm(
+ SendPasswordFormToBrowserProcess::kPasswordFormSentByStructureChange);
return true;
+ }
- if (form_field.form_control_type != cached_form_field.form_control_type)
+ if (form_field.form_control_type != cached_form_field.form_control_type) {
+ LogSendPasswordForm(
+ SendPasswordFormToBrowserProcess::kPasswordFormSentByStructureChange);
return true;
+ }
if (form_field.autocomplete_attribute !=
- cached_form_field.autocomplete_attribute)
+ cached_form_field.autocomplete_attribute) {
+ LogSendPasswordForm(
+ SendPasswordFormToBrowserProcess::kPasswordFormSentByStructureChange);
return true;
+ }
if (form_field.is_focusable != cached_form_field.is_focusable) {
+ LogSendPasswordForm(
+ SendPasswordFormToBrowserProcess::kPasswordFormSentByStructureChange);
return true;
}
}
diff --git a/chromium/components/autofill/content/renderer/password_autofill_agent.h b/chromium/components/autofill/content/renderer/password_autofill_agent.h
index f4f300a90d7..01cc65b4e55 100644
--- a/chromium/components/autofill/content/renderer/password_autofill_agent.h
+++ b/chromium/components/autofill/content/renderer/password_autofill_agent.h
@@ -60,6 +60,61 @@ enum class PrefilledUsernameFillOutcome {
kMaxValue = kPrefilledUsernameNotOverridden,
};
+// Used in UMA histograms, please do NOT reorder.
+// Metric: "PasswordManager.SendPasswordFormToBrowserProcess".
+// This metrics is relevant for PasswordAutofillAgent::SendPasswordForms method.
+enum class SendPasswordFormToBrowserProcess {
+ // Password form wasn't sent to the browser process.
+ kPasswordFormWasNotSent = 0,
+ // Password form was sent, because only_visible == true.
+ kPasswordFormSentByOnlyVisible = 1,
+ // Password form was sent, because it's newly added form.
+ kPasswordFormSentAsNewlyAdded = 2,
+ // Password form was sent, because the form structure was changed.
+ kPasswordFormSentByStructureChange = 3,
+ // Password form was sent, because there is no form-tag.
+ kPasswordFormSentByNoFormTag = 4,
+ // Password form was sent, because there is no id. this should never happen;
+ // this enum value exists only for checking.
+ kPasswordFormWithoutId = 5,
+ kMaxValue = kPasswordFormWithoutId,
+};
+
+// Used in UMA histogram, please do NOT reorder.
+// Metric: "PasswordManager.FirstRendererFillingResult".
+// This metric records whether the PasswordAutofillAgent succeeded in filling
+// credentials after being instructed to do so by the browser process.
+enum class FillingResult {
+ kSuccess = 0,
+ // The password element to be filled has not been found.
+ kNoPasswordElement = 1,
+ // Filling only happens in iframes, if all parent frames PSL match the
+ // security origin of the iframe containing the password field.
+ kBlockedByFrameHierarchy = 2,
+ // Passwords are not filled into fields that are not editable.
+ kPasswordElementIsNotAutocompleteable = 3,
+ // The username field contains a string that does not match the username of
+ // any available credential.
+ kUsernamePrefilledWithIncompatibleValue = 4,
+ // No credential was filled due to mismatches with the username. This can
+ // happen in a number of cases: In case the username field is empty and
+ // readonly. In case of a username-first-flow where a user's credentials do
+ // contain a username but the form contains only a password field and no
+ // username field. In case of change password forms that contain no username
+ // field. In case the user name is given on a page but only PSL matched
+ // credentials exist for this username. There may be further cases.
+ kFoundNoPasswordForUsername = 5,
+ // Renderer was instructed to wait until user has manually picked a
+ // credential. This happens for example if the session is an incognito
+ // session, the credendial's URL matches the mainframe only via the PSL, the
+ // site is on HTTP, or the form has no current password field.
+ // PasswordManager.FirstWaitForUsernameReason records the root causes.
+ kWaitForUsername = 6,
+ // No fillable elements were found, only possible for old form parser.
+ kNoFillableElementsFound = 7,
+ kMaxValue = kNoFillableElementsFound,
+};
+
// Names of HTML attributes to show form and field signatures for debugging.
extern const char kDebugAttributeForFormSignature[];
extern const char kDebugAttributeForFieldSignature[];
@@ -407,6 +462,13 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
// |form_data|.
void MaybeStoreFallbackData(const PasswordFormFillData& form_data);
+ // Records whether filling succeeded for the first attempt to fill on a site.
+ // The logging is a bit conservative: It is possible that user-perceived
+ // navigations (via dynamic HTML sites) not trigger any actual navigations
+ // and therefore, the |recorded_first_filling_result_| never gets reset.
+ void LogFirstFillingResult(const PasswordFormFillData& form_data,
+ FillingResult result);
+
// Extracts information about form structure.
static FormStructureInfo ExtractFormStructureInfo(const FormData& form_data);
// Checks whether the form structure (amount of elements, element types etc)
@@ -494,6 +556,12 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
// structure. Replace FormData with a smaller structure.
std::map<unsigned /*unique renderer element id*/, FormStructureInfo>
forms_structure_cache_;
+
+ // Flag to prevent that multiple PasswordManager.FirstRendererFillingResult
+ // UMA metrics are recorded per page load. This is reset on
+ // DidCommitProvisionalLoad() but only for non-same-document-navigations.
+ bool recorded_first_filling_result_ = false;
+
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 ae0bd7edc5d..ad4e5dda58f 100644
--- a/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc
+++ b/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc
@@ -660,8 +660,8 @@ bool GetPasswordForm(
// 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).
- password_form->only_for_fallback_saving = plausible_passwords.empty();
+ // 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 =
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 d2875aeb3f8..70e756afe3d 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,7 +5,7 @@
#include <stddef.h>
#include <memory>
-#include "base/macros.h"
+#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -187,19 +187,10 @@ class PasswordFormBuilder {
DISALLOW_COPY_AND_ASSIGN(PasswordFormBuilder);
};
-// RenderViewTest-based tests crash on Android
-// http://crbug.com/187500
-#if defined(OS_ANDROID)
-#define MAYBE_PasswordFormConversionUtilsTest \
- DISABLED_PasswordFormConversionUtilsTest
-#else
-#define MAYBE_PasswordFormConversionUtilsTest PasswordFormConversionUtilsTest
-#endif // defined(OS_ANDROID)
-
-class MAYBE_PasswordFormConversionUtilsTest : public content::RenderViewTest {
+class PasswordFormConversionUtilsTest : public content::RenderViewTest {
public:
- MAYBE_PasswordFormConversionUtilsTest() {}
- ~MAYBE_PasswordFormConversionUtilsTest() override {}
+ PasswordFormConversionUtilsTest() = default;
+ ~PasswordFormConversionUtilsTest() override = default;
protected:
// Loads the given |html|, retrieves the sole WebFormElement from it, and then
@@ -296,12 +287,12 @@ class MAYBE_PasswordFormConversionUtilsTest : public content::RenderViewTest {
UsernameDetectorCache username_detector_cache_;
private:
- DISALLOW_COPY_AND_ASSIGN(MAYBE_PasswordFormConversionUtilsTest);
+ DISALLOW_COPY_AND_ASSIGN(PasswordFormConversionUtilsTest);
};
} // namespace
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, BasicFormAttributes) {
+TEST_F(PasswordFormConversionUtilsTest, BasicFormAttributes) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddTextField("username", "johnsmith", nullptr);
builder.AddSubmitButton("inactive_submit");
@@ -314,7 +305,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, BasicFormAttributes) {
LoadHTMLAndConvertForm(html, nullptr, false);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ 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);
@@ -327,7 +318,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, BasicFormAttributes) {
EXPECT_EQ(PasswordForm::TYPE_MANUAL, password_form->type);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, DisabledFieldsAreIgnored) {
+TEST_F(PasswordFormConversionUtilsTest, DisabledFieldsAreIgnored) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddTextField("username", "johnsmith", nullptr);
builder.AddDisabledUsernameField();
@@ -339,7 +330,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, DisabledFieldsAreIgnored) {
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, nullptr, false);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ 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);
@@ -350,7 +341,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, DisabledFieldsAreIgnored) {
// 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(MAYBE_PasswordFormConversionUtilsTest, OnlyDisabledFields) {
+TEST_F(PasswordFormConversionUtilsTest, OnlyDisabledFields) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddDisabledUsernameField();
builder.AddDisabledPasswordField();
@@ -366,8 +357,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, OnlyDisabledFields) {
EXPECT_EQ(2u, password_form->form_data.fields.size());
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
- HTMLDetector_DeveloperGroupAttributes) {
+TEST_F(PasswordFormConversionUtilsTest, HTMLDetector_DeveloperGroupAttributes) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
password_manager::features::kHtmlBasedUsernameDetector);
@@ -454,7 +444,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
"id",
"123"}};
- for (size_t i = 0; i < arraysize(cases); ++i) {
+ for (size_t i = 0; i < base::size(cases); ++i) {
SCOPED_TRACE(testing::Message() << "Iteration " << i);
PasswordFormBuilder builder(kTestFormActionURL);
@@ -489,7 +479,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
}
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, HTMLDetector_SeveralDetections) {
+TEST_F(PasswordFormConversionUtilsTest, HTMLDetector_SeveralDetections) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
password_manager::features::kHtmlBasedUsernameDetector);
@@ -522,8 +512,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, HTMLDetector_SeveralDetections) {
username_detector_cache_.begin()->second[0].NameForAutofill().Utf8());
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
- HTMLDetector_UserGroupAttributes) {
+TEST_F(PasswordFormConversionUtilsTest, HTMLDetector_UserGroupAttributes) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
password_manager::features::kHtmlBasedUsernameDetector);
@@ -606,7 +595,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
"name1",
"johnsmith"}};
- for (size_t i = 0; i < arraysize(cases); ++i) {
+ for (size_t i = 0; i < base::size(cases); ++i) {
SCOPED_TRACE(testing::Message() << "Iteration " << i);
PasswordFormBuilder builder(kTestFormActionURL);
@@ -643,7 +632,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
}
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, HTMLDetectorCache) {
+TEST_F(PasswordFormConversionUtilsTest, HTMLDetectorCache) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
password_manager::features::kHtmlBasedUsernameDetector);
@@ -719,8 +708,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, HTMLDetectorCache) {
base::Bucket(UsernameDetectionMethod::HTML_BASED_CLASSIFIER, 2)));
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
- HTMLDetectorCache_SkipSomePredictions) {
+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
@@ -764,7 +752,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
EXPECT_EQ(base::UTF8ToUTF16("id"), password_form->username_element);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
+TEST_F(PasswordFormConversionUtilsTest,
IdentifyingUsernameFieldsWithBaseHeuristic) {
// Each test case consists of a set of parameters to be plugged into the
// PasswordFormBuilder below, plus the corresponding expectations.
@@ -839,7 +827,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
"John",
"William+usrname2, Smith+usrname3"}};
- for (size_t i = 0; i < arraysize(cases); ++i) {
+ 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()
@@ -870,7 +858,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
LoadHTMLAndConvertForm(html, nullptr, false);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ EXPECT_FALSE(password_form->only_for_fallback);
EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_element),
password_form->username_element);
@@ -892,7 +880,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
}
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, IdentifyingTwoPasswordFields) {
+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 {
@@ -916,7 +904,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, IdentifyingTwoPasswordFields) {
{{"", "beta"}, "password1", "", "password2", "beta", ""},
{{"alpha", "beta"}, "password1", "alpha", "password2", "beta", ""}};
- for (size_t i = 0; i < arraysize(cases); ++i) {
+ for (size_t i = 0; i < base::size(cases); ++i) {
SCOPED_TRACE(testing::Message() << "Iteration " << i);
PasswordFormBuilder builder(kTestFormActionURL);
@@ -931,7 +919,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, IdentifyingTwoPasswordFields) {
LoadHTMLAndConvertForm(html, nullptr, false);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ 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),
@@ -953,7 +941,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, IdentifyingTwoPasswordFields) {
}
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, IdentifyingThreePasswordFields) {
+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 {
@@ -985,7 +973,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, IdentifyingThreePasswordFields) {
// them the same for now to keep our abstract interpretation less flaky.
{{"", "", ""}, "password1", "", "password2", "", "password3"}};
- for (size_t i = 0; i < arraysize(cases); ++i) {
+ for (size_t i = 0; i < base::size(cases); ++i) {
SCOPED_TRACE(testing::Message() << "Iteration " << i);
PasswordFormBuilder builder(kTestFormActionURL);
@@ -1001,7 +989,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, IdentifyingThreePasswordFields) {
LoadHTMLAndConvertForm(html, nullptr, false);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ 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),
@@ -1023,7 +1011,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, IdentifyingThreePasswordFields) {
}
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
+TEST_F(PasswordFormConversionUtilsTest,
IdentifyingPasswordFieldsWithAutocompleteAttributes) {
// Each test case consists of a set of parameters to be plugged into the
// PasswordFormBuilder below, plus the corresponding expectations.
@@ -1348,7 +1336,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
"usrname2",
"Smith"}};
- for (size_t i = 0; i < arraysize(cases); ++i) {
+ for (size_t i = 0; i < base::size(cases); ++i) {
SCOPED_TRACE(testing::Message() << "Iteration " << i);
PasswordFormBuilder builder(kTestFormActionURL);
@@ -1366,7 +1354,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
LoadHTMLAndConvertForm(html, nullptr, false);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ 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'.
@@ -1398,7 +1386,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
}
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
+TEST_F(PasswordFormConversionUtilsTest,
UsernameDetection_AutocompleteAttribute) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddTextField("username", "JohnSmith", "username");
@@ -1418,7 +1406,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
UsernameDetectionMethod::AUTOCOMPLETE_ATTRIBUTE, 1);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, IgnoreInvisibledTextFields) {
+TEST_F(PasswordFormConversionUtilsTest, IgnoreInvisibledTextFields) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddNonDisplayedTextField("nondisplayed1", "nodispalyed_value1");
@@ -1434,7 +1422,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, IgnoreInvisibledTextFields) {
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, nullptr, false);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ 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);
@@ -1442,7 +1430,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, IgnoreInvisibledTextFields) {
EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->new_password_value);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, IgnoreInvisiblLoginPairs) {
+TEST_F(PasswordFormConversionUtilsTest, IgnoreInvisiblLoginPairs) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddNonDisplayedTextField("nondisplayed1", "nodispalyed_value1");
@@ -1462,7 +1450,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, IgnoreInvisiblLoginPairs) {
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, nullptr, false);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ 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);
@@ -1470,7 +1458,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, IgnoreInvisiblLoginPairs) {
EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->new_password_value);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, OnlyNonDisplayedLoginPair) {
+TEST_F(PasswordFormConversionUtilsTest, OnlyNonDisplayedLoginPair) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddNonDisplayedTextField("username", "William");
@@ -1481,7 +1469,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, OnlyNonDisplayedLoginPair) {
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, nullptr, false);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ EXPECT_FALSE(password_form->only_for_fallback);
EXPECT_EQ(base::UTF8ToUTF16("username"),
password_form->username_element);
EXPECT_EQ(base::UTF8ToUTF16("William"),
@@ -1492,7 +1480,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, OnlyNonDisplayedLoginPair) {
password_form->password_value);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, OnlyNonVisibleLoginPair) {
+TEST_F(PasswordFormConversionUtilsTest, OnlyNonVisibleLoginPair) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddNonVisibleTextField("username", "William");
@@ -1503,15 +1491,14 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, OnlyNonVisibleLoginPair) {
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, nullptr, false);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ 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(MAYBE_PasswordFormConversionUtilsTest,
- VisiblePasswordAndInvisibleUsername) {
+TEST_F(PasswordFormConversionUtilsTest, VisiblePasswordAndInvisibleUsername) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddNonDisplayedTextField("username", "William");
@@ -1522,14 +1509,14 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, nullptr, false);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ 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(MAYBE_PasswordFormConversionUtilsTest,
+TEST_F(PasswordFormConversionUtilsTest,
InvisiblePassword_LatestUsernameIsVisible) {
PasswordFormBuilder builder(kTestFormActionURL);
@@ -1542,14 +1529,14 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, nullptr, false);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ 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(MAYBE_PasswordFormConversionUtilsTest,
+TEST_F(PasswordFormConversionUtilsTest,
InvisiblePassword_LatestUsernameIsInvisible) {
PasswordFormBuilder builder(kTestFormActionURL);
@@ -1562,7 +1549,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, nullptr, false);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ 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);
@@ -1571,7 +1558,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
// Checks that username/password fields are detected based on user input even if
// visibility heuristics disagree.
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, UserInput) {
+TEST_F(PasswordFormConversionUtilsTest, UserInput) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddNonVisibleTextField("nonvisible_text", "actual_username");
@@ -1602,7 +1589,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, UserInput) {
form, &field_data_manager, nullptr, nullptr);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ EXPECT_FALSE(password_form->only_for_fallback);
EXPECT_EQ(base::UTF8ToUTF16("nonvisible_text"),
password_form->username_element);
EXPECT_EQ(base::UTF8ToUTF16("actual_username"),
@@ -1615,8 +1602,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, UserInput) {
EXPECT_EQ(base::UTF8ToUTF16(""), password_form->new_password_value);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
- TypedPasswordAndUsernameCachedOnPage) {
+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,
@@ -1660,7 +1646,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
form, &field_data_manager, nullptr, nullptr);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ EXPECT_FALSE(password_form->only_for_fallback);
EXPECT_EQ(base::UTF8ToUTF16("visible_text"), password_form->username_element);
EXPECT_EQ(base::UTF8ToUTF16("cached_username"),
@@ -1675,8 +1661,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
password_form->new_password_value);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
- TypedPasswordAndInvisibleUsername) {
+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
@@ -1718,7 +1703,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
form, &field_data_manager, nullptr, nullptr);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ EXPECT_FALSE(password_form->only_for_fallback);
EXPECT_EQ(base::UTF8ToUTF16("this_is_username"),
password_form->username_element);
@@ -1734,7 +1719,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
password_form->new_password_value);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, InvalidFormDueToBadActionURL) {
+TEST_F(PasswordFormConversionUtilsTest, InvalidFormDueToBadActionURL) {
PasswordFormBuilder builder("invalid_target");
builder.AddTextField("username", "JohnSmith", nullptr);
builder.AddSubmitButton("submit");
@@ -1746,8 +1731,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, InvalidFormDueToBadActionURL) {
EXPECT_FALSE(password_form);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
- InvalidFormDueToNoPasswordFields) {
+TEST_F(PasswordFormConversionUtilsTest, InvalidFormDueToNoPasswordFields) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddTextField("username1", "John", nullptr);
builder.AddTextField("username2", "Smith", nullptr);
@@ -1759,7 +1743,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
EXPECT_FALSE(password_form);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, ConfusingPasswordFields) {
+TEST_F(PasswordFormConversionUtilsTest, ConfusingPasswordFields) {
// Each test case consists of a set of parameters to be plugged into the
// PasswordFormBuilder below.
const char* cases[][3] = {
@@ -1772,7 +1756,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, ConfusingPasswordFields) {
{"alpha", "alpha", "alpha"},
{"alpha", "beta", "alpha"}};
- for (size_t i = 0; i < arraysize(cases); ++i) {
+ for (size_t i = 0; i < base::size(cases); ++i) {
SCOPED_TRACE(testing::Message() << "Iteration " << i);
PasswordFormBuilder builder(kTestFormActionURL);
@@ -1786,7 +1770,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, ConfusingPasswordFields) {
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, nullptr, false);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ 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);
@@ -1794,7 +1778,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, ConfusingPasswordFields) {
}
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
+TEST_F(PasswordFormConversionUtilsTest,
ManyPasswordFieldsWithoutAutocompleteAttributes) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddTextField("username1", "John", nullptr);
@@ -1808,14 +1792,14 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, nullptr, false);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ 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(MAYBE_PasswordFormConversionUtilsTest, SetOtherPossiblePasswords) {
+TEST_F(PasswordFormConversionUtilsTest, SetOtherPossiblePasswords) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddTextField("username1", "John", nullptr);
builder.AddPasswordField("password1", "alpha1", nullptr);
@@ -1849,7 +1833,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, SetOtherPossiblePasswords) {
ValueElementVectorToString(password_form->all_possible_passwords));
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
+TEST_F(PasswordFormConversionUtilsTest,
AllPossiblePasswordsIncludeAutofilledValue) {
for (bool autofilled_value_was_modified_by_user : {false, true}) {
PasswordFormBuilder builder(kTestFormActionURL);
@@ -1881,8 +1865,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
}
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
- CreditCardNumberWithTypePasswordForm) {
+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",
@@ -1900,7 +1883,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, &predictions, false);
EXPECT_TRUE(password_form);
- EXPECT_TRUE(password_form->only_for_fallback_saving);
+ 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);
@@ -1910,7 +1893,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
password_form->password_value);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, UsernamePredictionFromServer) {
+TEST_F(PasswordFormConversionUtilsTest, UsernamePredictionFromServer) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddTextField("username", "JohnSmith", nullptr);
// 'autocomplete' attribute cannot override server's prediction.
@@ -1935,7 +1918,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, UsernamePredictionFromServer) {
UsernameDetectionMethod::SERVER_SIDE_PREDICTION, 1);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
+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.
@@ -1969,7 +1952,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
EXPECT_EQ(base::UTF8ToUTF16("JohnSmith"), password_form->username_value);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
+TEST_F(PasswordFormConversionUtilsTest,
CreditCardVerificationNumberWithTypePasswordForm) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddTextField("Credit-card-owner-name", "John Smith", nullptr);
@@ -1987,7 +1970,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, &predictions, false);
EXPECT_TRUE(password_form);
- EXPECT_TRUE(password_form->only_for_fallback_saving);
+ 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"),
@@ -1996,7 +1979,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
EXPECT_EQ(base::UTF8ToUTF16("000"), password_form->password_value);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
+TEST_F(PasswordFormConversionUtilsTest,
CreditCardNumberWithTypePasswordFormWithAutocomplete) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddTextField("Credit-card-owner-name", "John Smith", nullptr);
@@ -2015,7 +1998,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, &predictions, false);
EXPECT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ 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);
@@ -2025,7 +2008,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
password_form->password_value);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
+TEST_F(PasswordFormConversionUtilsTest,
CreditCardVerificationNumberWithTypePasswordFormWithAutocomplete) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddTextField("Credit-card-owner-name", "John Smith", nullptr);
@@ -2043,7 +2026,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, &predictions, false);
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ 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"),
@@ -2054,7 +2037,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
EXPECT_EQ(base::UTF8ToUTF16("000"), password_form->new_password_value);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, IsGaiaReauthFormIgnored) {
+TEST_F(PasswordFormConversionUtilsTest, IsGaiaReauthFormIgnored) {
struct TestCase {
const char* origin;
struct KeyValue {
@@ -2151,7 +2134,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, IsGaiaReauthFormIgnored) {
}
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, IsGaiaWithSkipSavePasswordForm) {
+TEST_F(PasswordFormConversionUtilsTest, IsGaiaWithSkipSavePasswordForm) {
struct TestCase {
const char* origin;
bool expected_form_has_skip_save_password;
@@ -2185,7 +2168,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, IsGaiaWithSkipSavePasswordForm) {
}
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
+TEST_F(PasswordFormConversionUtilsTest,
IdentifyingFieldsWithoutNameOrIdAttributes) {
const char* kEmpty = nullptr;
const struct {
@@ -2206,7 +2189,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
"anonymous_new_password"},
};
- for (size_t i = 0; i < arraysize(test_cases); ++i) {
+ 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
@@ -2240,7 +2223,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
LoadHTMLAndConvertForm(html, nullptr, false);
EXPECT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ 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),
@@ -2250,7 +2233,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
}
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, TooManyFieldsToParseForm) {
+TEST_F(PasswordFormConversionUtilsTest, TooManyFieldsToParseForm) {
PasswordFormBuilder builder(kTestFormActionURL);
for (size_t i = 0; i < form_util::kMaxParseableFields + 1; ++i)
builder.AddTextField("id", "value", "autocomplete");
@@ -2259,7 +2242,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, TooManyFieldsToParseForm) {
EXPECT_FALSE(password_form);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, OnlyCreditCardFields) {
+TEST_F(PasswordFormConversionUtilsTest, OnlyCreditCardFields) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddTextField("ccname", "johnsmith", "cc-name");
builder.AddPasswordField("cc_security_code", "0123456789", "cc-csc");
@@ -2269,7 +2252,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, OnlyCreditCardFields) {
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, nullptr, false);
EXPECT_TRUE(password_form);
- EXPECT_TRUE(password_form->only_for_fallback_saving);
+ 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"),
@@ -2277,7 +2260,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, OnlyCreditCardFields) {
EXPECT_EQ(base::UTF8ToUTF16("0123456789"), password_form->password_value);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest,
+TEST_F(PasswordFormConversionUtilsTest,
FieldsWithAndWithoutCreditCardAttributes) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddTextField("username", "johnsmith", nullptr);
@@ -2292,14 +2275,14 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
ASSERT_TRUE(password_form);
- EXPECT_FALSE(password_form->only_for_fallback_saving);
+ 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(MAYBE_PasswordFormConversionUtilsTest, ResetPasswordForm) {
+TEST_F(PasswordFormConversionUtilsTest, ResetPasswordForm) {
// GetPassword (including HTML classifier) should process correctly forms
// without any text fields.
base::test::ScopedFeatureList feature_list;
@@ -2325,7 +2308,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, ResetPasswordForm) {
UsernameDetectionMethod::NO_USERNAME_DETECTED, 1);
}
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, StickyPasswordType) {
+TEST_F(PasswordFormConversionUtilsTest, StickyPasswordType) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddTextField("username", "johnsmith", nullptr);
builder.AddPasswordField("password", "secret", nullptr);
@@ -2362,7 +2345,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, StickyPasswordType) {
// Check that Chrome remembers the value typed by the user in cases when it gets
// overridden by the page.
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, TypedValuePreserved) {
+TEST_F(PasswordFormConversionUtilsTest, TypedValuePreserved) {
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddTextField("fine", "", "username");
builder.AddPasswordField("mangled", "", "current-password");
@@ -2420,7 +2403,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, TypedValuePreserved) {
}
// Check that non-text fields are ignored.
-TEST_F(MAYBE_PasswordFormConversionUtilsTest, NonTextFields) {
+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.
diff --git a/chromium/components/autofill/content/renderer/password_generation_agent.cc b/chromium/components/autofill/content/renderer/password_generation_agent.cc
index 841364a4350..deaa4959b13 100644
--- a/chromium/components/autofill/content/renderer/password_generation_agent.cc
+++ b/chromium/components/autofill/content/renderer/password_generation_agent.cc
@@ -36,9 +36,10 @@
#include "ui/gfx/geometry/rect.h"
using blink::WebAutofillState;
-using blink::WebInputElement;
+using blink::WebDocument;
using blink::WebFormControlElement;
using blink::WebFormElement;
+using blink::WebInputElement;
using blink::WebLocalFrame;
namespace autofill {
@@ -83,6 +84,28 @@ bool GetAccountCreationPasswordFields(
return !passwords->empty();
}
+// Returns the renderer id of the next password field in |control_elements|
+// after |new_password|. This field is likely to be the confirmation field.
+// Returns FormFieldData::kNotSetFormControlRendererId if there is no such
+// field.
+uint32_t FindConfirmationPasswordFieldId(
+ const std::vector<WebFormControlElement>& control_elements,
+ const WebFormControlElement& new_password) {
+ auto iter =
+ std::find(control_elements.begin(), control_elements.end(), new_password);
+
+ if (iter == control_elements.end())
+ return FormFieldData::kNotSetFormControlRendererId;
+
+ ++iter;
+ for (; iter != control_elements.end(); ++iter) {
+ const WebInputElement* input_element = ToWebInputElement(&(*iter));
+ if (input_element && input_element->IsPasswordFieldForAutofill())
+ return input_element->UniqueRendererFormControlId();
+ }
+ return FormFieldData::kNotSetFormControlRendererId;
+}
+
bool ContainsURL(const std::vector<GURL>& urls, const GURL& url) {
return base::ContainsValue(urls, url);
}
@@ -308,6 +331,7 @@ void PasswordGenerationAgent::DidCommitProvisionalLoad(
automatic_generation_element_.Reset();
current_generation_item_.reset();
last_focused_password_element_.Reset();
+ generation_enabled_fields_.clear();
}
void PasswordGenerationAgent::DidFinishDocumentLoad() {
@@ -442,7 +466,7 @@ void PasswordGenerationAgent::GeneratedPasswordAccepted(
std::unique_ptr<PasswordForm> presaved_form(CreatePasswordFormToPresave());
if (presaved_form) {
DCHECK_NE(base::string16(), presaved_form->password_value);
- GetPasswordManagerClient()->PresaveGeneratedPassword(*presaved_form);
+ GetPasswordGenerationDriver()->PresaveGeneratedPassword(*presaved_form);
}
// Call UpdateStateForTextChange after the corresponding PasswordFormManager
@@ -486,7 +510,27 @@ void PasswordGenerationAgent::FoundFormsEligibleForGeneration(
DetermineGenerationElement();
}
-void PasswordGenerationAgent::UserTriggeredGeneratePassword() {
+void PasswordGenerationAgent::FoundFormEligibleForGeneration(
+ const NewPasswordFormGenerationData& form) {
+ generation_enabled_fields_[form.new_password_renderer_id] = form;
+
+ if (mark_generation_element_) {
+ // Mark the input element with renderer id |form.new_password_renderer_id|.
+ if (!render_frame())
+ return;
+ WebDocument doc = render_frame()->GetWebFrame()->GetDocument();
+ if (doc.IsNull())
+ return;
+ WebFormControlElement new_password_input =
+ form_util::FindFormControlElementsByUniqueRendererId(
+ doc, form.new_password_renderer_id);
+ if (!new_password_input.IsNull())
+ new_password_input.SetAttribute("password_creation_field", "1");
+ }
+}
+
+void PasswordGenerationAgent::UserTriggeredGeneratePassword(
+ UserTriggeredGeneratePasswordCallback callback) {
if (SetUpUserTriggeredGeneration()) {
LogMessage(Logger::STRING_GENERATION_RENDERER_SHOW_MANUAL_GENERATION_POPUP);
autofill::password_generation::PasswordGenerationUIData
@@ -499,11 +543,10 @@ void PasswordGenerationAgent::UserTriggeredGeneratePassword() {
GetTextDirectionForElement(
current_generation_item_->generation_element_),
current_generation_item_->form_);
- // TODO(crbug.com/845458): remove it. The renderer should never invoke the
- // prompt directly.
- GetPasswordManagerClient()->ShowManualPasswordGenerationPopup(
- password_generation_ui_data);
+ std::move(callback).Run(std::move(password_generation_ui_data));
current_generation_item_->generation_popup_shown_ = true;
+ } else {
+ std::move(callback).Run(base::nullopt);
}
}
@@ -575,7 +618,7 @@ void PasswordGenerationAgent::DetermineGenerationElement() {
current_generation_item_.reset(new GenerationItemInfo(
*automatic_generation_form_data_, automatic_generation_element_));
}
- GetPasswordManagerClient()->GenerationAvailableForForm(
+ GetPasswordGenerationDriver()->GenerationAvailableForForm(
automatic_generation_form_data_->form);
return;
}
@@ -585,46 +628,58 @@ bool PasswordGenerationAgent::SetUpUserTriggeredGeneration() {
if (last_focused_password_element_.IsNull() || !render_frame())
return false;
- WebFormElement form = last_focused_password_element_.Form();
- std::unique_ptr<PasswordForm> password_form;
- std::vector<WebFormControlElement> control_elements;
- if (!form.IsNull()) {
- password_form = password_agent_->GetPasswordFormFromWebForm(form);
- control_elements = form_util::ExtractAutofillableElementsInForm(form);
+ uint32_t last_focused_password_element_id =
+ last_focused_password_element_.UniqueRendererFormControlId();
+
+ bool is_automatic_generation_available = base::ContainsKey(
+ generation_enabled_fields_, last_focused_password_element_id);
+
+ if (!is_automatic_generation_available) {
+ WebFormElement form = last_focused_password_element_.Form();
+ std::vector<WebFormControlElement> control_elements;
+ if (!form.IsNull()) {
+ control_elements = form_util::ExtractAutofillableElementsInForm(form);
+ } else {
+ const WebLocalFrame& frame = *render_frame()->GetWebFrame();
+ blink::WebDocument doc = frame.GetDocument();
+ if (doc.IsNull())
+ return false;
+ control_elements =
+ form_util::GetUnownedFormFieldElements(doc.All(), nullptr);
+ }
+
+ MaybeCreateCurrentGenerationItem(
+ last_focused_password_element_,
+ FindConfirmationPasswordFieldId(control_elements,
+ last_focused_password_element_));
} else {
- const WebLocalFrame& frame = *render_frame()->GetWebFrame();
- blink::WebDocument doc = frame.GetDocument();
- if (doc.IsNull())
- return false;
- password_form = password_agent_->GetPasswordFormFromUnownedInputElements();
- control_elements =
- form_util::GetUnownedFormFieldElements(doc.All(), nullptr);
+ auto it = generation_enabled_fields_.find(last_focused_password_element_id);
+ MaybeCreateCurrentGenerationItem(
+ last_focused_password_element_,
+ it->second.confirmation_password_renderer_id);
}
- if (!password_form)
+ if (!current_generation_item_)
return false;
- std::vector<WebInputElement> password_elements;
- GetAccountCreationPasswordFields(control_elements, &password_elements);
- password_elements = FindPasswordElementsForGeneration(
- password_elements,
- PasswordFormGenerationData(
- 0, /* form_signature */
- CalculateFieldSignatureByNameAndType(
- last_focused_password_element_.NameForAutofill().Utf16(),
- last_focused_password_element_.FormControlTypeForAutofill()
- .Utf8())));
- // TODO(crbug/866444): remove this once it's impossible that currently focused
- // password field isn't found by FindPasswordElementsForGeneration.
- if (!std::count(password_elements.begin(), password_elements.end(),
- last_focused_password_element_))
+ if (current_generation_item_->generation_element_ !=
+ last_focused_password_element_) {
return false;
- current_generation_item_.reset(new GenerationItemInfo(
- last_focused_password_element_, std::move(*password_form),
- std::move(password_elements)));
- // |automatic_generation_element_| should always generate the UI.
+ }
+
+ // Automatic generation depends on whether the new parser is on because the
+ // new parser sends now information to the renderer about fields for
+ // generation. In case when the new old parser is used the old path for
+ // automatic generation is used. So detecting which automatic generation
+ // depends on which parser is used.
+ // TODO(https://crbug.com/831123): Remove this variable when the old parser is
+ // gone.
+ bool automatic_generation_available_with_the_old_parser =
+ last_focused_password_element_ == automatic_generation_element_;
+
current_generation_item_->is_manually_triggered_ =
- (last_focused_password_element_ != automatic_generation_element_);
+ !is_automatic_generation_available &&
+ !automatic_generation_available_with_the_old_parser;
return true;
}
@@ -641,10 +696,20 @@ bool PasswordGenerationAgent::FocusedNodeHasChanged(
}
const WebInputElement* element = ToWebInputElement(&web_element);
- if (element && element->IsPasswordFieldForAutofill())
+ if (!element)
+ return false;
+
+ if (element->IsPasswordFieldForAutofill())
last_focused_password_element_ = *element;
- if (!element || !current_generation_item_ ||
+ auto it =
+ generation_enabled_fields_.find(element->UniqueRendererFormControlId());
+ if (it != generation_enabled_fields_.end()) {
+ MaybeCreateCurrentGenerationItem(
+ *element, it->second.confirmation_password_renderer_id);
+ }
+
+ if (!current_generation_item_ ||
*element != current_generation_item_->generation_element_) {
return false;
}
@@ -699,7 +764,7 @@ bool PasswordGenerationAgent::TextDidChangeInTextField(
std::unique_ptr<PasswordForm> presaved_form(
CreatePasswordFormToPresave());
if (presaved_form)
- GetPasswordManagerClient()->PresaveGeneratedPassword(*presaved_form);
+ GetPasswordGenerationDriver()->PresaveGeneratedPassword(*presaved_form);
}
return false;
}
@@ -737,7 +802,7 @@ bool PasswordGenerationAgent::TextDidChangeInTextField(
std::unique_ptr<PasswordForm> presaved_form(
CreatePasswordFormToPresave());
if (presaved_form) {
- GetPasswordManagerClient()->PresaveGeneratedPassword(*presaved_form);
+ GetPasswordGenerationDriver()->PresaveGeneratedPassword(*presaved_form);
}
}
}
@@ -770,19 +835,19 @@ void PasswordGenerationAgent::AutomaticGenerationStatusChanged(bool available) {
current_generation_item_->generation_element_),
current_generation_item_->form_);
current_generation_item_->generation_popup_shown_ = true;
- GetPasswordManagerClient()->AutomaticGenerationStatusChanged(
+ GetPasswordGenerationDriver()->AutomaticGenerationStatusChanged(
true, password_generation_ui_data);
} else {
// Hide the generation popup.
- GetPasswordManagerClient()->AutomaticGenerationStatusChanged(false,
- base::nullopt);
+ GetPasswordGenerationDriver()->AutomaticGenerationStatusChanged(
+ false, base::nullopt);
}
}
void PasswordGenerationAgent::ShowEditingPopup() {
if (!render_frame())
return;
- GetPasswordManagerClient()->ShowPasswordEditingPopup(
+ GetPasswordGenerationDriver()->ShowPasswordEditingPopup(
render_frame()->GetRenderView()->ElementBoundsInWindow(
current_generation_item_->generation_element_),
*CreatePasswordFormToPresave());
@@ -790,7 +855,7 @@ void PasswordGenerationAgent::ShowEditingPopup() {
}
void PasswordGenerationAgent::GenerationRejectedByTyping() {
- GetPasswordManagerClient()->PasswordGenerationRejectedByTyping();
+ GetPasswordGenerationDriver()->PasswordGenerationRejectedByTyping();
}
void PasswordGenerationAgent::PasswordNoLongerGenerated() {
@@ -813,7 +878,41 @@ void PasswordGenerationAgent::PasswordNoLongerGenerated() {
}
std::unique_ptr<PasswordForm> presaved_form(CreatePasswordFormToPresave());
if (presaved_form)
- GetPasswordManagerClient()->PasswordNoLongerGenerated(*presaved_form);
+ GetPasswordGenerationDriver()->PasswordNoLongerGenerated(*presaved_form);
+}
+
+void PasswordGenerationAgent::MaybeCreateCurrentGenerationItem(
+ WebInputElement element,
+ uint32_t confirmation_password_renderer_id) {
+ // Do not create |current_generation_item_| if it already is created for
+ // |element| or the user accepted generated password. So if the user accepted
+ // the generated password, generation is not offered on any other field.
+ if (current_generation_item_ &&
+ (current_generation_item_->generation_element_ == element ||
+ current_generation_item_->password_is_generated_))
+ return;
+
+ std::unique_ptr<PasswordForm> password_form =
+ element.Form().IsNull()
+ ? password_agent_->GetPasswordFormFromUnownedInputElements()
+ : password_agent_->GetPasswordFormFromWebForm(element.Form());
+
+ std::vector<blink::WebInputElement> passwords = {element};
+
+ WebFormControlElement confirmation_password =
+ form_util::FindFormControlElementsByUniqueRendererId(
+ element.GetDocument(), confirmation_password_renderer_id);
+
+ if (!confirmation_password.IsNull()) {
+ WebInputElement* input = ToWebInputElement(&confirmation_password);
+ if (input)
+ passwords.push_back(*input);
+ }
+
+ current_generation_item_.reset(new GenerationItemInfo(
+ element, std::move(*password_form), std::move(passwords)));
+
+ element.SetAttribute("aria-autocomplete", "list");
}
const mojom::PasswordManagerDriverAssociatedPtr&
@@ -822,14 +921,14 @@ PasswordGenerationAgent::GetPasswordManagerDriver() {
return password_agent_->GetPasswordManagerDriver();
}
-const mojom::PasswordManagerClientAssociatedPtr&
-PasswordGenerationAgent::GetPasswordManagerClient() {
- if (!password_manager_client_) {
+const mojom::PasswordGenerationDriverAssociatedPtr&
+PasswordGenerationAgent::GetPasswordGenerationDriver() {
+ if (!password_generation_client_) {
render_frame()->GetRemoteAssociatedInterfaces()->GetInterface(
- &password_manager_client_);
+ &password_generation_client_);
}
- return password_manager_client_;
+ return password_generation_client_;
}
void PasswordGenerationAgent::LogMessage(Logger::StringID message_id) {
diff --git a/chromium/components/autofill/content/renderer/password_generation_agent.h b/chromium/components/autofill/content/renderer/password_generation_agent.h
index 653e8349845..40915c52e06 100644
--- a/chromium/components/autofill/content/renderer/password_generation_agent.h
+++ b/chromium/components/autofill/content/renderer/password_generation_agent.h
@@ -55,9 +55,12 @@ class PasswordGenerationAgent : public content::RenderFrameObserver,
void GeneratedPasswordAccepted(const base::string16& password) override;
void FoundFormsEligibleForGeneration(
const std::vector<PasswordFormGenerationData>& forms) override;
- // Sets |generation_element_| to the focused password field and shows a
- // generation popup at this field.
- void UserTriggeredGeneratePassword() override;
+ void FoundFormEligibleForGeneration(
+ const NewPasswordFormGenerationData& form) override;
+ // Sets |generation_element_| to the focused password field and responds back
+ // if the generation was triggered successfully.
+ void UserTriggeredGeneratePassword(
+ UserTriggeredGeneratePasswordCallback callback) override;
// Returns true if the field being changed is one where a generated password
// is being offered. Updates the state of the popup if necessary.
@@ -86,7 +89,9 @@ class PasswordGenerationAgent : public content::RenderFrameObserver,
#if defined(UNIT_TEST)
// This method requests the autofill::mojom::PasswordManagerClient which binds
// requests the binding if it wasn't bound yet.
- void RequestPasswordManagerClientForTesting() { GetPasswordManagerClient(); }
+ void RequestPasswordManagerClientForTesting() {
+ GetPasswordGenerationDriver();
+ }
#endif
protected:
@@ -115,7 +120,8 @@ class PasswordGenerationAgent : public content::RenderFrameObserver,
const mojom::PasswordManagerDriverAssociatedPtr& GetPasswordManagerDriver();
- const mojom::PasswordManagerClientAssociatedPtr& GetPasswordManagerClient();
+ const mojom::PasswordGenerationDriverAssociatedPtr&
+ GetPasswordGenerationDriver();
// Helper function that will try and populate |password_elements_| and
// |possible_account_creation_form_|.
@@ -154,6 +160,13 @@ class PasswordGenerationAgent : public content::RenderFrameObserver,
// Stops treating a password as generated.
void PasswordNoLongerGenerated();
+ // Creates |current_generation_item_| for |element| if |element| is a
+ // generation enabled element. If |current_generation_item_| is already
+ // created for |element| it is not recreated.
+ void MaybeCreateCurrentGenerationItem(
+ blink::WebInputElement element,
+ uint32_t confirmation_password_renderer_id);
+
// Runs HTML parsing based classifier and saves its outcome to proto.
// TODO(crbug.com/621442): Remove client-side form classifier when server-side
// classifier is ready.
@@ -200,6 +213,10 @@ class PasswordGenerationAgent : public content::RenderFrameObserver,
// the last focused password element.
blink::WebInputElement last_focused_password_element_;
+ // Contains correspondence between generaiton enabled element and data for
+ // generation.
+ std::map<uint32_t, NewPasswordFormGenerationData> generation_enabled_fields_;
+
// If this feature is enabled. Controlled by Finch.
bool enabled_;
@@ -211,7 +228,7 @@ class PasswordGenerationAgent : public content::RenderFrameObserver,
// in password fields are updated.
PasswordAutofillAgent* password_agent_;
- mojom::PasswordManagerClientAssociatedPtr password_manager_client_;
+ mojom::PasswordGenerationDriverAssociatedPtr password_generation_client_;
mojo::AssociatedBinding<mojom::PasswordGenerationAgent> binding_;
diff --git a/chromium/components/autofill/content/renderer/prefilled_values_detector.cc b/chromium/components/autofill/content/renderer/prefilled_values_detector.cc
new file mode 100644
index 00000000000..c20059cf053
--- /dev/null
+++ b/chromium/components/autofill/content/renderer/prefilled_values_detector.cc
@@ -0,0 +1,107 @@
+// 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/prefilled_values_detector.h"
+
+#include "base/no_destructor.h"
+#include "base/strings/string_util.h"
+
+namespace autofill {
+
+const base::flat_set<std::string, std::less<>>& KnownUsernamePlaceholders() {
+ // Explicitly create a |StringFlatSet| when constructing
+ // kPrefilledUsernameValues to work around GCC bug 84849, which causes the
+ // initializer list not to be properly forwarded to base::flat_set's
+ // constructor.
+ using StringFlatSet = base::flat_set<std::string, std::less<>>;
+ static base::NoDestructor<StringFlatSet> kPrefilledUsernameValues(
+ StringFlatSet({"___.___.___-__",
+ "+1",
+ "3~15个字符,中文字符7个以内",
+ "benutzername",
+ "client id",
+ "codice titolare"
+ "digite seu cpf ou e-mail",
+ "ds logon username",
+ "email",
+ "email address",
+ "email masih kosong",
+ "email/手機號碼",
+ "e-mail/username",
+ "e-mail address",
+ "enter username",
+ "enter user name",
+ "identifiant",
+ "kullanıcı adı",
+ "kunden-id",
+ "login",
+ "nick",
+ "nom d'usuari",
+ "nom utilisateur",
+ "rut",
+ "siret",
+ "this is usually your email address",
+ "tu dni",
+ "uid/用戶名/email",
+ "uporabnik...",
+ "user/codice",
+ "user id",
+ "user name",
+ "username",
+ "username or email",
+ "username or email:",
+ "username/email",
+ "usuario",
+ "your email address",
+ "ååååmmddxxxx",
+ "아이디 or @이하 모두 입력",
+ "Имя",
+ "Имя (логин)"
+ "Логин",
+ "Логин...",
+ "Логин (e-mail)",
+ "שם משתמש",
+ "כתובת דוא''ל",
+ "اسم العضو",
+ "اسم المستخدم",
+ "الاسم",
+ "نام کاربری",
+ "メールアドレス",
+ "อีเมล",
+ "用户名",
+ "用户名/email",
+ "邮箱/手机",
+ "帳號",
+ "請輸入身份證字號",
+ "请用微博帐号登录",
+ "请输入手机号或邮箱",
+ "请输入邮箱或手机号",
+ "邮箱/手机/展位号"}));
+ return *kPrefilledUsernameValues;
+}
+
+bool PossiblePrefilledUsernameValue(const std::string& username_value,
+ const std::string& possible_email_domain) {
+ const auto& placeholders = KnownUsernamePlaceholders();
+
+ std::string normalized_username_value = base::ToLowerASCII(
+ base::TrimWhitespaceASCII(username_value, base::TRIM_ALL));
+
+ if (normalized_username_value.empty())
+ return true;
+
+ // Check whether the prefilled value looks like "@example.com",
+ // "@mail.example.com" or other strings matching the regex
+ // "^@.*possible_email_domain$" where the string possible_email_domain is
+ // replaced with the value of |possible_email_domain|.
+ if (normalized_username_value[0] == '@' && !possible_email_domain.empty() &&
+ base::EndsWith(normalized_username_value, possible_email_domain,
+ base::CompareCase::SENSITIVE)) {
+ return true;
+ }
+
+ return placeholders.find(normalized_username_value) != placeholders.end();
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/content/renderer/prefilled_values_detector.h b/chromium/components/autofill/content/renderer/prefilled_values_detector.h
new file mode 100644
index 00000000000..8c4c732dc26
--- /dev/null
+++ b/chromium/components/autofill/content/renderer/prefilled_values_detector.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_CONTENT_RENDERER_PREFILLED_VALUES_DETECTOR_H_
+#define COMPONENTS_AUTOFILL_CONTENT_RENDERER_PREFILLED_VALUES_DETECTOR_H_
+
+#include <string>
+
+#include "base/containers/flat_set.h"
+
+namespace autofill {
+
+// Returns a set of known username placeholders, all guaranteed to be lower
+// case.
+// This is only exposed for testing.
+const base::flat_set<std::string, std::less<>>& KnownUsernamePlaceholders();
+
+// Checks if the prefilled value of the username element is one of the known
+// values possibly used as placeholders. The list of possible placeholder
+// values comes from popular sites exhibiting this issue.
+//
+// If |username_value| is in KnownUsernamePlaceholder(), the password manager
+// takes the liberty to override the contents of the username field.
+//
+// The |possible_email_domain| is supposed to be the eTLD+1 for which the
+// credential was saved. So if the credential was saved for
+// https://www.example.com, there is a chance that the website prefills
+// the username field with "@example.com".
+//
+// TODO(crbug.com/832622): Remove this once a stable solution is in place.
+bool PossiblePrefilledUsernameValue(const std::string& username_value,
+ const std::string& possible_email_domain);
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CONTENT_RENDERER_PREFILLED_VALUES_DETECTOR_H_
diff --git a/chromium/components/autofill/content/renderer/prefilled_values_detector_unittest.cc b/chromium/components/autofill/content/renderer/prefilled_values_detector_unittest.cc
new file mode 100644
index 00000000000..6c3250665e3
--- /dev/null
+++ b/chromium/components/autofill/content/renderer/prefilled_values_detector_unittest.cc
@@ -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.
+
+#include "components/autofill/content/renderer/prefilled_values_detector.h"
+
+#include "base/strings/string_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+
+// Ensure that all entries in KnownUsernamePlaceholders() are lowercase because
+// the lowercase string of the website is tested against this set.
+TEST(PossiblePrefilledUsernameValue, AllLowerCase) {
+ for (const auto& entry : KnownUsernamePlaceholders())
+ EXPECT_EQ(entry, base::ToLowerASCII(entry));
+}
+
+TEST(PossiblePrefilledUsernameValue, Whitespace) {
+ EXPECT_TRUE(PossiblePrefilledUsernameValue(" ", ""));
+}
+
+TEST(PossiblePrefilledUsernameValue, EmailAddress) {
+ EXPECT_TRUE(PossiblePrefilledUsernameValue("@example.com", "example.com"));
+ EXPECT_TRUE(PossiblePrefilledUsernameValue("@EXAMPLE.COM", "example.com"));
+ EXPECT_TRUE(PossiblePrefilledUsernameValue(" @example.com", "example.com"));
+ EXPECT_TRUE(
+ PossiblePrefilledUsernameValue("@mail.example.com", "example.com"));
+ EXPECT_FALSE(
+ PossiblePrefilledUsernameValue("user@example.com", "example.com"));
+ EXPECT_FALSE(PossiblePrefilledUsernameValue("@example.com", "foo.com"));
+ EXPECT_FALSE(PossiblePrefilledUsernameValue("@example.com", ""));
+ EXPECT_FALSE(PossiblePrefilledUsernameValue("@", "foo.com"));
+ EXPECT_FALSE(PossiblePrefilledUsernameValue("@", ""));
+}
+
+} // namespace autofill
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 a6fd8da6d89..582915ac830 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
@@ -4,9 +4,9 @@
#include "components/autofill/content/renderer/renderer_save_password_progress_logger.h"
-#include "base/message_loop/message_loop.h"
#include "base/optional.h"
#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
#include "components/autofill/content/common/autofill_driver.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -74,6 +74,8 @@ class FakeContentPasswordManagerDriver : public mojom::PasswordManagerDriver {
const GURL& frame_url) override {}
void FocusedInputChanged(bool is_fillable, bool is_password_field) override {}
+ void LogFirstFillingResult(uint32_t form_renderer_id,
+ int32_t result) override {}
// Records whether RecordSavePasswordProgress() gets called.
bool called_record_save_;
@@ -94,7 +96,7 @@ class TestLogger : public RendererSavePasswordProgressLogger {
} // namespace
TEST(RendererSavePasswordProgressLoggerTest, SendLog) {
- base::MessageLoop loop;
+ base::test::ScopedTaskEnvironment task_environment;
FakeContentPasswordManagerDriver fake_driver;
mojom::PasswordManagerDriverPtr driver_ptr =
fake_driver.CreateInterfacePtrAndBind();
diff --git a/chromium/components/autofill/core/browser/BUILD.gn b/chromium/components/autofill/core/browser/BUILD.gn
index 5d4a8b08b0c..46afe629e70 100644
--- a/chromium/components/autofill/core/browser/BUILD.gn
+++ b/chromium/components/autofill/core/browser/BUILD.gn
@@ -4,6 +4,7 @@
import("//build/config/chrome_build.gni")
import("//build/config/jumbo.gni")
+import("//build/util/version.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
jumbo_static_library("browser") {
@@ -64,6 +65,8 @@ jumbo_static_library("browser") {
"autofill_metadata.h",
"autofill_metrics.cc",
"autofill_metrics.h",
+ "autofill_observer.cc",
+ "autofill_observer.h",
"autofill_popup_delegate.h",
"autofill_profile.cc",
"autofill_profile.h",
@@ -79,6 +82,8 @@ jumbo_static_library("browser") {
"autofill_provider.h",
"autofill_scanner.cc",
"autofill_scanner.h",
+ "autofill_subject.cc",
+ "autofill_subject.h",
"autofill_type.cc",
"autofill_type.h",
"autofill_wallet_data_type_controller.cc",
@@ -126,6 +131,8 @@ jumbo_static_library("browser") {
"legal_message_line.h",
"local_card_migration_manager.cc",
"local_card_migration_manager.h",
+ "local_card_migration_strike_database.cc",
+ "local_card_migration_strike_database.h",
"name_field.cc",
"name_field.h",
"password_requirements_spec_fetcher.h",
@@ -170,6 +177,8 @@ jumbo_static_library("browser") {
"state_names.h",
"strike_database.cc",
"strike_database.h",
+ "strike_database_integrator_base.cc",
+ "strike_database_integrator_base.h",
"subkey_requester.cc",
"subkey_requester.h",
"suggestion.cc",
@@ -177,6 +186,8 @@ jumbo_static_library("browser") {
"suggestion_selection.cc",
"suggestion_selection.h",
"sync_utils.h",
+ "test_data_creator.cc",
+ "test_data_creator.h",
"ui/card_unmask_prompt_controller.h",
"ui/card_unmask_prompt_controller_impl.cc",
"ui/card_unmask_prompt_controller_impl.h",
@@ -265,6 +276,8 @@ jumbo_static_library("browser") {
]
}
+ defines = [ "CHROME_VERSION_MAJOR=" + chrome_version_major ]
+
configs += [ "//build/config:precompiled_headers" ]
public_deps = [
@@ -332,11 +345,15 @@ jumbo_static_library("test_support") {
"autofill_test_utils.h",
"data_driven_test.cc",
"data_driven_test.h",
+ "mock_autocomplete_history_manager.cc",
+ "mock_autocomplete_history_manager.h",
"payments/test_payments_client.cc",
"payments/test_payments_client.h",
"suggestion_test_helpers.h",
"test_address_normalizer.cc",
"test_address_normalizer.h",
+ "test_autofill_async_observer.cc",
+ "test_autofill_async_observer.h",
"test_autofill_client.cc",
"test_autofill_client.h",
"test_autofill_clock.cc",
@@ -366,6 +383,8 @@ jumbo_static_library("test_support") {
"test_legacy_strike_database.h",
"test_local_card_migration_manager.cc",
"test_local_card_migration_manager.h",
+ "test_local_card_migration_strike_database.cc",
+ "test_local_card_migration_strike_database.h",
"test_personal_data_manager.cc",
"test_personal_data_manager.h",
"test_region_data_loader.cc",
@@ -483,6 +502,7 @@ source_set("unit_tests") {
"autofill_profile_unittest.cc",
"autofill_profile_validation_util_unittest.cc",
"autofill_profile_validator_unittest.cc",
+ "autofill_subject_unittest.cc",
"autofill_type_unittest.cc",
"autofill_wallet_data_type_controller_unittest.cc",
"contact_info_unittest.cc",
@@ -500,6 +520,7 @@ source_set("unit_tests") {
"legacy_strike_database_unittest.cc",
"legal_message_line_unittest.cc",
"local_card_migration_manager_unittest.cc",
+ "local_card_migration_strike_database_unittest.cc",
"name_field_unittest.cc",
"password_generator_fips181_unittest.cc",
"password_generator_unittest.cc",
@@ -547,6 +568,8 @@ source_set("unit_tests") {
]
}
+ defines = [ "CHROME_VERSION_MAJOR=" + chrome_version_major ]
+
deps = [
":browser",
":password_generator",
diff --git a/chromium/components/autofill/core/browser/DEPS b/chromium/components/autofill/core/browser/DEPS
index 889d6437e66..35cb68b74d4 100644
--- a/chromium/components/autofill/core/browser/DEPS
+++ b/chromium/components/autofill/core/browser/DEPS
@@ -9,6 +9,13 @@ include_rules = [
"+components/policy",
"+components/security_state",
"+components/signin/core/browser",
+ # Use identity_manager.h instead of the below files;
+ # see https://groups.google.com/a/chromium.org/d/msg/chromium-dev/dgFLuxqZt1o/iEqkyoQQBwAJ for help and info.
+ "-components/signin/core/browser/fake_profile_oauth2_token_service.h",
+ "-components/signin/core/browser/profile_oauth2_token_service.h",
+ "-components/signin/core/browser/fake_signin_manager.h",
+ "-components/signin/core/browser/signin_manager.h",
+ "-components/signin/core/browser/signin_manager_base.h",
"+components/sync",
"+components/variations",
"+components/version_info",
diff --git a/chromium/components/autofill/core/browser/OWNERS b/chromium/components/autofill/core/browser/OWNERS
deleted file mode 100644
index fa37e3a038b..00000000000
--- a/chromium/components/autofill/core/browser/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-per-file *password*=vabr@chromium.org
diff --git a/chromium/components/autofill/core/browser/address_field_unittest.cc b/chromium/components/autofill/core/browser/address_field_unittest.cc
index 4791ab09125..78549dfb657 100644
--- a/chromium/components/autofill/core/browser/address_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/address_field_unittest.cc
@@ -32,7 +32,8 @@ class AddressFieldTest : public testing::Test {
// Downcast for tests.
static std::unique_ptr<AddressField> Parse(AutofillScanner* scanner) {
std::unique_ptr<FormField> field = AddressField::Parse(scanner);
- return base::WrapUnique(static_cast<AddressField*>(field.release()));
+ return std::unique_ptr<AddressField>(
+ static_cast<AddressField*>(field.release()));
}
private:
diff --git a/chromium/components/autofill/core/browser/address_normalizer_impl.cc b/chromium/components/autofill/core/browser/address_normalizer_impl.cc
index ca78af9d58a..8c2e4f4dfca 100644
--- a/chromium/components/autofill/core/browser/address_normalizer_impl.cc
+++ b/chromium/components/autofill/core/browser/address_normalizer_impl.cc
@@ -77,9 +77,9 @@ std::unique_ptr<AddressValidator> CreateAddressValidator(
std::unique_ptr<Source> source,
DeleteOnTaskRunnerStorageUniquePtr storage,
LoadRulesListener* load_rules_listener) {
- return std::make_unique<AddressValidator>(std::move(source),
- base::WrapUnique(storage.release()),
- load_rules_listener);
+ return std::make_unique<AddressValidator>(
+ std::move(source), std::unique_ptr<Storage>(storage.release()),
+ load_rules_listener);
}
} // namespace
diff --git a/chromium/components/autofill/core/browser/autocomplete_history_manager.cc b/chromium/components/autofill/core/browser/autocomplete_history_manager.cc
index f68b96cb66a..d15eb19251a 100644
--- a/chromium/components/autofill/core/browser/autocomplete_history_manager.cc
+++ b/chromium/components/autofill/core/browser/autocomplete_history_manager.cc
@@ -4,19 +4,27 @@
#include "components/autofill/core/browser/autocomplete_history_manager.h"
+#include <unordered_map>
+#include <utility>
#include <vector>
+#include "base/memory/weak_ptr.h"
+#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/autofill_client.h"
-#include "components/autofill/core/browser/autofill_driver.h"
#include "components/autofill/core/browser/autofill_experiments.h"
-#include "components/autofill/core/browser/autofill_external_delegate.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/suggestion.h"
#include "components/autofill/core/browser/validation.h"
+#include "components/autofill/core/browser/webdata/autofill_entry.h"
+#include "components/autofill/core/common/autofill_clock.h"
+#include "components/autofill/core/common/autofill_features.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/form_data.h"
#include "components/prefs/pref_service.h"
+#include "components/version_info/version_info.h"
+
+using NotificationType = autofill::AutofillObserver::NotificationType;
namespace autofill {
namespace {
@@ -69,52 +77,108 @@ void AutocompleteHistoryManager::UMARecorder::OnWebDataServiceRequestDone(
AutofillMetrics::LogAutocompleteSuggestions(has_suggestion);
}
-AutocompleteHistoryManager::AutocompleteHistoryManager(
- AutofillDriver* driver,
- AutofillClient* autofill_client)
- : driver_(driver),
- database_(autofill_client->GetDatabase()),
- pending_query_handle_(0),
- query_id_(0),
- external_delegate_(nullptr),
- autofill_client_(autofill_client) {
- DCHECK(autofill_client_);
-}
+AutocompleteHistoryManager::QueryHandler::QueryHandler(
+ int client_query_id,
+ bool autoselect_first_suggestion,
+ base::string16 prefix,
+ base::WeakPtr<SuggestionsHandler> handler)
+ : client_query_id_(client_query_id),
+ autoselect_first_suggestion_(autoselect_first_suggestion),
+ prefix_(prefix),
+ handler_(std::move(handler)) {}
+
+AutocompleteHistoryManager::QueryHandler::QueryHandler(
+ const QueryHandler& original) = default;
+
+AutocompleteHistoryManager::QueryHandler::~QueryHandler() = default;
+
+AutocompleteHistoryManager::AutocompleteHistoryManager()
+ // It is safe to base::Unretained a raw pointer to the current instance,
+ // as it is already being owned elsewhere and will be cleaned-up properly.
+ // Also, the map of callbacks will be deleted when this instance is
+ // destroyed, which means we won't attempt to run one of these callbacks
+ // beyond the life of this instance.
+ : request_callbacks_(
+ {{AUTOFILL_VALUE_RESULT,
+ base::BindRepeating(
+ &AutocompleteHistoryManager::OnAutofillValuesReturned,
+ base::Unretained(this))},
+ {AUTOFILL_CLEANUP_RESULT,
+ base::BindRepeating(
+ &AutocompleteHistoryManager::OnAutofillCleanupReturned,
+ base::Unretained(this))}}),
+ weak_ptr_factory_(this) {}
AutocompleteHistoryManager::~AutocompleteHistoryManager() {
- CancelPendingQuery();
+ CancelAllPendingQueries();
+}
+
+void AutocompleteHistoryManager::Init(
+ scoped_refptr<AutofillWebDataService> profile_database,
+ PrefService* pref_service,
+ bool is_off_the_record) {
+ profile_database_ = profile_database;
+ pref_service_ = pref_service;
+ is_off_the_record_ = is_off_the_record;
+
+ // No need to run the retention policy in OTR.
+ if (!is_off_the_record_ &&
+ base::FeatureList::IsEnabled(
+ autofill::features::kAutocompleteRetentionPolicyEnabled)) {
+ // Upon successful cleanup, the last cleaned-up major version is being
+ // stored in this pref.
+ int last_cleaned_version = pref_service_->GetInteger(
+ prefs::kAutocompleteLastVersionRetentionPolicy);
+ if (CHROME_VERSION_MAJOR > last_cleaned_version) {
+ // Trigger the cleanup.
+ profile_database_->RemoveExpiredAutocompleteEntries(this);
+ }
+ }
+}
+
+base::WeakPtr<AutocompleteHistoryManager>
+AutocompleteHistoryManager::GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
}
void AutocompleteHistoryManager::OnGetAutocompleteSuggestions(
int query_id,
+ bool is_autocomplete_enabled,
+ bool autoselect_first_suggestion,
const base::string16& name,
const base::string16& prefix,
- const std::string& form_control_type) {
- CancelPendingQuery();
+ const std::string& form_control_type,
+ base::WeakPtr<SuggestionsHandler> handler) {
+ CancelPendingQueries(handler.get());
- query_id_ = query_id;
- if (!autofill_client_->IsAutocompleteEnabled() ||
- form_control_type == "textarea" ||
+ if (!is_autocomplete_enabled || form_control_type == "textarea" ||
IsInAutofillSuggestionsDisabledExperiment()) {
- SendSuggestions(nullptr);
+ SendSuggestions({}, QueryHandler(query_id, autoselect_first_suggestion,
+ prefix, handler));
uma_recorder_.OnGetAutocompleteSuggestions(name,
0 /* pending_query_handle */);
return;
}
- if (database_) {
- pending_query_handle_ = database_->GetFormValuesForElementName(
+ if (profile_database_) {
+ auto query_handle = profile_database_->GetFormValuesForElementName(
name, prefix, kMaxAutocompleteMenuItems, this);
- uma_recorder_.OnGetAutocompleteSuggestions(name, pending_query_handle_);
+ uma_recorder_.OnGetAutocompleteSuggestions(name, query_handle);
+
+ // We can simply insert, since |query_handle| is always unique.
+ pending_queries_.insert(
+ {query_handle,
+ QueryHandler(query_id, autoselect_first_suggestion, prefix, handler)});
}
}
-void AutocompleteHistoryManager::OnWillSubmitForm(const FormData& form) {
- if (!autofill_client_->IsAutocompleteEnabled())
- return;
-
- if (driver_->IsIncognito())
+void AutocompleteHistoryManager::OnWillSubmitForm(
+ const FormData& form,
+ bool is_autocomplete_enabled) {
+ if (!is_autocomplete_enabled || is_off_the_record_) {
+ Notify(NotificationType::AutocompleteFormSkipped);
return;
+ }
// We put the following restriction on stored FormFields:
// - non-empty name
@@ -137,67 +201,166 @@ void AutocompleteHistoryManager::OnWillSubmitForm(const FormData& form) {
}
}
- if (!values.empty() && database_.get())
- database_->AddFormFields(values);
+ if (!values.empty() && profile_database_.get()) {
+ profile_database_->AddFormFields(values);
+
+ Notify(NotificationType::AutocompleteFormSubmitted);
+ }
}
void AutocompleteHistoryManager::OnRemoveAutocompleteEntry(
const base::string16& name, const base::string16& value) {
- if (database_)
- database_->RemoveFormValueForElementName(name, value);
+ if (profile_database_)
+ profile_database_->RemoveFormValueForElementName(name, value);
}
-void AutocompleteHistoryManager::SetExternalDelegate(
- AutofillExternalDelegate* delegate) {
- external_delegate_ = delegate;
+void AutocompleteHistoryManager::OnAutocompleteEntrySelected(
+ const base::string16& value) {
+ // Try to find the AutofillEntry associated with the given suggestion.
+ auto last_entries_iter = last_entries_.find(value);
+ if (last_entries_iter == last_entries_.end()) {
+ // Not found, therefore nothing to do. Most likely there was a race
+ // condition, but it's not that big of a deal in the current scenario
+ // (logging metrics).
+ NOTREACHED();
+ return;
+ }
+
+ // The AutofillEntry was found, use it to log the DaysSinceLastUsed.
+ const AutofillEntry& entry = last_entries_iter->second;
+ base::TimeDelta time_delta = AutofillClock::Now() - entry.date_last_used();
+ AutofillMetrics::LogAutocompleteDaysSinceLastUse(time_delta.InDays());
}
-void AutocompleteHistoryManager::CancelPendingQuery() {
- if (pending_query_handle_) {
- if (database_)
- database_->CancelRequest(pending_query_handle_);
- pending_query_handle_ = 0;
+void AutocompleteHistoryManager::CancelPendingQueries(
+ const SuggestionsHandler* handler) {
+ if (handler && profile_database_) {
+ for (auto iter : pending_queries_) {
+ const QueryHandler& query_handler = iter.second;
+
+ if (query_handler.handler_ && query_handler.handler_.get() == handler) {
+ profile_database_->CancelRequest(iter.first);
+ }
+ }
}
+
+ // Cleaning up the map with the cancelled handler to remove cancelled
+ // requests.
+ CleanupEntries(handler);
+}
+
+void AutocompleteHistoryManager::OnWebDataServiceRequestDone(
+ WebDataServiceBase::Handle current_handle,
+ std::unique_ptr<WDTypedResult> result) {
+ DCHECK(current_handle);
+
+ if (!result) {
+ // Returning early here if |result| is null. We've seen this happen on
+ // Linux due to NFS dismounting and causing sql failures.
+ // See http://crbug.com/68783.
+ return;
+ }
+
+ WDResultType result_type = result->GetType();
+
+ auto request_callbacks_iter = request_callbacks_.find(result_type);
+ if (request_callbacks_iter == request_callbacks_.end()) {
+ // There are no callbacks for this response, hence nothing to do.
+ return;
+ }
+
+ request_callbacks_iter->second.Run(current_handle, std::move(result));
}
void AutocompleteHistoryManager::SendSuggestions(
- const std::vector<base::string16>* autocomplete_results) {
+ const std::vector<AutofillEntry>& entries,
+ const QueryHandler& query_handler) {
+ if (!query_handler.handler_) {
+ // Either the handler has been destroyed, or it is invalid.
+ return;
+ }
+
+ // If there is only one suggestion that is the exact same string as
+ // what is in the input box, then don't show the suggestion.
+ bool hide_suggestions =
+ entries.size() == 1 && query_handler.prefix_ == entries[0].key().value();
+
std::vector<Suggestion> suggestions;
- if (autocomplete_results) {
- for (const auto& result : *autocomplete_results) {
- suggestions.push_back(Suggestion(result));
+ last_entries_.clear();
+
+ if (!hide_suggestions) {
+ for (const AutofillEntry& entry : entries) {
+ suggestions.push_back(Suggestion(entry.key().value()));
+ last_entries_.insert({entry.key().value(), AutofillEntry(entry)});
}
}
- external_delegate_->OnSuggestionsReturned(query_id_, suggestions, false);
- query_id_ = 0;
+ query_handler.handler_->OnSuggestionsReturned(
+ query_handler.client_query_id_,
+ query_handler.autoselect_first_suggestion_, suggestions);
}
-void AutocompleteHistoryManager::OnWebDataServiceRequestDone(
- WebDataServiceBase::Handle h,
+void AutocompleteHistoryManager::OnAutofillValuesReturned(
+ WebDataServiceBase::Handle current_handle,
std::unique_ptr<WDTypedResult> result) {
- DCHECK(pending_query_handle_);
- auto current_query_handle = pending_query_handle_;
- pending_query_handle_ = 0;
-
DCHECK(result);
- // Returning early here if |result| is NULL. We've seen this happen on
- // Linux due to NFS dismounting and causing sql failures.
- // See http://crbug.com/68783.
- if (!result) {
- SendSuggestions(nullptr);
- uma_recorder_.OnWebDataServiceRequestDone(current_query_handle,
- false /* has_suggestion */);
+ DCHECK_EQ(AUTOFILL_VALUE_RESULT, result->GetType());
+
+ auto pending_queries_iter = pending_queries_.find(current_handle);
+ if (pending_queries_iter == pending_queries_.end()) {
+ // There's no handler for this query, hence nothing to do.
return;
}
- DCHECK_EQ(AUTOFILL_VALUE_RESULT, result->GetType());
- const WDResult<std::vector<base::string16>>* autofill_result =
- static_cast<const WDResult<std::vector<base::string16>>*>(result.get());
- std::vector<base::string16> suggestions = autofill_result->GetValue();
- SendSuggestions(&suggestions);
+ // Moving the handler since we're erasing the entry.
+ auto query_handler = std::move(pending_queries_iter->second);
+
+ // Removing the query, as it is no longer pending.
+ pending_queries_.erase(pending_queries_iter);
+
+ const WDResult<std::vector<AutofillEntry>>* autofill_result =
+ static_cast<const WDResult<std::vector<AutofillEntry>>*>(result.get());
+ std::vector<AutofillEntry> entries = autofill_result->GetValue();
+ SendSuggestions(entries, query_handler);
uma_recorder_.OnWebDataServiceRequestDone(
- current_query_handle, !suggestions.empty() /* has_suggestion */);
+ current_handle, !entries.empty() /* has_suggestion */);
+}
+
+void AutocompleteHistoryManager::OnAutofillCleanupReturned(
+ WebDataServiceBase::Handle current_handle,
+ std::unique_ptr<WDTypedResult> result) {
+ DCHECK(result);
+ DCHECK_EQ(AUTOFILL_CLEANUP_RESULT, result->GetType());
+
+ const WDResult<size_t>* cleanup_wdresult =
+ static_cast<const WDResult<size_t>*>(result.get());
+
+ AutofillMetrics::LogNumberOfAutocompleteEntriesCleanedUp(
+ cleanup_wdresult->GetValue());
+
+ // Cleanup was successful, update the latest run milestone.
+ pref_service_->SetInteger(prefs::kAutocompleteLastVersionRetentionPolicy,
+ CHROME_VERSION_MAJOR);
+
+ Notify(NotificationType::AutocompleteCleanupDone);
+}
+
+void AutocompleteHistoryManager::CancelAllPendingQueries() {
+ if (profile_database_) {
+ for (const auto& pending_query : pending_queries_) {
+ profile_database_->CancelRequest(pending_query.first);
+ }
+ }
+
+ pending_queries_.clear();
+}
+
+void AutocompleteHistoryManager::CleanupEntries(
+ const SuggestionsHandler* handler) {
+ base::EraseIf(pending_queries_, [handler](const auto& pending_query) {
+ const QueryHandler& query_handler = pending_query.second;
+ return !query_handler.handler_ || query_handler.handler_.get() == handler;
+ });
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autocomplete_history_manager.h b/chromium/components/autofill/core/browser/autocomplete_history_manager.h
index 84ad773b834..3f5536d2a23 100644
--- a/chromium/components/autofill/core/browser/autocomplete_history_manager.h
+++ b/chromium/components/autofill/core/browser/autocomplete_history_manager.h
@@ -5,57 +5,110 @@
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOCOMPLETE_HISTORY_MANAGER_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOCOMPLETE_HISTORY_MANAGER_H_
+#include <map>
#include <vector>
+#include "base/callback.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "components/autofill/core/browser/autofill_subject.h"
+#include "components/autofill/core/browser/suggestion.h"
+#include "components/autofill/core/browser/webdata/autofill_entry.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/common/form_data.h"
+#include "components/keyed_service/core/keyed_service.h"
#include "components/prefs/pref_member.h"
+#include "components/prefs/pref_service.h"
#include "components/webdata/common/web_data_service_consumer.h"
namespace autofill {
-class AutofillDriver;
-class AutofillExternalDelegate;
-class AutofillClient;
-struct FormData;
-
-// Per-tab Autocomplete history manager. Handles receiving form data
-// from the renderer and the storing and retrieving of form data
+// Per-profile Autocomplete history manager. Handles receiving form data
+// from the renderers and the storing and retrieving of form data
// through WebDataServiceBase.
-class AutocompleteHistoryManager : public WebDataServiceConsumer {
+class AutocompleteHistoryManager : public KeyedService,
+ public WebDataServiceConsumer,
+ public AutofillSubject {
public:
- AutocompleteHistoryManager(AutofillDriver* driver,
- AutofillClient* autofill_client);
+ // Interface to be implemented by classes that want to fetch autocomplete
+ // suggestions.
+ class SuggestionsHandler {
+ public:
+ virtual ~SuggestionsHandler() = default;
+
+ // Function that will be called-back once AutocompleteHistoryManager gets
+ // the corresponding response from the DB.
+ // |query_id| is the value given by the implementor when
+ // OnGetAutocompleteSuggestions was called (it is not the DB query ID).
+ // |suggestions| is the list of fetched autocomplete suggestions.
+ virtual void OnSuggestionsReturned(
+ int query_id,
+ bool autoselect_first_suggestion,
+ const std::vector<Suggestion>& suggestions) = 0;
+ };
+
+ AutocompleteHistoryManager();
~AutocompleteHistoryManager() override;
- // Pass-through functions that are called by AutofillManager, after it has
- // dispatched a message.
+ // Initializes the instance with the given parameters.
+ // |profile_database_| is a profile-scope DB used to access autocomplete data.
+ // |is_off_the_record| indicates wheter the user is currently operating in an
+ // off-the-record context (i.e. incognito).
+ void Init(scoped_refptr<AutofillWebDataService> profile_database,
+ PrefService* pref_service,
+ bool is_off_the_record);
+
+ // Returns a weak pointer to the current AutocompleteHistoryManager instance.
+ base::WeakPtr<AutocompleteHistoryManager> GetWeakPtr();
+
+ // Initiates a DB query to get suggestions given a field's information.
+ // |query_id| is given by the client as context.
+ // |is_autocomplete_enabled| is to determine if the feature is enable for the
+ // requestor's context (e.g. Android WebViews have different contexts).
+ // |name| is the name of the field,
+ // |prefix| is the field's values
+ // |form_control_type| is the field's control type.
+ // |handler| is weak pointer to the requestor, which we will callback once we
+ // receive the response. There can only be one pending query per |handler|,
+ // hence this function will cancel the previous pending query if it hadn't
+ // already been resolved, at which point no method of the handler will be
+ // called.
virtual void OnGetAutocompleteSuggestions(
int query_id,
+ bool is_autocomplete_enabled,
+ bool autoselect_first_suggestion,
const base::string16& name,
const base::string16& prefix,
- const std::string& form_control_type);
- virtual void OnWillSubmitForm(const FormData& form);
+ const std::string& form_control_type,
+ base::WeakPtr<SuggestionsHandler> handler);
- // Cancels the currently pending WebDataService query, if there is one.
- void CancelPendingQuery();
+ // Will save the given input from the |form| as a new, or updated,
+ // autocomplete entry, which will be served in the future as a suggestion.
+ // This update is dependent on whether we are running in incognito and if
+ // autocomplete is enabled or not.
+ virtual void OnWillSubmitForm(const FormData& form,
+ bool is_autocomplete_enabled);
- // Must be public for the external delegate to use.
- void OnRemoveAutocompleteEntry(const base::string16& name,
- const base::string16& value);
+ // WebDataServiceConsumer implementation.
+ void OnWebDataServiceRequestDone(
+ WebDataServiceBase::Handle h,
+ std::unique_ptr<WDTypedResult> result) override;
- // Sets our external delegate.
- void SetExternalDelegate(AutofillExternalDelegate* delegate);
+ // Cancels the currently pending WebDataService queries associated with the
+ // given |handler|.
+ virtual void CancelPendingQueries(const SuggestionsHandler* handler);
- protected:
- friend class AutofillManagerTest;
+ // Must be public for the autofill manager to use.
+ virtual void OnRemoveAutocompleteEntry(const base::string16& name,
+ const base::string16& value);
- // Sends the stored suggestions plus the new autocomplete results for display
- // in the Autofill popup. The parameter may be null if there are no new
- // autocomplete additions.
- void SendSuggestions(const std::vector<base::string16>* new_results);
+ // Invoked when the user selected |value| in the Autocomplete drop-down. This
+ // function logs the DaysSinceLastUse of the Autocomplete entry associated
+ // with |value|.
+ virtual void OnAutocompleteEntrySelected(const base::string16& value);
private:
+ friend class AutocompleteHistoryManagerTest;
FRIEND_TEST_ALL_PREFIXES(AutocompleteHistoryManagerTest,
AutocompleteUMAQueryCreated);
@@ -86,33 +139,94 @@ class AutocompleteHistoryManager : public WebDataServiceConsumer {
DISALLOW_COPY_AND_ASSIGN(UMARecorder);
};
- // WebDataServiceConsumer implementation.
- void OnWebDataServiceRequestDone(
- WebDataServiceBase::Handle h,
- std::unique_ptr<WDTypedResult> result) override;
+ // Internal data object used to keep a request's context to associate it
+ // with the appropriate response.
+ struct QueryHandler {
+ QueryHandler(int client_query_id,
+ bool autoselect_first_suggestion,
+ base::string16 prefix,
+ base::WeakPtr<SuggestionsHandler> handler);
+ QueryHandler(const QueryHandler& original);
+ ~QueryHandler();
+
+ // Query ID living in the handler's scope, which is NOT the same as the
+ // database query ID. This ID is unique per frame, but not per profile.
+ int client_query_id_;
+
+ // Determines whether we should auto-select the first suggestion when
+ // returning. This value was given by the handler when requesting
+ // suggestions.
+ bool autoselect_first_suggestion_;
+
+ // Prefix used to search suggestions, submitted by the handler.
+ base::string16 prefix_;
+
+ // Weak pointer to the handler instance which will be called-back when
+ // we get the response for the associate query.
+ base::WeakPtr<SuggestionsHandler> handler_;
+ };
- // Provides driver-level context. Must outlive this object.
- AutofillDriver* driver_;
- scoped_refptr<AutofillWebDataService> database_;
+ // Sends the autocomplete |suggestions| to the |query_handler|'s handler for
+ // display in the associated Autofill popup. The parameter may be empty if
+ // there are no new autocomplete additions.
+ void SendSuggestions(const std::vector<AutofillEntry>& entries,
+ const QueryHandler& query_handler);
+
+ // Cancels all outstanding queries and clears out the |pending_queries_| map.
+ void CancelAllPendingQueries();
+
+ // Cleans-up the dictionary of |pending_queries_| by checking
+ // - If any handler instance was destroyed (known via WeakPtr)
+ // - If the given |handler| pointer is associated with a query.
+ void CleanupEntries(const SuggestionsHandler* handler);
+
+ // Function handling WebDataService responses of type AUTOFILL_VALUE_RESULT.
+ // |current_handle| is the DB query handle, and is used to retrieve the
+ // handler associated with that query.
+ // |result| contains the Autocomplete suggestions retrieved from the DB that,
+ // if valid and if the handler exists, are to be returned to the handler.
+ void OnAutofillValuesReturned(WebDataServiceBase::Handle current_handle,
+ std::unique_ptr<WDTypedResult> result);
+
+ // Function handling WebDataService responses of type AUTOFILL_CLEANUP_RESULT.
+ // |current_handle| is the DB query handle, and is used to retrieve the
+ // handler associated with that query.
+ // |result| contains the number of entries that were cleaned-up.
+ void OnAutofillCleanupReturned(WebDataServiceBase::Handle current_handle,
+ std::unique_ptr<WDTypedResult> result);
+
+ // Must outlive this object.
+ scoped_refptr<AutofillWebDataService> profile_database_;
+
+ // Map used to store WebDataService response callbacks, associating a
+ // response's WDResultType to the appropriate callback.
+ std::map<WDResultType,
+ base::RepeatingCallback<void(WebDataServiceBase::Handle,
+ std::unique_ptr<WDTypedResult>)>>
+ request_callbacks_;
+
+ // The PrefService that this instance uses. Must outlive this instance.
+ PrefService* pref_service_;
// When the manager makes a request from WebDataServiceBase, the database is
- // queried on another thread, we record the query handle until we get called
- // back.
- WebDataServiceBase::Handle pending_query_handle_;
- int query_id_;
-
- // Delegate to perform external processing (display, selection) on
- // our behalf. Weak.
- AutofillExternalDelegate* external_delegate_;
+ // queried asynchronously. We associate the query handle to the requestor
+ // (with some context parameters) and store the association here until we get
+ // called back. Then we update the initial requestor, and deleting the
+ // no-longer-pending query from this map.
+ std::map<WebDataServiceBase::Handle, QueryHandler> pending_queries_;
- // Delegate to provide whether or not autocomplete functionality is enabled.
- AutofillClient* const autofill_client_;
+ // Cached results of the last batch of autocomplete suggestions.
+ // Key are the suggestions' values, and values are the associated
+ // AutofillEntry.
+ std::map<base::string16, AutofillEntry> last_entries_;
- // Whether IPC is sent.
- bool send_ipc_;
+ // Whether the service is associated with an off-the-record browser context.
+ bool is_off_the_record_ = false;
UMARecorder uma_recorder_;
+ base::WeakPtrFactory<AutocompleteHistoryManager> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(AutocompleteHistoryManager);
};
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 cf785b2bc5c..249abd01d70 100644
--- a/chromium/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
@@ -6,6 +6,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
@@ -14,16 +15,19 @@
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
#include "components/autofill/core/browser/autocomplete_history_manager.h"
-#include "components/autofill/core/browser/autofill_external_delegate.h"
-#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#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_clock.h"
+#include "components/autofill/core/browser/webdata/autofill_entry.h"
#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_prefs.h"
#include "components/autofill/core/common/form_data.h"
-#include "components/prefs/pref_service.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/version_info/version_info.h"
#include "components/webdata_services/web_data_service_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -31,6 +35,10 @@
using base::ASCIIToUTF16;
using testing::_;
+using testing::Eq;
+using testing::Field;
+using testing::Return;
+using testing::UnorderedElementsAre;
namespace autofill {
@@ -43,44 +51,50 @@ class MockWebDataService : public AutofillWebDataService {
base::ThreadTaskRunnerHandle::Get()) {}
MOCK_METHOD1(AddFormFields, void(const std::vector<FormFieldData>&));
-
- WebDataServiceBase::Handle GetFormValuesForElementName(
- const base::string16& name,
- const base::string16& prefix,
- int limit,
- WebDataServiceConsumer* consumer) override {
- return mock_handle_;
- }
-
- void set_mock_handle(WebDataServiceBase::Handle handle) {
- mock_handle_ = handle;
- }
+ MOCK_METHOD1(CancelRequest, void(int));
+ MOCK_METHOD4(GetFormValuesForElementName,
+ WebDataServiceBase::Handle(const base::string16& name,
+ const base::string16& prefix,
+ int limit,
+ WebDataServiceConsumer* consumer));
+ MOCK_METHOD1(RemoveExpiredAutocompleteEntries,
+ WebDataServiceBase::Handle(WebDataServiceConsumer* consumer));
protected:
~MockWebDataService() override {}
-
- private:
- WebDataServiceBase::Handle mock_handle_ = 0;
};
class MockAutofillClient : public TestAutofillClient {
public:
- MockAutofillClient(scoped_refptr<MockWebDataService> web_data_service)
- : web_data_service_(web_data_service),
- prefs_(test::PrefServiceForTesting()) {}
+ MockAutofillClient() : prefs_(test::PrefServiceForTesting()) {}
~MockAutofillClient() override {}
- scoped_refptr<AutofillWebDataService> GetDatabase() override {
- return web_data_service_;
- }
PrefService* GetPrefs() override { return prefs_.get(); }
private:
- scoped_refptr<MockWebDataService> web_data_service_;
std::unique_ptr<PrefService> prefs_;
DISALLOW_COPY_AND_ASSIGN(MockAutofillClient);
};
+class MockSuggestionsHandler
+ : public AutocompleteHistoryManager::SuggestionsHandler {
+ public:
+ MockSuggestionsHandler() : weak_ptr_factory_(this) {}
+
+ MOCK_METHOD3(OnSuggestionsReturned,
+ void(int query_id,
+ bool autoselect_first_suggestion,
+ const std::vector<Suggestion>& suggestions));
+
+ base::WeakPtr<MockSuggestionsHandler> GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+ }
+
+ private:
+ base::WeakPtrFactory<MockSuggestionsHandler> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockSuggestionsHandler);
+};
} // namespace
class AutocompleteHistoryManagerTest : public testing::Test {
@@ -88,20 +102,62 @@ class AutocompleteHistoryManagerTest : public testing::Test {
AutocompleteHistoryManagerTest() {}
void SetUp() override {
+ prefs_ = test::PrefServiceForTesting();
+
+ // Mock such that we don't trigger the cleanup.
+ prefs_->SetInteger(prefs::kAutocompleteLastVersionRetentionPolicy,
+ CHROME_VERSION_MAJOR);
+
+ // Set time to some arbitrary date.
+ test_clock.SetNow(base::Time::FromDoubleT(1546889367));
web_data_service_ = base::MakeRefCounted<MockWebDataService>();
- autofill_client_ = std::make_unique<MockAutofillClient>(web_data_service_);
- autofill_driver_ = std::make_unique<TestAutofillDriver>();
- autocomplete_manager_ = std::make_unique<AutocompleteHistoryManager>(
- autofill_driver_.get(), autofill_client_.get());
+ autocomplete_manager_ = std::make_unique<AutocompleteHistoryManager>();
+ autocomplete_manager_->Init(web_data_service_, prefs_.get(), false);
+ }
+
+ void TearDown() override {
+ // Ensure there are no left-over entries in the map (leak check).
+ EXPECT_TRUE(PendingQueriesEmpty());
+
+ autocomplete_manager_.reset();
+ }
+
+ bool PendingQueriesEmpty() {
+ return !autocomplete_manager_ ||
+ autocomplete_manager_->pending_queries_.empty();
}
- void TearDown() override { autocomplete_manager_.reset(); }
+ static bool IsEmptySuggestionVector(
+ const std::vector<Suggestion>& suggestions) {
+ return suggestions.empty();
+ }
+
+ static bool NonEmptySuggestionVector(
+ const std::vector<Suggestion>& suggestions) {
+ return !suggestions.empty();
+ }
+
+ std::unique_ptr<WDTypedResult> GetMockedDbResults(
+ std::vector<AutofillEntry> values) {
+ return std::make_unique<WDResult<std::vector<AutofillEntry>>>(
+ AUTOFILL_VALUE_RESULT, values);
+ }
+
+ AutofillEntry GetAutofillEntry(
+ const base::string16& name,
+ const base::string16& value,
+ const base::Time& date_created = AutofillClock::Now(),
+ const base::Time& date_last_used = AutofillClock::Now()) {
+ return AutofillEntry(AutofillKey(name, value), date_created,
+ date_last_used);
+ }
base::test::ScopedTaskEnvironment scoped_task_environment_;
scoped_refptr<MockWebDataService> web_data_service_;
std::unique_ptr<AutocompleteHistoryManager> autocomplete_manager_;
- std::unique_ptr<AutofillDriver> autofill_driver_;
- std::unique_ptr<MockAutofillClient> autofill_client_;
+ std::unique_ptr<PrefService> prefs_;
+ base::test::ScopedFeatureList scoped_features;
+ TestAutofillClock test_clock;
};
// Tests that credit card numbers are not sent to the WebDatabase to be saved.
@@ -119,8 +175,9 @@ TEST_F(AutocompleteHistoryManagerTest, CreditCardNumberValue) {
valid_cc.form_control_type = "text";
form.fields.push_back(valid_cc);
- EXPECT_CALL(*web_data_service_, AddFormFields(_)).Times(0);
- autocomplete_manager_->OnWillSubmitForm(form);
+ EXPECT_CALL(*(web_data_service_.get()), AddFormFields(_)).Times(0);
+ autocomplete_manager_->OnWillSubmitForm(form,
+ /*is_autocomplete_enabled=*/true);
}
// Contrary test to AutocompleteHistoryManagerTest.CreditCardNumberValue. The
@@ -141,7 +198,8 @@ TEST_F(AutocompleteHistoryManagerTest, NonCreditCardNumberValue) {
form.fields.push_back(invalid_cc);
EXPECT_CALL(*(web_data_service_.get()), AddFormFields(_)).Times(1);
- autocomplete_manager_->OnWillSubmitForm(form);
+ autocomplete_manager_->OnWillSubmitForm(form,
+ /*is_autocomplete_enabled=*/true);
}
// Tests that SSNs are not sent to the WebDatabase to be saved.
@@ -159,7 +217,8 @@ TEST_F(AutocompleteHistoryManagerTest, SSNValue) {
form.fields.push_back(ssn);
EXPECT_CALL(*web_data_service_, AddFormFields(_)).Times(0);
- autocomplete_manager_->OnWillSubmitForm(form);
+ autocomplete_manager_->OnWillSubmitForm(form,
+ /*is_autocomplete_enabled=*/true);
}
// Verify that autocomplete text is saved for search fields.
@@ -178,7 +237,27 @@ TEST_F(AutocompleteHistoryManagerTest, SearchField) {
form.fields.push_back(search_field);
EXPECT_CALL(*(web_data_service_.get()), AddFormFields(_)).Times(1);
- autocomplete_manager_->OnWillSubmitForm(form);
+ autocomplete_manager_->OnWillSubmitForm(form,
+ /*is_autocomplete_enabled=*/true);
+}
+
+TEST_F(AutocompleteHistoryManagerTest, AutocompleteFeatureOff) {
+ FormData form;
+ form.name = ASCIIToUTF16("MyForm");
+ form.origin = GURL("http://myform.com/form.html");
+ form.action = GURL("http://myform.com/submit.html");
+
+ // Search field.
+ FormFieldData search_field;
+ search_field.label = ASCIIToUTF16("Search");
+ search_field.name = ASCIIToUTF16("search");
+ search_field.value = ASCIIToUTF16("my favorite query");
+ search_field.form_control_type = "search";
+ form.fields.push_back(search_field);
+
+ EXPECT_CALL(*(web_data_service_.get()), AddFormFields(_)).Times(0);
+ autocomplete_manager_->OnWillSubmitForm(form,
+ /*is_autocomplete_enabled=*/false);
}
// Tests that text entered into fields specifying autocomplete="off" is not sent
@@ -201,7 +280,30 @@ TEST_F(AutocompleteHistoryManagerTest, FieldWithAutocompleteOff) {
form.fields.push_back(field);
EXPECT_CALL(*web_data_service_, AddFormFields(_)).Times(0);
- autocomplete_manager_->OnWillSubmitForm(form);
+ autocomplete_manager_->OnWillSubmitForm(form,
+ /*is_autocomplete_enabled=*/true);
+}
+
+// Shouldn't save entries when in Incognito mode.
+TEST_F(AutocompleteHistoryManagerTest, Incognito) {
+ autocomplete_manager_->Init(web_data_service_, prefs_.get(),
+ /*is_off_the_record_=*/true);
+ FormData form;
+ form.name = ASCIIToUTF16("MyForm");
+ form.origin = GURL("http://myform.com/form.html");
+ form.action = GURL("http://myform.com/submit.html");
+
+ // Search field.
+ FormFieldData search_field;
+ search_field.label = ASCIIToUTF16("Search");
+ search_field.name = ASCIIToUTF16("search");
+ search_field.value = ASCIIToUTF16("my favorite query");
+ search_field.form_control_type = "search";
+ form.fields.push_back(search_field);
+
+ EXPECT_CALL(*web_data_service_, AddFormFields(_)).Times(0);
+ autocomplete_manager_->OnWillSubmitForm(form,
+ /*is_autocomplete_enabled=*/true);
}
// Tests that text entered into fields that are not focusable is not sent to the
@@ -222,7 +324,8 @@ TEST_F(AutocompleteHistoryManagerTest, NonFocusableField) {
form.fields.push_back(field);
EXPECT_CALL(*web_data_service_, AddFormFields(_)).Times(0);
- autocomplete_manager_->OnWillSubmitForm(form);
+ autocomplete_manager_->OnWillSubmitForm(form,
+ /*is_autocomplete_enabled=*/true);
}
// Tests that text entered into presentation fields is not sent to the
@@ -243,78 +346,530 @@ TEST_F(AutocompleteHistoryManagerTest, PresentationField) {
form.fields.push_back(field);
EXPECT_CALL(*web_data_service_, AddFormFields(_)).Times(0);
- autocomplete_manager_->OnWillSubmitForm(form);
+ autocomplete_manager_->OnWillSubmitForm(form,
+ /*is_autocomplete_enabled=*/true);
}
-namespace {
+// Tests that the Init function will trigger the Autocomplete Retention Policy
+// cleanup if the flag is enabled, we're not in OTR and it hadn't run in the
+// current major version.
+TEST_F(AutocompleteHistoryManagerTest, Init_TriggersCleanup) {
+ // Enable the feature, and set the major version.
+ scoped_features.InitAndEnableFeature(
+ features::kAutocompleteRetentionPolicyEnabled);
+ prefs_->SetInteger(prefs::kAutocompleteLastVersionRetentionPolicy,
+ CHROME_VERSION_MAJOR - 1);
+
+ EXPECT_CALL(*web_data_service_,
+ RemoveExpiredAutocompleteEntries(autocomplete_manager_.get()))
+ .Times(1);
+ autocomplete_manager_->Init(web_data_service_, prefs_.get(),
+ /*is_off_the_record=*/false);
+}
-class MockAutofillExternalDelegate : public AutofillExternalDelegate {
- public:
- MockAutofillExternalDelegate(AutofillManager* autofill_manager,
- AutofillDriver* autofill_driver)
- : AutofillExternalDelegate(autofill_manager, autofill_driver) {}
- ~MockAutofillExternalDelegate() override {}
+// Tests that the Init function will not trigger the Autocomplete Retention
+// Policy when running in OTR.
+TEST_F(AutocompleteHistoryManagerTest, Init_OTR_Not_TriggersCleanup) {
+ // Enable the feature, and set the major version.
+ scoped_features.InitAndEnableFeature(
+ features::kAutocompleteRetentionPolicyEnabled);
+ prefs_->SetInteger(prefs::kAutocompleteLastVersionRetentionPolicy,
+ CHROME_VERSION_MAJOR - 1);
+
+ EXPECT_CALL(*web_data_service_,
+ RemoveExpiredAutocompleteEntries(autocomplete_manager_.get()))
+ .Times(0);
+ autocomplete_manager_->Init(web_data_service_, prefs_.get(),
+ /*is_off_the_record=*/true);
+}
- MOCK_METHOD4(OnSuggestionsReturned,
- void(int query_id,
- const std::vector<Suggestion>& suggestions,
- bool autoselect_first_suggestion,
- bool is_all_server_suggestions));
+// Tests that the Init function will not trigger the Autocomplete Retention
+// Policy when the feature is disabled.
+TEST_F(AutocompleteHistoryManagerTest,
+ Init_FeatureDisabled_Not_TriggersCleanup) {
+ // Disable the feature, and set the major version.
+ scoped_features.InitAndDisableFeature(
+ features::kAutocompleteRetentionPolicyEnabled);
+ prefs_->SetInteger(prefs::kAutocompleteLastVersionRetentionPolicy,
+ CHROME_VERSION_MAJOR - 1);
+
+ EXPECT_CALL(*web_data_service_,
+ RemoveExpiredAutocompleteEntries(autocomplete_manager_.get()))
+ .Times(0);
+ autocomplete_manager_->Init(web_data_service_, prefs_.get(),
+ /*is_off_the_record=*/false);
+}
- private:
- DISALLOW_COPY_AND_ASSIGN(MockAutofillExternalDelegate);
-};
+// Tests that the Init function will not trigger the Autocomplete Retention
+// Policy when running in a major version that was already cleaned.
+TEST_F(AutocompleteHistoryManagerTest,
+ Init_SameMajorVersion_Not_TriggersCleanup) {
+ // Enable the feature, and set the major version.
+ scoped_features.InitAndEnableFeature(
+ features::kAutocompleteRetentionPolicyEnabled);
+ prefs_->SetInteger(prefs::kAutocompleteLastVersionRetentionPolicy,
+ CHROME_VERSION_MAJOR);
+
+ EXPECT_CALL(*web_data_service_,
+ RemoveExpiredAutocompleteEntries(autocomplete_manager_.get()))
+ .Times(0);
+ autocomplete_manager_->Init(web_data_service_, prefs_.get(),
+ /*is_off_the_record=*/false);
+}
-class TestAutocompleteHistoryManager : public AutocompleteHistoryManager {
- public:
- TestAutocompleteHistoryManager(AutofillDriver* driver, AutofillClient* client)
- : AutocompleteHistoryManager(driver, client) {}
+// Make sure our handler is called at the right time.
+TEST_F(AutocompleteHistoryManagerTest,
+ SuggestionsReturned_InvokeHandler_Empty) {
+ int mocked_db_query_id = 100;
+
+ auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
+ int test_query_id = 2;
+ auto test_name = ASCIIToUTF16("Some Field Name");
+ auto test_prefix = ASCIIToUTF16("SomePrefix");
+
+ std::vector<AutofillEntry> expected_values;
+
+ std::unique_ptr<WDTypedResult> mocked_results =
+ GetMockedDbResults(expected_values);
+
+ EXPECT_CALL(*web_data_service_,
+ GetFormValuesForElementName(test_name, test_prefix, _,
+ autocomplete_manager_.get()))
+ .WillOnce(Return(mocked_db_query_id));
+
+ // Simulate request for suggestions.
+ autocomplete_manager_->OnGetAutocompleteSuggestions(
+ test_query_id, /*is_autocomplete_enabled=*/true,
+ /*autoselect_first_suggestion=*/false, test_name, test_prefix,
+ "Some Type", suggestions_handler->GetWeakPtr());
+
+ // Setting up mock to verify that DB response triggers a call to the handler's
+ // OnSuggestionsReturned
+ EXPECT_CALL(*suggestions_handler.get(),
+ OnSuggestionsReturned(test_query_id,
+ /*autoselect_first_suggestion=*/false,
+ testing::Truly(IsEmptySuggestionVector)));
+
+ // Simulate response from DB.
+ autocomplete_manager_->OnWebDataServiceRequestDone(mocked_db_query_id,
+ std::move(mocked_results));
+}
- using AutocompleteHistoryManager::SendSuggestions;
-};
+TEST_F(AutocompleteHistoryManagerTest,
+ SuggestionsReturned_InvokeHandler_SingleValue) {
+ int mocked_db_query_id = 100;
+
+ auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
+ int test_query_id = 2;
+ auto test_name = ASCIIToUTF16("Some Field Name");
+ auto test_prefix = ASCIIToUTF16("SomePrefix");
+
+ std::vector<AutofillEntry> expected_values = {
+ GetAutofillEntry(test_name, ASCIIToUTF16("SomePrefixOne"))};
+
+ std::unique_ptr<WDTypedResult> mocked_results =
+ GetMockedDbResults(expected_values);
+
+ EXPECT_CALL(*web_data_service_,
+ GetFormValuesForElementName(test_name, test_prefix, _,
+ autocomplete_manager_.get()))
+ .WillOnce(Return(mocked_db_query_id));
+
+ // Simulate request for suggestions.
+ autocomplete_manager_->OnGetAutocompleteSuggestions(
+ test_query_id, /*is_autocomplete_enabled=*/true,
+ /*autoselect_first_suggestion=*/false, test_name, test_prefix,
+ "Some Type", suggestions_handler->GetWeakPtr());
+
+ // Setting up mock to verify that DB response triggers a call to the handler's
+ EXPECT_CALL(*suggestions_handler.get(),
+ OnSuggestionsReturned(
+ test_query_id, /*autoselect_first_suggestion=*/false,
+ UnorderedElementsAre(Field(
+ &Suggestion::value, expected_values[0].key().value()))));
+
+ // Simulate response from DB.
+ autocomplete_manager_->OnWebDataServiceRequestDone(mocked_db_query_id,
+ std::move(mocked_results));
+}
-// Predicate for GMock.
-bool IsEmptySuggestionVector(const std::vector<Suggestion>& suggestions) {
- return suggestions.empty();
+// Tests that we are correctly forwarding the value of
+// |autoselect_first_suggestion| back to the handler.
+TEST_F(AutocompleteHistoryManagerTest,
+ SuggestionsReturned_InvokeHandler_PassesAutoSelect) {
+ int mocked_db_query_id = 100;
+
+ auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
+ int test_query_id = 2;
+ auto test_name = ASCIIToUTF16("Some Field Name");
+ auto test_prefix = ASCIIToUTF16("SomePrefix");
+
+ std::vector<AutofillEntry> expected_values = {
+ GetAutofillEntry(test_name, ASCIIToUTF16("SomePrefixOne"))};
+
+ std::unique_ptr<WDTypedResult> mocked_results =
+ GetMockedDbResults(expected_values);
+
+ EXPECT_CALL(*web_data_service_,
+ GetFormValuesForElementName(test_name, test_prefix, _,
+ autocomplete_manager_.get()))
+ .WillOnce(Return(mocked_db_query_id));
+
+ // Simulate request for suggestions.
+ autocomplete_manager_->OnGetAutocompleteSuggestions(
+ test_query_id, /*is_autocomplete_enabled=*/true,
+ /*autoselect_first_suggestion=*/true, test_name, test_prefix, "Some Type",
+ suggestions_handler->GetWeakPtr());
+
+ // Setting up mock to verify that DB response triggers a call to the handler's
+ EXPECT_CALL(*suggestions_handler.get(),
+ OnSuggestionsReturned(
+ test_query_id, /*autoselect_first_suggestion=*/true,
+ UnorderedElementsAre(Field(
+ &Suggestion::value, expected_values[0].key().value()))));
+
+ // Simulate response from DB.
+ autocomplete_manager_->OnWebDataServiceRequestDone(mocked_db_query_id,
+ std::move(mocked_results));
}
-bool NonEmptySuggestionVector(const std::vector<Suggestion>& suggestions) {
- return !suggestions.empty();
+// Tests that we don't return any suggestion if we only have one suggestion that
+// is case-sensitive equal to the given prefix.
+TEST_F(AutocompleteHistoryManagerTest,
+ SuggestionsReturned_InvokeHandler_SingleValue_EqualsPrefix) {
+ int mocked_db_query_id = 100;
+
+ auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
+ int test_query_id = 2;
+ auto test_name = ASCIIToUTF16("Some Field Name");
+ auto test_prefix = ASCIIToUTF16("SomePrefix");
+
+ std::vector<AutofillEntry> expected_values = {
+ GetAutofillEntry(test_name, test_prefix)};
+
+ std::unique_ptr<WDTypedResult> mocked_results =
+ GetMockedDbResults(expected_values);
+
+ EXPECT_CALL(*web_data_service_,
+ GetFormValuesForElementName(test_name, test_prefix, _,
+ autocomplete_manager_.get()))
+ .WillOnce(Return(mocked_db_query_id));
+
+ // Simulate request for suggestions.
+ autocomplete_manager_->OnGetAutocompleteSuggestions(
+ test_query_id, /*is_autocomplete_enabled=*/true,
+ /*autoselect_first_suggestion=*/false, test_name, test_prefix,
+ "Some Type", suggestions_handler->GetWeakPtr());
+
+ // Setting up mock to verify that DB response triggers a call to the handler's
+ EXPECT_CALL(*suggestions_handler.get(),
+ OnSuggestionsReturned(test_query_id,
+ /*autoselect_first_suggestion=*/false,
+ testing::Truly(IsEmptySuggestionVector)));
+
+ // Simulate response from DB.
+ autocomplete_manager_->OnWebDataServiceRequestDone(mocked_db_query_id,
+ std::move(mocked_results));
}
-} // namespace
+// Tests the case sensitivity of the unique suggestion equal to the prefix
+// filter.
+TEST_F(AutocompleteHistoryManagerTest,
+ SuggestionsReturned_InvokeHandler_SingleValue_EqualsPrefix_DiffCase) {
+ int mocked_db_query_id = 100;
+
+ auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
+ int test_query_id = 2;
+ auto test_name = ASCIIToUTF16("Some Field Name");
+ auto test_prefix = ASCIIToUTF16("SomePrefix");
+
+ std::vector<AutofillEntry> expected_values = {
+ GetAutofillEntry(test_name, ASCIIToUTF16("someprefix"))};
+
+ std::unique_ptr<WDTypedResult> mocked_results =
+ GetMockedDbResults(expected_values);
+
+ EXPECT_CALL(*web_data_service_,
+ GetFormValuesForElementName(test_name, test_prefix, _,
+ autocomplete_manager_.get()))
+ .WillOnce(Return(mocked_db_query_id));
+
+ // Simulate request for suggestions.
+ autocomplete_manager_->OnGetAutocompleteSuggestions(
+ test_query_id, /*is_autocomplete_enabled=*/true,
+ /*autoselect_first_suggestion=*/false, test_name, test_prefix,
+ "Some Type", suggestions_handler->GetWeakPtr());
+
+ // Setting up mock to verify that DB response triggers a call to the handler's
+ EXPECT_CALL(*suggestions_handler.get(),
+ OnSuggestionsReturned(
+ test_query_id, /*autoselect_first_suggestion=*/false,
+ UnorderedElementsAre(Field(
+ &Suggestion::value, expected_values[0].key().value()))));
+
+ // Simulate response from DB.
+ autocomplete_manager_->OnWebDataServiceRequestDone(mocked_db_query_id,
+ std::move(mocked_results));
+}
-// Make sure our external delegate is called at the right time.
-TEST_F(AutocompleteHistoryManagerTest, ExternalDelegate) {
- TestAutocompleteHistoryManager autocomplete_history_manager(
- autofill_driver_.get(), autofill_client_.get());
+TEST_F(AutocompleteHistoryManagerTest,
+ OnAutocompleteEntrySelected_Found_ShouldLogDays) {
+ // Setting up by simulating that there was a query for autocomplete
+ // suggestions, and that two values were found.
+ int mocked_db_query_id = 100;
+
+ auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
+ int test_query_id = 2;
+ auto test_name = ASCIIToUTF16("Some Field Name");
+ auto test_prefix = ASCIIToUTF16("SomePrefix");
+ auto test_value = ASCIIToUTF16("SomePrefixOne");
+ auto other_test_value = ASCIIToUTF16("SomePrefixOne");
+ int days_since_last_use = 10;
+
+ std::vector<AutofillEntry> expected_values = {
+ GetAutofillEntry(test_name, test_value,
+ AutofillClock::Now() - base::TimeDelta::FromDays(30),
+ AutofillClock::Now() -
+ base::TimeDelta::FromDays(days_since_last_use)),
+ GetAutofillEntry(test_name, other_test_value,
+ AutofillClock::Now() - base::TimeDelta::FromDays(30),
+ AutofillClock::Now() -
+ base::TimeDelta::FromDays(days_since_last_use))};
+
+ std::unique_ptr<WDTypedResult> mocked_results =
+ GetMockedDbResults(expected_values);
+
+ EXPECT_CALL(*web_data_service_,
+ GetFormValuesForElementName(test_name, test_prefix, _,
+ autocomplete_manager_.get()))
+ .WillOnce(Return(mocked_db_query_id));
+
+ EXPECT_CALL(*suggestions_handler.get(), OnSuggestionsReturned);
+
+ // Simulate request for suggestions.
+ autocomplete_manager_->OnGetAutocompleteSuggestions(
+ test_query_id, /*is_autocomplete_enabled=*/true,
+ /*autoselect_first_suggestion=*/false, test_name, test_prefix,
+ "Some Type", suggestions_handler->GetWeakPtr());
+
+ // Simulate response from DB.
+ autocomplete_manager_->OnWebDataServiceRequestDone(mocked_db_query_id,
+ std::move(mocked_results));
- auto autofill_manager = std::make_unique<AutofillManager>(
- autofill_driver_.get(), autofill_client_.get(), "en-US",
- AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
+ base::HistogramTester histogram_tester;
- MockAutofillExternalDelegate external_delegate(autofill_manager.get(),
- autofill_driver_.get());
- autocomplete_history_manager.SetExternalDelegate(&external_delegate);
+ // Now simulate one autocomplete entry being selected, and expect a metric
+ // being logged for that value alone.
+ autocomplete_manager_->OnAutocompleteEntrySelected(test_value);
- // Should trigger a call to OnSuggestionsReturned, verified by the mock.
- EXPECT_CALL(external_delegate, OnSuggestionsReturned(_, _, _, _));
- autocomplete_history_manager.SendSuggestions(nullptr);
+ histogram_tester.ExpectBucketCount("Autocomplete.DaysSinceLastUse",
+ days_since_last_use, 1);
}
-// Verify that no autocomplete suggestion is returned for textarea.
-TEST_F(AutocompleteHistoryManagerTest, NoAutocompleteSuggestionsForTextarea) {
- TestAutocompleteHistoryManager autocomplete_history_manager(
- autofill_driver_.get(), autofill_client_.get());
+TEST_F(AutocompleteHistoryManagerTest,
+ SuggestionsReturned_InvokeHandler_TwoRequests_OneHandler_Cancels) {
+ int mocked_db_query_id_first = 100;
+ int mocked_db_query_id_second = 101;
+
+ auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
+ int test_query_id_first = 2;
+ int test_query_id_second = 3;
+ auto test_name = ASCIIToUTF16("Some Field Name");
+ auto test_prefix = ASCIIToUTF16("SomePrefix");
+
+ std::vector<AutofillEntry> expected_values_first = {
+ GetAutofillEntry(test_name, ASCIIToUTF16("SomePrefixOne"))};
+
+ std::vector<AutofillEntry> expected_values_second = {
+ GetAutofillEntry(test_name, ASCIIToUTF16("SomePrefixTwo"))};
+
+ std::unique_ptr<WDTypedResult> mocked_results_first =
+ GetMockedDbResults(expected_values_first);
+
+ std::unique_ptr<WDTypedResult> mocked_results_second =
+ GetMockedDbResults(expected_values_second);
+
+ EXPECT_CALL(*web_data_service_,
+ GetFormValuesForElementName(test_name, test_prefix, _,
+ autocomplete_manager_.get()))
+ .WillOnce(Return(mocked_db_query_id_first))
+ .WillOnce(Return(mocked_db_query_id_second));
+
+ // Simulate request for the first suggestions.
+ autocomplete_manager_->OnGetAutocompleteSuggestions(
+ test_query_id_first, /*is_autocomplete_enabled=*/true,
+ /*autoselect_first_suggestion=*/false, test_name, test_prefix,
+ "Some Type", suggestions_handler->GetWeakPtr());
+
+ // Simulate request for the second suggestions (this will cancel the first
+ // one).
+ EXPECT_CALL(*web_data_service_, CancelRequest(mocked_db_query_id_first))
+ .Times(1);
+ autocomplete_manager_->OnGetAutocompleteSuggestions(
+ test_query_id_second, /*is_autocomplete_enabled=*/true,
+ /*autoselect_first_suggestion=*/false, test_name, test_prefix,
+ "Some Type", suggestions_handler->GetWeakPtr());
+
+ // Setting up mock to verify that we can get the second response first.
+ EXPECT_CALL(
+ *suggestions_handler.get(),
+ OnSuggestionsReturned(
+ test_query_id_second, /*autoselect_first_suggestion=*/false,
+ UnorderedElementsAre(Field(
+ &Suggestion::value, expected_values_second[0].key().value()))));
+
+ // Simulate response from DB, second request comes back before.
+ autocomplete_manager_->OnWebDataServiceRequestDone(
+ mocked_db_query_id_second, std::move(mocked_results_second));
+
+ // Setting up mock to verify that the handler doesn't get called for the first
+ // request, which was cancelled.
+ EXPECT_CALL(*suggestions_handler.get(),
+ OnSuggestionsReturned(test_query_id_first,
+ /*autoselect_first_suggestion=*/false, _))
+ .Times(0);
+
+ // Simulate response from DB, first request comes back after.
+ autocomplete_manager_->OnWebDataServiceRequestDone(
+ mocked_db_query_id_first, std::move(mocked_results_first));
+}
- auto autofill_manager = std::make_unique<AutofillManager>(
- autofill_driver_.get(), autofill_client_.get(), "en-US",
- AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
+TEST_F(AutocompleteHistoryManagerTest,
+ SuggestionsReturned_InvokeHandler_TwoRequests_TwoHandlers) {
+ int mocked_db_query_id_first = 100;
+ int mocked_db_query_id_second = 101;
+
+ auto suggestions_handler_first = std::make_unique<MockSuggestionsHandler>();
+ auto suggestions_handler_second = std::make_unique<MockSuggestionsHandler>();
+ int test_query_id_first = 2;
+ int test_query_id_second = 3;
+ auto test_name = ASCIIToUTF16("Some Field Name");
+ auto test_prefix = ASCIIToUTF16("SomePrefix");
+
+ std::vector<AutofillEntry> expected_values_first = {
+ GetAutofillEntry(test_name, ASCIIToUTF16("SomePrefixOne"))};
+
+ std::vector<AutofillEntry> expected_values_second = {
+ GetAutofillEntry(test_name, ASCIIToUTF16("SomePrefixTwo"))};
+
+ std::unique_ptr<WDTypedResult> mocked_results_first =
+ GetMockedDbResults(expected_values_first);
+
+ std::unique_ptr<WDTypedResult> mocked_results_second =
+ GetMockedDbResults(expected_values_second);
+
+ EXPECT_CALL(*web_data_service_,
+ GetFormValuesForElementName(test_name, test_prefix, _,
+ autocomplete_manager_.get()))
+ .WillOnce(Return(mocked_db_query_id_first))
+ .WillOnce(Return(mocked_db_query_id_second));
+
+ // Simulate request for the first suggestions.
+ autocomplete_manager_->OnGetAutocompleteSuggestions(
+ test_query_id_first, /*is_autocomplete_enabled=*/true,
+ /*autoselect_first_suggestion=*/false, test_name, test_prefix,
+ "Some Type", suggestions_handler_first->GetWeakPtr());
+
+ // Simulate request for the second suggestions.
+ autocomplete_manager_->OnGetAutocompleteSuggestions(
+ test_query_id_second, /*is_autocomplete_enabled=*/true,
+ /*autoselect_first_suggestion=*/false, test_name, test_prefix,
+ "Some Type", suggestions_handler_second->GetWeakPtr());
+
+ // Setting up mock to verify that we get the second response first.
+ EXPECT_CALL(
+ *suggestions_handler_second.get(),
+ OnSuggestionsReturned(
+ test_query_id_second, /*autoselect_first_suggestion=*/false,
+ UnorderedElementsAre(Field(
+ &Suggestion::value, expected_values_second[0].key().value()))));
+
+ // Simulate response from DB, second request comes back before.
+ autocomplete_manager_->OnWebDataServiceRequestDone(
+ mocked_db_query_id_second, std::move(mocked_results_second));
+
+ // Setting up mock to verify that we get the first response second.
+ EXPECT_CALL(
+ *suggestions_handler_first.get(),
+ OnSuggestionsReturned(
+ test_query_id_first, /*autoselect_first_suggestion=*/false,
+ UnorderedElementsAre(Field(&Suggestion::value,
+ expected_values_first[0].key().value()))));
+
+ // Simulate response from DB, first request comes back after.
+ autocomplete_manager_->OnWebDataServiceRequestDone(
+ mocked_db_query_id_first, std::move(mocked_results_first));
+}
- MockAutofillExternalDelegate external_delegate(autofill_manager.get(),
- autofill_driver_.get());
- autocomplete_history_manager.SetExternalDelegate(&external_delegate);
+TEST_F(AutocompleteHistoryManagerTest,
+ SuggestionsReturned_CancelOne_ReturnOne) {
+ auto test_name = ASCIIToUTF16("Some Field Name");
+ auto test_prefix = ASCIIToUTF16("SomePrefix");
+
+ // Initialize variables for the first handler, which is the one that will be
+ // cancelled.
+ auto suggestions_handler_one = std::make_unique<MockSuggestionsHandler>();
+ int mocked_db_query_id_one = 100;
+ int test_query_id_one = 1;
+ std::vector<AutofillEntry> expected_values_one = {
+ GetAutofillEntry(test_name, ASCIIToUTF16("SomePrefixOne"))};
+ std::unique_ptr<WDTypedResult> mocked_results_one =
+ GetMockedDbResults(expected_values_one);
+
+ // Initialize variables for the second handler, which will be fulfilled.
+ auto suggestions_handler_two = std::make_unique<MockSuggestionsHandler>();
+ int test_query_id_two = 2;
+ int mocked_db_query_id_two = 101;
+ std::vector<AutofillEntry> expected_values_two = {
+ GetAutofillEntry(test_name, ASCIIToUTF16("SomePrefixTwo"))};
+ std::unique_ptr<WDTypedResult> mocked_results_two =
+ GetMockedDbResults(expected_values_two);
+
+ // Simulate first handler request for autocomplete suggestions.
+ EXPECT_CALL(*web_data_service_,
+ GetFormValuesForElementName(test_name, test_prefix, _,
+ autocomplete_manager_.get()))
+ .WillOnce(Return(mocked_db_query_id_one))
+ .WillOnce(Return(mocked_db_query_id_two));
+
+ autocomplete_manager_->OnGetAutocompleteSuggestions(
+ test_query_id_one, /*is_autocomplete_enabled=*/true,
+ /*autoselect_first_suggestion=*/false, test_name, test_prefix,
+ "Some Type", suggestions_handler_one->GetWeakPtr());
+
+ // Simlate second handler request for autocomplete suggestions.
+ autocomplete_manager_->OnGetAutocompleteSuggestions(
+ test_query_id_two, /*is_autocomplete_enabled=*/true,
+ /*autoselect_first_suggestion=*/false, test_name, test_prefix,
+ "Some Type", suggestions_handler_two->GetWeakPtr());
+
+ // Simlate first handler cancelling its request.
+ EXPECT_CALL(*web_data_service_, CancelRequest(mocked_db_query_id_one))
+ .Times(1);
+ autocomplete_manager_->CancelPendingQueries(suggestions_handler_one.get());
+
+ // Simulate second handler receiving the suggestions.
+ EXPECT_CALL(
+ *suggestions_handler_two.get(),
+ OnSuggestionsReturned(
+ test_query_id_two, /*autoselect_first_suggestion=*/false,
+ UnorderedElementsAre(Field(&Suggestion::value,
+ expected_values_two[0].key().value()))));
+ autocomplete_manager_->OnWebDataServiceRequestDone(
+ mocked_db_query_id_two, std::move(mocked_results_two));
+
+ // Make sure first handler is not called when the DB responds.
+ EXPECT_CALL(*suggestions_handler_one.get(),
+ OnSuggestionsReturned(test_query_id_one,
+ /*autoselect_first_suggestion=*/false, _))
+ .Times(0);
+ autocomplete_manager_->OnWebDataServiceRequestDone(
+ mocked_db_query_id_one, std::move(mocked_results_one));
+}
+// // Verify that no autocomplete suggestion is returned for textarea and UMA is
+// // logged correctly.
+TEST_F(AutocompleteHistoryManagerTest, NoAutocompleteSuggestionsForTextarea) {
FormData form;
form.name = ASCIIToUTF16("MyForm");
form.origin = GURL("http://myform.com/form.html");
@@ -323,109 +878,160 @@ TEST_F(AutocompleteHistoryManagerTest, NoAutocompleteSuggestionsForTextarea) {
FormFieldData field;
test::CreateTestFormField("Address", "address", "", "textarea", &field);
- EXPECT_CALL(external_delegate,
- OnSuggestionsReturned(0, testing::Truly(IsEmptySuggestionVector),
- false, _));
- autocomplete_history_manager.OnGetAutocompleteSuggestions(
- 0,
- field.name,
- field.value,
- field.form_control_type);
-}
-
-// Verify that no autocomplete suggestion is returned for textarea and UMA is
-// logged correctly.
-TEST_F(AutocompleteHistoryManagerTest, AutocompleteUMAQueryNotCreated) {
- TestAutocompleteHistoryManager autocomplete_history_manager(
- autofill_driver_.get(), autofill_client_.get());
- auto autofill_manager = std::make_unique<AutofillManager>(
- autofill_driver_.get(), autofill_client_.get(), "en-US",
- AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
+ auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
+ EXPECT_CALL(*suggestions_handler.get(),
+ OnSuggestionsReturned(0, /*autoselect_first_suggestion=*/false,
+ testing::Truly(IsEmptySuggestionVector)));
- MockAutofillExternalDelegate external_delegate(autofill_manager.get(),
- autofill_driver_.get());
- autocomplete_history_manager.SetExternalDelegate(&external_delegate);
+ base::HistogramTester histogram_tester;
- FormFieldData field;
- test::CreateTestFormField("Address", "address", "", "textarea", &field);
+ autocomplete_manager_->OnGetAutocompleteSuggestions(
+ 0, /*is_autocomplete_enabled=*/true,
+ /*autoselect_first_suggestion=*/false, field.name, field.value,
+ field.form_control_type, suggestions_handler->GetWeakPtr());
- base::HistogramTester histogram_tester;
- EXPECT_CALL(external_delegate,
- OnSuggestionsReturned(0, testing::Truly(IsEmptySuggestionVector),
- false, _));
- autocomplete_history_manager.OnGetAutocompleteSuggestions(
- 0, field.name, field.value, field.form_control_type);
histogram_tester.ExpectBucketCount("Autofill.AutocompleteQuery", 0, 1);
histogram_tester.ExpectBucketCount("Autofill.AutocompleteQuery", 1, 0);
}
-// Verify that autocomplete suggestion is returned and suggestions is logged
-// correctly.
+// // Verify that autocomplete suggestion is returned and suggestions is logged
+// // correctly.
TEST_F(AutocompleteHistoryManagerTest, AutocompleteUMAQueryCreated) {
- TestAutocompleteHistoryManager autocomplete_history_manager(
- autofill_driver_.get(), autofill_client_.get());
- auto autofill_manager = std::make_unique<AutofillManager>(
- autofill_driver_.get(), autofill_client_.get(), "en-US",
- AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
-
- MockAutofillExternalDelegate external_delegate(autofill_manager.get(),
- autofill_driver_.get());
- autocomplete_history_manager.SetExternalDelegate(&external_delegate);
-
+ auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
FormFieldData field;
test::CreateTestFormField("Address", "address", "", "text", &field);
// Mock returned handle to match it in OnWebDataServiceRequestDone().
- scoped_refptr<AutofillWebDataService> service =
- autofill_client_->GetDatabase();
- MockWebDataService* data_service =
- static_cast<MockWebDataService*>(service.get());
WebDataServiceBase::Handle mock_handle = 1;
- data_service->set_mock_handle(mock_handle);
+
+ EXPECT_CALL(*web_data_service_,
+ GetFormValuesForElementName(field.name, field.value, _,
+ autocomplete_manager_.get()))
+ .WillOnce(Return(mock_handle));
// Verify that the query has been created.
base::HistogramTester histogram_tester;
- EXPECT_CALL(external_delegate,
- OnSuggestionsReturned(0, testing::Truly(IsEmptySuggestionVector),
- false, _));
- autocomplete_history_manager.OnGetAutocompleteSuggestions(
- 0, field.name, field.value, field.form_control_type);
+ EXPECT_CALL(*suggestions_handler.get(),
+ OnSuggestionsReturned(0, /*autoselect_first_suggestion=*/false,
+ testing::Truly(IsEmptySuggestionVector)));
+ autocomplete_manager_->OnGetAutocompleteSuggestions(
+ 0, /*is_autocomplete_enabled=*/true,
+ /*autoselect_first_suggestion=*/false, field.name, field.value,
+ field.form_control_type, suggestions_handler->GetWeakPtr());
histogram_tester.ExpectBucketCount("Autofill.AutocompleteQuery", 1, 1);
histogram_tester.ExpectBucketCount("Autofill.AutocompleteQuery", 0, 0);
// Mock no suggestion returned and verify that the suggestion UMA is correct.
std::unique_ptr<WDTypedResult> result =
- std::make_unique<WDResult<std::vector<base::string16>>>(
- AUTOFILL_VALUE_RESULT, std::vector<base::string16>());
- autocomplete_history_manager.OnWebDataServiceRequestDone(mock_handle,
- std::move(result));
+ std::make_unique<WDResult<std::vector<AutofillEntry>>>(
+ AUTOFILL_VALUE_RESULT, std::vector<AutofillEntry>());
+ autocomplete_manager_->OnWebDataServiceRequestDone(mock_handle,
+ std::move(result));
histogram_tester.ExpectBucketCount("Autofill.AutocompleteSuggestions", 0, 1);
histogram_tester.ExpectBucketCount("Autofill.AutocompleteSuggestions", 1, 0);
// Changed the returned handle
- mock_handle = 2;
- data_service->set_mock_handle(mock_handle);
// Changed field's name to trigger UMA again.
+ mock_handle = 2;
test::CreateTestFormField("Address", "address1", "", "text", &field);
- EXPECT_CALL(external_delegate,
- OnSuggestionsReturned(0, testing::Truly(NonEmptySuggestionVector),
- false, _));
- autocomplete_history_manager.OnGetAutocompleteSuggestions(
- 0, field.name, field.value, field.form_control_type);
+
+ EXPECT_CALL(*web_data_service_,
+ GetFormValuesForElementName(field.name, field.value, _,
+ autocomplete_manager_.get()))
+ .WillOnce(Return(mock_handle));
+
+ EXPECT_CALL(*suggestions_handler.get(),
+ OnSuggestionsReturned(0, /*autoselect_first_suggestion=*/false,
+ testing::Truly(NonEmptySuggestionVector)));
+ autocomplete_manager_->OnGetAutocompleteSuggestions(
+ 0, /*is_autocomplete_enabled=*/true,
+ /*autoselect_first_suggestion=*/false, field.name, field.value,
+ field.form_control_type, suggestions_handler->GetWeakPtr());
histogram_tester.ExpectBucketCount("Autofill.AutocompleteQuery", 1, 2);
histogram_tester.ExpectBucketCount("Autofill.AutocompleteQuery", 0, 0);
// Mock one suggestion returned and verify that the suggestion UMA is correct.
- std::vector<base::string16> values;
- values.push_back(ASCIIToUTF16("value"));
- result = std::make_unique<WDResult<std::vector<base::string16>>>(
- AUTOFILL_VALUE_RESULT, values);
- autocomplete_history_manager.OnWebDataServiceRequestDone(mock_handle,
- std::move(result));
+ std::vector<AutofillEntry> values;
+ values.push_back(GetAutofillEntry(field.name, ASCIIToUTF16("value")));
+ result = GetMockedDbResults(values);
+ autocomplete_manager_->OnWebDataServiceRequestDone(mock_handle,
+ std::move(result));
histogram_tester.ExpectBucketCount("Autofill.AutocompleteSuggestions", 0, 1);
histogram_tester.ExpectBucketCount("Autofill.AutocompleteSuggestions", 1, 1);
}
+TEST_F(AutocompleteHistoryManagerTest, DestructorCancelsRequests) {
+ int mocked_db_query_id_first = 100;
+ int mocked_db_query_id_second = 101;
+
+ auto suggestions_handler_first = std::make_unique<MockSuggestionsHandler>();
+ auto suggestions_handler_second = std::make_unique<MockSuggestionsHandler>();
+ int test_query_id_first = 2;
+ int test_query_id_second = 3;
+ auto test_name = ASCIIToUTF16("Some Field Name");
+ auto test_prefix = ASCIIToUTF16("SomePrefix");
+
+ EXPECT_CALL(*web_data_service_,
+ GetFormValuesForElementName(test_name, test_prefix, _,
+ autocomplete_manager_.get()))
+ .WillOnce(Return(mocked_db_query_id_first))
+ .WillOnce(Return(mocked_db_query_id_second));
+
+ // Simulate request for the first suggestions.
+ autocomplete_manager_->OnGetAutocompleteSuggestions(
+ test_query_id_first, /*is_autocomplete_enabled=*/true,
+ /*autoselect_first_suggestion=*/false, test_name, test_prefix,
+ "Some Type", suggestions_handler_first->GetWeakPtr());
+
+ // Simulate request for the second suggestions.
+ autocomplete_manager_->OnGetAutocompleteSuggestions(
+ test_query_id_second, /*is_autocomplete_enabled=*/true,
+ /*autoselect_first_suggestion=*/false, test_name, test_prefix,
+ "Some Type", suggestions_handler_second->GetWeakPtr());
+
+ // Expect cancel calls for both requests.
+ EXPECT_CALL(*web_data_service_, CancelRequest(mocked_db_query_id_first))
+ .Times(1);
+ EXPECT_CALL(*web_data_service_, CancelRequest(mocked_db_query_id_second))
+ .Times(1);
+
+ autocomplete_manager_.reset();
+
+ EXPECT_TRUE(PendingQueriesEmpty());
+}
+
+// Tests that a successful Autocomplete Retention Policy cleanup will
+// overwrite the last cleaned major version preference, and will also
+// log a Autocomplete.Cleanup metric.
+TEST_F(AutocompleteHistoryManagerTest, EntriesCleanup_Success) {
+ // Set Pref major version to some impossible number.
+ prefs_->SetInteger(prefs::kAutocompleteLastVersionRetentionPolicy, -1);
+
+ EXPECT_EQ(-1,
+ prefs_->GetInteger(prefs::kAutocompleteLastVersionRetentionPolicy));
+
+ size_t cleanup_result = 10;
+ base::HistogramTester histogram_tester;
+
+ autocomplete_manager_->OnWebDataServiceRequestDone(
+ 1, std::make_unique<WDResult<size_t>>(AUTOFILL_CLEANUP_RESULT,
+ cleanup_result));
+
+ EXPECT_EQ(CHROME_VERSION_MAJOR,
+ prefs_->GetInteger(prefs::kAutocompleteLastVersionRetentionPolicy));
+ histogram_tester.ExpectBucketCount("Autocomplete.Cleanup", cleanup_result, 1);
+}
+
+// Tests that AutocompleteHistoryManager::OnWebDataServiceRequestDone does not
+// crash on empty results.
+TEST_F(AutocompleteHistoryManagerTest, EmptyResult_DoesNotCrash) {
+ auto empty_unique_ptr = std::unique_ptr<WDTypedResult>(nullptr);
+
+ // The expectation in this test is that the following call doesn't crash.
+ autocomplete_manager_->OnWebDataServiceRequestDone(
+ 1, std::move(empty_unique_ptr));
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_address_util.cc b/chromium/components/autofill/core/browser/autofill_address_util.cc
index 3a2dafd17c4..34806bcdb77 100644
--- a/chromium/components/autofill/core/browser/autofill_address_util.cc
+++ b/chromium/components/autofill/core/browser/autofill_address_util.cc
@@ -103,7 +103,7 @@ void GetAddressComponents(const std::string& country_code,
components[i - 1].length_hint == AddressUiComponent::HINT_LONG ||
components[i].length_hint == AddressUiComponent::HINT_LONG) {
line = new base::ListValue;
- address_components->Append(base::WrapUnique(line));
+ address_components->Append(std::unique_ptr<base::ListValue>(line));
// |line| is invalidated at this point, so it needs to be reset.
address_components->GetList(address_components->GetSize() - 1, &line);
}
diff --git a/chromium/components/autofill/core/browser/autofill_assistant_unittest.cc b/chromium/components/autofill/core/browser/autofill_assistant_unittest.cc
index fbd2a3cab8f..958759bc688 100644
--- a/chromium/components/autofill/core/browser/autofill_assistant_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_assistant_unittest.cc
@@ -9,14 +9,15 @@
#include "base/callback.h"
#include "base/feature_list.h"
-#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_task_environment.h"
#include "components/autofill/core/browser/autofill_driver.h"
#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/form_structure.h"
+#include "components/autofill/core/browser/mock_autocomplete_history_manager.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
#include "components/autofill/core/browser/test_credit_card_save_manager.h"
@@ -37,9 +38,10 @@ class MockAutofillManager : public AutofillManager {
public:
MockAutofillManager(TestAutofillDriver* driver,
TestAutofillClient* client,
- PersonalDataManager* pdm)
+ PersonalDataManager* pdm,
+ AutocompleteHistoryManager* ahm)
// Force to use the constructor designated for unit test.
- : AutofillManager(driver, client, pdm) {}
+ : AutofillManager(driver, client, pdm, ahm) {}
virtual ~MockAutofillManager() {}
MOCK_METHOD5(FillCreditCardForm,
@@ -60,7 +62,11 @@ class MockAutofillManager : public AutofillManager {
class AutofillAssistantTest : public testing::Test {
protected:
AutofillAssistantTest()
- : message_loop_(), autofill_client_(), autofill_driver_(), pdm_() {}
+ : task_environment_(),
+ autofill_client_(),
+ autofill_driver_(),
+ pdm_(),
+ ahm_() {}
void SetUp() {
payments::TestPaymentsClient* payments_client =
@@ -81,7 +87,7 @@ class AutofillAssistantTest : public testing::Test {
std::unique_ptr<TestFormDataImporter>(test_form_data_importer));
autofill_manager_ = std::make_unique<MockAutofillManager>(
- &autofill_driver_, &autofill_client_, &pdm_);
+ &autofill_driver_, &autofill_client_, &pdm_, &ahm_);
autofill_assistant_ =
std::make_unique<AutofillAssistant>(autofill_manager_.get());
@@ -133,10 +139,11 @@ class AutofillAssistantTest : public testing::Test {
return form_structure;
}
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
TestAutofillClient autofill_client_;
testing::NiceMock<TestAutofillDriver> autofill_driver_;
TestPersonalDataManager pdm_;
+ MockAutocompleteHistoryManager ahm_;
std::unique_ptr<MockAutofillManager> autofill_manager_;
std::unique_ptr<AutofillAssistant> autofill_assistant_;
base::test::ScopedFeatureList scoped_feature_list_;
diff --git a/chromium/components/autofill/core/browser/autofill_client.h b/chromium/components/autofill/core/browser/autofill_client.h
index 5b6ab0ad44a..cb53a600e65 100644
--- a/chromium/components/autofill/core/browser/autofill_client.h
+++ b/chromium/components/autofill/core/browser/autofill_client.h
@@ -50,9 +50,9 @@ enum class Channel;
namespace autofill {
class AddressNormalizer;
+class AutocompleteHistoryManager;
class AutofillPopupDelegate;
class AutofillProfile;
-class AutofillWebDataService;
class CardUnmaskDelegate;
class CreditCard;
class FormDataImporter;
@@ -60,6 +60,7 @@ class FormStructure;
class LegacyStrikeDatabase;
class MigratableCreditCard;
class PersonalDataManager;
+class StrikeDatabase;
struct Suggestion;
namespace payments {
@@ -95,6 +96,17 @@ class AutofillClient : public RiskDataLoader {
NETWORK_ERROR,
};
+ enum SaveCardOfferUserDecision {
+ // The user accepted credit card save.
+ ACCEPTED,
+
+ // The user explicitly declined credit card save.
+ DECLINED,
+
+ // The user ignored the credit card save prompt.
+ IGNORED,
+ };
+
enum UnmaskCardReason {
// The card is being unmasked for PaymentRequest.
UNMASK_FOR_PAYMENT_REQUEST,
@@ -110,11 +122,22 @@ class AutofillClient : public RiskDataLoader {
base::string16 expiration_date_month;
base::string16 expiration_date_year;
};
+
+ // Callback to run after local credit card save is offered. Sends whether the
+ // prompt was accepted, declined, or ignored in |user_decision|.
+ typedef base::OnceCallback<void(SaveCardOfferUserDecision user_decision)>
+ LocalSaveCardPromptCallback;
+
+ // Callback to run after upload credit card save is offered. Sends whether the
+ // prompt was accepted, declined, or ignored in |user_decision|, and
+ // additional |user_provided_card_details| if applicable.
typedef base::OnceCallback<void(
+ SaveCardOfferUserDecision user_decision,
const UserProvidedCardDetails& user_provided_card_details)>
- UserAcceptedUploadCallback;
+ UploadSaveCardPromptCallback;
typedef base::Callback<void(const CreditCard&)> CreditCardScanCallback;
+
// Callback to run if user presses the Save button in the migration dialog.
// Will pass a vector of GUIDs of cards that the user selected to upload to
// LocalCardMigrationManager.
@@ -139,8 +162,8 @@ class AutofillClient : public RiskDataLoader {
// Gets the PersonalDataManager instance associated with the client.
virtual PersonalDataManager* GetPersonalDataManager() = 0;
- // Gets the AutofillWebDataService instance associated with the client.
- virtual scoped_refptr<AutofillWebDataService> GetDatabase() = 0;
+ // Gets the AutocompleteHistoryManager instance associate with the client.
+ virtual AutocompleteHistoryManager* GetAutocompleteHistoryManager() = 0;
// Gets the preferences associated with the client.
virtual PrefService* GetPrefs() = 0;
@@ -161,6 +184,9 @@ class AutofillClient : public RiskDataLoader {
// TODO(crbug.com/884817): Delete this once v2 of StrikeDatabase is launched.
virtual LegacyStrikeDatabase* GetLegacyStrikeDatabase() = 0;
+ // Gets the StrikeDatabase associated with the client.
+ virtual StrikeDatabase* GetStrikeDatabase() = 0;
+
// Gets the UKM service associated with this client (for metrics).
virtual ukm::UkmRecorder* GetUkmRecorder() = 0;
@@ -193,11 +219,12 @@ class AutofillClient : public RiskDataLoader {
virtual void ShowLocalCardMigrationDialog(
base::OnceClosure show_migration_dialog_closure) = 0;
- // Shows a dialog with the given |legal_message|. Runs
+ // 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.
virtual void ConfirmMigrateLocalCardToCloud(
std::unique_ptr<base::DictionaryValue> legal_message,
+ const std::string& user_email,
const std::vector<MigratableCreditCard>& migratable_credit_cards,
LocalCardMigrationCallback start_migrating_cards_callback) = 0;
@@ -218,13 +245,15 @@ class AutofillClient : public RiskDataLoader {
virtual void ConfirmSaveAutofillProfile(const AutofillProfile& profile,
base::OnceClosure callback) = 0;
- // Runs |callback| if the |card| should be imported as personal data. On
- // desktop, shows the offer-to-save bubble if |show_prompt| is true; otherwise
- // only shows the omnibox icon. On mobile, shows the offer-to-save infobar if
- // |show_prompt| is true; otherwise does not offer to save at all.
- virtual void ConfirmSaveCreditCardLocally(const CreditCard& card,
- bool show_prompt,
- base::OnceClosure callback) = 0;
+ // Runs |callback| once the user makes a decision with respect to the
+ // offer-to-save prompt. On desktop, shows the offer-to-save bubble if
+ // |show_prompt| is true; otherwise only shows the omnibox icon. On mobile,
+ // shows the offer-to-save infobar if |show_prompt| is true; otherwise does
+ // not offer to save at all.
+ virtual void ConfirmSaveCreditCardLocally(
+ const CreditCard& card,
+ bool show_prompt,
+ LocalSaveCardPromptCallback callback) = 0;
#if defined(OS_ANDROID)
// Run |callback| if the card should be uploaded to payments with updated
@@ -233,21 +262,21 @@ class AutofillClient : public RiskDataLoader {
base::OnceCallback<void(const base::string16&)> callback) = 0;
#endif // defined(OS_ANDROID)
- // Runs |callback| if the |card| should be uploaded to Payments. Displays the
- // contents of |legal_message| to the user. Displays a cardholder name
- // textfield in the bubble if |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 offer-to-save bubble if |show_prompt| is true; otherwise only
- // shows the omnibox icon. On mobile, shows the offer-to-save infobar if
- // |show_prompt| is true; otherwise does not offer to save at all.
+ // 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
+ // |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 offer-to-save bubble if |show_prompt| is true;
+ // otherwise only shows the omnibox icon. On mobile, shows the offer-to-save
+ // infobar if |show_prompt| is true; otherwise does not offer to save at all.
virtual void ConfirmSaveCreditCardToCloud(
const CreditCard& card,
std::unique_ptr<base::DictionaryValue> legal_message,
bool should_request_name_from_user,
bool should_request_expiration_date_from_user,
bool show_prompt,
- UserAcceptedUploadCallback callback) = 0;
+ UploadSaveCardPromptCallback callback) = 0;
// Will show an infobar to get user consent for Credit Card assistive filling.
// Will run |callback| on success.
@@ -295,10 +324,6 @@ class AutofillClient : public RiskDataLoader {
const base::string16& autofilled_value,
const base::string16& profile_full_name) = 0;
- // Inform the client that the user interacted with a non-secure credit card
- // field.
- virtual void DidInteractWithNonsecureCreditCardInput() = 0;
-
// If the context is secure.
virtual bool IsContextSecure() = 0;
diff --git a/chromium/components/autofill/core/browser/autofill_data_model.cc b/chromium/components/autofill/core/browser/autofill_data_model.cc
index 72464e8e5bc..913bfe22e69 100644
--- a/chromium/components/autofill/core/browser/autofill_data_model.cc
+++ b/chromium/components/autofill/core/browser/autofill_data_model.cc
@@ -9,17 +9,17 @@
#include "components/autofill/core/browser/autofill_metadata.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/common/autofill_clock.h"
+#include "components/autofill/core/common/autofill_constants.h"
#include "url/gurl.h"
namespace autofill {
AutofillDataModel::AutofillDataModel(const std::string& guid,
const std::string& origin)
- : guid_(guid),
- origin_(origin),
- use_count_(1),
- use_date_(AutofillClock::Now()),
- modification_date_(AutofillClock::Now()) {}
+ : guid_(guid), origin_(origin), use_count_(1) {
+ set_use_date(AutofillClock::Now());
+ set_modification_date(AutofillClock::Now());
+}
AutofillDataModel::~AutofillDataModel() {}
bool AutofillDataModel::IsVerified() const {
@@ -29,7 +29,12 @@ bool AutofillDataModel::IsVerified() const {
// TODO(crbug.com/629507): Add support for injected mock clock for testing.
void AutofillDataModel::RecordUse() {
++use_count_;
- use_date_ = AutofillClock::Now();
+ set_use_date(AutofillClock::Now());
+}
+
+bool AutofillDataModel::UseDateEqualsInSeconds(
+ const AutofillDataModel* other) const {
+ return !((other->use_date() - use_date()).InSeconds());
}
bool AutofillDataModel::CompareFrecency(const AutofillDataModel* other,
@@ -70,4 +75,8 @@ double AutofillDataModel::GetFrecencyScore(base::Time time) const {
return -log((time - use_date_).InDays() + 2) / log(use_count_ + 1);
}
+bool AutofillDataModel::IsDeletable() const {
+ return use_date_ < AutofillClock::Now() - kDisusedDataModelDeletionTimeDelta;
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_data_model.h b/chromium/components/autofill/core/browser/autofill_data_model.h
index a9f562ac5ff..719df504e04 100644
--- a/chromium/components/autofill/core/browser/autofill_data_model.h
+++ b/chromium/components/autofill/core/browser/autofill_data_model.h
@@ -38,9 +38,14 @@ class AutofillDataModel : public FormGroup {
size_t use_count() const { return use_count_; }
void set_use_count(size_t count) { use_count_ = count; }
+ // Writing in and reading from database converts dates between time_t and
+ // Time, therefore the microseconds get lost. Therefore, we need to round the
+ // dates to seconds for both |use_date_| and |modification_date_|.
const base::Time& use_date() const { return use_date_; }
void set_use_date(const base::Time& time) { use_date_ = time; }
+ bool UseDateEqualsInSeconds(const AutofillDataModel* other) const;
+
const base::Time& modification_date() const { return modification_date_; }
// This should only be called from database code.
void set_modification_date(const base::Time& time) {
@@ -61,6 +66,10 @@ class AutofillDataModel : public FormGroup {
// whether the metadata was set.
virtual bool SetMetadata(const AutofillMetadata metadata);
+ // Returns whether the data model is deletable: if it has not been used for
+ // longer than |kDisusedCreditCardDeletionTimeDelta|.
+ virtual bool IsDeletable() const;
+
protected:
// Called to update |use_count_| and |use_date_| when this data model is
// the subject of user interaction (usually, when it's used to fill a form).
@@ -81,10 +90,12 @@ class AutofillDataModel : public FormGroup {
// The number of times this model has been used.
size_t use_count_;
- // The last time the model was used.
+ // The last time the model was used, rounded in seconds. Any change should
+ // use set_previous_use_date()
base::Time use_date_;
- // The last time data in the model was modified.
+ // The last time data in the model was modified, rounded in seconds. Any
+ // change should use set_previous_modification_date()
base::Time modification_date_;
// Returns a score based on both the recency (relative to |time|) and
diff --git a/chromium/components/autofill/core/browser/autofill_data_model_unittest.cc b/chromium/components/autofill/core/browser/autofill_data_model_unittest.cc
index 5ab0d1be3fe..670e50ce8d1 100644
--- a/chromium/components/autofill/core/browser/autofill_data_model_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_data_model_unittest.cc
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/autofill_metadata.h"
+#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -95,6 +96,19 @@ TEST(AutofillDataModelTest, SetMetadata) {
EXPECT_EQ(metadata.use_date, model.use_date());
}
+TEST(AutofillDataModelTest, IsDeletable) {
+ TestAutofillDataModel model("guid", std::string());
+ model.set_use_date(kArbitraryTime);
+
+ TestAutofillClock test_clock;
+ test_clock.SetNow(kArbitraryTime);
+ EXPECT_FALSE(model.IsDeletable());
+
+ test_clock.SetNow(kArbitraryTime + kDisusedDataModelDeletionTimeDelta +
+ base::TimeDelta::FromDays(1));
+ EXPECT_TRUE(model.IsDeletable());
+}
+
enum Expectation { GREATER, LESS };
struct CompareFrecencyTestCase {
const std::string guid_a;
diff --git a/chromium/components/autofill/core/browser/autofill_data_util.cc b/chromium/components/autofill/core/browser/autofill_data_util.cc
index af020675b6e..542571769a6 100644
--- a/chromium/components/autofill/core/browser/autofill_data_util.cc
+++ b/chromium/components/autofill/core/browser/autofill_data_util.cc
@@ -8,6 +8,7 @@
#include <vector>
#include "base/i18n/char_iterator.h"
+#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
@@ -114,7 +115,7 @@ bool ContainsString(const char* const set[],
void StripPrefixes(std::vector<base::StringPiece16>* name_tokens) {
auto iter = name_tokens->begin();
while (iter != name_tokens->end()) {
- if (!ContainsString(name_prefixes, arraysize(name_prefixes), *iter))
+ if (!ContainsString(name_prefixes, base::size(name_prefixes), *iter))
break;
++iter;
}
@@ -127,7 +128,7 @@ void StripPrefixes(std::vector<base::StringPiece16>* name_tokens) {
// Removes common name suffixes from |name_tokens|.
void StripSuffixes(std::vector<base::StringPiece16>* name_tokens) {
while (!name_tokens->empty()) {
- if (!ContainsString(name_suffixes, arraysize(name_suffixes),
+ if (!ContainsString(name_suffixes, base::size(name_suffixes),
name_tokens->back())) {
break;
}
@@ -216,13 +217,13 @@ bool SplitCJKName(const std::vector<base::StringPiece16>& name_tokens,
// ones)
surname_length = std::max<size_t>(
1, StartsWithAny(name, korean_multi_char_surnames,
- arraysize(korean_multi_char_surnames)));
+ base::size(korean_multi_char_surnames)));
} else {
// Default to 1 character if the surname is not in
// |common_cjk_multi_char_surnames|.
surname_length = std::max<size_t>(
1, StartsWithAny(name, common_cjk_multi_char_surnames,
- arraysize(common_cjk_multi_char_surnames)));
+ base::size(common_cjk_multi_char_surnames)));
}
parts->family = name.substr(0, surname_length).as_string();
parts->given = name.substr(surname_length).as_string();
@@ -335,7 +336,7 @@ NameParts SplitName(base::StringPiece16 name) {
reverse_family_tokens.push_back(name_tokens.back());
name_tokens.pop_back();
while (name_tokens.size() >= 1 &&
- ContainsString(family_name_prefixes, arraysize(family_name_prefixes),
+ ContainsString(family_name_prefixes, base::size(family_name_prefixes),
name_tokens.back())) {
reverse_family_tokens.push_back(name_tokens.back());
name_tokens.pop_back();
diff --git a/chromium/components/autofill/core/browser/autofill_download_manager.cc b/chromium/components/autofill/core/browser/autofill_download_manager.cc
index ac679de3a0d..adeb0145dd7 100644
--- a/chromium/components/autofill/core/browser/autofill_download_manager.cc
+++ b/chromium/components/autofill/core/browser/autofill_download_manager.cc
@@ -158,9 +158,6 @@ void LogHttpResponseData(AutofillDownloadManager::RequestType request_type,
break;
default:
NOTREACHED();
- base::UmaHistogramSparse("Autofill.Unknown.HttpResponseOrErrorCode",
- response_or_error_code);
- UMA_HISTOGRAM_TIMES("Autofill.Unknown.RequestDuration", request_duration);
}
}
@@ -179,8 +176,6 @@ void LogFailingPayloadSize(AutofillDownloadManager::RequestType request_type,
break;
default:
NOTREACHED();
- UMA_HISTOGRAM_COUNTS_100000("Autofill.Unknown.FailingPayloadSize",
- num_bytes);
}
}
@@ -197,7 +192,6 @@ void LogExponentialBackoffDelay(
break;
default:
NOTREACHED();
- UMA_HISTOGRAM_MEDIUM_TIMES("Autofill.Unknown.BackoffDelay", delay);
}
}
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 69e2bd66516..13d7f760d5c 100644
--- a/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc
@@ -14,7 +14,6 @@
#include "base/base64url.h"
#include "base/bind.h"
#include "base/format_macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -187,7 +186,7 @@ class AutofillDownloadManagerTest : public AutofillDownloadManager::Observer,
ResponseData() : type_of_response(REQUEST_QUERY_FAILED), error(0) {}
};
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
std::list<ResponseData> responses_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
network::TestURLLoaderFactory test_url_loader_factory_;
diff --git a/chromium/components/autofill/core/browser/autofill_driver.h b/chromium/components/autofill/core/browser/autofill_driver.h
index 304d818bf87..82f8a68839f 100644
--- a/chromium/components/autofill/core/browser/autofill_driver.h
+++ b/chromium/components/autofill/core/browser/autofill_driver.h
@@ -102,10 +102,6 @@ class AutofillDriver {
// renderers cannot do this transformation themselves.
virtual gfx::RectF TransformBoundingBoxToViewportCoordinates(
const gfx::RectF& bounding_box) = 0;
-
- // Called when the user interacted with a credit card form, so that
- // the current page's security state can be updated appropriately.
- virtual void DidInteractWithCreditCardForm() = 0;
};
} // namespace autofill
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 9637edfe9cb..0df561935d5 100644
--- a/chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc
@@ -8,7 +8,7 @@
#include <utility>
#include "base/bind_helpers.h"
-#include "base/message_loop/message_loop.h"
+#include "base/test/scoped_task_environment.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -98,7 +98,8 @@ class AutofillDriverFactoryTest : public testing::Test {
}
protected:
- base::MessageLoop message_loop_; // For TestAutofillDriver.
+ // For TestAutofillDriver.
+ base::test::ScopedTaskEnvironment 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 76816b84f0a..13e96ebe22c 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments.cc
+++ b/chromium/components/autofill/core/browser/autofill_experiments.cc
@@ -29,26 +29,6 @@
namespace autofill {
#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
-namespace {
-// Returns the font weight corresponding to the value of param
-// kAutofillForcedFontWeightParameterName, or kDefault if the param is not
-// valid.
-ForcedFontWeight GetFontWeightFromParam() {
- std::string param = base::GetFieldTrialParamValueByFeature(
- kAutofillPrimaryInfoStyleExperiment,
- kAutofillForcedFontWeightParameterName);
-
- if (param == kAutofillForcedFontWeightParameterMedium)
- return ForcedFontWeight::kMedium;
- if (param == kAutofillForcedFontWeightParameterBold)
- return ForcedFontWeight::kBold;
-
- return ForcedFontWeight::kDefault;
-}
-} // namespace
-#endif // defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
-
-#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
const base::Feature kAutofillDropdownLayoutExperiment{
"AutofillDropdownLayout", base::FEATURE_DISABLED_BY_DEFAULT};
const char kAutofillDropdownLayoutParameterName[] = "variant";
@@ -58,14 +38,6 @@ const char kAutofillDropdownLayoutParameterTwoLinesLeadingIcon[] =
"two-lines-leading-icon";
#endif // defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
-#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
-const base::Feature kAutofillPrimaryInfoStyleExperiment{
- "AutofillPrimaryInfoStyleExperiment", base::FEATURE_DISABLED_BY_DEFAULT};
-const char kAutofillForcedFontWeightParameterName[] = "font_weight";
-const char kAutofillForcedFontWeightParameterMedium[] = "medium";
-const char kAutofillForcedFontWeightParameterBold[] = "bold";
-#endif // defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
-
bool IsCreditCardUploadEnabled(const PrefService* pref_service,
const syncer::SyncService* sync_service,
const std::string& user_email) {
@@ -118,10 +90,13 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
// If the "allow all email domains" flag is off, restrict credit card upload
// only to Google Accounts with @googlemail, @gmail, @google, or @chromium
// domains.
+ // example.com is on the list because ChromeOS tests rely on using this. That
+ // should be fine, since example.com is an IANA reserved domain.
if (!base::FeatureList::IsEnabled(
features::kAutofillUpstreamAllowAllEmailDomains) &&
!(domain == "googlemail.com" || domain == "gmail.com" ||
- domain == "google.com" || domain == "chromium.org")) {
+ domain == "google.com" || domain == "chromium.org" ||
+ domain == "example.com")) {
return false;
}
@@ -167,13 +142,18 @@ bool IsAutofillNoLocalSaveOnUploadSuccessExperimentEnabled() {
features::kAutofillNoLocalSaveOnUploadSuccess);
}
-bool OfferStoreUnmaskedCards() {
+bool OfferStoreUnmaskedCards(bool is_off_the_record) {
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
// The checkbox can be forced on with a flag, but by default we don't store
// on Linux due to lack of system keychain integration. See crbug.com/162735
return base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableOfferStoreUnmaskedWalletCards);
#else
+ // Never offer to store unmasked cards when off the record.
+ if (is_off_the_record) {
+ return false;
+ }
+
// Query the field trial before checking command line flags to ensure UMA
// reports the correct group.
std::string group_name =
@@ -202,17 +182,6 @@ bool ShouldUseActiveSignedInAccount() {
}
#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
-ForcedFontWeight GetForcedFontWeight() {
- if (!base::FeatureList::IsEnabled(kAutofillPrimaryInfoStyleExperiment))
- return ForcedFontWeight::kDefault;
-
- // Only read the feature param's value the first time it's needed.
- static ForcedFontWeight font_weight_from_param = GetFontWeightFromParam();
- return font_weight_from_param;
-}
-#endif // defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
-
-#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
ForcedPopupLayoutState GetForcedPopupLayoutState() {
if (!base::FeatureList::IsEnabled(
autofill::kAutofillDropdownLayoutExperiment))
diff --git a/chromium/components/autofill/core/browser/autofill_experiments.h b/chromium/components/autofill/core/browser/autofill_experiments.h
index ee4bf603f7b..d4247999259 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments.h
+++ b/chromium/components/autofill/core/browser/autofill_experiments.h
@@ -31,13 +31,6 @@ extern const char kAutofillDropdownLayoutParameterTrailingIcon[];
extern const char kAutofillDropdownLayoutParameterTwoLinesLeadingIcon[];
#endif // defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
-#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
-extern const base::Feature kAutofillPrimaryInfoStyleExperiment;
-extern const char kAutofillForcedFontWeightParameterName[];
-extern const char kAutofillForcedFontWeightParameterMedium[];
-extern const char kAutofillForcedFontWeightParameterBold[];
-#endif // defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
-
// Returns true if uploading credit cards to Wallet servers is enabled. This
// requires the appropriate flags and user settings to be true and the user to
// be a member of a supported domain.
@@ -61,26 +54,12 @@ bool IsAutofillNoLocalSaveOnUploadSuccessExperimentEnabled();
// Returns true if the user should be offered to locally store unmasked cards.
// This controls whether the option is presented at all rather than the default
// response of the option.
-bool OfferStoreUnmaskedCards();
+bool OfferStoreUnmaskedCards(bool is_off_the_record);
// Returns whether the account of the active signed-in user should be used.
bool ShouldUseActiveSignedInAccount();
#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
-enum class ForcedFontWeight {
- kDefault, // No change to the font weight.
- kMedium,
- kBold,
-};
-
-// Returns the font weight to be used for primary information on the Autofill
-// dropdown for Addresses and Credit Cards. Returns kDefault if feature
-// kAutofillPrimaryInfoStyleExperiment is disabled or if the corresponding
-// feature param is invalid.
-ForcedFontWeight GetForcedFontWeight();
-#endif // defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
-
-#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
enum class ForcedPopupLayoutState {
kDefault, // No popup layout forced by experiment.
kLeadingIcon, // Experiment forces leading (left in LTR) icon layout.
diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate.cc b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
index 3a440c1260e..f1f617296f1 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
@@ -82,17 +82,6 @@ void AutofillExternalDelegate::OnSuggestionsReturned(
// Hide warnings as appropriate.
PossiblyRemoveAutofillWarnings(&suggestions);
-#if !defined(OS_ANDROID)
- // If there are above the fold suggestions at this point, add a separator to
- // go between the values and menu items. Skip this when using the Native Views
- // implementation, which has its own logic for distinguishing footer rows.
- // TODO(crbug.com/831603): Remove this when the relevant feature is on 100%.
- if (!suggestions.empty() && !features::ShouldUseNativeViews()) {
- suggestions.push_back(Suggestion());
- suggestions.back().frontend_id = POPUP_ITEM_ID_SEPARATOR;
- }
-#endif
-
if (should_show_scan_credit_card_) {
Suggestion scan_credit_card(
l10n_util::GetStringUTF16(IDS_AUTOFILL_SCAN_CREDIT_CARD));
@@ -124,16 +113,6 @@ void AutofillExternalDelegate::OnSuggestionsReturned(
// Append the credit card signin promo, if appropriate (there are no other
// suggestions).
if (suggestions.empty() && should_show_cc_signin_promo_) {
-// No separator on Android.
-#if !defined(OS_ANDROID)
- // If there are autofill suggestions, the "Autofill options" row was added
- // above. Add a separator between it and the signin promo.
- if (has_autofill_suggestions_) {
- suggestions.push_back(Suggestion());
- suggestions.back().frontend_id = POPUP_ITEM_ID_SEPARATOR;
- }
-#endif
-
Suggestion signin_promo_suggestion(
l10n_util::GetStringUTF16(IDS_AUTOFILL_CREDIT_CARD_SIGNIN_PROMO));
signin_promo_suggestion.frontend_id =
@@ -143,14 +122,6 @@ void AutofillExternalDelegate::OnSuggestionsReturned(
signin_metrics::AccessPoint::ACCESS_POINT_AUTOFILL_DROPDOWN);
}
-#if !defined(OS_ANDROID)
- // Remove the separator if there is one, and if it is the last element.
- if (!suggestions.empty() &&
- suggestions.back().frontend_id == POPUP_ITEM_ID_SEPARATOR) {
- suggestions.pop_back();
- }
-#endif
-
// If anything else is added to modify the values after inserting the data
// list, AutofillPopupControllerImpl::UpdateDataListValues will need to be
// updated to match.
@@ -242,6 +213,7 @@ void AutofillExternalDelegate::DidAcceptSuggestion(const base::string16& value,
// User selected an Autocomplete, so we fill directly.
driver_->RendererShouldFillFieldWithValue(value);
AutofillMetrics::LogAutocompleteSuggestionAcceptedIndex(position);
+ manager_->OnAutocompleteEntrySelected(value);
} else if (identifier == POPUP_ITEM_ID_SCAN_CREDIT_CARD) {
manager_->client()->ScanCreditCard(base::Bind(
&AutofillExternalDelegate::OnCreditCardScanned, GetWeakPtr()));
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 044913561f6..32c3dd956b0 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc
@@ -8,12 +8,12 @@
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.h"
#include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_task_environment.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_external_delegate.h"
@@ -95,7 +95,10 @@ class MockAutofillManager : public AutofillManager {
public:
MockAutofillManager(AutofillDriver* driver, MockAutofillClient* client)
// Force to use the constructor designated for unit test.
- : AutofillManager(driver, client, client->GetPersonalDataManager()) {}
+ : AutofillManager(driver,
+ client,
+ client->GetPersonalDataManager(),
+ client->GetAutocompleteHistoryManager()) {}
~MockAutofillManager() override {}
PopupType GetPopupType(const FormData& form,
@@ -176,7 +179,7 @@ class AutofillExternalDelegateUnitTest : public testing::Test {
kQueryId, suggestions, /*autoselect_first_suggestion=*/false);
}
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
testing::NiceMock<MockAutofillClient> autofill_client_;
std::unique_ptr<testing::NiceMock<MockAutofillDriver>> autofill_driver_;
@@ -736,6 +739,9 @@ TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateFillFieldWithValue) {
base::string16 dummy_string(ASCIIToUTF16("baz foo"));
EXPECT_CALL(*autofill_driver_,
RendererShouldFillFieldWithValue(dummy_string));
+ EXPECT_CALL(*autofill_client_.GetMockAutocompleteHistoryManager(),
+ OnAutocompleteEntrySelected(dummy_string))
+ .Times(1);
base::HistogramTester histogram_tester;
external_delegate_->DidAcceptSuggestion(dummy_string,
POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY,
@@ -890,46 +896,4 @@ TEST_F(AutofillExternalDelegateCardsFromAccountTest,
/*autoselect_first_suggestion=*/false);
}
-#if !defined(OS_ANDROID)
-// Test that the delegate includes a separator between the content rows and the
-// footer, if and only if the kAutofillExpandedPopupViews feature is disabled.
-TEST_F(AutofillExternalDelegateUnitTest, IncludeFooterSeparatorForOldUIOnly) {
- // The guts of the test. This will be run once with the feature enabled,
- // expecting not to find a separator, and a second time with the feature
- // disabled, expecting to find a separator.
- auto tester = [this](bool enabled, auto element_ids) {
- base::test::ScopedFeatureList scoped_feature_list;
-
- if (enabled) {
- scoped_feature_list.InitAndEnableFeature(
- features::kAutofillExpandedPopupViews);
- } else {
- scoped_feature_list.InitAndDisableFeature(
- features::kAutofillExpandedPopupViews);
- }
-
- IssueOnQuery(kQueryId);
-
- EXPECT_CALL(
- autofill_client_,
- ShowAutofillPopup(_, _, SuggestionVectorIdsAre(element_ids), false, _));
-
- std::vector<Suggestion> autofill_item;
- autofill_item.push_back(Suggestion());
- autofill_item[0].frontend_id = kAutofillProfileId;
- external_delegate_->OnSuggestionsReturned(
- kQueryId, autofill_item, /*autoselect_first_suggestion=*/false);
- };
-
- tester(false,
- testing::ElementsAre(
- kAutofillProfileId, static_cast<int>(POPUP_ITEM_ID_SEPARATOR),
- static_cast<int>(POPUP_ITEM_ID_AUTOFILL_OPTIONS)));
-
- tester(true, testing::ElementsAre(
- kAutofillProfileId,
- static_cast<int>(POPUP_ITEM_ID_AUTOFILL_OPTIONS)));
-}
-#endif // !defined(OS_ANDROID)
-
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_handler.cc b/chromium/components/autofill/core/browser/autofill_handler.cc
index 865ecd43122..a495cefa853 100644
--- a/chromium/components/autofill/core/browser/autofill_handler.cc
+++ b/chromium/components/autofill/core/browser/autofill_handler.cc
@@ -54,10 +54,9 @@ AutofillHandler::~AutofillHandler() = default;
void AutofillHandler::OnFormSubmitted(const FormData& form,
bool known_success,
- SubmissionSource source,
- base::TimeTicks timestamp) {
+ SubmissionSource source) {
if (IsValidFormData(form))
- OnFormSubmittedImpl(form, known_success, source, timestamp);
+ OnFormSubmittedImpl(form, known_success, source);
}
void AutofillHandler::OnFormsSeen(const std::vector<FormData>& forms,
diff --git a/chromium/components/autofill/core/browser/autofill_handler.h b/chromium/components/autofill/core/browser/autofill_handler.h
index f228eaff880..16f06b44368 100644
--- a/chromium/components/autofill/core/browser/autofill_handler.h
+++ b/chromium/components/autofill/core/browser/autofill_handler.h
@@ -76,8 +76,7 @@ class AutofillHandler {
// personal profile.
void OnFormSubmitted(const FormData& form,
bool known_success,
- SubmissionSource source,
- base::TimeTicks timestamp);
+ SubmissionSource source);
// Invoked when |forms| has been detected.
void OnFormsSeen(const std::vector<FormData>& forms,
@@ -135,8 +134,7 @@ class AutofillHandler {
virtual void OnFormSubmittedImpl(const FormData& form,
bool known_success,
- SubmissionSource source,
- base::TimeTicks timestamp) = 0;
+ SubmissionSource source) = 0;
virtual void OnTextFieldDidChangeImpl(const FormData& form,
const FormFieldData& field,
diff --git a/chromium/components/autofill/core/browser/autofill_handler_proxy.cc b/chromium/components/autofill/core/browser/autofill_handler_proxy.cc
index 7ed1e4e63eb..cf75c3d4165 100644
--- a/chromium/components/autofill/core/browser/autofill_handler_proxy.cc
+++ b/chromium/components/autofill/core/browser/autofill_handler_proxy.cc
@@ -18,9 +18,8 @@ AutofillHandlerProxy::~AutofillHandlerProxy() {}
void AutofillHandlerProxy::OnFormSubmittedImpl(const FormData& form,
bool known_success,
- SubmissionSource source,
- base::TimeTicks timestamp) {
- provider_->OnFormSubmitted(this, form, known_success, source, timestamp);
+ SubmissionSource source) {
+ provider_->OnFormSubmitted(this, form, known_success, source);
}
void AutofillHandlerProxy::OnTextFieldDidChangeImpl(
diff --git a/chromium/components/autofill/core/browser/autofill_handler_proxy.h b/chromium/components/autofill/core/browser/autofill_handler_proxy.h
index 364643a9aae..3c560df3e3f 100644
--- a/chromium/components/autofill/core/browser/autofill_handler_proxy.h
+++ b/chromium/components/autofill/core/browser/autofill_handler_proxy.h
@@ -39,8 +39,7 @@ class AutofillHandlerProxy : public AutofillHandler {
protected:
void OnFormSubmittedImpl(const FormData& form,
bool known_success,
- SubmissionSource source,
- base::TimeTicks timestamp) override;
+ SubmissionSource source) override;
void OnTextFieldDidChangeImpl(const FormData& form,
const FormFieldData& field,
diff --git a/chromium/components/autofill/core/browser/autofill_ie_toolbar_import_win_unittest.cc b/chromium/components/autofill/core/browser/autofill_ie_toolbar_import_win_unittest.cc
index abc0088a62f..1d218fcc902 100644
--- a/chromium/components/autofill/core/browser/autofill_ie_toolbar_import_win_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_ie_toolbar_import_win_unittest.cc
@@ -6,7 +6,7 @@
#include <stddef.h>
-#include "base/macros.h"
+#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/win/registry.h"
#include "components/autofill/core/browser/autofill_profile.h"
@@ -152,13 +152,13 @@ TEST_F(AutofillIeToolbarImportTest, TestAutofillImport) {
profile_key.Create(HKEY_CURRENT_USER, kProfileKey, KEY_ALL_ACCESS);
EXPECT_TRUE(profile_key.Valid());
- CreateSubkey(&profile_key, L"0", profile1, arraysize(profile1));
- CreateSubkey(&profile_key, L"1", profile2, arraysize(profile2));
+ CreateSubkey(&profile_key, L"0", profile1, base::size(profile1));
+ CreateSubkey(&profile_key, L"1", profile2, base::size(profile2));
RegKey cc_key;
cc_key.Create(HKEY_CURRENT_USER, kCreditCardKey, KEY_ALL_ACCESS);
EXPECT_TRUE(cc_key.Valid());
- CreateSubkey(&cc_key, L"0", credit_card, arraysize(credit_card));
+ CreateSubkey(&cc_key, L"0", credit_card, base::size(credit_card));
EncryptAndWrite(&cc_key, &empty_password);
EncryptAndWrite(&cc_key, &empty_salt);
diff --git a/chromium/components/autofill/core/browser/autofill_manager.cc b/chromium/components/autofill/core/browser/autofill_manager.cc
index d68e6bdfd11..95dcd22455c 100644
--- a/chromium/components/autofill/core/browser/autofill_manager.cc
+++ b/chromium/components/autofill/core/browser/autofill_manager.cc
@@ -24,6 +24,7 @@
#include "base/i18n/rtl.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "base/path_service.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
@@ -198,17 +199,21 @@ AutofillManager::AutofillManager(
: AutofillManager(driver,
client,
client->GetPersonalDataManager(),
+ client->GetAutocompleteHistoryManager(),
app_locale,
enable_download_manager) {}
-AutofillManager::~AutofillManager() {}
+AutofillManager::~AutofillManager() {
+ if (autocomplete_history_manager_) {
+ autocomplete_history_manager_->CancelPendingQueries(this);
+ }
+}
void AutofillManager::SetExternalDelegate(AutofillExternalDelegate* delegate) {
// TODO(jrg): consider passing delegate into the ctor. That won't
// work if the delegate has a pointer to the AutofillManager, but
// future directions may not need such a pointer.
external_delegate_ = delegate;
- autocomplete_history_manager_->SetExternalDelegate(delegate);
}
void AutofillManager::ShowAutofillSettings(bool show_credit_card_settings) {
@@ -361,8 +366,7 @@ bool AutofillManager::ShouldParseForms(const std::vector<FormData>& forms,
void AutofillManager::OnFormSubmittedImpl(const FormData& form,
bool known_success,
- SubmissionSource source,
- base::TimeTicks timestamp) {
+ SubmissionSource source) {
// TODO(crbug.com/801698): handle PROBABLY_FORM_SUBMITTED.
if (source == SubmissionSource::PROBABLY_FORM_SUBMITTED &&
!base::FeatureList::IsEnabled(
@@ -373,7 +377,8 @@ void AutofillManager::OnFormSubmittedImpl(const FormData& form,
// We will always give Autocomplete a chance to save the data.
std::unique_ptr<FormStructure> submitted_form = ValidateSubmittedForm(form);
if (!submitted_form) {
- autocomplete_history_manager_->OnWillSubmitForm(form);
+ autocomplete_history_manager_->OnWillSubmitForm(
+ form, client_->IsAutocompleteEnabled());
return;
}
@@ -386,7 +391,8 @@ void AutofillManager::OnFormSubmittedImpl(const FormData& form,
form_for_autocomplete.fields[i].should_autocomplete = false;
}
}
- autocomplete_history_manager_->OnWillSubmitForm(form_for_autocomplete);
+ autocomplete_history_manager_->OnWillSubmitForm(
+ form_for_autocomplete, client_->IsAutocompleteEnabled());
if (IsProfileAutofillEnabled()) {
address_form_event_logger_->OnWillSubmitForm(sync_state_);
@@ -396,7 +402,7 @@ void AutofillManager::OnFormSubmittedImpl(const FormData& form,
}
submitted_form->set_submission_source(source);
- MaybeStartVoteUploadProcess(std::move(submitted_form), timestamp,
+ MaybeStartVoteUploadProcess(std::move(submitted_form),
/*observed_submission=*/true);
// TODO(crbug.com/803334): Add FormStructure::Clone() method.
@@ -435,7 +441,6 @@ void AutofillManager::OnFormSubmittedImpl(const FormData& form,
bool AutofillManager::MaybeStartVoteUploadProcess(
std::unique_ptr<FormStructure> form_structure,
- const TimeTicks& timestamp,
bool observed_submission) {
// It is possible for |personal_data_| to be null, such as when used in the
// Android webview.
@@ -445,7 +450,7 @@ bool AutofillManager::MaybeStartVoteUploadProcess(
// Only upload server statistics and UMA metrics if at least some local data
// is available to use as a baseline.
std::vector<AutofillProfile*> profiles = personal_data_->GetProfiles();
- personal_data_->UpdateProfilesValidityMapsIfNeeded(profiles);
+ personal_data_->UpdateProfilesServerValidityMapsIfNeeded(profiles);
if (observed_submission && form_structure->IsAutofillable()) {
AutofillMetrics::LogNumberOfProfilesAtAutofillableFormSubmission(
personal_data_->GetProfiles().size());
@@ -485,10 +490,11 @@ bool AutofillManager::MaybeStartVoteUploadProcess(
base::BindOnce(&AutofillManager::DeterminePossibleFieldTypesForUpload,
copied_profiles, copied_credit_cards, app_locale_,
raw_form),
- base::BindOnce(
- &AutofillManager::UploadFormDataAsyncCallback,
- weak_ptr_factory_.GetWeakPtr(), base::Owned(form_structure.release()),
- initial_interaction_timestamp_, timestamp, observed_submission));
+ base::BindOnce(&AutofillManager::UploadFormDataAsyncCallback,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Owned(form_structure.release()),
+ initial_interaction_timestamp_, base::TimeTicks::Now(),
+ observed_submission));
return true;
}
@@ -513,7 +519,7 @@ void AutofillManager::ProcessPendingFormForUpload() {
if (!upload_form)
return;
- MaybeStartVoteUploadProcess(std::move(upload_form), TimeTicks::Now(),
+ MaybeStartVoteUploadProcess(std::move(upload_form),
/*observed_submission=*/false);
}
@@ -602,7 +608,7 @@ void AutofillManager::OnQueryFormFieldAutofillImpl(
case SuppressReason::kCreditCardsAblation:
enable_ablation_logging_ = true;
- autocomplete_history_manager_->CancelPendingQuery();
+ autocomplete_history_manager_->CancelPendingQueries(this);
external_delegate_->OnSuggestionsReturned(query_id, suggestions,
autoselect_first_suggestion);
return;
@@ -646,12 +652,14 @@ void AutofillManager::OnQueryFormFieldAutofillImpl(
// Suggestions come back asynchronously, so the Autocomplete manager will
// handle sending the results back to the renderer.
autocomplete_history_manager_->OnGetAutocompleteSuggestions(
- query_id, field.name, field.value, field.form_control_type);
+ query_id, client_->IsAutocompleteEnabled(), autoselect_first_suggestion,
+ field.name, field.value, field.form_control_type,
+ weak_ptr_factory_.GetWeakPtr());
return;
}
// Send Autofill suggestions (could be an empty list).
- autocomplete_history_manager_->CancelPendingQuery();
+ autocomplete_history_manager_->CancelPendingQueries(this);
external_delegate_->OnSuggestionsReturned(query_id, suggestions,
autoselect_first_suggestion,
context.is_all_server_suggestions);
@@ -903,7 +911,7 @@ void AutofillManager::OnHidePopup() {
if (!IsAutofillEnabled())
return;
- autocomplete_history_manager_->CancelPendingQuery();
+ autocomplete_history_manager_->CancelPendingQueries(this);
client_->HideAutofillPopup();
}
@@ -991,6 +999,10 @@ void AutofillManager::RemoveAutocompleteEntry(const base::string16& name,
autocomplete_history_manager_->OnRemoveAutocompleteEntry(name, value);
}
+void AutofillManager::OnAutocompleteEntrySelected(const base::string16& value) {
+ autocomplete_history_manager_->OnAutocompleteEntrySelected(value);
+}
+
bool AutofillManager::IsShowingUnmaskPrompt() {
return full_card_request_ && full_card_request_->IsGettingFullCard();
}
@@ -1154,6 +1166,15 @@ bool AutofillManager::ShouldUploadForm(const FormStructure& form) {
form.ShouldBeUploaded();
}
+// AutocompleteHistoryManager::SuggestionsHandler implementation
+void AutofillManager::OnSuggestionsReturned(
+ int query_id,
+ bool autoselect_first_suggestion,
+ const std::vector<Suggestion>& suggestions) {
+ external_delegate_->OnSuggestionsReturned(query_id, suggestions,
+ autoselect_first_suggestion);
+}
+
// Note that |submitted_form| is passed as a pointer rather than as a reference
// so that we can get memory management right across threads. Note also that we
// explicitly pass in all the time stamps of interest, as the cached ones might
@@ -1236,6 +1257,7 @@ AutofillManager::AutofillManager(
AutofillDriver* driver,
AutofillClient* client,
PersonalDataManager* personal_data,
+ AutocompleteHistoryManager* autocomplete_history_manager,
const std::string app_locale,
AutofillDownloadManagerState enable_download_manager)
: AutofillHandler(driver),
@@ -1243,8 +1265,7 @@ AutofillManager::AutofillManager(
app_locale_(app_locale),
personal_data_(personal_data),
field_filler_(app_locale, client->GetAddressNormalizer()),
- autocomplete_history_manager_(
- std::make_unique<AutocompleteHistoryManager>(driver, client)),
+ autocomplete_history_manager_(autocomplete_history_manager->GetWeakPtr()),
form_interactions_ukm_logger_(
std::make_unique<AutofillMetrics::FormInteractionsUkmLogger>(
client->GetUkmRecorder(),
@@ -1272,8 +1293,14 @@ AutofillManager::AutofillManager(
new AutofillDownloadManager(driver, this, GetAPIKeyForUrl(channel)));
}
CountryNames::SetLocaleString(app_locale_);
- if (personal_data_ && client_)
+ // Since we want Downstream to still work in incognito, only overwrite the
+ // PDM's sync service if this is not an incognito AutofillManager. However, if
+ // the opened window is in incognito, the sync service would be null. Unless
+ // there is a major refactor with the Autofill Sync interation, there is
+ // nothing we can do for that specific case.
+ if (personal_data_ && client_ && !driver->IsIncognito()) {
personal_data_->OnSyncServiceInitialized(client_->GetSyncService());
+ }
}
bool AutofillManager::RefreshDataModels() {
@@ -1361,13 +1388,9 @@ void AutofillManager::FillOrPreviewDataModelForm(
DCHECK(form_structure);
DCHECK(autofill_field);
- FormData result = form;
-
- if (base::FeatureList::IsEnabled(
- features::kAutofillRationalizeFieldTypePredictions)) {
- form_structure->RationalizePhoneNumbersInSection(autofill_field->section);
- }
+ form_structure->RationalizePhoneNumbersInSection(autofill_field->section);
+ FormData result = form;
DCHECK_EQ(form_structure->field_count(), form.fields.size());
// Only record the types that are filled for an eventual refill if all the
@@ -2093,7 +2116,6 @@ void AutofillManager::GetAvailableSuggestions(
if (got_autofillable_form) {
if (context->focused_field->Type().group() == CREDIT_CARD) {
context->is_filling_credit_card = true;
- driver()->DidInteractWithCreditCardForm();
credit_card_form_event_logger_->OnDidInteractWithAutofillableForm(
context->form_structure->form_signature(), sync_state_);
} else {
diff --git a/chromium/components/autofill/core/browser/autofill_manager.h b/chromium/components/autofill/core/browser/autofill_manager.h
index bcb6ac6bdfe..588f1ee0693 100644
--- a/chromium/components/autofill/core/browser/autofill_manager.h
+++ b/chromium/components/autofill/core/browser/autofill_manager.h
@@ -68,7 +68,8 @@ extern const int kCreditCardSigninPromoImpressionLimit;
class AutofillManager : public AutofillHandler,
public AutofillDownloadManager::Observer,
public payments::FullCardRequest::ResultDelegate,
- public payments::FullCardRequest::UIDelegate {
+ public payments::FullCardRequest::UIDelegate,
+ public AutocompleteHistoryManager::SuggestionsHandler {
public:
AutofillManager(AutofillDriver* driver,
AutofillClient* client,
@@ -140,6 +141,9 @@ class AutofillManager : public AutofillHandler,
void RemoveAutocompleteEntry(const base::string16& name,
const base::string16& value);
+ // Invoked when the user selected |value| in the Autocomplete drop-down.
+ void OnAutocompleteEntrySelected(const base::string16& value);
+
// Returns true when the Payments card unmask prompt is being displayed.
bool IsShowingUnmaskPrompt();
@@ -170,7 +174,6 @@ class AutofillManager : public AutofillHandler,
// start.
virtual bool MaybeStartVoteUploadProcess(
std::unique_ptr<FormStructure> form_structure,
- const base::TimeTicks& timestamp,
bool observed_submission);
// Update the pending form with |form|, possibly processing the current
@@ -199,6 +202,12 @@ class AutofillManager : public AutofillHandler,
void SelectFieldOptionsDidChange(const FormData& form) override;
void Reset() override;
+ // AutocompleteHistoryManager::SuggestionsHandler:
+ void OnSuggestionsReturned(
+ int query_id,
+ bool autoselect_first_suggestion,
+ const std::vector<Suggestion>& suggestions) override;
+
// Returns the value of AutofillEnabled pref.
virtual bool IsAutofillEnabled() const;
@@ -224,6 +233,7 @@ class AutofillManager : public AutofillHandler,
AutofillManager(AutofillDriver* driver,
AutofillClient* client,
PersonalDataManager* personal_data,
+ AutocompleteHistoryManager* autocomplete_history_manager,
const std::string app_locale = "en-US",
AutofillDownloadManagerState enable_download_manager =
DISABLE_AUTOFILL_DOWNLOAD_MANAGER);
@@ -259,8 +269,7 @@ class AutofillManager : public AutofillHandler,
// AutofillHandler:
void OnFormSubmittedImpl(const FormData& form,
bool known_success,
- SubmissionSource source,
- base::TimeTicks timestamp) override;
+ SubmissionSource source) override;
void OnTextFieldDidChangeImpl(const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box,
@@ -533,7 +542,8 @@ class AutofillManager : public AutofillHandler,
std::unique_ptr<AutofillDownloadManager> download_manager_;
// Handles single-field autocomplete form data.
- std::unique_ptr<AutocompleteHistoryManager> autocomplete_history_manager_;
+ // May be NULL. NULL indicates OTR.
+ base::WeakPtr<AutocompleteHistoryManager> autocomplete_history_manager_;
// Utility for logging URL keyed metrics.
std::unique_ptr<AutofillMetrics::FormInteractionsUkmLogger>
diff --git a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
index 879e3d7ecb9..68c0d62c8da 100644
--- a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -14,10 +14,10 @@
#include "base/base64.h"
#include "base/command_line.h"
#include "base/feature_list.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/metrics_hashes.h"
+#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -33,6 +33,7 @@
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/mock_autocomplete_history_manager.h"
#include "components/autofill/core/browser/payments/test_payments_client.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/popup_item_ids.h"
@@ -59,6 +60,7 @@
#include "components/prefs/pref_service.h"
#include "components/security_state/core/security_state.h"
#include "components/strings/grit/components_strings.h"
+#include "components/sync/driver/test_sync_service.h"
#include "components/variations/variations_associated_data.h"
#include "components/variations/variations_params_manager.h"
#include "components/version_info/channel.h"
@@ -262,22 +264,6 @@ void ExpectFilledCreditCardYearMonthWithYearMonth(int page_id,
month, year, has_address_fields, true, true);
}
-class MockAutocompleteHistoryManager : public AutocompleteHistoryManager {
- public:
- MockAutocompleteHistoryManager(AutofillDriver* driver, AutofillClient* client)
- : AutocompleteHistoryManager(driver, client) {}
-
- MOCK_METHOD4(OnGetAutocompleteSuggestions,
- void(int query_id,
- const base::string16& name,
- const base::string16& prefix,
- const std::string& form_control_type));
- MOCK_METHOD1(OnWillSubmitForm, void(const FormData& form));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockAutocompleteHistoryManager);
-};
-
class MockAutofillDriver : public TestAutofillDriver {
public:
MockAutofillDriver() {}
@@ -303,7 +289,7 @@ class AutofillManagerTest : public testing::Test {
void SetUp() override {
autofill_client_.SetPrefs(test::PrefServiceForTesting());
- personal_data_.Init(/*profile_database=*/autofill_client_.GetDatabase(),
+ personal_data_.Init(/*profile_database=*/database_,
/*account_database=*/nullptr,
/*pref_service=*/autofill_client_.GetPrefs(),
/*identity_manager=*/nullptr,
@@ -312,6 +298,13 @@ class AutofillManagerTest : public testing::Test {
/*cookie_manager_sevice=*/nullptr,
/*is_off_the_record=*/false);
personal_data_.SetPrefService(autofill_client_.GetPrefs());
+
+ autocomplete_history_manager_ =
+ std::make_unique<MockAutocompleteHistoryManager>();
+ autocomplete_history_manager_->Init(
+ /*profile_database=*/database_,
+ /*is_off_the_record=*/false);
+
autofill_driver_ =
std::make_unique<testing::NiceMock<MockAutofillDriver>>();
request_context_ = new net::TestURLRequestContextGetter(
@@ -336,7 +329,8 @@ class AutofillManagerTest : public testing::Test {
std::unique_ptr<autofill::TestFormDataImporter>(
test_form_data_importer));
autofill_manager_ = std::make_unique<TestAutofillManager>(
- autofill_driver_.get(), &autofill_client_, &personal_data_);
+ autofill_driver_.get(), &autofill_client_, &personal_data_,
+ autocomplete_history_manager_.get());
download_manager_ = new MockAutofillDownloadManager(
autofill_driver_.get(), autofill_manager_.get());
// AutofillManager takes ownership of |download_manager_|.
@@ -427,8 +421,15 @@ class AutofillManagerTest : public testing::Test {
}
void AutocompleteSuggestionsReturned(
- const std::vector<base::string16>& result) {
- autofill_manager_->autocomplete_history_manager_->SendSuggestions(&result);
+ const std::vector<base::string16>& results,
+ int query_id = kDefaultPageID) {
+ std::vector<Suggestion> suggestions;
+ std::transform(results.begin(), results.end(),
+ std::back_inserter(suggestions),
+ [](auto result) { return Suggestion(result); });
+
+ autofill_manager_->OnSuggestionsReturned(
+ query_id, /*autoselect_first_suggestion=*/false, suggestions);
}
void FormsSeen(const std::vector<FormData>& forms) {
@@ -436,8 +437,8 @@ class AutofillManagerTest : public testing::Test {
}
void FormSubmitted(const FormData& form) {
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, base::TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
}
void FillAutofillFormData(int query_id,
@@ -530,16 +531,6 @@ class AutofillManagerTest : public testing::Test {
form->fields[0], *card);
}
- // Convenience method for using and retrieving a mock autocomplete history
- // manager.
- MockAutocompleteHistoryManager* RecreateMockAutocompleteHistoryManager() {
- MockAutocompleteHistoryManager* manager =
- new MockAutocompleteHistoryManager(autofill_driver_.get(),
- autofill_manager_->client());
- autofill_manager_->autocomplete_history_manager_.reset(manager);
- return manager;
- }
-
// Convenience method to cast the FullCardRequest into a CardUnmaskDelegate.
CardUnmaskDelegate* full_card_unmask_delegate() {
DCHECK(autofill_manager_->full_card_request_);
@@ -589,8 +580,10 @@ class AutofillManagerTest : public testing::Test {
std::unique_ptr<TestAutofillManager> autofill_manager_;
std::unique_ptr<TestAutofillExternalDelegate> external_delegate_;
scoped_refptr<net::TestURLRequestContextGetter> request_context_;
+ scoped_refptr<AutofillWebDataService> database_;
MockAutofillDownloadManager* download_manager_;
TestPersonalDataManager personal_data_;
+ std::unique_ptr<MockAutocompleteHistoryManager> autocomplete_history_manager_;
base::test::ScopedFeatureList scoped_feature_list_;
variations::testing::VariationParamsManager variation_params_;
@@ -761,8 +754,9 @@ TEST_F(AutofillManagerTest, GetProfileSuggestions_UnrecognizedAttribute) {
FormsSeen(forms);
// Ensure that autocomplete manager is not called for suggestions either.
- MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
- EXPECT_CALL(*m, OnGetAutocompleteSuggestions(_, _, _, _)).Times(0);
+ EXPECT_CALL(*(autocomplete_history_manager_.get()),
+ OnGetAutocompleteSuggestions)
+ .Times(0);
// Suggestions should be returned for the first two fields.
GetAutofillSuggestions(form, form.fields[0]);
@@ -799,8 +793,9 @@ TEST_F(AutofillManagerTest,
FormsSeen(forms);
// Ensure that autocomplete manager is called for both fields.
- MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
- EXPECT_CALL(*m, OnGetAutocompleteSuggestions(_, _, _, _)).Times(2);
+ EXPECT_CALL(*(autocomplete_history_manager_.get()),
+ OnGetAutocompleteSuggestions)
+ .Times(2);
GetAutofillSuggestions(form, form.fields[0]);
EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
@@ -867,8 +862,9 @@ TEST_F(AutofillManagerTest,
FormsSeen(forms);
// Ensure that autocomplete manager is called for both fields.
- MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
- EXPECT_CALL(*m, OnGetAutocompleteSuggestions(_, _, _, _)).Times(0);
+ EXPECT_CALL(*(autocomplete_history_manager_.get()),
+ OnGetAutocompleteSuggestions)
+ .Times(0);
GetAutofillSuggestions(form, form.fields[0]);
CheckSuggestions(kDefaultPageID,
@@ -951,6 +947,16 @@ TEST_F(AutofillManagerTest,
Suggestion("Presley", "Elvis Aaron Presley", "", 2));
}
+// Test that the call is properly forwarded to AutocompleteHistoryManager.
+TEST_F(AutofillManagerTest, OnAutocompleteEntrySelected) {
+ base::string16 test_value = ASCIIToUTF16("TestValue");
+ EXPECT_CALL(*autocomplete_history_manager_.get(),
+ OnAutocompleteEntrySelected(test_value))
+ .Times(1);
+
+ autofill_manager_->OnAutocompleteEntrySelected(test_value);
+}
+
// Test that we return all address profile suggestions when all form fields are
// empty.
TEST_F(AutofillManagerTest, GetProfileSuggestions_EmptyValue) {
@@ -1126,6 +1132,27 @@ TEST_F(AutofillManagerTest, GetProfileSuggestions_AutofillDisabledByUser) {
EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
}
+TEST_F(AutofillManagerTest, OnSuggestionsReturned_CallsExternalDelegate) {
+ std::vector<Suggestion> suggestions = {
+ Suggestion("Charles", "123 Apple St.", "", 1),
+ Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 2)};
+
+ {
+ autofill_manager_->OnSuggestionsReturned(
+ kDefaultPageID, /*autoselect_first_suggestion=*/false, suggestions);
+
+ EXPECT_FALSE(external_delegate_->autoselect_first_suggestion());
+ CheckSuggestions(kDefaultPageID, suggestions[0], suggestions[1]);
+ }
+ {
+ autofill_manager_->OnSuggestionsReturned(
+ kDefaultPageID, /*autoselect_first_suggestion=*/true, suggestions);
+
+ EXPECT_TRUE(external_delegate_->autoselect_first_suggestion());
+ CheckSuggestions(kDefaultPageID, suggestions[0], suggestions[1]);
+ }
+}
+
// Test that we return all credit card profile suggestions when all form fields
// are empty.
TEST_F(AutofillManagerTest, GetCreditCardSuggestions_EmptyValue) {
@@ -1327,8 +1354,9 @@ TEST_F(AutofillManagerTest, GetCreditCardSuggestions_OnlySigninPromo) {
EXPECT_TRUE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
// Autocomplete suggestions are not queried.
- MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
- EXPECT_CALL(*m, OnGetAutocompleteSuggestions(_, _, _, _)).Times(0);
+ EXPECT_CALL(*(autocomplete_history_manager_.get()),
+ OnGetAutocompleteSuggestions)
+ .Times(0);
GetAutofillSuggestions(form, field);
@@ -2973,60 +3001,27 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_ComponentizedNumbers) {
std::vector<FormData> forms_copy;
forms_copy.push_back(form_data_copy);
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormsSeen(forms);
- int page_id = 1;
- int response_page_id = 0;
- FormData response_data;
- FillAutofillFormDataAndSaveResults(
- page_id, form_with_multiple_componentized_phone_fields,
- *form_with_multiple_componentized_phone_fields.fields.begin(),
- MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
- EXPECT_EQ(1, response_page_id);
-
- // Verify only the first complete set of phone number fields are filled.
- ASSERT_EQ(8U, response_data.fields.size());
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[0].value);
- EXPECT_EQ(ASCIIToUTF16("1"), response_data.fields[1].value);
- EXPECT_EQ(ASCIIToUTF16("650"), response_data.fields[2].value);
- EXPECT_EQ(ASCIIToUTF16("5554567"), response_data.fields[3].value);
- EXPECT_EQ(base::string16(), response_data.fields[4].value);
- EXPECT_EQ(base::string16(), response_data.fields[5].value);
- EXPECT_EQ(base::string16(), response_data.fields[6].value);
- EXPECT_EQ(base::string16(), response_data.fields[7].value);
- }
+ FormsSeen(forms);
+ int page_id = 1;
+ int response_page_id = 0;
+ FormData response_data;
+ FillAutofillFormDataAndSaveResults(
+ page_id, form_with_multiple_componentized_phone_fields,
+ *form_with_multiple_componentized_phone_fields.fields.begin(),
+ MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
+ EXPECT_EQ(1, response_page_id);
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormsSeen(forms_copy);
- int page_id = 1;
- int response_page_id = 0;
- FormData response_data;
- FillAutofillFormDataAndSaveResults(
- page_id, form_data_copy, *form_data_copy.fields.begin(),
- MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
- EXPECT_EQ(1, response_page_id);
-
- // Sanity check for old behavior: all phone number fields are filled.
- ASSERT_EQ(8U, response_data.fields.size());
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[0].value);
- EXPECT_EQ(ASCIIToUTF16("1"), response_data.fields[1].value);
- EXPECT_EQ(ASCIIToUTF16("650"), response_data.fields[2].value);
- EXPECT_EQ(ASCIIToUTF16("5554567"), response_data.fields[3].value);
- EXPECT_EQ(base::string16(), response_data.fields[4].value);
- EXPECT_EQ(ASCIIToUTF16("1"), response_data.fields[5].value);
- EXPECT_EQ(ASCIIToUTF16("650"), response_data.fields[6].value);
- EXPECT_EQ(ASCIIToUTF16("5554567"), response_data.fields[7].value);
- }
+ // Verify only the first complete set of phone number fields are filled.
+ ASSERT_EQ(8U, response_data.fields.size());
+ EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
+ response_data.fields[0].value);
+ EXPECT_EQ(ASCIIToUTF16("1"), response_data.fields[1].value);
+ EXPECT_EQ(ASCIIToUTF16("650"), response_data.fields[2].value);
+ EXPECT_EQ(ASCIIToUTF16("5554567"), response_data.fields[3].value);
+ EXPECT_EQ(base::string16(), response_data.fields[4].value);
+ EXPECT_EQ(base::string16(), response_data.fields[5].value);
+ EXPECT_EQ(base::string16(), response_data.fields[6].value);
+ EXPECT_EQ(base::string16(), response_data.fields[7].value);
}
TEST_F(AutofillManagerTest, FillFirstPhoneNumber_WholeNumbers) {
@@ -3062,52 +3057,23 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_WholeNumbers) {
std::vector<FormData> forms_copy;
forms_copy.push_back(form_data_copy);
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormsSeen(forms);
- int page_id = 1;
- int response_page_id = 0;
- FormData response_data;
- FillAutofillFormDataAndSaveResults(
- page_id, form_with_multiple_whole_number_fields,
- *form_with_multiple_whole_number_fields.fields.begin(),
- MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
- EXPECT_EQ(1, response_page_id);
-
- // Verify only the first complete set of phone number fields are filled.
- ASSERT_EQ(4U, response_data.fields.size());
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[0].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[1].value);
- EXPECT_EQ(base::string16(), response_data.fields[2].value);
- EXPECT_EQ(base::string16(), response_data.fields[3].value);
- }
+ FormsSeen(forms);
+ int page_id = 1;
+ int response_page_id = 0;
+ FormData response_data;
+ FillAutofillFormDataAndSaveResults(
+ page_id, form_with_multiple_whole_number_fields,
+ *form_with_multiple_whole_number_fields.fields.begin(),
+ MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
+ EXPECT_EQ(1, response_page_id);
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormsSeen(forms_copy);
- int page_id = 1;
- int response_page_id = 0;
- FormData response_data;
- FillAutofillFormDataAndSaveResults(
- page_id, form_data_copy, *form_data_copy.fields.begin(),
- MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
- EXPECT_EQ(1, response_page_id);
-
- // Sanity check for old behavior: all phone number fields are filled.
- ASSERT_EQ(4U, response_data.fields.size());
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[0].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[1].value);
- EXPECT_EQ(base::string16(), response_data.fields[2].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[3].value);
- }
+ // Verify only the first complete set of phone number fields are filled.
+ ASSERT_EQ(4U, response_data.fields.size());
+ EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
+ response_data.fields[0].value);
+ EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[1].value);
+ EXPECT_EQ(base::string16(), response_data.fields[2].value);
+ EXPECT_EQ(base::string16(), response_data.fields[3].value);
}
TEST_F(AutofillManagerTest, FillFirstPhoneNumber_FillPartsOnceOnly) {
@@ -3158,61 +3124,28 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_FillPartsOnceOnly) {
std::vector<FormData> forms_copy;
forms_copy.push_back(form_data_copy);
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormsSeen(forms);
- int page_id = 1;
- int response_page_id = 0;
- FormData response_data;
- FillAutofillFormDataAndSaveResults(
- page_id, form_with_multiple_componentized_phone_fields,
- *form_with_multiple_componentized_phone_fields.fields.begin(),
- MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
- EXPECT_EQ(1, response_page_id);
-
- // Verify only the first complete set of phone number fields are filled,
- // and phone components are not filled more than once.
- ASSERT_EQ(8U, response_data.fields.size());
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[0].value);
- EXPECT_EQ(ASCIIToUTF16("1"), response_data.fields[1].value);
- EXPECT_EQ(base::string16(), response_data.fields[2].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[3].value);
- EXPECT_EQ(base::string16(), response_data.fields[4].value);
- EXPECT_EQ(base::string16(), response_data.fields[5].value);
- EXPECT_EQ(base::string16(), response_data.fields[6].value);
- EXPECT_EQ(base::string16(), response_data.fields[7].value);
- }
+ FormsSeen(forms);
+ int page_id = 1;
+ int response_page_id = 0;
+ FormData response_data;
+ FillAutofillFormDataAndSaveResults(
+ page_id, form_with_multiple_componentized_phone_fields,
+ *form_with_multiple_componentized_phone_fields.fields.begin(),
+ MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
+ EXPECT_EQ(1, response_page_id);
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormsSeen(forms_copy);
- int page_id = 1;
- int response_page_id = 0;
- FormData response_data;
- FillAutofillFormDataAndSaveResults(
- page_id, form_data_copy, *form_data_copy.fields.begin(),
- MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
- EXPECT_EQ(1, response_page_id);
-
- // Sanity check for old behavior: all phone number fields are filled.
- ASSERT_EQ(8U, response_data.fields.size());
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[0].value);
- EXPECT_EQ(ASCIIToUTF16("1"), response_data.fields[1].value);
- EXPECT_EQ(ASCIIToUTF16("650"), response_data.fields[2].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[3].value);
- EXPECT_EQ(base::string16(), response_data.fields[4].value);
- EXPECT_EQ(ASCIIToUTF16("1"), response_data.fields[5].value);
- EXPECT_EQ(ASCIIToUTF16("650"), response_data.fields[6].value);
- EXPECT_EQ(ASCIIToUTF16("5554567"), response_data.fields[7].value);
- }
+ // Verify only the first complete set of phone number fields are filled,
+ // and phone components are not filled more than once.
+ ASSERT_EQ(8U, response_data.fields.size());
+ EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
+ response_data.fields[0].value);
+ EXPECT_EQ(ASCIIToUTF16("1"), response_data.fields[1].value);
+ EXPECT_EQ(base::string16(), response_data.fields[2].value);
+ EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[3].value);
+ EXPECT_EQ(base::string16(), response_data.fields[4].value);
+ EXPECT_EQ(base::string16(), response_data.fields[5].value);
+ EXPECT_EQ(base::string16(), response_data.fields[6].value);
+ EXPECT_EQ(base::string16(), response_data.fields[7].value);
}
// Verify when extension is misclassified, and there is a complete
@@ -3258,55 +3191,24 @@ TEST_F(AutofillManagerTest,
std::vector<FormData> forms_copy;
forms_copy.push_back(form_data_copy);
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormsSeen(forms);
- int page_id = 1;
- int response_page_id = 0;
- FormData response_data;
- FillAutofillFormDataAndSaveResults(
- page_id, form_with_misclassified_extension,
- *form_with_misclassified_extension.fields.begin(),
- MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
- EXPECT_EQ(1, response_page_id);
-
- // Verify the misclassified extension field is not filled.
- ASSERT_EQ(5U, response_data.fields.size());
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[0].value);
- EXPECT_EQ(base::string16(), response_data.fields[1].value);
- EXPECT_EQ(ASCIIToUTF16("650"), response_data.fields[2].value);
- EXPECT_EQ(ASCIIToUTF16("5554567"), response_data.fields[3].value);
- EXPECT_EQ(base::string16(), response_data.fields[4].value);
- }
+ FormsSeen(forms);
+ int page_id = 1;
+ int response_page_id = 0;
+ FormData response_data;
+ FillAutofillFormDataAndSaveResults(
+ page_id, form_with_misclassified_extension,
+ *form_with_misclassified_extension.fields.begin(),
+ MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
+ EXPECT_EQ(1, response_page_id);
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormsSeen(forms_copy);
- int page_id = 1;
- int response_page_id = 0;
- FormData response_data;
- FillAutofillFormDataAndSaveResults(
- page_id, form_data_copy, *form_data_copy.fields.begin(),
- MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
- EXPECT_EQ(1, response_page_id);
-
- // Sanity check for old behavior: the misclassified extension field is
- // filled.
- ASSERT_EQ(5U, response_data.fields.size());
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[0].value);
- EXPECT_EQ(base::string16(), response_data.fields[1].value);
- EXPECT_EQ(ASCIIToUTF16("650"), response_data.fields[2].value);
- EXPECT_EQ(ASCIIToUTF16("5554567"), response_data.fields[3].value);
- EXPECT_EQ(ASCIIToUTF16("5554567"), response_data.fields[4].value);
- }
+ // Verify the misclassified extension field is not filled.
+ ASSERT_EQ(5U, response_data.fields.size());
+ EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
+ response_data.fields[0].value);
+ EXPECT_EQ(base::string16(), response_data.fields[1].value);
+ EXPECT_EQ(ASCIIToUTF16("650"), response_data.fields[2].value);
+ EXPECT_EQ(ASCIIToUTF16("5554567"), response_data.fields[3].value);
+ EXPECT_EQ(base::string16(), response_data.fields[4].value);
}
// Verify when no complete number can be found, we do best-effort filling.
@@ -3346,53 +3248,24 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_BestEfforFilling) {
std::vector<FormData> forms_copy;
forms_copy.push_back(form_data_copy);
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormsSeen(forms);
- int page_id = 1;
- int response_page_id = 0;
- FormData response_data;
- FillAutofillFormDataAndSaveResults(
- page_id, form_with_no_complete_number,
- *form_with_no_complete_number.fields.begin(),
- MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
- EXPECT_EQ(1, response_page_id);
-
- // Verify when there is no complete phone number fields, we do best effort
- // filling.
- ASSERT_EQ(4U, response_data.fields.size());
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[0].value);
- EXPECT_EQ(base::string16(), response_data.fields[1].value);
- EXPECT_EQ(ASCIIToUTF16("650"), response_data.fields[2].value);
- EXPECT_EQ(base::string16(), response_data.fields[3].value);
- }
+ FormsSeen(forms);
+ int page_id = 1;
+ int response_page_id = 0;
+ FormData response_data;
+ FillAutofillFormDataAndSaveResults(
+ page_id, form_with_no_complete_number,
+ *form_with_no_complete_number.fields.begin(),
+ MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
+ EXPECT_EQ(1, response_page_id);
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormsSeen(forms);
- int page_id = 1;
- int response_page_id = 0;
- FormData response_data;
- FillAutofillFormDataAndSaveResults(
- page_id, form_data_copy, *form_data_copy.fields.begin(),
- MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
- EXPECT_EQ(1, response_page_id);
-
- // Sanity check for old behavior: always do best effort filling.
- ASSERT_EQ(4U, response_data.fields.size());
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[0].value);
- EXPECT_EQ(base::string16(), response_data.fields[1].value);
- EXPECT_EQ(ASCIIToUTF16("650"), response_data.fields[2].value);
- EXPECT_EQ(base::string16(), response_data.fields[3].value);
- }
+ // Verify when there is no complete phone number fields, we do best effort
+ // filling.
+ ASSERT_EQ(4U, response_data.fields.size());
+ EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
+ response_data.fields[0].value);
+ EXPECT_EQ(base::string16(), response_data.fields[1].value);
+ EXPECT_EQ(ASCIIToUTF16("650"), response_data.fields[2].value);
+ EXPECT_EQ(base::string16(), response_data.fields[3].value);
}
// When the focus is on second phone field explicitly, we will fill the
@@ -3430,58 +3303,26 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_FocusOnSecondPhoneNumber) {
std::vector<FormData> forms_copy;
forms_copy.push_back(form_data_copy);
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormsSeen(forms);
- int page_id = 1;
- int response_page_id = 0;
- FormData response_data;
- auto it = form_with_multiple_whole_number_fields.fields.begin();
- // Move it to point to "shipping number".
- std::advance(it, 3);
- FillAutofillFormDataAndSaveResults(
- page_id, form_with_multiple_whole_number_fields, *it,
- MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
- EXPECT_EQ(1, response_page_id);
-
- // Verify when the second phone number field is being focused, we fill
- // that field *AND* the first phone number field.
- ASSERT_EQ(4U, response_data.fields.size());
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[0].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[1].value);
- EXPECT_EQ(base::string16(), response_data.fields[2].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[3].value);
- }
+ FormsSeen(forms);
+ int page_id = 1;
+ int response_page_id = 0;
+ FormData response_data;
+ auto it = form_with_multiple_whole_number_fields.fields.begin();
+ // Move it to point to "shipping number".
+ std::advance(it, 3);
+ FillAutofillFormDataAndSaveResults(
+ page_id, form_with_multiple_whole_number_fields, *it,
+ MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
+ EXPECT_EQ(1, response_page_id);
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormsSeen(forms);
- int page_id = 1;
- int response_page_id = 0;
- FormData response_data;
- auto it = form_data_copy.fields.begin();
- // Move it to point to "shipping number".
- std::advance(it, 3);
- FillAutofillFormDataAndSaveResults(page_id, form_data_copy, *it,
- MakeFrontendID(std::string(), guid),
- &response_page_id, &response_data);
- EXPECT_EQ(1, response_page_id);
-
- // Sanity check for old behavior: fill all the phone fields we can find.
- ASSERT_EQ(4U, response_data.fields.size());
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[0].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[1].value);
- EXPECT_EQ(base::string16(), response_data.fields[2].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[3].value);
- }
+ // Verify when the second phone number field is being focused, we fill
+ // that field *AND* the first phone number field.
+ ASSERT_EQ(4U, response_data.fields.size());
+ EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
+ response_data.fields[0].value);
+ EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[1].value);
+ EXPECT_EQ(base::string16(), response_data.fields[2].value);
+ EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[3].value);
}
TEST_F(AutofillManagerTest, FillFirstPhoneNumber_HiddenFieldShouldNotCount) {
@@ -3519,52 +3360,23 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_HiddenFieldShouldNotCount) {
std::vector<FormData> forms_copy;
forms_copy.push_back(form_data_copy);
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormsSeen(forms);
- int page_id = 1;
- int response_page_id = 0;
- FormData response_data;
- FillAutofillFormDataAndSaveResults(
- page_id, form_with_multiple_whole_number_fields,
- *form_with_multiple_whole_number_fields.fields.begin(),
- MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
- EXPECT_EQ(1, response_page_id);
-
- // Verify hidden/non-focusable phone field is set to only_fill_when_focused.
- ASSERT_EQ(4U, response_data.fields.size());
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[0].value);
- EXPECT_EQ(base::string16(), response_data.fields[1].value);
- EXPECT_EQ(base::string16(), response_data.fields[2].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[3].value);
- }
+ FormsSeen(forms);
+ int page_id = 1;
+ int response_page_id = 0;
+ FormData response_data;
+ FillAutofillFormDataAndSaveResults(
+ page_id, form_with_multiple_whole_number_fields,
+ *form_with_multiple_whole_number_fields.fields.begin(),
+ MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
+ EXPECT_EQ(1, response_page_id);
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormsSeen(forms);
- int page_id = 1;
- int response_page_id = 0;
- FormData response_data;
- FillAutofillFormDataAndSaveResults(
- page_id, form_data_copy, *form_data_copy.fields.begin(),
- MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
- EXPECT_EQ(1, response_page_id);
-
- // Sanity check for old behavior: fill hidden phone fields.
- ASSERT_EQ(4U, response_data.fields.size());
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[0].value);
- EXPECT_EQ(ASCIIToUTF16(""), response_data.fields[1].value);
- EXPECT_EQ(base::string16(), response_data.fields[2].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[3].value);
- }
+ // Verify hidden/non-focusable phone field is set to only_fill_when_focused.
+ ASSERT_EQ(4U, response_data.fields.size());
+ EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
+ response_data.fields[0].value);
+ EXPECT_EQ(base::string16(), response_data.fields[1].value);
+ EXPECT_EQ(base::string16(), response_data.fields[2].value);
+ EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[3].value);
}
// The hidden and the presentational fields should be filled, only if their
@@ -3685,107 +3497,51 @@ TEST_F(AutofillManagerTest,
std::vector<FormData> forms_copy;
forms_copy.push_back(form_data_copy);
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormsSeen(forms);
- int page_id = 1;
- int response_page_id = 0;
- FormData response_data;
- // Fill first sections.
- FillAutofillFormDataAndSaveResults(
- page_id, form_with_multiple_sections,
- *form_with_multiple_sections.fields.begin(),
- MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
- EXPECT_EQ(1, response_page_id);
-
- // Verify first section is filled with rationalization.
- ASSERT_EQ(9U, response_data.fields.size());
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[0].value);
- EXPECT_EQ(ASCIIToUTF16("123 Apple St."), response_data.fields[1].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[2].value);
- EXPECT_EQ(base::string16(), response_data.fields[3].value);
- EXPECT_EQ(base::string16(), response_data.fields[4].value);
- EXPECT_EQ(base::string16(), response_data.fields[5].value);
- EXPECT_EQ(base::string16(), response_data.fields[6].value);
- EXPECT_EQ(base::string16(), response_data.fields[7].value);
- EXPECT_EQ(base::string16(), response_data.fields[8].value);
-
- // Fill second section.
- auto it = form_with_multiple_sections.fields.begin();
- std::advance(it, 6); // Pointing to second section.
-
- FillAutofillFormDataAndSaveResults(page_id, form_with_multiple_sections,
- *it, MakeFrontendID(std::string(), guid),
- &response_page_id, &response_data);
- EXPECT_EQ(1, response_page_id);
-
- // Verify second section is filled with rationalization.
- ASSERT_EQ(9U, response_data.fields.size());
- EXPECT_EQ(base::string16(), response_data.fields[0].value);
- EXPECT_EQ(base::string16(), response_data.fields[1].value);
- EXPECT_EQ(base::string16(), response_data.fields[2].value);
- EXPECT_EQ(base::string16(), response_data.fields[3].value);
- EXPECT_EQ(base::string16(), response_data.fields[4].value);
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[5].value);
- EXPECT_EQ(ASCIIToUTF16("123 Apple St."), response_data.fields[6].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[7].value);
- EXPECT_EQ(base::string16(), response_data.fields[8].value);
- }
+ FormsSeen(forms);
+ int page_id = 1;
+ int response_page_id = 0;
+ FormData response_data;
+ // Fill first sections.
+ FillAutofillFormDataAndSaveResults(
+ page_id, form_with_multiple_sections,
+ *form_with_multiple_sections.fields.begin(),
+ MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
+ EXPECT_EQ(1, response_page_id);
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormsSeen(forms);
- int page_id = 1;
- int response_page_id = 0;
- FormData response_data;
- // Fill first section.
- FillAutofillFormDataAndSaveResults(
- page_id, form_data_copy, *form_data_copy.fields.begin(),
- MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
-
- // Verify first section is filled without rationalization.
- ASSERT_EQ(9U, response_data.fields.size());
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[0].value);
- EXPECT_EQ(ASCIIToUTF16("123 Apple St."), response_data.fields[1].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[2].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[3].value);
- EXPECT_EQ(base::string16(), response_data.fields[4].value);
- EXPECT_EQ(base::string16(), response_data.fields[5].value);
- EXPECT_EQ(base::string16(), response_data.fields[6].value);
- EXPECT_EQ(base::string16(), response_data.fields[7].value);
- EXPECT_EQ(base::string16(), response_data.fields[8].value);
-
- // Fill second section.
- auto it = form_data_copy.fields.begin();
- std::advance(it, 6); // Pointing to second section.
-
- FillAutofillFormDataAndSaveResults(page_id, form_data_copy, *it,
- MakeFrontendID(std::string(), guid),
- &response_page_id, &response_data);
- EXPECT_EQ(1, response_page_id);
-
- // Verify second section is filled without rationalization.
- ASSERT_EQ(9U, response_data.fields.size());
- EXPECT_EQ(base::string16(), response_data.fields[0].value);
- EXPECT_EQ(base::string16(), response_data.fields[1].value);
- EXPECT_EQ(base::string16(), response_data.fields[2].value);
- EXPECT_EQ(base::string16(), response_data.fields[3].value);
- EXPECT_EQ(base::string16(), response_data.fields[4].value);
- EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
- response_data.fields[5].value);
- EXPECT_EQ(ASCIIToUTF16("123 Apple St."), response_data.fields[6].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[7].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[8].value);
- }
+ // Verify first section is filled with rationalization.
+ ASSERT_EQ(9U, response_data.fields.size());
+ EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
+ response_data.fields[0].value);
+ EXPECT_EQ(ASCIIToUTF16("123 Apple St."), response_data.fields[1].value);
+ EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[2].value);
+ EXPECT_EQ(base::string16(), response_data.fields[3].value);
+ EXPECT_EQ(base::string16(), response_data.fields[4].value);
+ EXPECT_EQ(base::string16(), response_data.fields[5].value);
+ EXPECT_EQ(base::string16(), response_data.fields[6].value);
+ EXPECT_EQ(base::string16(), response_data.fields[7].value);
+ EXPECT_EQ(base::string16(), response_data.fields[8].value);
+
+ // Fill second section.
+ auto it = form_with_multiple_sections.fields.begin();
+ std::advance(it, 6); // Pointing to second section.
+
+ FillAutofillFormDataAndSaveResults(page_id, form_with_multiple_sections, *it,
+ MakeFrontendID(std::string(), guid),
+ &response_page_id, &response_data);
+ EXPECT_EQ(1, response_page_id);
+
+ // Verify second section is filled with rationalization.
+ ASSERT_EQ(9U, response_data.fields.size());
+ EXPECT_EQ(base::string16(), response_data.fields[0].value);
+ EXPECT_EQ(base::string16(), response_data.fields[1].value);
+ EXPECT_EQ(base::string16(), response_data.fields[2].value);
+ EXPECT_EQ(base::string16(), response_data.fields[3].value);
+ EXPECT_EQ(base::string16(), response_data.fields[4].value);
+ EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
+ response_data.fields[5].value);
+ EXPECT_EQ(ASCIIToUTF16("123 Apple St."), response_data.fields[6].value);
+ EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[7].value);
+ EXPECT_EQ(base::string16(), response_data.fields[8].value);
}
// Test that we can still fill a form when a field has been removed from it.
@@ -3963,8 +3719,7 @@ TEST_F(AutofillManagerTest, FormSubmittedSaveData) {
false);
autofill_manager_->OnFormSubmitted(response_data, false,
- SubmissionSource::FORM_SUBMISSION,
- base::TimeTicks::Now());
+ SubmissionSource::FORM_SUBMISSION);
EXPECT_EQ(1, personal_data_.num_times_save_imported_profile_called());
}
@@ -3972,16 +3727,17 @@ TEST_F(AutofillManagerTest, FormSubmittedSaveData) {
// submissions are still received by AutocompleteHistoryManager.
TEST_F(AutofillManagerTest, FormSubmittedAutocompleteEnabled) {
TestAutofillClient client;
- autofill_manager_.reset(new TestAutofillManager(autofill_driver_.get(),
- &client, &personal_data_));
+ autofill_manager_.reset(
+ new TestAutofillManager(autofill_driver_.get(), &client, &personal_data_,
+ autocomplete_history_manager_.get()));
autofill_manager_->SetAutofillEnabled(false);
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
- MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
- EXPECT_CALL(*m, OnWillSubmitForm(_));
+ EXPECT_CALL(*(autocomplete_history_manager_.get()),
+ OnWillSubmitForm(_, true));
FormSubmitted(form);
}
@@ -3989,8 +3745,9 @@ TEST_F(AutofillManagerTest, FormSubmittedAutocompleteEnabled) {
// queried.
TEST_F(AutofillManagerTest, AutocompleteSuggestions_SomeWhenAutofillDisabled) {
TestAutofillClient client;
- autofill_manager_.reset(new TestAutofillManager(autofill_driver_.get(),
- &client, &personal_data_));
+ autofill_manager_.reset(
+ new TestAutofillManager(autofill_driver_.get(), &client, &personal_data_,
+ autocomplete_history_manager_.get()));
autofill_manager_->SetAutofillEnabled(false);
autofill_manager_->SetExternalDelegate(external_delegate_.get());
@@ -4002,8 +3759,8 @@ TEST_F(AutofillManagerTest, AutocompleteSuggestions_SomeWhenAutofillDisabled) {
const FormFieldData& field = form.fields[0];
// Expect Autocomplete manager to be called for suggestions.
- MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
- EXPECT_CALL(*m, OnGetAutocompleteSuggestions(_, _, _, _));
+ EXPECT_CALL(*(autocomplete_history_manager_.get()),
+ OnGetAutocompleteSuggestions);
GetAutofillSuggestions(form, field);
}
@@ -4013,8 +3770,9 @@ TEST_F(AutofillManagerTest, AutocompleteSuggestions_SomeWhenAutofillDisabled) {
TEST_F(AutofillManagerTest,
AutocompleteSuggestions_AutofillDisabledAndFieldShouldNotAutocomplete) {
TestAutofillClient client;
- autofill_manager_.reset(new TestAutofillManager(autofill_driver_.get(),
- &client, &personal_data_));
+ autofill_manager_.reset(
+ new TestAutofillManager(autofill_driver_.get(), &client, &personal_data_,
+ autocomplete_history_manager_.get()));
autofill_manager_->SetAutofillEnabled(false);
autofill_manager_->SetExternalDelegate(external_delegate_.get());
@@ -4028,8 +3786,9 @@ TEST_F(AutofillManagerTest,
// Autocomplete manager is not called for suggestions.
- MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
- EXPECT_CALL(*m, OnGetAutocompleteSuggestions(_, _, _, _)).Times(0);
+ EXPECT_CALL(*(autocomplete_history_manager_.get()),
+ OnGetAutocompleteSuggestions)
+ .Times(0);
GetAutofillSuggestions(form, field);
}
@@ -4046,8 +3805,9 @@ TEST_F(AutofillManagerTest, AutocompleteSuggestions_NoneWhenAutofillPresent) {
const FormFieldData& field = form.fields[0];
// Autocomplete manager is not called for suggestions.
- MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
- EXPECT_CALL(*m, OnGetAutocompleteSuggestions(_, _, _, _)).Times(0);
+ EXPECT_CALL(*(autocomplete_history_manager_.get()),
+ OnGetAutocompleteSuggestions)
+ .Times(0);
GetAutofillSuggestions(form, field);
@@ -4073,8 +3833,8 @@ TEST_F(AutofillManagerTest, AutocompleteSuggestions_SomeWhenAutofillEmpty) {
test::CreateTestFormField("Email", "email", "donkey", "email", &field);
// Autocomplete manager is called for suggestions because Autofill is empty.
- MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
- EXPECT_CALL(*m, OnGetAutocompleteSuggestions(_, _, _, _));
+ EXPECT_CALL(*(autocomplete_history_manager_.get()),
+ OnGetAutocompleteSuggestions);
GetAutofillSuggestions(form, field);
}
@@ -4085,8 +3845,9 @@ TEST_F(AutofillManagerTest, AutocompleteSuggestions_SomeWhenAutofillEmpty) {
TEST_F(AutofillManagerTest,
AutocompleteSuggestions_CreditCardNameFieldShouldAutocomplete) {
TestAutofillClient client;
- autofill_manager_.reset(new TestAutofillManager(autofill_driver_.get(),
- &client, &personal_data_));
+ autofill_manager_.reset(
+ new TestAutofillManager(autofill_driver_.get(), &client, &personal_data_,
+ autocomplete_history_manager_.get()));
autofill_manager_->SetAutofillEnabled(false);
autofill_manager_->SetExternalDelegate(external_delegate_.get());
@@ -4100,8 +3861,8 @@ TEST_F(AutofillManagerTest,
field.should_autocomplete = true;
// Autocomplete manager is not called for suggestions.
- MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
- EXPECT_CALL(*m, OnGetAutocompleteSuggestions(_, _, _, _));
+ EXPECT_CALL(*(autocomplete_history_manager_.get()),
+ OnGetAutocompleteSuggestions);
GetAutofillSuggestions(form, field);
}
@@ -4111,8 +3872,9 @@ TEST_F(AutofillManagerTest,
TEST_F(AutofillManagerTest,
AutocompleteSuggestions_CreditCardNumberShouldNotAutocomplete) {
TestAutofillClient client;
- autofill_manager_.reset(new TestAutofillManager(autofill_driver_.get(),
- &client, &personal_data_));
+ autofill_manager_.reset(
+ new TestAutofillManager(autofill_driver_.get(), &client, &personal_data_,
+ autocomplete_history_manager_.get()));
autofill_manager_->SetAutofillEnabled(false);
autofill_manager_->SetExternalDelegate(external_delegate_.get());
@@ -4126,8 +3888,9 @@ TEST_F(AutofillManagerTest,
field.should_autocomplete = true;
// Autocomplete manager is not called for suggestions.
- MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
- EXPECT_CALL(*m, OnGetAutocompleteSuggestions(_, _, _, _)).Times(0);
+ EXPECT_CALL(*(autocomplete_history_manager_.get()),
+ OnGetAutocompleteSuggestions)
+ .Times(0);
GetAutofillSuggestions(form, field);
}
@@ -4149,21 +3912,24 @@ TEST_F(
test::CreateTestFormField("Email", "email", "donkey", "email", &field);
// Autocomplete manager is not called for suggestions.
- MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
- EXPECT_CALL(*m, OnGetAutocompleteSuggestions(_, _, _, _)).Times(0);
+ EXPECT_CALL(*(autocomplete_history_manager_.get()),
+ OnGetAutocompleteSuggestions)
+ .Times(0);
GetAutofillSuggestions(form, field);
}
TEST_F(AutofillManagerTest, AutocompleteOffRespectedForAutocomplete) {
TestAutofillClient client;
- autofill_manager_.reset(new TestAutofillManager(autofill_driver_.get(),
- &client, &personal_data_));
+ autofill_manager_.reset(
+ new TestAutofillManager(autofill_driver_.get(), &client, &personal_data_,
+ autocomplete_history_manager_.get()));
autofill_manager_->SetAutofillEnabled(false);
autofill_manager_->SetExternalDelegate(external_delegate_.get());
- MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
- EXPECT_CALL(*m, OnGetAutocompleteSuggestions(_, _, _, _)).Times(0);
+ EXPECT_CALL(*(autocomplete_history_manager_.get()),
+ OnGetAutocompleteSuggestions)
+ .Times(0);
// Set up our form data.
FormData form;
@@ -4175,6 +3941,20 @@ TEST_F(AutofillManagerTest, AutocompleteOffRespectedForAutocomplete) {
GetAutofillSuggestions(form, *field);
}
+TEST_F(AutofillManagerTest, DestructorCancelsAutocompleteQueries) {
+ EXPECT_CALL(*(autocomplete_history_manager_.get()), CancelPendingQueries)
+ .Times(1);
+ autofill_manager_.reset();
+}
+
+// Make sure that we don't error out when AutocompleteHistoryManager was
+// destroyed before AutofillManager.
+TEST_F(AutofillManagerTest, Destructor_DeletedAutocomplete_Works) {
+ // The assertion here is that no exceptions will be thrown.
+ autocomplete_history_manager_.reset();
+ autofill_manager_.reset();
+}
+
// Test that OnLoadedServerPredictions can obtain the FormStructure with the
// signature of the queried form and apply type predictions.
TEST_F(AutofillManagerTest, OnLoadedServerPredictions) {
@@ -4186,7 +3966,8 @@ TEST_F(AutofillManagerTest, OnLoadedServerPredictions) {
// |form_structure| will be owned by |autofill_manager_|.
TestFormStructure* form_structure = new TestFormStructure(form);
form_structure->DetermineHeuristicTypes();
- autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure));
+ autofill_manager_->AddSeenFormStructure(
+ std::unique_ptr<TestFormStructure>(form_structure));
// Similarly, a second form.
FormData form2;
@@ -4206,7 +3987,8 @@ TEST_F(AutofillManagerTest, OnLoadedServerPredictions) {
TestFormStructure* form_structure2 = new TestFormStructure(form2);
form_structure2->DetermineHeuristicTypes();
- autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure2));
+ autofill_manager_->AddSeenFormStructure(
+ std::unique_ptr<TestFormStructure>(form_structure2));
AutofillQueryResponseContents response;
response.add_field()->set_overall_type_prediction(3);
@@ -4368,7 +4150,8 @@ TEST_F(AutofillManagerTest, OnLoadedServerPredictions_ResetManager) {
// |form_structure| will be owned by |autofill_manager_|.
TestFormStructure* form_structure = new TestFormStructure(form);
form_structure->DetermineHeuristicTypes();
- autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure));
+ autofill_manager_->AddSeenFormStructure(
+ std::unique_ptr<TestFormStructure>(form_structure));
AutofillQueryResponseContents response;
response.add_field()->set_overall_type_prediction(3);
@@ -4422,7 +4205,8 @@ TEST_F(AutofillManagerTest, DetermineHeuristicsWithOverallPrediction) {
// |form_structure| will be owned by |autofill_manager_|.
TestFormStructure* form_structure = new TestFormStructure(form);
form_structure->DetermineHeuristicTypes();
- autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure));
+ autofill_manager_->AddSeenFormStructure(
+ std::unique_ptr<TestFormStructure>(form_structure));
AutofillQueryResponseContents response;
response.add_field()->set_overall_type_prediction(CREDIT_CARD_NAME_FIRST);
@@ -4497,7 +4281,8 @@ TEST_F(AutofillManagerTest, FormSubmittedServerTypes) {
server_types.push_back(form_structure->field(i)->heuristic_type());
}
form_structure->SetFieldTypes(heuristic_types, server_types);
- autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure));
+ autofill_manager_->AddSeenFormStructure(
+ std::unique_ptr<TestFormStructure>(form_structure));
// Fill the form.
const char guid[] = "00000000-0000-0000-0000-000000000001";
@@ -5452,8 +5237,8 @@ TEST_F(AutofillManagerTest,
// !should_autocomplete for AutocompleteHistoryManager::OnWillSubmitForm.
TEST_F(AutofillManagerTest, DontSaveCvcInAutocompleteHistory) {
FormData form_seen_by_ahm;
- MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
- EXPECT_CALL(*m, OnWillSubmitForm(_)).WillOnce(SaveArg<0>(&form_seen_by_ahm));
+ EXPECT_CALL(*(autocomplete_history_manager_.get()), OnWillSubmitForm(_, true))
+ .WillOnce(SaveArg<0>(&form_seen_by_ahm));
FormData form;
form.name = ASCIIToUTF16("MyForm");
@@ -5483,8 +5268,8 @@ TEST_F(AutofillManagerTest, DontSaveCvcInAutocompleteHistory) {
FormSubmitted(form);
EXPECT_EQ(form.fields.size(), form_seen_by_ahm.fields.size());
- ASSERT_EQ(arraysize(test_fields), form_seen_by_ahm.fields.size());
- for (size_t i = 0; i < arraysize(test_fields); ++i) {
+ ASSERT_EQ(base::size(test_fields), form_seen_by_ahm.fields.size());
+ for (size_t i = 0; i < base::size(test_fields); ++i) {
EXPECT_EQ(
form_seen_by_ahm.fields[i].should_autocomplete,
test_fields[i].expected_field_type != CREDIT_CARD_VERIFICATION_CODE);
@@ -5514,8 +5299,8 @@ TEST_F(AutofillManagerTest, DontOfferToSavePaymentsCard) {
full_card_unmask_delegate()->OnUnmaskResponse(response);
autofill_manager_->OnDidGetRealPan(AutofillClient::SUCCESS,
"4012888888881881");
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, base::TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
}
TEST_F(AutofillManagerTest, FillInUpdatedExpirationDate) {
@@ -6174,38 +5959,6 @@ TEST_F(AutofillManagerTest,
}
}
-// Tests that querying for credit card field suggestions notifies the
-// driver of an interaction with a credit card field.
-TEST_F(AutofillManagerTest, NotifyDriverOfCreditCardInteraction) {
- // Set up a credit card form.
- FormData form;
- form.name = ASCIIToUTF16("MyForm");
- form.origin = GURL("https://myform.com/form.html");
- form.action = GURL("https://myform.com/submit.html");
- FormFieldData field;
- test::CreateTestFormField("Name on Card", "nameoncard", "", "text", &field);
- field.should_autocomplete = false;
- form.fields.push_back(field);
- test::CreateTestFormField("Card Number", "cardnumber", "", "text", &field);
- field.should_autocomplete = true;
- form.fields.push_back(field);
- test::CreateTestFormField("Expiration Month", "ccexpiresmonth", "", "text",
- &field);
- field.should_autocomplete = false;
- form.fields.push_back(field);
- form.fields.push_back(field);
- std::vector<FormData> forms(1, form);
- FormsSeen(forms);
- EXPECT_FALSE(autofill_driver_->GetDidInteractWithCreditCardForm());
-
- // The driver should always be notified.
- for (const FormFieldData& field : form.fields) {
- GetAutofillSuggestions(form, field);
- EXPECT_TRUE(autofill_driver_->GetDidInteractWithCreditCardForm());
- autofill_driver_->ClearDidInteractWithCreditCardForm();
- }
-}
-
// Tests that a form with server only types is still autofillable if the form
// gets updated in cache.
TEST_F(AutofillManagerTest, DisplaySuggestionsForUpdatedServerTypedForm) {
@@ -6401,7 +6154,8 @@ TEST_F(AutofillManagerTest, IsRichQueryEnabled_FeatureEnabled) {
<< "Channel " << static_cast<int>(channel));
EXPECT_CALL(autofill_client_, GetChannel()).WillOnce(Return(channel));
TestAutofillManager test_instance(autofill_driver_.get(), &autofill_client_,
- &personal_data_);
+ &personal_data_,
+ autocomplete_history_manager_.get());
switch (channel) {
case version_info::Channel::STABLE:
case version_info::Channel::BETA:
@@ -6434,7 +6188,8 @@ TEST_F(AutofillManagerTest, IsRichQueryEnabled_FeatureDisabled) {
EXPECT_FALSE(AutofillManager::IsRichQueryEnabled(channel));
EXPECT_CALL(autofill_client_, GetChannel()).WillOnce(Return(channel));
TestAutofillManager test_instance(autofill_driver_.get(), &autofill_client_,
- &personal_data_);
+ &personal_data_,
+ autocomplete_history_manager_.get());
EXPECT_FALSE(test_instance.is_rich_query_enabled());
}
}
@@ -6559,6 +6314,47 @@ TEST_F(AutofillManagerTest,
HasSubstr("Autofill.FormEvents.Address"))));
}
+// Tests that a call to the PDM's SyncServiceInitialized happens if in incognito
+// mode even if the sync service is null.
+TEST_F(AutofillManagerTest, CallingOnSyncServiceInitialized_NotOffTheRecord) {
+ // Setup the test PDM.
+ TestPersonalDataManager test_pdm;
+ ASSERT_FALSE(test_pdm.sync_service_initialized());
+
+ // Set the client to return a null sync service (default).
+ TestAutofillClient client;
+
+ // Create a new AutofillManager.
+ autofill_manager_.reset(
+ new TestAutofillManager(autofill_driver_.get(), &client, &test_pdm,
+ autocomplete_history_manager_.get()));
+
+ // Make sure the PDM's sync service was initialized.
+ EXPECT_TRUE(test_pdm.sync_service_initialized());
+}
+
+// Tests that no call to the PDM's SyncServiceInitialized happens in incognito
+// mode.
+TEST_F(AutofillManagerTest, CallingOnSyncServiceInitialized_OffTheRecord) {
+ // Setup the test PDM.
+ TestPersonalDataManager test_pdm;
+ ASSERT_FALSE(test_pdm.sync_service_initialized());
+
+ // Set the client to return a null sync service (default).
+ TestAutofillClient client;
+
+ // Set the driver to return that the user is off the record.
+ TestAutofillDriver driver;
+ driver.SetIsIncognito(true);
+
+ // Create a new AutofillManager.
+ autofill_manager_.reset(new TestAutofillManager(
+ &driver, &client, &test_pdm, autocomplete_history_manager_.get()));
+
+ // Make sure the PDM's sync service was not initialized.
+ EXPECT_FALSE(test_pdm.sync_service_initialized());
+}
+
// 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_metadata.cc b/chromium/components/autofill/core/browser/autofill_metadata.cc
index fa5619f701f..99527207f77 100644
--- a/chromium/components/autofill/core/browser/autofill_metadata.cc
+++ b/chromium/components/autofill/core/browser/autofill_metadata.cc
@@ -13,4 +13,14 @@ bool AutofillMetadata::operator==(const AutofillMetadata& metadata) const {
billing_address_id == metadata.billing_address_id;
}
+bool AutofillMetadata::operator!=(const AutofillMetadata& metadata) const {
+ return !(*this == metadata);
+}
+
+std::ostream& operator<<(std::ostream& os, const AutofillMetadata& metadata) {
+ return os << metadata.id << " " << metadata.use_count << " "
+ << metadata.use_date << " " << metadata.has_converted << " "
+ << metadata.billing_address_id;
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_metadata.h b/chromium/components/autofill/core/browser/autofill_metadata.h
index 50c67d16f19..6a70a06bb49 100644
--- a/chromium/components/autofill/core/browser/autofill_metadata.h
+++ b/chromium/components/autofill/core/browser/autofill_metadata.h
@@ -19,6 +19,7 @@ struct AutofillMetadata {
~AutofillMetadata(){};
bool operator==(const AutofillMetadata&) const;
+ bool operator!=(const AutofillMetadata&) const;
// The ID for the model. This should be the guid for local data and server_id
// for the server data.
@@ -39,6 +40,9 @@ struct AutofillMetadata {
std::string billing_address_id;
};
+// So we can compare AutofillMetadata with EXPECT_EQ().
+std::ostream& operator<<(std::ostream& os, const AutofillMetadata& metadata);
+
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_METADATA_H_
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.cc b/chromium/components/autofill/core/browser/autofill_metrics.cc
index 9c199d4d3cc..6e405659280 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics.cc
@@ -57,10 +57,6 @@ enum FieldTypeGroupForMetrics {
NUM_FIELD_TYPE_GROUPS_FOR_METRICS
};
-const int KMaxFieldTypeGroupMetric =
- (NUM_FIELD_TYPE_GROUPS_FOR_METRICS << 8) |
- AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS;
-
std::string PreviousSaveCreditCardPromptUserDecisionToString(
int previous_save_credit_card_prompt_user_decision) {
DCHECK_LT(previous_save_credit_card_prompt_user_decision,
@@ -236,22 +232,6 @@ int GetFieldTypeGroupMetric(ServerFieldType field_type,
namespace {
-// A version of the UMA_HISTOGRAM_ENUMERATION macro that allows the |name|
-// to vary over the program's runtime.
-// TODO(crbug.com/850520): Remove this function when the remaining logs use the
-// histogram_functions instead.
-void LogUMAHistogramEnumeration(const std::string& name,
- int sample,
- int boundary_value) {
- DCHECK_LT(sample, boundary_value);
-
- // Note: This leaks memory, which is expected behavior.
- base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
- name, 1, boundary_value, boundary_value + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add(sample);
-}
-
const char* GetQualityMetricPredictionSource(
AutofillMetrics::QualityMetricPredictionSource source) {
switch (source) {
@@ -371,18 +351,16 @@ void LogPredictionQualityMetricsForFieldsOnlyFilledWhenFocused(
// Only log aggregate true negative; do not log type specific metrics
// for UNKNOWN/EMPTY.
DVLOG(2) << "TRUE NEGATIVE";
- base::UmaHistogramEnumeration(
+ base::UmaHistogramSparse(
aggregate_histogram,
(is_empty ? AutofillMetrics::TRUE_NEGATIVE_EMPTY
: (is_ambiguous ? AutofillMetrics::TRUE_NEGATIVE_AMBIGUOUS
- : AutofillMetrics::TRUE_NEGATIVE_UNKNOWN)),
- AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS);
+ : AutofillMetrics::TRUE_NEGATIVE_UNKNOWN)));
if (log_rationalization_metrics) {
- base::UmaHistogramEnumeration(
+ base::UmaHistogramSparse(
rationalization_quality_histogram,
(is_empty ? AutofillMetrics::RATIONALIZATION_GOOD
- : AutofillMetrics::RATIONALIZATION_OK),
- AutofillMetrics::NUM_RATIONALIZATION_QUALITY_METRICS);
+ : AutofillMetrics::RATIONALIZATION_OK));
}
return;
}
@@ -393,20 +371,17 @@ void LogPredictionQualityMetricsForFieldsOnlyFilledWhenFocused(
// automatically if there has been no rationalization.
if (predicted_type == actual_type) {
DVLOG(2) << "TRUE POSITIVE";
- base::UmaHistogramEnumeration(
- aggregate_histogram, AutofillMetrics::TRUE_POSITIVE,
- AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS);
- LogUMAHistogramEnumeration(
+ base::UmaHistogramSparse(aggregate_histogram,
+ AutofillMetrics::TRUE_POSITIVE);
+ base::UmaHistogramSparse(
type_specific_histogram,
- GetFieldTypeGroupMetric(actual_type, AutofillMetrics::TRUE_POSITIVE),
- KMaxFieldTypeGroupMetric);
+ GetFieldTypeGroupMetric(actual_type, AutofillMetrics::TRUE_POSITIVE));
if (log_rationalization_metrics) {
bool duplicated_filling = DuplicatedFilling(form, field);
- base::UmaHistogramEnumeration(
+ base::UmaHistogramSparse(
rationalization_quality_histogram,
(duplicated_filling ? AutofillMetrics::RATIONALIZATION_BAD
- : AutofillMetrics::RATIONALIZATION_OK),
- AutofillMetrics::NUM_RATIONALIZATION_QUALITY_METRICS);
+ : AutofillMetrics::RATIONALIZATION_OK));
}
return;
}
@@ -414,24 +389,21 @@ void LogPredictionQualityMetricsForFieldsOnlyFilledWhenFocused(
DVLOG(2) << "MISMATCH";
// Here the prediction is wrong, but user has to provide some value still.
// This should be a false negative.
- base::UmaHistogramEnumeration(
- aggregate_histogram, AutofillMetrics::FALSE_NEGATIVE_MISMATCH,
- AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS);
+ base::UmaHistogramSparse(aggregate_histogram,
+ AutofillMetrics::FALSE_NEGATIVE_MISMATCH);
// Log FALSE_NEGATIVE_MISMATCH for predicted type if it did predicted
// something but actual type is different.
if (predicted_type != UNKNOWN_TYPE)
- LogUMAHistogramEnumeration(
+ base::UmaHistogramSparse(
type_specific_histogram,
GetFieldTypeGroupMetric(predicted_type,
- AutofillMetrics::FALSE_NEGATIVE_MISMATCH),
- KMaxFieldTypeGroupMetric);
+ AutofillMetrics::FALSE_NEGATIVE_MISMATCH));
if (log_rationalization_metrics) {
// Logging RATIONALIZATION_OK despite of type mismatch here because autofill
// would have got it wrong with or without rationalization. Rationalization
// here does not help, neither does it do any harm.
- base::UmaHistogramEnumeration(
- rationalization_quality_histogram, AutofillMetrics::RATIONALIZATION_OK,
- AutofillMetrics::NUM_RATIONALIZATION_QUALITY_METRICS);
+ base::UmaHistogramSparse(rationalization_quality_histogram,
+ AutofillMetrics::RATIONALIZATION_OK);
}
return;
}
@@ -451,25 +423,22 @@ void LogPredictionQualityMetricsForCommonFields(
// Only log aggregate true negative; do not log type specific metrics
// for UNKNOWN/EMPTY.
DVLOG(2) << "TRUE NEGATIVE";
- base::UmaHistogramEnumeration(
+ base::UmaHistogramSparse(
aggregate_histogram,
(is_empty ? AutofillMetrics::TRUE_NEGATIVE_EMPTY
: (is_ambiguous ? AutofillMetrics::TRUE_NEGATIVE_AMBIGUOUS
- : AutofillMetrics::TRUE_NEGATIVE_UNKNOWN)),
- AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS);
+ : AutofillMetrics::TRUE_NEGATIVE_UNKNOWN)));
return;
}
DVLOG(2) << "TRUE POSITIVE";
// Log both aggregate and type specific true positive if we correctly
// predict that type with which the field was filled.
- base::UmaHistogramEnumeration(
- aggregate_histogram, AutofillMetrics::TRUE_POSITIVE,
- AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS);
- LogUMAHistogramEnumeration(
+ base::UmaHistogramSparse(aggregate_histogram,
+ AutofillMetrics::TRUE_POSITIVE);
+ base::UmaHistogramSparse(
type_specific_histogram,
- GetFieldTypeGroupMetric(actual_type, AutofillMetrics::TRUE_POSITIVE),
- KMaxFieldTypeGroupMetric);
+ GetFieldTypeGroupMetric(actual_type, AutofillMetrics::TRUE_POSITIVE));
return;
}
@@ -483,12 +452,9 @@ void LogPredictionQualityMetricsForCommonFields(
(is_empty ? AutofillMetrics::FALSE_POSITIVE_EMPTY
: (is_ambiguous ? AutofillMetrics::FALSE_POSITIVE_AMBIGUOUS
: AutofillMetrics::FALSE_POSITIVE_UNKNOWN));
- base::UmaHistogramEnumeration(
- aggregate_histogram, metric,
- AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS);
- LogUMAHistogramEnumeration(type_specific_histogram,
- GetFieldTypeGroupMetric(predicted_type, metric),
- KMaxFieldTypeGroupMetric);
+ base::UmaHistogramSparse(aggregate_histogram, metric);
+ base::UmaHistogramSparse(type_specific_histogram,
+ GetFieldTypeGroupMetric(predicted_type, metric));
return;
}
@@ -497,14 +463,12 @@ void LogPredictionQualityMetricsForCommonFields(
// unknown.
if (predicted_type == UNKNOWN_TYPE) {
DVLOG(2) << "FALSE NEGATIVE";
- base::UmaHistogramEnumeration(
- aggregate_histogram, AutofillMetrics::FALSE_NEGATIVE_UNKNOWN,
- AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS);
- LogUMAHistogramEnumeration(
+ base::UmaHistogramSparse(aggregate_histogram,
+ AutofillMetrics::FALSE_NEGATIVE_UNKNOWN);
+ base::UmaHistogramSparse(
type_specific_histogram,
GetFieldTypeGroupMetric(actual_type,
- AutofillMetrics::FALSE_NEGATIVE_UNKNOWN),
- KMaxFieldTypeGroupMetric);
+ AutofillMetrics::FALSE_NEGATIVE_UNKNOWN));
return;
}
@@ -515,19 +479,16 @@ void LogPredictionQualityMetricsForCommonFields(
// This is a mismatch. From the reference of the actual type, this is a false
// negative (it was T, but predicted U). From the reference of the prediction,
// this is a false positive (predicted it was T, but it was U).
- base::UmaHistogramEnumeration(
- aggregate_histogram, AutofillMetrics::FALSE_NEGATIVE_MISMATCH,
- AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS);
- LogUMAHistogramEnumeration(
+ base::UmaHistogramSparse(aggregate_histogram,
+ AutofillMetrics::FALSE_NEGATIVE_MISMATCH);
+ base::UmaHistogramSparse(
type_specific_histogram,
GetFieldTypeGroupMetric(actual_type,
- AutofillMetrics::FALSE_NEGATIVE_MISMATCH),
- KMaxFieldTypeGroupMetric);
- LogUMAHistogramEnumeration(
+ AutofillMetrics::FALSE_NEGATIVE_MISMATCH));
+ base::UmaHistogramSparse(
type_specific_histogram,
GetFieldTypeGroupMetric(predicted_type,
- AutofillMetrics::FALSE_POSITIVE_MISMATCH),
- KMaxFieldTypeGroupMetric);
+ AutofillMetrics::FALSE_POSITIVE_MISMATCH));
}
// Logs field type prediction quality metrics. The primary histogram name is
@@ -1512,6 +1473,7 @@ void AutofillMetrics::LogProfileActionOnFormSubmitted(
void AutofillMetrics::LogAutofillFormSubmittedState(
AutofillFormSubmittedState state,
bool is_for_credit_card,
+ bool has_upi_vpa_field,
const std::set<FormType>& form_types,
const base::TimeTicks& form_parsed_timestamp,
FormSignature form_signature,
@@ -1549,9 +1511,9 @@ void AutofillMetrics::LogAutofillFormSubmittedState(
NOTREACHED();
break;
}
- form_interactions_ukm_logger->LogFormSubmitted(is_for_credit_card, form_types,
- state, form_parsed_timestamp,
- form_signature);
+ form_interactions_ukm_logger->LogFormSubmitted(
+ is_for_credit_card, has_upi_vpa_field, form_types, state,
+ form_parsed_timestamp, form_signature);
}
// static
@@ -1601,6 +1563,11 @@ void AutofillMetrics::LogShowedHttpNotSecureExplanation() {
}
// static
+void AutofillMetrics::LogAutocompleteDaysSinceLastUse(size_t days) {
+ UMA_HISTOGRAM_COUNTS_1000("Autocomplete.DaysSinceLastUse", days);
+}
+
+// static
void AutofillMetrics::LogAutocompleteSuggestionAcceptedIndex(int index) {
base::UmaHistogramSparse("Autofill.SuggestionAcceptedIndex.Autocomplete",
std::min(index, kMaxBucketsCount));
@@ -1622,6 +1589,10 @@ void AutofillMetrics::OnAutocompleteSuggestionsShown() {
AutofillMetrics::Log(AutocompleteEvent::AUTOCOMPLETE_SUGGESTIONS_SHOWN);
}
+void AutofillMetrics::LogNumberOfAutocompleteEntriesCleanedUp(int nb_entries) {
+ UMA_HISTOGRAM_COUNTS_1000("Autocomplete.Cleanup", nb_entries);
+}
+
// static
void AutofillMetrics::Log(AutocompleteEvent event) {
DCHECK_LT(event, AutocompleteEvent::NUM_AUTOCOMPLETE_EVENTS);
@@ -1657,8 +1628,9 @@ const char* AutofillMetrics::SubmissionSourceToUploadEventMetric(
void AutofillMetrics::LogUploadEvent(SubmissionSource submission_source,
bool was_sent) {
UMA_HISTOGRAM_BOOLEAN("Autofill.UploadEvent", was_sent);
- LogUMAHistogramEnumeration(
- SubmissionSourceToUploadEventMetric(submission_source), was_sent, 2);
+ base::UmaHistogramEnumeration(
+ SubmissionSourceToUploadEventMetric(submission_source),
+ was_sent ? UploadEventStatus::kSent : UploadEventStatus::kNotSent);
}
// static
@@ -2227,6 +2199,7 @@ void AutofillMetrics::LogWalletSyncTransportCardsOptIn(bool is_opted_in) {
void AutofillMetrics::FormInteractionsUkmLogger::LogFormSubmitted(
bool is_for_credit_card,
+ bool has_upi_vpa_field,
const std::set<FormType>& form_types,
AutofillFormSubmittedState state,
const base::TimeTicks& form_parsed_timestamp,
@@ -2237,6 +2210,7 @@ void AutofillMetrics::FormInteractionsUkmLogger::LogFormSubmitted(
ukm::builders::Autofill_FormSubmitted builder(source_id_);
builder.SetAutofillFormSubmittedState(static_cast<int>(state))
.SetIsForCreditCard(is_for_credit_card)
+ .SetHasUpiVpaField(has_upi_vpa_field)
.SetFormTypes(FormTypesToBitVector(form_types))
.SetFormSignature(HashFormSignature(form_signature));
if (form_parsed_timestamp.is_null())
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.h b/chromium/components/autofill/core/browser/autofill_metrics.h
index eef415c2805..2e2f6150140 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.h
+++ b/chromium/components/autofill/core/browser/autofill_metrics.h
@@ -843,6 +843,9 @@ class AutofillMetrics {
NUM_CONVERTED_ADDRESS_CONVERSION_TYPES
};
+ // To record whether or not the upload event was sent,
+ enum class UploadEventStatus { kNotSent, kSent, kMaxValue = kSent };
+
// Utility to log URL keyed form interaction events.
class FormInteractionsUkmLogger {
public:
@@ -888,6 +891,7 @@ class AutofillMetrics {
ServerFieldType predicted_type,
ServerFieldType actual_type);
void LogFormSubmitted(bool is_for_credit_card,
+ bool has_upi_vpa_field,
const std::set<FormType>& form_types,
AutofillFormSubmittedState state,
const base::TimeTicks& form_parsed_timestamp,
@@ -1177,12 +1181,19 @@ class AutofillMetrics {
// Log the index of the selected Autofill suggestion in the popup.
static void LogAutofillSuggestionAcceptedIndex(int index);
+ // Log the number of days since an Autocomplete suggestion was last used.
+ static void LogAutocompleteDaysSinceLastUse(size_t days);
+
// Log the index of the selected Autocomplete suggestion in the popup.
static void LogAutocompleteSuggestionAcceptedIndex(int index);
- // Log the fact that a autocomplete popup was shown.
+ // Log the fact that an autocomplete popup was shown.
static void OnAutocompleteSuggestionsShown();
+ // Log the number of autocomplete entries that were cleaned-up as a result
+ // of the Autocomplete Retention Policy.
+ static void LogNumberOfAutocompleteEntriesCleanedUp(int nb_entries);
+
// Log how many autofilled fields in a given form were edited before the
// submission or when the user unfocused the form (depending on
// |observed_submission|).
@@ -1202,6 +1213,7 @@ class AutofillMetrics {
static void LogAutofillFormSubmittedState(
AutofillFormSubmittedState state,
bool is_for_credit_card,
+ bool has_upi_vpa_field,
const std::set<FormType>& form_types,
const base::TimeTicks& form_parsed_timestamp,
FormSignature form_signature,
diff --git a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
index e027498d675..213d7d340fa 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -23,6 +23,7 @@
#include "base/time/time.h"
#include "components/autofill/core/browser/autofill_external_delegate.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/browser/mock_autocomplete_history_manager.h"
#include "components/autofill/core/browser/payments/test_payments_client.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/popup_item_ids.h"
@@ -151,12 +152,14 @@ void VerifySubmitFormUkm(const ukm::TestAutoSetUkmRecorder& ukm_recorder,
const FormData& form,
AutofillMetrics::AutofillFormSubmittedState state,
bool is_for_credit_card,
+ bool has_upi_vpa_field,
const std::set<FormType>& form_types) {
VerifyFormInteractionUkm(
ukm_recorder, form, UkmFormSubmittedType::kEntryName,
{{{UkmFormSubmittedType::kAutofillFormSubmittedStateName, state},
{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
{UkmFormSubmittedType::kIsForCreditCardName, is_for_credit_card},
+ {UkmFormSubmittedType::kHasUpiVpaFieldName, has_upi_vpa_field},
{UkmFormSubmittedType::kFormTypesName,
AutofillMetrics::FormTypesToBitVector(form_types)},
{UkmFormSubmittedType::kFormSignatureName,
@@ -265,6 +268,7 @@ class AutofillMetricsTest : public testing::Test {
std::unique_ptr<TestAutofillDriver> autofill_driver_;
std::unique_ptr<TestAutofillManager> autofill_manager_;
std::unique_ptr<TestPersonalDataManager> personal_data_;
+ std::unique_ptr<MockAutocompleteHistoryManager> autocomplete_history_manager_;
std::unique_ptr<AutofillExternalDelegate> external_delegate_;
base::test::ScopedFeatureList scoped_feature_list_;
@@ -289,6 +293,9 @@ void AutofillMetricsTest::SetUp() {
personal_data_->SetPrefService(autofill_client_.GetPrefs());
personal_data_->SetSyncServiceForTest(&sync_service_);
+ autocomplete_history_manager_ =
+ std::make_unique<MockAutocompleteHistoryManager>();
+
payments::TestPaymentsClient* payments_client =
new payments::TestPaymentsClient(
autofill_driver_->GetURLLoaderFactory(), autofill_client_.GetPrefs(),
@@ -307,7 +314,8 @@ void AutofillMetricsTest::SetUp() {
std::unique_ptr<TestFormDataImporter>(test_form_data_importer));
autofill_manager_ = std::make_unique<TestAutofillManager>(
- autofill_driver_.get(), &autofill_client_, personal_data_.get());
+ autofill_driver_.get(), &autofill_client_, personal_data_.get(),
+ autocomplete_history_manager_.get());
external_delegate_ = std::make_unique<AutofillExternalDelegate>(
autofill_manager_.get(), autofill_driver_.get());
autofill_manager_->SetExternalDelegate(external_delegate_.get());
@@ -528,8 +536,8 @@ TEST_F(AutofillMetricsTest, QualityMetrics) {
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// Heuristic predictions.
{
@@ -725,8 +733,8 @@ TEST_F(AutofillMetricsTest,
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// Rationalization quality.
{
@@ -790,8 +798,8 @@ TEST_F(AutofillMetricsTest,
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// Rationalization quality.
{
@@ -1244,8 +1252,8 @@ TEST_F(AutofillMetricsTest,
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// Rationalization quality.
{
@@ -1325,8 +1333,8 @@ TEST_F(AutofillMetricsTest,
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// Rationalization quality.
{
@@ -1608,8 +1616,8 @@ TEST_P(QualityMetricsTest, Classification) {
// Run the form submission code while tracking the histograms.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
ExpectedUkmMetrics expected_ukm_metrics;
AppendFieldTypeUkm(form, heuristic_types, server_types, actual_types,
@@ -2115,8 +2123,8 @@ TEST_F(AutofillMetricsTest, UpiVirtualPaymentAddress) {
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.UserHappiness", AutofillMetrics::USER_DID_ENTER_UPI_VPA, 1);
@@ -2167,8 +2175,8 @@ TEST_F(AutofillMetricsTest, PredictedMetricsWithAutocomplete) {
// match what is in the test profile.
form.fields[1].value = base::ASCIIToUTF16("79401");
form.fields[2].value = base::ASCIIToUTF16("2345678901");
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
for (const std::string source : {"Heuristic", "Server", "Overall"}) {
std::string histogram_name =
@@ -2268,8 +2276,8 @@ TEST_F(AutofillMetricsTest, SaneMetricsWithCacheMismatch) {
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
for (const std::string source : {"Heuristic", "Server", "Overall"}) {
std::string aggregate_histogram =
@@ -2337,8 +2345,8 @@ TEST_F(AutofillMetricsTest, StoredProfileCountAutofillableFormSubmission) {
// Simulate form submission.
base::HistogramTester histogram_tester;
autofill_manager_->OnFormsSeen(forms, TimeTicks());
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// An autofillable form was submitted, and the number of stored profiles is
// logged.
@@ -2371,8 +2379,8 @@ TEST_F(AutofillMetricsTest, StoredProfileCountNonAutofillableFormSubmission) {
// Simulate form submission.
base::HistogramTester histogram_tester;
autofill_manager_->OnFormsSeen(forms, TimeTicks());
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// A non-autofillable form was submitted, and number of stored profiles is NOT
// logged.
@@ -2425,8 +2433,8 @@ TEST_F(AutofillMetricsTest, NumberOfEditedAutofilledFields) {
TimeTicks());
// Simulate form submission.
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// An autofillable form was submitted, and the number of edited autofilled
// fields is logged.
@@ -2868,7 +2876,7 @@ TEST_F(AutofillMetricsTest, LogStoredCreditCardMetrics) {
TEST_F(AutofillMetricsTest, AutofillIsEnabledAtStartup) {
base::HistogramTester histogram_tester;
personal_data_->SetAutofillEnabled(true);
- personal_data_->Init(autofill_client_.GetDatabase(),
+ personal_data_->Init(scoped_refptr<AutofillWebDataService>(nullptr),
/*account_database=*/nullptr,
autofill_client_.GetPrefs(),
/*identity_manager=*/nullptr,
@@ -2883,7 +2891,7 @@ TEST_F(AutofillMetricsTest, AutofillIsEnabledAtStartup) {
TEST_F(AutofillMetricsTest, AutofillIsDisabledAtStartup) {
base::HistogramTester histogram_tester;
personal_data_->SetAutofillEnabled(false);
- personal_data_->Init(autofill_client_.GetDatabase(),
+ personal_data_->Init(scoped_refptr<AutofillWebDataService>(nullptr),
/*account_database=*/nullptr,
autofill_client_.GetPrefs(),
/*identity_manager=*/nullptr,
@@ -3001,8 +3009,7 @@ TEST_P(AutofillMetricsCompanyTest, CompanyNameSuggestions) {
histogram_tester.ExpectUniqueSample("Autofill.AddressSuggestionsCount", 2,
1);
} else {
- EXPECT_EQ(nullptr, base::StatisticsRecorder::FindHistogram(
- "Autofill.AddressSuggestionsCount"));
+ histogram_tester.ExpectTotalCount("Autofill.AddressSuggestionsCount", 0);
}
}
}
@@ -3092,8 +3099,8 @@ TEST_F(AutofillMetricsTest, CreditCardCheckoutFlowUserActions) {
base::UserActionTester user_action_tester;
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
EXPECT_EQ(1,
user_action_tester.GetActionCount("Autofill_OnWillSubmitForm"));
EXPECT_EQ(1, user_action_tester.GetActionCount(
@@ -3139,9 +3146,37 @@ TEST_F(AutofillMetricsTest, CreditCardCheckoutFlowUserActions) {
Collapse(CalculateFormSignature(form))}}});
// Expect |NON_FILLABLE_FORM_OR_NEW_DATA| in |AutofillFormSubmittedState|
// because |field.value| is empty in |DeterminePossibleFieldTypesForUpload|.
- VerifySubmitFormUkm(
- test_ukm_recorder_, form, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
- /*is_for_credit_card=*/true, {FormType::CREDIT_CARD_FORM});
+ VerifySubmitFormUkm(test_ukm_recorder_, form,
+ AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
+ /*is_for_credit_card=*/true, /* has_upi_vpa_field=*/false,
+ {FormType::CREDIT_CARD_FORM});
+}
+
+// Test that the UPI Checkout flow form submit is correctly logged
+TEST_F(AutofillMetricsTest, UpiVpaUkmTest) {
+ FormData form;
+ form.name = ASCIIToUTF16("TestForm");
+ form.origin = GURL("http://example.com/form.html");
+ form.action = GURL("http://example.com/submit.html");
+ form.main_frame_origin = url::Origin::Create(autofill_client_.form_origin());
+ FormFieldData field;
+ test::CreateTestFormField("Enter VPA", "upi-vpa", "unique_id@upi", "text",
+ &field);
+ form.fields.push_back(field);
+
+ std::vector<FormData> forms(1, form);
+
+ {
+ autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
+
+ VerifySubmitFormUkm(test_ukm_recorder_, forms.back(),
+ AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
+ /*is_for_credit_card=*/false,
+ /* has_upi_vpa_field */ true,
+ /* UPI VPA has Unknown form type.*/
+ {FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE});
+ PurgeUKM();
+ }
}
// Test that the profile checkout flow user actions are correctly logged.
@@ -3227,8 +3262,8 @@ TEST_F(AutofillMetricsTest, ProfileCheckoutFlowUserActions) {
base::UserActionTester user_action_tester;
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
EXPECT_EQ(1,
user_action_tester.GetActionCount("Autofill_OnWillSubmitForm"));
EXPECT_EQ(1, user_action_tester.GetActionCount(
@@ -3278,7 +3313,8 @@ TEST_F(AutofillMetricsTest, ProfileCheckoutFlowUserActions) {
// because |field.value| is empty in |DeterminePossibleFieldTypesForUpload|.
VerifySubmitFormUkm(test_ukm_recorder_, form,
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
- /*is_for_credit_card=*/false, {FormType::ADDRESS_FORM});
+ /*is_for_credit_card=*/false,
+ /* has_upi_vpa_field=*/false, {FormType::ADDRESS_FORM});
}
// Tests that the Autofill_PolledCreditCardSuggestions user action is only
@@ -3998,8 +4034,8 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardFilledFormEvents) {
autofill_manager_->MakeFrontendID(guid, std::string()));
autofill_manager_->OnDidGetRealPan(AutofillClient::SUCCESS,
"6011000990139424");
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, 1);
@@ -4100,8 +4136,8 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardFilledFormEvents) {
autofill_manager_->MakeFrontendID(guid, std::string()));
autofill_manager_->OnDidGetRealPan(AutofillClient::SUCCESS,
"4444333322221111");
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard.BankNameDisplayed",
AutofillMetrics::
@@ -4125,8 +4161,8 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardFilledFormEvents) {
autofill_manager_->MakeFrontendID(guid, std::string()));
autofill_manager_->OnDidGetRealPan(AutofillClient::SUCCESS,
"4444333322221111");
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard.BankNameDisplayed",
AutofillMetrics::
@@ -4288,8 +4324,8 @@ TEST_F(AutofillMetricsTest,
autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD,
@@ -4330,8 +4366,8 @@ TEST_P(AutofillMetricsIFrameTest,
autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::
@@ -4379,8 +4415,8 @@ TEST_P(AutofillMetricsIFrameTest,
autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::
@@ -4429,8 +4465,8 @@ TEST_P(AutofillMetricsIFrameTest,
autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::
@@ -4479,8 +4515,8 @@ TEST_P(AutofillMetricsIFrameTest,
autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::
@@ -4534,8 +4570,8 @@ TEST_P(AutofillMetricsIFrameTest,
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
autofill_manager_->MakeFrontendID(guid, std::string()));
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::
@@ -4598,8 +4634,8 @@ TEST_F(AutofillMetricsTest, ShouldNotLogFormEventNoCardForAddressForm) {
autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD,
@@ -4640,8 +4676,8 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
base::HistogramTester histogram_tester;
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
@@ -4659,6 +4695,7 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
VerifySubmitFormUkm(test_ukm_recorder_, form,
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
/*is_for_credit_card=*/true,
+ /* has_upi_vpa_field=*/false,
{FormType::CREDIT_CARD_FORM});
}
@@ -4673,8 +4710,8 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1);
@@ -4702,6 +4739,7 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
VerifySubmitFormUkm(test_ukm_recorder_, form,
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
/*is_for_credit_card=*/true,
+ /* has_upi_vpa_field=*/false,
{FormType::CREDIT_CARD_FORM});
}
@@ -4718,8 +4756,8 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// Trigger UploadFormDataAsyncCallback.
autofill_manager_->Reset();
histogram_tester.ExpectBucketCount(
@@ -4749,6 +4787,7 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
VerifySubmitFormUkm(test_ukm_recorder_, form,
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
/*is_for_credit_card=*/true,
+ /* has_upi_vpa_field=*/false,
{FormType::CREDIT_CARD_FORM});
}
@@ -4766,8 +4805,8 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
autofill_manager_->MakeFrontendID(guid, std::string()));
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -4793,6 +4832,7 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
VerifySubmitFormUkm(test_ukm_recorder_, form,
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
/*is_for_credit_card=*/true,
+ /* has_upi_vpa_field=*/false,
{FormType::CREDIT_CARD_FORM});
}
@@ -4811,8 +4851,8 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
autofill_manager_->MakeFrontendID(guid, std::string()));
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -4839,6 +4879,7 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
VerifySubmitFormUkm(test_ukm_recorder_, form,
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
/*is_for_credit_card=*/true,
+ /* has_upi_vpa_field=*/false,
{FormType::CREDIT_CARD_FORM});
}
@@ -4857,8 +4898,8 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
autofill_manager_->MakeFrontendID(guid, std::string()));
autofill_manager_->OnDidGetRealPan(AutofillClient::SUCCESS,
"6011000990139424");
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, 1);
@@ -4890,6 +4931,7 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
VerifySubmitFormUkm(test_ukm_recorder_, form,
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
/*is_for_credit_card=*/true,
+ /* has_upi_vpa_field=*/false,
{FormType::CREDIT_CARD_FORM});
}
@@ -4911,16 +4953,17 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
base::HistogramTester histogram_tester;
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
VerifySubmitFormUkm(test_ukm_recorder_, form,
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
/*is_for_credit_card=*/true,
+ /* has_upi_vpa_field=*/false,
{FormType::CREDIT_CARD_FORM});
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
VerifyFormInteractionUkm(
test_ukm_recorder_, form, UkmFormSubmittedType::kEntryName,
@@ -4928,6 +4971,7 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA},
{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
{UkmFormSubmittedType::kIsForCreditCardName, true},
+ {UkmFormSubmittedType::kHasUpiVpaFieldName, false},
{UkmFormSubmittedType::kFormTypesName,
AutofillMetrics::FormTypesToBitVector({FormType::CREDIT_CARD_FORM})},
{UkmFormSubmittedType::kFormSignatureName,
@@ -4936,6 +4980,7 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA},
{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
{UkmFormSubmittedType::kIsForCreditCardName, true},
+ {UkmFormSubmittedType::kHasUpiVpaFieldName, false},
{UkmFormSubmittedType::kFormTypesName,
AutofillMetrics::FormTypesToBitVector({FormType::CREDIT_CARD_FORM})},
{UkmFormSubmittedType::kFormSignatureName,
@@ -5021,8 +5066,8 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
// interaction.
base::HistogramTester histogram_tester;
autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
@@ -5106,6 +5151,7 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
VerifySubmitFormUkm(test_ukm_recorder_, form,
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
/*is_for_credit_card=*/true,
+ /* has_upi_vpa_field=*/false,
{FormType::CREDIT_CARD_FORM});
}
}
@@ -5145,8 +5191,8 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) {
base::HistogramTester histogram_tester;
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -5171,8 +5217,8 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) {
autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1);
@@ -5200,8 +5246,8 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) {
autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
autofill_manager_->MakeFrontendID(guid, std::string()));
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -5230,8 +5276,8 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) {
autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
autofill_manager_->MakeFrontendID(guid, std::string()));
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -5291,10 +5337,10 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) {
base::HistogramTester histogram_tester;
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -5374,8 +5420,8 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) {
// interaction.
base::HistogramTester histogram_tester;
autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
@@ -5818,8 +5864,8 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
base::HistogramTester histogram_tester;
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -5829,7 +5875,8 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
VerifySubmitFormUkm(test_ukm_recorder_, form,
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
- /*is_for_credit_card=*/false, {FormType::ADDRESS_FORM});
+ /*is_for_credit_card=*/false,
+ /* has_upi_vpa_field=*/false, {FormType::ADDRESS_FORM});
}
// Reset the autofill manager state and purge UKM logs.
@@ -5844,8 +5891,8 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
base::HistogramTester histogram_tester;
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// Trigger UploadFormDataAsyncCallback.
autofill_manager_->Reset();
histogram_tester.ExpectBucketCount(
@@ -5857,7 +5904,8 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
VerifySubmitFormUkm(test_ukm_recorder_, form,
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
- /*is_for_credit_card=*/false, {FormType::ADDRESS_FORM});
+ /*is_for_credit_card=*/false,
+ /* has_upi_vpa_field=*/false, {FormType::ADDRESS_FORM});
}
// Reset the autofill manager state and purge UKM logs.
@@ -5871,8 +5919,8 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1);
@@ -5894,8 +5942,8 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
autofill_manager_->MakeFrontendID(std::string(), guid));
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -5913,10 +5961,10 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
base::HistogramTester histogram_tester;
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
@@ -5953,8 +6001,8 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
// interaction.
base::HistogramTester histogram_tester;
autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
@@ -6025,8 +6073,8 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
base::HistogramTester histogram_tester;
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -6045,8 +6093,8 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1);
@@ -6068,8 +6116,8 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
autofill_manager_->MakeFrontendID(std::string(), guid));
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -6087,10 +6135,10 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
base::HistogramTester histogram_tester;
autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
@@ -6136,8 +6184,8 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
// interaction.
base::HistogramTester histogram_tester;
autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
@@ -6409,8 +6457,8 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
{
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FormSubmittedState",
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, 1);
@@ -6422,6 +6470,7 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA},
{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
{UkmFormSubmittedType::kIsForCreditCardName, false},
+ {UkmFormSubmittedType::kHasUpiVpaFieldName, false},
{UkmFormSubmittedType::kFormTypesName,
AutofillMetrics::FormTypesToBitVector(
{FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})},
@@ -6445,8 +6494,8 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
{
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FormSubmittedState",
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, 1);
@@ -6458,6 +6507,7 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA},
{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
{UkmFormSubmittedType::kIsForCreditCardName, false},
+ {UkmFormSubmittedType::kHasUpiVpaFieldName, false},
{UkmFormSubmittedType::kFormTypesName,
AutofillMetrics::FormTypesToBitVector(
{FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})},
@@ -6483,8 +6533,8 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
{
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FormSubmittedState",
AutofillMetrics::FILLABLE_FORM_AUTOFILLED_NONE_DID_NOT_SHOW_SUGGESTIONS,
@@ -6498,6 +6548,7 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
FILLABLE_FORM_AUTOFILLED_NONE_DID_NOT_SHOW_SUGGESTIONS},
{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
{UkmFormSubmittedType::kIsForCreditCardName, false},
+ {UkmFormSubmittedType::kHasUpiVpaFieldName, false},
{UkmFormSubmittedType::kFormTypesName,
AutofillMetrics::FormTypesToBitVector(
{FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})},
@@ -6519,8 +6570,8 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
{
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FormSubmittedState",
AutofillMetrics::FILLABLE_FORM_AUTOFILLED_NONE_DID_SHOW_SUGGESTIONS, 1);
@@ -6545,6 +6596,7 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
AutofillMetrics::FILLABLE_FORM_AUTOFILLED_NONE_DID_SHOW_SUGGESTIONS},
{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
{UkmFormSubmittedType::kIsForCreditCardName, false},
+ {UkmFormSubmittedType::kHasUpiVpaFieldName, false},
{UkmFormSubmittedType::kFormTypesName,
AutofillMetrics::FormTypesToBitVector(
{FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})},
@@ -6568,8 +6620,8 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
{
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FormSubmittedState",
AutofillMetrics::FILLABLE_FORM_AUTOFILLED_SOME, 1);
@@ -6581,6 +6633,7 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
AutofillMetrics::FILLABLE_FORM_AUTOFILLED_SOME},
{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
{UkmFormSubmittedType::kIsForCreditCardName, false},
+ {UkmFormSubmittedType::kHasUpiVpaFieldName, false},
{UkmFormSubmittedType::kFormTypesName,
AutofillMetrics::FormTypesToBitVector(
{FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})},
@@ -6605,8 +6658,8 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
{
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FormSubmittedState",
AutofillMetrics::FILLABLE_FORM_AUTOFILLED_ALL, 1);
@@ -6618,6 +6671,7 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
AutofillMetrics::FILLABLE_FORM_AUTOFILLED_ALL},
{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
{UkmFormSubmittedType::kIsForCreditCardName, false},
+ {UkmFormSubmittedType::kHasUpiVpaFieldName, false},
{UkmFormSubmittedType::kFormTypesName,
AutofillMetrics::FormTypesToBitVector(
{FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})},
@@ -6649,8 +6703,8 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
{});
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FormSubmittedState",
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, 1);
@@ -6662,6 +6716,7 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA},
{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
{UkmFormSubmittedType::kIsForCreditCardName, false},
+ {UkmFormSubmittedType::kHasUpiVpaFieldName, false},
{UkmFormSubmittedType::kFormTypesName,
AutofillMetrics::FormTypesToBitVector(
{FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})},
@@ -6721,8 +6776,8 @@ TEST_F(
form.fields[2].value = ASCIIToUTF16("12345678901");
form.fields[2].is_autofilled = true;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FormSubmittedState",
AutofillMetrics::FILLABLE_FORM_AUTOFILLED_ALL, 1);
@@ -6737,6 +6792,7 @@ TEST_F(
AutofillMetrics::FILLABLE_FORM_AUTOFILLED_ALL},
{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
{UkmFormSubmittedType::kIsForCreditCardName, false},
+ {UkmFormSubmittedType::kHasUpiVpaFieldName, false},
{UkmFormSubmittedType::kFormTypesName,
AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})},
{UkmFormSubmittedType::kFormSignatureName,
@@ -7299,12 +7355,8 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
{
base::HistogramTester histogram_tester;
autofill_manager_->OnFormsSeen(forms, TimeTicks::Now());
- base::TimeTicks parse_time = autofill_manager_->form_structures()
- .begin()
- ->second->form_parsed_timestamp();
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION,
- parse_time + base::TimeDelta::FromMicroseconds(17));
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectTotalCount(
"Autofill.FillDuration.FromLoad.WithAutofill", 0);
@@ -7328,9 +7380,8 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
autofill_manager_->OnTextFieldDidChange(
form, form.fields.front(), gfx::RectF(),
parse_time + base::TimeDelta::FromMicroseconds(3));
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION,
- parse_time + base::TimeDelta::FromMicroseconds(17));
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectTotalCount(
"Autofill.FillDuration.FromLoad.WithAutofill", 0);
@@ -7355,9 +7406,8 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
->second->form_parsed_timestamp();
autofill_manager_->OnDidFillAutofillFormData(
form, parse_time + base::TimeDelta::FromMicroseconds(5));
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION,
- parse_time + base::TimeDelta::FromMicroseconds(17));
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FillDuration.FromLoad.WithAutofill", 16, 1);
@@ -7387,9 +7437,8 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
autofill_manager_->OnTextFieldDidChange(
form, form.fields.front(), gfx::RectF(),
parse_time + base::TimeDelta::FromMicroseconds(3));
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION,
- parse_time + base::TimeDelta::FromMicroseconds(17));
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FillDuration.FromLoad.WithAutofill", 16, 1);
@@ -7418,9 +7467,8 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
autofill_manager_->OnTextFieldDidChange(
form, form.fields.front(), gfx::RectF(),
parse_time + base::TimeDelta::FromMicroseconds(3));
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION,
- parse_time + base::TimeDelta::FromMicroseconds(17));
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FillDuration.FromLoad.WithAutofill", 16, 1);
@@ -7446,9 +7494,8 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
if (kv.second->form_parsed_timestamp() > parse_time)
parse_time = kv.second->form_parsed_timestamp();
}
- autofill_manager_->OnFormSubmitted(
- second_form, false, SubmissionSource::FORM_SUBMISSION,
- parse_time + base::TimeDelta::FromMicroseconds(17));
+ autofill_manager_->OnFormSubmitted(second_form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectTotalCount(
"Autofill.FillDuration.FromLoad.WithAutofill", 0);
@@ -7746,8 +7793,8 @@ 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_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
AutofillMetrics::NEW_PROFILE_CREATED, 1);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
@@ -7759,8 +7806,8 @@ 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_->OnFormSubmitted(
- second_form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(second_form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
AutofillMetrics::NEW_PROFILE_CREATED, 1);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
@@ -7772,8 +7819,8 @@ 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_->OnFormSubmitted(
- third_form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(third_form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
AutofillMetrics::NEW_PROFILE_CREATED, 2);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
@@ -7785,8 +7832,8 @@ 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_->OnFormSubmitted(
- fourth_form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(fourth_form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
AutofillMetrics::NEW_PROFILE_CREATED, 2);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
@@ -7959,8 +8006,8 @@ TEST_F(AutofillMetricsTest, NonsecureCreditCardForm) {
// Simulate submitting the credit card form.
{
base::HistogramTester histograms;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histograms.ExpectBucketCount(
"Autofill.FormEvents.CreditCard.OnNonsecurePage",
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1);
@@ -8017,8 +8064,8 @@ TEST_F(AutofillMetricsTest,
// Simulate submitting the credit card form.
{
base::HistogramTester histograms;
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histograms.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -8441,6 +8488,14 @@ TEST_F(AutofillMetricsTest, OnAutocompleteSuggestionsShown) {
/*expected_count=*/1);
}
+TEST_F(AutofillMetricsTest, LogNumberOfAutocompleteEntriesCleanedUp) {
+ base::HistogramTester histogram_tester;
+ const int kNbEntries = 10;
+ AutofillMetrics::LogNumberOfAutocompleteEntriesCleanedUp(kNbEntries);
+ histogram_tester.ExpectBucketCount("Autocomplete.Cleanup", kNbEntries,
+ /*expected_count=*/1);
+}
+
// Verify that we correctly log FormEvent metrics with the appropriate sync
// state.
TEST_F(AutofillMetricsTest, FormEventMetrics_BySyncState) {
diff --git a/chromium/components/autofill/core/browser/autofill_observer.cc b/chromium/components/autofill/core/browser/autofill_observer.cc
new file mode 100644
index 00000000000..43030e44811
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_observer.cc
@@ -0,0 +1,16 @@
+// Copyright (c) 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_observer.h"
+
+#include "base/run_loop.h"
+
+namespace autofill {
+
+AutofillObserver::AutofillObserver(NotificationType notification_type,
+ bool detach_on_notify)
+ : notification_type_(notification_type),
+ detach_on_notify_(detach_on_notify) {}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_observer.h b/chromium/components/autofill/core/browser/autofill_observer.h
new file mode 100644
index 00000000000..ea32c66fc1f
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_observer.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_AUTOFILL_OBSERVER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_OBSERVER_H_
+
+#include "base/observer_list_types.h"
+
+namespace autofill {
+
+class AutofillObserver : public base::CheckedObserver {
+ public:
+ enum NotificationType {
+ AutocompleteFormSubmitted,
+ AutocompleteFormSkipped,
+ AutocompleteCleanupDone
+ };
+
+ // |notification_type| is the notification type that this observer observes.
+ // |detach_on_notify| will let the AutofillSubject know that this
+ // observer only wants to watch for the first notification of that type.
+ AutofillObserver(NotificationType notification_type, bool detach_on_notify);
+
+ // Invoked by the watched AutofillSubject.
+ virtual void OnNotify() = 0;
+
+ NotificationType notification_type() { return notification_type_; }
+ bool detach_on_notify() { return detach_on_notify_; }
+
+ private:
+ NotificationType notification_type_;
+ bool detach_on_notify_;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_OBSERVER_H_
diff --git a/chromium/components/autofill/core/browser/autofill_profile.cc b/chromium/components/autofill/core/browser/autofill_profile.cc
index 71606bb2b61..750b4bb9b34 100644
--- a/chromium/components/autofill/core/browser/autofill_profile.cc
+++ b/chromium/components/autofill/core/browser/autofill_profile.cc
@@ -15,10 +15,10 @@
#include "base/i18n/case_conversion.h"
#include "base/i18n/char_iterator.h"
#include "base/logging.h"
-#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/sha1.h"
#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversion_utils.h"
#include "base/strings/utf_string_conversions.h"
@@ -151,9 +151,9 @@ void GetFieldsForDistinguishingProfiles(
std::vector<ServerFieldType> default_fields;
if (!suggested_fields) {
- default_fields.assign(
- kDefaultDistinguishingFields,
- kDefaultDistinguishingFields + arraysize(kDefaultDistinguishingFields));
+ default_fields.assign(kDefaultDistinguishingFields,
+ kDefaultDistinguishingFields +
+ base::size(kDefaultDistinguishingFields));
if (excluded_field == UNKNOWN_TYPE) {
distinguishing_fields->swap(default_fields);
return;
@@ -312,6 +312,10 @@ bool AutofillProfile::SetMetadata(const AutofillMetadata metadata) {
return true;
}
+bool AutofillProfile::IsDeletable() const {
+ return AutofillDataModel::IsDeletable() && !IsVerified();
+}
+
// TODO(crbug.com/589535): Disambiguate similar field types before uploading.
void AutofillProfile::GetMatchingTypes(
const base::string16& text,
@@ -444,22 +448,36 @@ int AutofillProfile::Compare(const AutofillProfile& profile) const {
bool AutofillProfile::EqualsSansOrigin(const AutofillProfile& profile) const {
return guid() == profile.guid() &&
language_code() == profile.language_code() &&
- is_client_validity_states_updated() ==
- profile.is_client_validity_states_updated() &&
Compare(profile) == 0;
}
bool AutofillProfile::EqualsForSyncPurposes(const AutofillProfile& profile)
const {
return use_count() == profile.use_count() &&
- use_date() == profile.use_date() &&
- EqualsSansGuid(profile);
+ UseDateEqualsInSeconds(&profile) && EqualsSansGuid(profile);
+}
+
+bool AutofillProfile::EqualsForUpdatePurposes(
+ const AutofillProfile& profile) const {
+ return use_count() == profile.use_count() &&
+ UseDateEqualsInSeconds(&profile) &&
+ language_code() == profile.language_code() && Compare(profile) == 0;
+}
+
+bool AutofillProfile::EqualsForClientValidationPurpose(
+ const AutofillProfile& profile) const {
+ for (ServerFieldType type : kSupportedTypesByClientForValidation) {
+ if (GetRawInfo(type).compare(profile.GetRawInfo(type))) {
+ return false;
+ }
+ }
+ return true;
}
bool AutofillProfile::EqualsIncludingUsageStatsForTesting(
const AutofillProfile& profile) const {
return use_count() == profile.use_count() &&
- use_date() == profile.use_date() && *this == profile;
+ UseDateEqualsInSeconds(&profile) && *this == profile;
}
bool AutofillProfile::operator==(const AutofillProfile& profile) const {
@@ -804,7 +822,7 @@ void AutofillProfile::GenerateServerProfileIdentifier() {
}
void AutofillProfile::RecordAndLogUse() {
- previous_use_date_ = use_date();
+ set_previous_use_date(use_date());
UMA_HISTOGRAM_COUNTS_1000("Autofill.DaysSinceLastUse.Profile",
(AutofillClock::Now() - use_date()).InDays());
RecordUse();
@@ -1097,13 +1115,15 @@ FormGroup* AutofillProfile::MutableFormGroupForType(const AutofillType& type) {
bool AutofillProfile::EqualsSansGuid(const AutofillProfile& profile) const {
return origin() == profile.origin() &&
language_code() == profile.language_code() &&
- is_client_validity_states_updated() ==
- profile.is_client_validity_states_updated() &&
Compare(profile) == 0;
}
std::ostream& operator<<(std::ostream& os, const AutofillProfile& profile) {
- return os << profile.guid() << " " << profile.origin() << " "
+ return os << (profile.record_type() == AutofillProfile::LOCAL_PROFILE
+ ? profile.guid()
+ : base::HexEncode(profile.server_id().data(),
+ profile.server_id().size()))
+ << " " << profile.origin() << " "
<< UTF16ToUTF8(profile.GetRawInfo(NAME_FULL)) << " "
<< UTF16ToUTF8(profile.GetRawInfo(NAME_FIRST)) << " "
<< UTF16ToUTF8(profile.GetRawInfo(NAME_MIDDLE)) << " "
@@ -1122,7 +1142,8 @@ std::ostream& operator<<(std::ostream& os, const AutofillProfile& profile) {
<< profile.language_code() << " "
<< UTF16ToUTF8(profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER)) << " "
<< profile.GetClientValidityBitfieldValue() << " "
- << profile.use_count() << " " << profile.use_date();
+ << profile.has_converted() << " " << profile.use_count() << " "
+ << profile.use_date();
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_profile.h b/chromium/components/autofill/core/browser/autofill_profile.h
index 0a60b08a863..3d051f90202 100644
--- a/chromium/components/autofill/core/browser/autofill_profile.h
+++ b/chromium/components/autofill/core/browser/autofill_profile.h
@@ -77,6 +77,9 @@ class AutofillProfile : public AutofillDataModel {
// AutofillDataModel:
AutofillMetadata GetMetadata() const override;
bool SetMetadata(const AutofillMetadata metadata) override;
+ // Returns whether the profile is deletable: if it is not verified and has not
+ // been used for longer than |kDisusedAddressDeletionTimeDelta|.
+ bool IsDeletable() const override;
// FormGroup:
void GetMatchingTypes(const base::string16& text,
@@ -123,6 +126,11 @@ class AutofillProfile : public AutofillDataModel {
// differences in usage stats.
bool EqualsForSyncPurposes(const AutofillProfile& profile) const;
+ bool EqualsForUpdatePurposes(const AutofillProfile& profile) const;
+
+ // Compares the values of kSupportedTypesByClientForValidation fields.
+ bool EqualsForClientValidationPurpose(const AutofillProfile& profile) const;
+
// Same as operator==, but cares about differences in usage stats.
bool EqualsIncludingUsageStatsForTesting(
const AutofillProfile& profile) const;
diff --git a/chromium/components/autofill/core/browser/autofill_profile_unittest.cc b/chromium/components/autofill/core/browser/autofill_profile_unittest.cc
index 5da52384aaa..2a045233d55 100644
--- a/chromium/components/autofill/core/browser/autofill_profile_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_profile_unittest.cc
@@ -11,7 +11,6 @@
#include "base/format_macros.h"
#include "base/guid.h"
-#include "base/macros.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/strings/stringprintf.h"
@@ -20,6 +19,7 @@
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/form_field_data.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -289,7 +289,7 @@ TEST(AutofillProfileTest, CreateInferredLabelsI18n_CH) {
};
std::vector<base::string16> labels;
- for (size_t i = 0; i < arraysize(kExpectedLabels); ++i) {
+ for (size_t i = 0; i < base::size(kExpectedLabels); ++i) {
AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles), nullptr,
UNKNOWN_TYPE, i, "en-US", &labels);
ASSERT_FALSE(labels.empty());
@@ -328,7 +328,7 @@ TEST(AutofillProfileTest, CreateInferredLabelsI18n_FR) {
};
std::vector<base::string16> labels;
- for (size_t i = 0; i < arraysize(kExpectedLabels); ++i) {
+ for (size_t i = 0; i < base::size(kExpectedLabels); ++i) {
AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles), nullptr,
UNKNOWN_TYPE, i, "en-US", &labels);
ASSERT_FALSE(labels.empty());
@@ -372,7 +372,7 @@ TEST(AutofillProfileTest, CreateInferredLabelsI18n_KR) {
};
std::vector<base::string16> labels;
- for (size_t i = 0; i < arraysize(kExpectedLabels); ++i) {
+ for (size_t i = 0; i < base::size(kExpectedLabels); ++i) {
AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles), nullptr,
UNKNOWN_TYPE, i, "en-US", &labels);
ASSERT_FALSE(labels.empty());
@@ -409,7 +409,7 @@ TEST(AutofillProfileTest, CreateInferredLabelsI18n_JP_Latn) {
};
std::vector<base::string16> labels;
- for (size_t i = 0; i < arraysize(kExpectedLabels); ++i) {
+ for (size_t i = 0; i < base::size(kExpectedLabels); ++i) {
AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles), nullptr,
UNKNOWN_TYPE, i, "en-US", &labels);
ASSERT_FALSE(labels.empty());
@@ -442,7 +442,7 @@ TEST(AutofillProfileTest, CreateInferredLabelsI18n_JP_ja) {
};
std::vector<base::string16> labels;
- for (size_t i = 0; i < arraysize(kExpectedLabels); ++i) {
+ for (size_t i = 0; i < base::size(kExpectedLabels); ++i) {
AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles), nullptr,
UNKNOWN_TYPE, i, "en-US", &labels);
ASSERT_FALSE(labels.empty());
@@ -1792,4 +1792,47 @@ TEST(AutofillProfileTest, SetMetadata_NotMatchingId) {
EXPECT_NE(server_metadata.use_date, server_profile.use_date());
}
+// Tests that the profile is only deletable if it is not verified.
+TEST(AutofillProfileTest, IsDeletable) {
+ // Set up an arbitrary time, as setup the current time to just above the
+ // threshold later than that time.
+ const base::Time kArbitraryTime = base::Time::FromDoubleT(25000000000);
+ TestAutofillClock test_clock;
+ test_clock.SetNow(kArbitraryTime + kDisusedDataModelDeletionTimeDelta +
+ base::TimeDelta::FromDays(1));
+
+ // Created a profile that has not been used since over the deletion threshold.
+ AutofillProfile profile = test::GetFullProfile();
+ profile.set_use_date(kArbitraryTime);
+
+ // Make sure it's deletable.
+ EXPECT_TRUE(profile.IsDeletable());
+
+ // Set the profile as being verified.
+ profile.set_origin("Not empty");
+ ASSERT_TRUE(profile.IsVerified());
+
+ // Make sure it's not deletable.
+ EXPECT_FALSE(profile.IsDeletable());
+}
+
+// Tests that the two profiles can be compared for validation purposes.
+TEST(AutofillProfileTest, EqualsForClientValidationPurpose) {
+ AutofillProfile profile = test::GetFullProfile();
+
+ AutofillProfile profile2(profile);
+ profile2.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("different@email.com"));
+
+ AutofillProfile profile3(profile);
+ profile3.SetRawInfo(NAME_FULL, base::ASCIIToUTF16("Alice Munro"));
+
+ // For client validation purposes,
+ // profile2 != profile, because they differ in the email, which is validated
+ // by the client.
+ // profile3 == profile, because they only differ in name, and name is not
+ // validated by the client.
+ EXPECT_FALSE(profile.EqualsForClientValidationPurpose(profile2));
+ EXPECT_TRUE(profile.EqualsForClientValidationPurpose(profile3));
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_profile_validator.cc b/chromium/components/autofill/core/browser/autofill_profile_validator.cc
index 6616bb002f0..35d0a46aa30 100644
--- a/chromium/components/autofill/core/browser/autofill_profile_validator.cc
+++ b/chromium/components/autofill/core/browser/autofill_profile_validator.cc
@@ -43,8 +43,9 @@ AutofillProfileValidator::ValidationRequest::ValidationRequest(
validator_(validator),
on_validated_(std::move(on_validated)),
has_responded_(false),
- on_timeout_(base::Bind(&ValidationRequest::OnRulesLoaded,
- base::Unretained(this))) {
+ weak_factory_(this) {
+ on_timeout_.Reset(base::BindOnce(&ValidationRequest::OnRulesLoaded,
+ weak_factory_.GetWeakPtr()));
DCHECK(profile_);
base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, on_timeout_.callback(),
diff --git a/chromium/components/autofill/core/browser/autofill_profile_validator.h b/chromium/components/autofill/core/browser/autofill_profile_validator.h
index cf562b2749b..52d88a8d677 100644
--- a/chromium/components/autofill/core/browser/autofill_profile_validator.h
+++ b/chromium/components/autofill/core/browser/autofill_profile_validator.h
@@ -68,8 +68,8 @@ class AutofillProfileValidator : public autofill::LoadRulesListener {
AutofillProfileValidatorCallback on_validated_;
bool has_responded_ = false;
- base::CancelableCallback<void()> on_timeout_;
-
+ base::CancelableOnceCallback<void()> on_timeout_;
+ base::WeakPtrFactory<ValidationRequest> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ValidationRequest);
};
diff --git a/chromium/components/autofill/core/browser/autofill_provider.h b/chromium/components/autofill/core/browser/autofill_provider.h
index 359c3b62995..ada8e1d0c32 100644
--- a/chromium/components/autofill/core/browser/autofill_provider.h
+++ b/chromium/components/autofill/core/browser/autofill_provider.h
@@ -50,8 +50,7 @@ class AutofillProvider {
virtual void OnFormSubmitted(AutofillHandlerProxy* handler,
const FormData& form,
bool known_success,
- SubmissionSource source,
- base::TimeTicks timestamp) = 0;
+ SubmissionSource source) = 0;
virtual void OnFocusNoLongerOnForm(AutofillHandlerProxy* handler) = 0;
diff --git a/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc b/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc
index dc5766a8cba..f46ca53cf0c 100644
--- a/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc
+++ b/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc
@@ -11,7 +11,6 @@
#include "base/values.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/credit_card.h"
-#include "components/autofill/core/browser/legacy_strike_database.h"
#include "components/autofill/core/browser/legal_message_line.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_features.h"
@@ -32,30 +31,28 @@ AutofillSaveCardInfoBarDelegateMobile::AutofillSaveCardInfoBarDelegateMobile(
bool should_request_name_from_user,
const CreditCard& card,
std::unique_ptr<base::DictionaryValue> legal_message,
- LegacyStrikeDatabase* strike_database,
- AutofillClient::UserAcceptedUploadCallback upload_save_card_callback,
- base::OnceClosure local_save_card_callback,
- PrefService* pref_service)
+ AutofillClient::UploadSaveCardPromptCallback
+ upload_save_card_prompt_callback,
+ AutofillClient::LocalSaveCardPromptCallback local_save_card_prompt_callback,
+ PrefService* pref_service,
+ bool is_off_the_record)
: ConfirmInfoBarDelegate(),
upload_(upload),
should_request_name_from_user_(should_request_name_from_user),
- upload_save_card_callback_(std::move(upload_save_card_callback)),
- local_save_card_callback_(std::move(local_save_card_callback)),
+ upload_save_card_prompt_callback_(
+ std::move(upload_save_card_prompt_callback)),
+ local_save_card_prompt_callback_(
+ std::move(local_save_card_prompt_callback)),
pref_service_(pref_service),
- legacy_strike_database_(strike_database),
had_user_interaction_(false),
issuer_icon_id_(CreditCard::IconResourceId(card.network())),
card_label_(card.NetworkAndLastFourDigits()),
card_sub_label_(card.AbbreviatedExpirationDateForDisplay(
!features::IsAutofillSaveCardDialogUnlabeledExpirationDateEnabled())),
- card_last_four_digits_(card.LastFourDigits()) {
- if (upload) {
- DCHECK(!upload_save_card_callback_.is_null());
- DCHECK(local_save_card_callback_.is_null());
- } else {
- DCHECK(upload_save_card_callback_.is_null());
- DCHECK(!local_save_card_callback_.is_null());
- }
+ card_last_four_digits_(card.LastFourDigits()),
+ 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_,
@@ -78,16 +75,8 @@ AutofillSaveCardInfoBarDelegateMobile::AutofillSaveCardInfoBarDelegateMobile(
AutofillSaveCardInfoBarDelegateMobile::
~AutofillSaveCardInfoBarDelegateMobile() {
if (!had_user_interaction_) {
+ RunSaveCardPromptCallbackWithUserDecision(AutofillClient::IGNORED);
LogUserAction(AutofillMetrics::INFOBAR_IGNORED);
- if (base::FeatureList::IsEnabled(
- features::kAutofillSaveCreditCardUsesStrikeSystem)) {
- // If the infobar was ignored, count that as a strike against offering
- // save in the future.
- legacy_strike_database_->AddStrike(
- legacy_strike_database_->GetKeyForCreditCardSave(
- base::UTF16ToUTF8(card_last_four_digits_)),
- base::DoNothing());
- }
}
}
@@ -103,9 +92,7 @@ bool AutofillSaveCardInfoBarDelegateMobile::LegalMessagesParsedSuccessfully() {
}
bool AutofillSaveCardInfoBarDelegateMobile::IsGooglePayBrandingEnabled() const {
- return upload_ &&
- base::FeatureList::IsEnabled(
- features::kAutofillUpstreamUseGooglePayBrandingOnMobile);
+ return upload_;
}
base::string16 AutofillSaveCardInfoBarDelegateMobile::GetDescriptionText()
@@ -116,7 +103,7 @@ base::string16 AutofillSaveCardInfoBarDelegateMobile::GetDescriptionText()
return base::string16();
bool offer_to_save_on_device_message =
- OfferStoreUnmaskedCards() &&
+ OfferStoreUnmaskedCards(is_off_the_record_) &&
!IsAutofillNoLocalSaveOnUploadSuccessExperimentEnabled();
return l10n_util::GetStringUTF16(
offer_to_save_on_device_message
@@ -151,16 +138,8 @@ bool AutofillSaveCardInfoBarDelegateMobile::ShouldExpire(
}
void AutofillSaveCardInfoBarDelegateMobile::InfoBarDismissed() {
+ RunSaveCardPromptCallbackWithUserDecision(AutofillClient::DECLINED);
LogUserAction(AutofillMetrics::INFOBAR_DENIED);
- if (base::FeatureList::IsEnabled(
- features::kAutofillSaveCreditCardUsesStrikeSystem)) {
- // If the infobar was explicitly denied, count that as a strike against
- // offering save in the future.
- legacy_strike_database_->AddStrike(
- legacy_strike_database_->GetKeyForCreditCardSave(
- base::UTF16ToUTF8(card_last_four_digits_)),
- base::DoNothing());
- }
}
int AutofillSaveCardInfoBarDelegateMobile::GetButtons() const {
@@ -175,20 +154,25 @@ base::string16 AutofillSaveCardInfoBarDelegateMobile::GetButtonLabel(
}
return should_request_name_from_user_
- ? l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_CARD_PROMPT_NEXT)
+ ? l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_CARD_PROMPT_CONTINUE)
: l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_CARD_PROMPT_ACCEPT);
}
bool AutofillSaveCardInfoBarDelegateMobile::Accept() {
- if (upload_)
- std::move(upload_save_card_callback_).Run({});
- else
- std::move(local_save_card_callback_).Run();
-
+ RunSaveCardPromptCallbackWithUserDecision(AutofillClient::ACCEPTED);
LogUserAction(AutofillMetrics::INFOBAR_ACCEPTED);
return true;
}
+void AutofillSaveCardInfoBarDelegateMobile::
+ RunSaveCardPromptCallbackWithUserDecision(
+ AutofillClient::SaveCardOfferUserDecision user_decision) {
+ if (upload_)
+ std::move(upload_save_card_prompt_callback_).Run(user_decision, {});
+ else
+ std::move(local_save_card_prompt_callback_).Run(user_decision);
+}
+
void AutofillSaveCardInfoBarDelegateMobile::LogUserAction(
AutofillMetrics::InfoBarMetric user_action) {
DCHECK(!had_user_interaction_);
diff --git a/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h b/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h
index 9b2af4c7cf1..ed98a20297b 100644
--- a/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h
+++ b/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h
@@ -24,7 +24,6 @@ class DictionaryValue;
namespace autofill {
class CreditCard;
-class LegacyStrikeDatabase;
// An InfoBarDelegate that enables the user to allow or deny storing credit
// card information gathered from a form submission. Only used on mobile.
@@ -35,10 +34,12 @@ class AutofillSaveCardInfoBarDelegateMobile : public ConfirmInfoBarDelegate {
bool should_request_name_from_user,
const CreditCard& card,
std::unique_ptr<base::DictionaryValue> legal_message,
- LegacyStrikeDatabase* legacy_strike_database,
- AutofillClient::UserAcceptedUploadCallback upload_save_card_callback,
- base::OnceClosure local_save_card_callback,
- PrefService* pref_service);
+ AutofillClient::UploadSaveCardPromptCallback
+ upload_save_card_prompt_callback,
+ AutofillClient::LocalSaveCardPromptCallback
+ local_save_card_prompt_callback,
+ PrefService* pref_service,
+ bool is_off_the_record);
~AutofillSaveCardInfoBarDelegateMobile() override;
@@ -73,6 +74,11 @@ class AutofillSaveCardInfoBarDelegateMobile : public ConfirmInfoBarDelegate {
bool Accept() override;
private:
+ // Runs the appropriate local or upload save callback with the given
+ // |user_decision|.
+ void RunSaveCardPromptCallbackWithUserDecision(
+ AutofillClient::SaveCardOfferUserDecision user_decision);
+
void LogUserAction(AutofillMetrics::InfoBarMetric user_action);
// Whether the action is an upload or a local save.
@@ -81,20 +87,18 @@ class AutofillSaveCardInfoBarDelegateMobile : public ConfirmInfoBarDelegate {
// Whether the user should enter/confirm cardholder name.
bool should_request_name_from_user_;
- // The callback to save the credit card to Google Payments if |upload_| is
- // true and the user accepts the infobar.
- AutofillClient::UserAcceptedUploadCallback upload_save_card_callback_;
+ // The callback to run once the user makes a decision with respect to the
+ // credit card upload offer-to-save prompt (if |upload_| is true).
+ AutofillClient::UploadSaveCardPromptCallback
+ upload_save_card_prompt_callback_;
- // The callback to save the credit card locally to the device if |upload_| is
- // false and the user accepts the infobar.
- base::OnceClosure local_save_card_callback_;
+ // The callback to run once the user makes a decision with respect to the
+ // local credit card offer-to-save prompt (if |upload_| is false).
+ AutofillClient::LocalSaveCardPromptCallback local_save_card_prompt_callback_;
// Weak reference to read & write |kAutofillAcceptSaveCreditCardPromptState|,
PrefService* pref_service_;
- // Weak reference to the Autofill LegacyStrikeDatabase.
- LegacyStrikeDatabase* legacy_strike_database_;
-
// Did the user ever explicitly accept or dismiss this infobar?
bool had_user_interaction_;
@@ -113,6 +117,9 @@ class AutofillSaveCardInfoBarDelegateMobile : public ConfirmInfoBarDelegate {
// The legal messages to show in the content of the infobar.
LegalMessageLines legal_messages_;
+ // Whether the save is offered while off the record
+ bool is_off_the_record_;
+
DISALLOW_COPY_AND_ASSIGN(AutofillSaveCardInfoBarDelegateMobile);
};
diff --git a/chromium/components/autofill/core/browser/autofill_subject.cc b/chromium/components/autofill/core/browser/autofill_subject.cc
new file mode 100644
index 00000000000..d67961074fb
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_subject.cc
@@ -0,0 +1,54 @@
+// Copyright (c) 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_subject.h"
+
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/observer_list.h"
+#include "components/autofill/core/browser/autofill_observer.h"
+
+using NotificationType = autofill::AutofillObserver::NotificationType;
+
+namespace autofill {
+
+AutofillSubject::AutofillSubject() = default;
+AutofillSubject::~AutofillSubject() = default;
+
+void AutofillSubject::Attach(AutofillObserver* observer) {
+ observers_map_[observer->notification_type()].AddObserver(observer);
+}
+
+void AutofillSubject::Detach(AutofillObserver* observer) {
+ auto it = observers_map_.find(observer->notification_type());
+ if (it == observers_map_.end()) {
+ return;
+ }
+ it->second.RemoveObserver(observer);
+}
+
+void AutofillSubject::Notify(NotificationType notification_type) {
+ auto it = observers_map_.find(notification_type);
+ if (it == observers_map_.end()) {
+ return;
+ }
+
+ std::vector<AutofillObserver*> observers_to_remove;
+ for (AutofillObserver& observer : it->second) {
+ if (notification_type == observer.notification_type()) {
+ observer.OnNotify();
+
+ if (observer.detach_on_notify()) {
+ observers_to_remove.push_back(&observer);
+ }
+ }
+ }
+
+ for (AutofillObserver* observer : observers_to_remove) {
+ it->second.RemoveObserver(observer);
+ }
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_subject.h b/chromium/components/autofill/core/browser/autofill_subject.h
new file mode 100644
index 00000000000..2e4f222fa59
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_subject.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_AUTOFILL_SUBJECT_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_SUBJECT_H_
+
+#include <map>
+
+#include "base/observer_list.h"
+#include "components/autofill/core/browser/autofill_observer.h"
+
+using NotificationType = autofill::AutofillObserver::NotificationType;
+
+namespace autofill {
+
+// Subject that can emit notifications of specific types to observers that were
+// opted-in.
+class AutofillSubject {
+ public:
+ AutofillSubject();
+ ~AutofillSubject();
+
+ void Attach(AutofillObserver* observer);
+ void Detach(AutofillObserver* observer);
+
+ // Will notify observers that are watching for the same |notification_type|.
+ // This function is O(n^2) in case all observers are auto-detaching.
+ void Notify(NotificationType notification_type);
+
+ private:
+ std::map<NotificationType, base::ObserverList<AutofillObserver>>
+ observers_map_;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_SUBJECT_H_
diff --git a/chromium/components/autofill/core/browser/autofill_subject_unittest.cc b/chromium/components/autofill/core/browser/autofill_subject_unittest.cc
new file mode 100644
index 00000000000..f1c8eca786c
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_subject_unittest.cc
@@ -0,0 +1,140 @@
+// Copyright (c) 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_subject.h"
+
+#include "components/autofill/core/browser/autofill_observer.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using NotificationType = autofill::AutofillObserver::NotificationType;
+
+namespace autofill {
+
+namespace {
+
+class TestAutofillObserver : public AutofillObserver {
+ public:
+ TestAutofillObserver(NotificationType notification_type,
+ bool detach_on_notify)
+ : AutofillObserver(notification_type, detach_on_notify) {}
+
+ void OnNotify() override { was_notified_ = true; }
+
+ void Reset() { was_notified_ = false; }
+
+ bool IsActive() { return IsInObserverList(); }
+
+ bool was_notified() { return was_notified_; }
+
+ private:
+ bool was_notified_ = false;
+};
+
+} // namespace
+
+class AutofillSubjectTest : public testing::Test {
+ public:
+ AutofillSubjectTest() : subject_() {}
+
+ protected:
+ AutofillSubject subject_;
+};
+
+// Tests that a basic notification works.
+TEST_F(AutofillSubjectTest, Simple_Notification_NoAutoDetach) {
+ TestAutofillObserver observer(NotificationType::AutocompleteFormSubmitted,
+ /*detach_on_notify=*/false);
+
+ subject_.Attach(&observer);
+
+ EXPECT_TRUE(observer.IsActive());
+
+ subject_.Notify(NotificationType::AutocompleteFormSubmitted);
+
+ EXPECT_TRUE(observer.was_notified());
+
+ // Still active.
+ EXPECT_TRUE(observer.IsActive());
+
+ subject_.Detach(&observer);
+
+ observer.Reset();
+ subject_.Notify(NotificationType::AutocompleteFormSubmitted);
+
+ EXPECT_FALSE(observer.was_notified());
+ EXPECT_FALSE(observer.IsActive());
+}
+
+// Tests that a basic notification with auto-detach works.
+TEST_F(AutofillSubjectTest, Simple_Notification_WithAutoDetach) {
+ TestAutofillObserver observer(NotificationType::AutocompleteFormSubmitted,
+ /*detach_on_notify=*/true);
+
+ subject_.Attach(&observer);
+
+ subject_.Notify(NotificationType::AutocompleteFormSubmitted);
+
+ EXPECT_TRUE(observer.was_notified());
+ EXPECT_FALSE(observer.IsActive());
+
+ observer.Reset();
+ subject_.Notify(NotificationType::AutocompleteFormSubmitted);
+
+ EXPECT_FALSE(observer.was_notified());
+ EXPECT_FALSE(observer.IsActive());
+}
+
+// Tests that NotificationType properly isolates notifications.
+TEST_F(AutofillSubjectTest, MultipleObservers_SimpleNotification) {
+ TestAutofillObserver submit_observer(
+ NotificationType::AutocompleteFormSubmitted,
+ /*detach_on_notify=*/false);
+ TestAutofillObserver cleanup_observer(
+ NotificationType::AutocompleteCleanupDone,
+ /*detach_on_notify=*/false);
+
+ subject_.Attach(&submit_observer);
+ subject_.Attach(&cleanup_observer);
+
+ subject_.Notify(NotificationType::AutocompleteCleanupDone);
+
+ EXPECT_FALSE(submit_observer.was_notified());
+ EXPECT_TRUE(cleanup_observer.was_notified());
+}
+
+// Tests that auto-detach doesn't detach all observers.
+TEST_F(AutofillSubjectTest,
+ MultipleObservers_SimpleNotification_OneAutoDetach) {
+ TestAutofillObserver detach_submit_observer(
+ NotificationType::AutocompleteFormSubmitted,
+ /*detach_on_notify=*/true);
+ TestAutofillObserver stay_submit_observer(
+ NotificationType::AutocompleteFormSubmitted,
+ /*detach_on_notify=*/false);
+
+ subject_.Attach(&detach_submit_observer);
+ subject_.Attach(&stay_submit_observer);
+
+ subject_.Notify(NotificationType::AutocompleteFormSubmitted);
+
+ EXPECT_TRUE(detach_submit_observer.was_notified());
+ EXPECT_TRUE(stay_submit_observer.was_notified());
+
+ EXPECT_FALSE(detach_submit_observer.IsActive());
+ EXPECT_TRUE(stay_submit_observer.IsActive());
+
+ detach_submit_observer.Reset();
+ stay_submit_observer.Reset();
+
+ subject_.Notify(NotificationType::AutocompleteFormSubmitted);
+
+ EXPECT_FALSE(detach_submit_observer.was_notified());
+ EXPECT_TRUE(stay_submit_observer.was_notified());
+
+ EXPECT_FALSE(detach_submit_observer.IsActive());
+ EXPECT_TRUE(stay_submit_observer.IsActive());
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_test_utils.cc b/chromium/components/autofill/core/browser/autofill_test_utils.cc
index 6be48ef3369..9126d95ec29 100644
--- a/chromium/components/autofill/core/browser/autofill_test_utils.cc
+++ b/chromium/components/autofill/core/browser/autofill_test_utils.cc
@@ -113,7 +113,8 @@ void CreateTestAddressFormData(FormData* form,
const char* unique_id) {
form->name =
ASCIIToUTF16("MyForm") + ASCIIToUTF16(unique_id ? unique_id : "");
- form->button_title = ASCIIToUTF16("Submit");
+ form->button_titles = {std::make_pair(
+ ASCIIToUTF16("Submit"), ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
form->origin = GURL("http://myform.com/form.html");
form->action = GURL("http://myform.com/submit.html");
form->main_frame_origin =
@@ -714,15 +715,20 @@ std::string ObfuscatedCardDigitsAsUTF8(const std::string& str) {
internal::GetObfuscatedStringForCardDigits(base::ASCIIToUTF16(str)));
}
+std::string LastYear() {
+ base::Time::Exploded now;
+ base::Time::Now().LocalExplode(&now);
+ return std::to_string(now.year - 1);
+}
std::string NextYear() {
base::Time::Exploded now;
base::Time::Now().LocalExplode(&now);
return std::to_string(now.year + 1);
}
-std::string LastYear() {
+std::string TenYearsFromNow() {
base::Time::Exploded now;
base::Time::Now().LocalExplode(&now);
- return std::to_string(now.year - 1);
+ return std::to_string(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 2e7aebdac03..b67a11c3655 100644
--- a/chromium/components/autofill/core/browser/autofill_test_utils.h
+++ b/chromium/components/autofill/core/browser/autofill_test_utils.h
@@ -260,8 +260,9 @@ void GenerateTestAutofillPopup(
std::string ObfuscatedCardDigitsAsUTF8(const std::string& str);
-std::string NextYear();
std::string LastYear();
+std::string NextYear();
+std::string TenYearsFromNow();
} // namespace test
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.cc b/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.cc
index b4ab4196270..0459e25d4ff 100644
--- a/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.cc
+++ b/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.cc
@@ -22,10 +22,12 @@ AutofillWalletDataTypeController::AutofillWalletDataTypeController(
syncer::ModelType type,
scoped_refptr<base::SingleThreadTaskRunner> db_thread,
const base::Closure& dump_stack,
+ syncer::SyncService* sync_service,
syncer::SyncClient* sync_client,
const scoped_refptr<autofill::AutofillWebDataService>& web_data_service)
: AsyncDirectoryTypeController(type,
dump_stack,
+ sync_service,
sync_client,
syncer::GROUP_DB,
std::move(db_thread)),
@@ -34,7 +36,7 @@ AutofillWalletDataTypeController::AutofillWalletDataTypeController(
currently_enabled_(IsEnabled()) {
DCHECK(type == syncer::AUTOFILL_WALLET_DATA ||
type == syncer::AUTOFILL_WALLET_METADATA);
- pref_registrar_.Init(sync_client_->GetPrefService());
+ pref_registrar_.Init(sync_client->GetPrefService());
pref_registrar_.Add(
autofill::prefs::kAutofillWalletImportEnabled,
base::BindRepeating(&AutofillWalletDataTypeController::OnUserPrefChanged,
@@ -85,16 +87,16 @@ void AutofillWalletDataTypeController::StopModels() {
// cards and addresses copied from the server. This is different than other
// sync cases since this type of data reflects what's on the server rather
// than syncing local data between clients, so this extra step is required.
- syncer::SyncService* service = sync_client_->GetSyncService();
// CanSyncFeatureStart indicates if sync is currently enabled at all. The
// preferred data type indicates if wallet sync data is enabled, and
// currently_enabled_ indicates if the other prefs are enabled. All of these
// have to be enabled to sync wallet data.
- if (!service->CanSyncFeatureStart() ||
- !service->GetPreferredDataTypes().Has(type()) || !currently_enabled_) {
+ if (!sync_service()->CanSyncFeatureStart() ||
+ !sync_service()->GetPreferredDataTypes().Has(type()) ||
+ !currently_enabled_) {
autofill::PersonalDataManager* pdm =
- sync_client_->GetPersonalDataManager();
+ sync_client()->GetPersonalDataManager();
if (pdm)
pdm->ClearAllServerData();
}
@@ -117,8 +119,7 @@ void AutofillWalletDataTypeController::OnUserPrefChanged() {
if (currently_enabled_) {
// The preference was just enabled. Trigger a reconfiguration. This will do
// nothing if the type isn't preferred.
- syncer::SyncService* sync_service = sync_client_->GetSyncService();
- sync_service->ReenableDatatype(type());
+ sync_service()->ReenableDatatype(type());
} else {
DisableForPolicy();
}
@@ -128,9 +129,9 @@ bool AutofillWalletDataTypeController::IsEnabled() {
DCHECK(CalledOnValidThread());
// Require the user-visible pref to be enabled to sync Wallet data/metadata.
- return sync_client_->GetPrefService()->GetBoolean(
+ return sync_client()->GetPrefService()->GetBoolean(
autofill::prefs::kAutofillWalletImportEnabled) &&
- sync_client_->GetPrefService()->GetBoolean(
+ sync_client()->GetPrefService()->GetBoolean(
autofill::prefs::kAutofillCreditCardEnabled);
}
void AutofillWalletDataTypeController::DisableForPolicy() {
diff --git a/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.h b/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.h
index 481968919ce..837d293a4be 100644
--- a/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.h
+++ b/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.h
@@ -14,6 +14,11 @@ namespace autofill {
class AutofillWebDataService;
}
+namespace syncer {
+class SyncClient;
+class SyncService;
+} // namespace syncer
+
namespace browser_sync {
// Controls syncing of either AUTOFILL_WALLET or AUTOFILL_WALLET_METADATA.
@@ -26,6 +31,7 @@ class AutofillWalletDataTypeController
syncer::ModelType type,
scoped_refptr<base::SingleThreadTaskRunner> db_thread,
const base::Closure& dump_stack,
+ syncer::SyncService* sync_service,
syncer::SyncClient* sync_client,
const scoped_refptr<autofill::AutofillWebDataService>& web_data_service);
~AutofillWalletDataTypeController() override;
diff --git a/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller_unittest.cc b/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller_unittest.cc
index 7ab34935b5a..1d391861d1b 100644
--- a/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller_unittest.cc
@@ -11,9 +11,9 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/test/scoped_task_environment.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
@@ -25,6 +25,7 @@
#include "components/sync/driver/data_type_controller_mock.h"
#include "components/sync/driver/fake_generic_change_processor.h"
#include "components/sync/driver/fake_sync_client.h"
+#include "components/sync/driver/fake_sync_service.h"
#include "components/sync/driver/sync_api_component_factory_mock.h"
#include "components/sync/driver/sync_service.h"
#include "components/sync/model/fake_syncable_service.h"
@@ -94,7 +95,7 @@ class AutofillWalletDataTypeControllerTest : public testing::Test,
base::ThreadTaskRunnerHandle::Get());
autofill_wallet_dtc_ = std::make_unique<AutofillWalletDataTypeController>(
syncer::AUTOFILL_WALLET_DATA, base::ThreadTaskRunnerHandle::Get(),
- base::DoNothing(), this, web_data_service_);
+ base::DoNothing(), &sync_service_, this, web_data_service_);
last_type_ = syncer::UNSPECIFIED;
last_error_ = syncer::SyncError();
@@ -142,8 +143,9 @@ class AutofillWalletDataTypeControllerTest : public testing::Test,
last_error_ = error;
}
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
TestingPrefServiceSimple prefs_;
+ syncer::FakeSyncService sync_service_;
syncer::StartCallbackMock start_callback_;
syncer::SyncApiComponentFactoryMock profile_sync_factory_;
syncer::FakeSyncableService syncable_service_;
diff --git a/chromium/components/autofill/core/browser/autofill_wallet_model_type_controller.cc b/chromium/components/autofill/core/browser/autofill_wallet_model_type_controller.cc
index e0428315739..e725f1e87c9 100644
--- a/chromium/components/autofill/core/browser/autofill_wallet_model_type_controller.cc
+++ b/chromium/components/autofill/core/browser/autofill_wallet_model_type_controller.cc
@@ -10,7 +10,6 @@
#include "base/bind_helpers.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/prefs/pref_service.h"
-#include "components/sync/driver/sync_client.h"
#include "components/sync/driver/sync_service.h"
namespace browser_sync {
@@ -18,9 +17,11 @@ namespace browser_sync {
AutofillWalletModelTypeController::AutofillWalletModelTypeController(
syncer::ModelType type,
std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk,
- syncer::SyncClient* sync_client)
+ PrefService* pref_service,
+ syncer::SyncService* sync_service)
: ModelTypeController(type, std::move(delegate_on_disk)),
- sync_client_(sync_client) {
+ pref_service_(pref_service),
+ sync_service_(sync_service) {
DCHECK(type == syncer::AUTOFILL_WALLET_DATA ||
type == syncer::AUTOFILL_WALLET_METADATA);
currently_enabled_ = IsEnabled();
@@ -31,11 +32,13 @@ AutofillWalletModelTypeController::AutofillWalletModelTypeController(
syncer::ModelType type,
std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk,
std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_in_memory,
- syncer::SyncClient* sync_client)
+ PrefService* pref_service,
+ syncer::SyncService* sync_service)
: ModelTypeController(type,
std::move(delegate_on_disk),
std::move(delegate_in_memory)),
- sync_client_(sync_client) {
+ pref_service_(pref_service),
+ sync_service_(sync_service) {
DCHECK(type == syncer::AUTOFILL_WALLET_DATA ||
type == syncer::AUTOFILL_WALLET_METADATA);
currently_enabled_ = IsEnabled();
@@ -56,24 +59,22 @@ void AutofillWalletModelTypeController::OnUserPrefChanged() {
if (currently_enabled_ == newly_enabled) {
return; // No change to sync state.
}
- currently_enabled_ = newly_enabled;
- syncer::SyncService* sync_service = sync_client_->GetSyncService();
- sync_service->ReadyForStartChanged(type());
+ currently_enabled_ = newly_enabled;
+ sync_service_->ReadyForStartChanged(type());
}
bool AutofillWalletModelTypeController::IsEnabled() const {
DCHECK(CalledOnValidThread());
// Require two user-visible prefs to be enabled to sync Wallet data/metadata.
- return sync_client_->GetPrefService()->GetBoolean(
+ return pref_service_->GetBoolean(
autofill::prefs::kAutofillWalletImportEnabled) &&
- sync_client_->GetPrefService()->GetBoolean(
- autofill::prefs::kAutofillCreditCardEnabled);
+ pref_service_->GetBoolean(autofill::prefs::kAutofillCreditCardEnabled);
}
void AutofillWalletModelTypeController::SubscribeToPrefChanges() {
- pref_registrar_.Init(sync_client_->GetPrefService());
+ pref_registrar_.Init(pref_service_);
pref_registrar_.Add(
autofill::prefs::kAutofillWalletImportEnabled,
base::BindRepeating(&AutofillWalletModelTypeController::OnUserPrefChanged,
diff --git a/chromium/components/autofill/core/browser/autofill_wallet_model_type_controller.h b/chromium/components/autofill/core/browser/autofill_wallet_model_type_controller.h
index 5d0feacd9e5..1f9fcb50815 100644
--- a/chromium/components/autofill/core/browser/autofill_wallet_model_type_controller.h
+++ b/chromium/components/autofill/core/browser/autofill_wallet_model_type_controller.h
@@ -12,8 +12,10 @@
#include "components/prefs/pref_change_registrar.h"
#include "components/sync/driver/model_type_controller.h"
+class PrefService;
+
namespace syncer {
-class SyncClient;
+class SyncService;
}
namespace browser_sync {
@@ -26,12 +28,14 @@ class AutofillWalletModelTypeController : public syncer::ModelTypeController {
AutofillWalletModelTypeController(
syncer::ModelType type,
std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk,
- syncer::SyncClient* sync_client);
+ 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,
- syncer::SyncClient* sync_client);
+ PrefService* pref_service,
+ syncer::SyncService* sync_service);
~AutofillWalletModelTypeController() override;
// DataTypeController overrides.
@@ -44,7 +48,8 @@ class AutofillWalletModelTypeController : public syncer::ModelTypeController {
bool IsEnabled() const;
void SubscribeToPrefChanges();
- syncer::SyncClient* const sync_client_;
+ PrefService* const pref_service_;
+ syncer::SyncService* const sync_service_;
PrefChangeRegistrar pref_registrar_;
diff --git a/chromium/components/autofill/core/browser/country_data.cc b/chromium/components/autofill/core/browser/country_data.cc
index 90401b09aa4..a0c4e6a7a8f 100644
--- a/chromium/components/autofill/core/browser/country_data.cc
+++ b/chromium/components/autofill/core/browser/country_data.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/memory/singleton.h"
+#include "base/stl_util.h"
#include "components/strings/grit/components_strings.h"
#include "third_party/icu/source/common/unicode/locid.h"
@@ -782,7 +783,7 @@ const StaticCountryData kCountryData[] = {
// based on |kCountryData|.
std::vector<std::string> GetCountryCodes() {
std::vector<std::string> country_codes;
- country_codes.reserve(arraysize(kCountryData));
+ country_codes.reserve(base::size(kCountryData));
for (const auto& static_data : kCountryData) {
country_codes.push_back(static_data.country_code);
}
diff --git a/chromium/components/autofill/core/browser/credit_card.cc b/chromium/components/autofill/core/browser/credit_card.cc
index aa254d955cb..139dca405e1 100644
--- a/chromium/components/autofill/core/browser/credit_card.cc
+++ b/chromium/components/autofill/core/browser/credit_card.cc
@@ -332,6 +332,11 @@ bool CreditCard::SetMetadata(const AutofillMetadata metadata) {
return true;
}
+bool CreditCard::IsDeletable() const {
+ return AutofillDataModel::IsDeletable() &&
+ IsExpired(AutofillClock::Now() - kDisusedDataModelDeletionTimeDelta);
+}
+
base::string16 CreditCard::GetRawInfo(ServerFieldType type) const {
DCHECK_EQ(CREDIT_CARD, AutofillType(type).group());
switch (type) {
@@ -587,8 +592,7 @@ int CreditCard::Compare(const CreditCard& credit_card) const {
// The following CreditCard field types are the only types we store in the
// WebDB so far, so we're only concerned with matching these types in the
// credit card.
- const ServerFieldType types[] = {CREDIT_CARD_NAME_FULL, CREDIT_CARD_NUMBER,
- CREDIT_CARD_EXP_MONTH,
+ const ServerFieldType types[] = {CREDIT_CARD_NAME_FULL, CREDIT_CARD_EXP_MONTH,
CREDIT_CARD_EXP_4_DIGIT_YEAR};
for (ServerFieldType type : types) {
int comparison = GetRawInfo(type).compare(credit_card.GetRawInfo(type));
@@ -596,6 +600,10 @@ int CreditCard::Compare(const CreditCard& credit_card) const {
return comparison;
}
+ if (!HasSameNumberAs(credit_card)) {
+ return number().compare(credit_card.number());
+ }
+
int comparison = server_id_.compare(credit_card.server_id_);
if (comparison != 0)
return comparison;
@@ -614,11 +622,13 @@ int CreditCard::Compare(const CreditCard& credit_card) const {
if (static_cast<int>(server_status_) >
static_cast<int>(credit_card.server_status_))
return 1;
- if (static_cast<int>(record_type_) <
- static_cast<int>(credit_card.record_type_))
+
+ // Do not distinguish masked server cards from full server cards as this is
+ // not needed and not desired - we want to identify masked server card from
+ // sync with the (potential) full server card stored locally.
+ if (record_type_ == LOCAL_CARD && credit_card.record_type_ != LOCAL_CARD)
return -1;
- if (static_cast<int>(record_type_) >
- static_cast<int>(credit_card.record_type_))
+ if (record_type_ != LOCAL_CARD && credit_card.record_type_ == LOCAL_CARD)
return 1;
return 0;
}
@@ -655,8 +665,8 @@ bool CreditCard::HasSameNumberAs(const CreditCard& other) const {
}
bool CreditCard::operator==(const CreditCard& credit_card) const {
- return guid() == credit_card.guid() &&
- origin() == credit_card.origin() &&
+ return guid() == credit_card.guid() && origin() == credit_card.origin() &&
+ record_type() == credit_card.record_type() &&
Compare(credit_card) == 0;
}
@@ -1019,7 +1029,11 @@ bool CreditCard::ShouldUpdateExpiration(const base::Time& current_time) const {
// So we can compare CreditCards with EXPECT_EQ().
std::ostream& operator<<(std::ostream& os, const CreditCard& credit_card) {
return os << base::UTF16ToUTF8(credit_card.Label()) << " "
- << credit_card.guid() << " " << credit_card.origin() << " "
+ << (credit_card.record_type() == CreditCard::LOCAL_CARD
+ ? credit_card.guid()
+ : base::HexEncode(credit_card.server_id().data(),
+ credit_card.server_id().size()))
+ << " " << credit_card.origin() << " "
<< base::UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_NAME_FULL))
<< " "
<< base::UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_TYPE))
@@ -1027,8 +1041,13 @@ std::ostream& operator<<(std::ostream& os, const CreditCard& credit_card) {
<< base::UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_NUMBER))
<< " "
<< base::UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_EXP_MONTH))
- << " " << base::UTF16ToUTF8(
- credit_card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
+ << " "
+ << base::UTF16ToUTF8(
+ credit_card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR))
+ << " " << credit_card.bank_name() << " "
+ << " " << credit_card.record_type() << " "
+ << credit_card.use_count() << " " << credit_card.use_date() << " "
+ << credit_card.billing_address_id();
}
void CreditCard::SetNameOnCardFromSeparateParts() {
diff --git a/chromium/components/autofill/core/browser/credit_card.h b/chromium/components/autofill/core/browser/credit_card.h
index 5c73b863c69..deff6364ddc 100644
--- a/chromium/components/autofill/core/browser/credit_card.h
+++ b/chromium/components/autofill/core/browser/credit_card.h
@@ -48,8 +48,8 @@ class CreditCard : public AutofillDataModel {
// convert to a FULL_SERVER_CARD.
MASKED_SERVER_CARD,
- // A card from the Wallet server with full information. This card is not
- // locally editable.
+ // A card from the Wallet server with full information store locally. This
+ // card is not locally editable.
FULL_SERVER_CARD,
};
@@ -111,6 +111,9 @@ class CreditCard : public AutofillDataModel {
// AutofillDataModel:
AutofillMetadata GetMetadata() const override;
bool SetMetadata(const AutofillMetadata metadata) override;
+ // Returns whether the card is deletable: if it is expired and has not been
+ // used for longer than |kDisusedCreditCardDeletionTimeDelta|.
+ bool IsDeletable() const override;
// FormGroup:
void GetMatchingTypes(const base::string16& text,
@@ -154,7 +157,8 @@ class CreditCard : public AutofillDataModel {
// duplicates. The ordering is based on collation order of the textual
// contents of the fields.
// GUIDs, origins, labels, and unique IDs are not compared, only the values of
- // the cards themselves.
+ // the cards themselves. A full card is equivalent to its corresponding masked
+ // card.
int Compare(const CreditCard& credit_card) const;
// Determines if |this| is a local version of the server card |other|.
diff --git a/chromium/components/autofill/core/browser/credit_card_field.cc b/chromium/components/autofill/core/browser/credit_card_field.cc
index a0c484b8dd9..fb1f8bf9914 100644
--- a/chromium/components/autofill/core/browser/credit_card_field.cc
+++ b/chromium/components/autofill/core/browser/credit_card_field.cc
@@ -85,8 +85,7 @@ std::unique_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
if (scanner->IsEnd())
return nullptr;
- // Using 'new' to access private constructor.
- auto credit_card_field = base::WrapUnique(new CreditCardField());
+ auto credit_card_field = std::make_unique<CreditCardField>();
size_t saved_cursor = scanner->SaveCursor();
int nb_unknown_fields = 0;
diff --git a/chromium/components/autofill/core/browser/credit_card_field.h b/chromium/components/autofill/core/browser/credit_card_field.h
index 3d462507fb7..b1bbbe022d1 100644
--- a/chromium/components/autofill/core/browser/credit_card_field.h
+++ b/chromium/components/autofill/core/browser/credit_card_field.h
@@ -20,6 +20,7 @@ class AutofillScanner;
class CreditCardField : public FormField {
public:
+ CreditCardField();
~CreditCardField() override;
static std::unique_ptr<FormField> Parse(AutofillScanner* scanner);
@@ -48,8 +49,6 @@ class CreditCardField : public FormField {
// a credit card.
static bool IsGiftCardField(AutofillScanner* scanner);
- CreditCardField();
-
// Parses the expiration month/year/date fields. Returns true if it finds
// something new.
bool ParseExpirationDate(AutofillScanner* scanner);
diff --git a/chromium/components/autofill/core/browser/credit_card_field_unittest.cc b/chromium/components/autofill/core/browser/credit_card_field_unittest.cc
index 8cc36860260..f701a390212 100644
--- a/chromium/components/autofill/core/browser/credit_card_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/credit_card_field_unittest.cc
@@ -34,7 +34,8 @@ class CreditCardFieldTestBase {
void Parse() {
AutofillScanner scanner(list_);
std::unique_ptr<FormField> field = CreditCardField::Parse(&scanner);
- field_ = base::WrapUnique(static_cast<CreditCardField*>(field.release()));
+ field_ = std::unique_ptr<CreditCardField>(
+ static_cast<CreditCardField*>(field.release()));
}
void MultipleParses() {
@@ -43,7 +44,8 @@ class CreditCardFieldTestBase {
AutofillScanner scanner(list_);
while (!scanner.IsEnd()) {
field = CreditCardField::Parse(&scanner);
- field_ = base::WrapUnique(static_cast<CreditCardField*>(field.release()));
+ field_ = std::unique_ptr<CreditCardField>(
+ static_cast<CreditCardField*>(field.release()));
if (field_ == nullptr) {
scanner.Advance();
} else {
diff --git a/chromium/components/autofill/core/browser/credit_card_save_manager.cc b/chromium/components/autofill/core/browser/credit_card_save_manager.cc
index 26ec8b15c7b..cef57c082f9 100644
--- a/chromium/components/autofill/core/browser/credit_card_save_manager.cc
+++ b/chromium/components/autofill/core/browser/credit_card_save_manager.cc
@@ -36,6 +36,7 @@
#include "components/autofill/core/browser/payments/payments_client.h"
#include "components/autofill/core/browser/payments/payments_util.h"
#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/strike_database.h"
#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_constants.h"
@@ -82,7 +83,17 @@ CreditCardSaveManager::CreditCardSaveManager(
payments_client_(payments_client),
app_locale_(app_locale),
personal_data_manager_(personal_data_manager),
- weak_ptr_factory_(this) {}
+ weak_ptr_factory_(this) {
+ // 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 CCSM is created.
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2)) {
+ // Only init when |kAutofillSaveCreditCardUsesStrikeSystemV2| is enabled. If
+ // flag is off and LegacyStrikeDatabase instead of StrikeDatabase is used,
+ // this init will cause failure on GetStrikes().
+ client_->GetStrikeDatabase();
+ }
+}
CreditCardSaveManager::~CreditCardSaveManager() {}
@@ -91,10 +102,14 @@ void CreditCardSaveManager::AttemptToOfferCardLocalSave(
local_card_save_candidate_ = card;
show_save_prompt_ = base::nullopt;
- // Query the Autofill LegacyStrikeDatabase on if we should pop up the
+ // Query the Autofill StrikeDatabase on if we should pop up the
// offer-to-save prompt for this card.
if (base::FeatureList::IsEnabled(
- features::kAutofillSaveCreditCardUsesStrikeSystem)) {
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2)) {
+ OnDidGetStrikesForLocalSave(GetCreditCardSaveStrikeDatabase()->GetStrikes(
+ base::UTF16ToUTF8(local_card_save_candidate_.LastFourDigits())));
+ } else if (base::FeatureList::IsEnabled(
+ features::kAutofillSaveCreditCardUsesStrikeSystem)) {
LegacyStrikeDatabase* strike_database = client_->GetLegacyStrikeDatabase();
strike_database->GetStrikes(
strike_database->GetKeyForCreditCardSave(
@@ -231,11 +246,16 @@ void CreditCardSaveManager::AttemptToOfferCardUploadSave(
app_locale_,
base::BindOnce(&CreditCardSaveManager::OnDidGetUploadDetails,
weak_ptr_factory_.GetWeakPtr()),
- payments::kUploadCardBillableServiceNumber);
- // Query the Autofill LegacyStrikeDatabase on if we should pop up the
+ payments::kUploadCardBillableServiceNumber,
+ payments::PaymentsClient::UploadCardSource::UPSTREAM_CHECKOUT_FLOW);
+ // Query the Autofill StrikeDatabase on if we should pop up the
// offer-to-save prompt for this card.
if (base::FeatureList::IsEnabled(
- features::kAutofillSaveCreditCardUsesStrikeSystem)) {
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2)) {
+ OnDidGetStrikesForUploadSave(GetCreditCardSaveStrikeDatabase()->GetStrikes(
+ base::UTF16ToUTF8(upload_request_.card.LastFourDigits())));
+ } else if (base::FeatureList::IsEnabled(
+ features::kAutofillSaveCreditCardUsesStrikeSystem)) {
LegacyStrikeDatabase* strike_database = client_->GetLegacyStrikeDatabase();
strike_database->GetStrikes(
strike_database->GetKeyForCreditCardSave(
@@ -251,12 +271,16 @@ void CreditCardSaveManager::AttemptToOfferCardUploadSave(
}
bool CreditCardSaveManager::IsCreditCardUploadEnabled() {
+#if defined(OS_IOS)
// If observer_for_testing_ is set, assume we are in a browsertest and
// credit card upload should be enabled by default.
- return observer_for_testing_ ||
- ::autofill::IsCreditCardUploadEnabled(
- client_->GetPrefs(), client_->GetSyncService(),
- personal_data_manager_->GetAccountInfoForPaymentsServer().email);
+ // TODO(crbug.com/859761): Remove dependency from iOS tests on this behavior.
+ if (observer_for_testing_)
+ return true;
+#endif // defined(OS_IOS)
+ return ::autofill::IsCreditCardUploadEnabled(
+ client_->GetPrefs(), client_->GetSyncService(),
+ personal_data_manager_->GetAccountInfoForPaymentsServer().email);
}
bool CreditCardSaveManager::IsUploadEnabledForNetwork(
@@ -287,7 +311,8 @@ void CreditCardSaveManager::OnDidUploadCard(
if (result == AutofillClient::SUCCESS) {
// If the upload succeeds and we can store unmasked cards on this OS, we
// will keep a copy of the card as a full server card on the device.
- if (!server_id.empty() && OfferStoreUnmaskedCards() &&
+ if (!server_id.empty() &&
+ OfferStoreUnmaskedCards(payments_client_->is_off_the_record()) &&
!IsAutofillNoLocalSaveOnUploadSuccessExperimentEnabled()) {
upload_request_.card.set_record_type(CreditCard::FULL_SERVER_CARD);
upload_request_.card.SetServerStatus(CreditCard::OK);
@@ -297,7 +322,17 @@ void CreditCardSaveManager::OnDidUploadCard(
personal_data_manager_->AddFullServerCreditCard(upload_request_.card);
}
if (base::FeatureList::IsEnabled(
- features::kAutofillSaveCreditCardUsesStrikeSystem)) {
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2)) {
+ // Log how many strikes the card had when it was saved.
+ LogStrikesPresentWhenCardSaved(
+ /*is_local=*/false,
+ GetCreditCardSaveStrikeDatabase()->GetStrikes(
+ base::UTF16ToUTF8(upload_request_.card.LastFourDigits())));
+ // Clear all strikes for this card, in case it is later removed.
+ GetCreditCardSaveStrikeDatabase()->ClearStrikes(
+ base::UTF16ToUTF8(upload_request_.card.LastFourDigits()));
+ } else if (base::FeatureList::IsEnabled(
+ features::kAutofillSaveCreditCardUsesStrikeSystem)) {
LegacyStrikeDatabase* strike_database =
client_->GetLegacyStrikeDatabase();
// Log how many strikes the card had when it was saved.
@@ -315,22 +350,40 @@ void CreditCardSaveManager::OnDidUploadCard(
base::DoNothing());
}
} else {
- if (base::FeatureList::IsEnabled(
- features::kAutofillSaveCreditCardUsesStrikeSystem) &&
- 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.
- LegacyStrikeDatabase* strike_database =
- client_->GetLegacyStrikeDatabase();
- strike_database->AddStrike(
- strike_database->GetKeyForCreditCardSave(
- base::UTF16ToUTF8(upload_request_.card.LastFourDigits())),
- base::BindRepeating(&CreditCardSaveManager::OnStrikeChangeComplete,
- weak_ptr_factory_.GetWeakPtr()));
+ if (show_save_prompt_.value()) {
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2)) {
+ // 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.
+ int nth_strike_added = GetCreditCardSaveStrikeDatabase()->AddStrike(
+ base::UTF16ToUTF8(upload_request_.card.LastFourDigits()));
+ // Notify the browsertests that a strike was added.
+ OnStrikeChangeComplete(nth_strike_added);
+ } else if (base::FeatureList::IsEnabled(
+ features::kAutofillSaveCreditCardUsesStrikeSystem)) {
+ // 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.
+ LegacyStrikeDatabase* strike_database =
+ client_->GetLegacyStrikeDatabase();
+ strike_database->AddStrike(
+ strike_database->GetKeyForCreditCardSave(
+ base::UTF16ToUTF8(upload_request_.card.LastFourDigits())),
+ base::BindRepeating(&CreditCardSaveManager::OnStrikeChangeComplete,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
}
}
}
+CreditCardSaveStrikeDatabase*
+CreditCardSaveManager::GetCreditCardSaveStrikeDatabase() {
+ if (strike_database_.get() == nullptr) {
+ strike_database_ = std::make_unique<CreditCardSaveStrikeDatabase>(
+ CreditCardSaveStrikeDatabase(client_->GetStrikeDatabase()));
+ }
+ return strike_database_.get();
+}
+
void CreditCardSaveManager::OnDidGetStrikesForLocalSave(const int num_strikes) {
show_save_prompt_ =
num_strikes < kMaxStrikesToPreventPoppingUpOfferToSavePrompt;
@@ -354,14 +407,14 @@ void CreditCardSaveManager::OnDidGetStrikesForUploadSave(
void CreditCardSaveManager::OnDidGetUploadDetails(
AutofillClient::PaymentsRpcResult result,
const base::string16& context_token,
- std::unique_ptr<base::DictionaryValue> legal_message) {
+ std::unique_ptr<base::Value> legal_message) {
if (observer_for_testing_)
observer_for_testing_->OnReceivedGetUploadDetailsResponse();
if (result == AutofillClient::SUCCESS) {
// Do *not* call payments_client_->Prepare() here. We shouldn't send
// credentials until the user has explicitly accepted a prompt to upload.
upload_request_.context_token = context_token;
- legal_message_ = std::move(legal_message);
+ legal_message_ = base::DictionaryValue::From(std::move(legal_message));
// Only offer upload once both Payments and the Autofill
// LegacyStrikeDatabase have returned their decisions. Use presence of
@@ -415,7 +468,7 @@ void CreditCardSaveManager::OfferCardLocalSave() {
observer_for_testing_->OnOfferLocalSave();
client_->ConfirmSaveCreditCardLocally(
local_card_save_candidate_, show_save_prompt_.value(),
- base::BindOnce(&CreditCardSaveManager::OnUserDidAcceptLocalSave,
+ base::BindOnce(&CreditCardSaveManager::OnUserDidDecideOnLocalSave,
weak_ptr_factory_.GetWeakPtr()));
// Log metrics.
@@ -446,7 +499,7 @@ void CreditCardSaveManager::OfferCardUploadSave() {
upload_request_.card, std::move(legal_message_),
should_request_name_from_user_,
should_request_expiration_date_from_user_, show_save_prompt_.value(),
- base::BindOnce(&CreditCardSaveManager::OnUserDidAcceptUpload,
+ base::BindOnce(&CreditCardSaveManager::OnUserDidDecideOnUploadSave,
weak_ptr_factory_.GetWeakPtr()));
client_->LoadRiskData(
base::BindOnce(&CreditCardSaveManager::OnDidGetUploadRiskData,
@@ -475,30 +528,51 @@ void CreditCardSaveManager::OfferCardUploadSave() {
}
}
-void CreditCardSaveManager::OnUserDidAcceptLocalSave() {
- if (local_card_save_candidate_.HasFirstAndLastName())
- AutofillMetrics::LogSaveCardWithFirstAndLastNameComplete(/*is_local=*/true);
+void CreditCardSaveManager::OnUserDidDecideOnLocalSave(
+ AutofillClient::SaveCardOfferUserDecision user_decision) {
+ switch (user_decision) {
+ case AutofillClient::ACCEPTED:
+ if (local_card_save_candidate_.HasFirstAndLastName())
+ AutofillMetrics::LogSaveCardWithFirstAndLastNameComplete(
+ /*is_local=*/true);
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2)) {
+ // Log how many strikes the card had when it was saved.
+ LogStrikesPresentWhenCardSaved(
+ /*is_local=*/true,
+ GetCreditCardSaveStrikeDatabase()->GetStrikes(base::UTF16ToUTF8(
+ local_card_save_candidate_.LastFourDigits())));
+ // Clear all strikes for this card, in case it is later removed.
+ GetCreditCardSaveStrikeDatabase()->ClearStrikes(
+ base::UTF16ToUTF8(local_card_save_candidate_.LastFourDigits()));
+ } else if (base::FeatureList::IsEnabled(
+ features::kAutofillSaveCreditCardUsesStrikeSystem)) {
+ LegacyStrikeDatabase* strike_database =
+ client_->GetLegacyStrikeDatabase();
+ // Log how many strikes the card had when it was saved.
+ strike_database->GetStrikes(
+ strike_database->GetKeyForCreditCardSave(
+ base::UTF16ToUTF8(local_card_save_candidate_.LastFourDigits())),
+ base::BindRepeating(
+ &CreditCardSaveManager::LogStrikesPresentWhenCardSaved,
+ weak_ptr_factory_.GetWeakPtr(),
+ /*is_local=*/true));
+ // Clear all strikes for this card, in case it is later removed.
+ strike_database->ClearAllStrikesForKey(
+ strike_database->GetKeyForCreditCardSave(
+ base::UTF16ToUTF8(local_card_save_candidate_.LastFourDigits())),
+ base::DoNothing());
+ }
- if (base::FeatureList::IsEnabled(
- features::kAutofillSaveCreditCardUsesStrikeSystem)) {
- LegacyStrikeDatabase* strike_database = client_->GetLegacyStrikeDatabase();
- // Log how many strikes the card had when it was saved.
- strike_database->GetStrikes(
- strike_database->GetKeyForCreditCardSave(
- base::UTF16ToUTF8(local_card_save_candidate_.LastFourDigits())),
- base::BindRepeating(
- &CreditCardSaveManager::LogStrikesPresentWhenCardSaved,
- weak_ptr_factory_.GetWeakPtr(),
- /*is_local=*/true));
- // Clear all strikes for this card, in case it is later removed.
- strike_database->ClearAllStrikesForKey(
- strike_database->GetKeyForCreditCardSave(
- base::UTF16ToUTF8(local_card_save_candidate_.LastFourDigits())),
- base::DoNothing());
- }
+ personal_data_manager_->OnAcceptedLocalCreditCardSave(
+ local_card_save_candidate_);
+ break;
- personal_data_manager_->OnAcceptedLocalCreditCardSave(
- local_card_save_candidate_);
+ case AutofillClient::DECLINED:
+ case AutofillClient::IGNORED:
+ OnUserDidIgnoreOrDeclineSave(local_card_save_candidate_.LastFourDigits());
+ break;
+ }
}
void CreditCardSaveManager::LogStrikesPresentWhenCardSaved(
@@ -739,21 +813,30 @@ int CreditCardSaveManager::GetDetectedValues() const {
return detected_values;
}
-void CreditCardSaveManager::OnUserDidAcceptUpload(
+void CreditCardSaveManager::OnUserDidDecideOnUploadSave(
+ AutofillClient::SaveCardOfferUserDecision user_decision,
const AutofillClient::UserProvidedCardDetails& user_provided_card_details) {
+ switch (user_decision) {
+ case AutofillClient::ACCEPTED:
// On Android, requesting cardholder name is a two step flow.
#if defined(OS_ANDROID)
- if (should_request_name_from_user_) {
- client_->ConfirmAccountNameFixFlow(
- base::BindOnce(
+ if (should_request_name_from_user_) {
+ client_->ConfirmAccountNameFixFlow(base::BindOnce(
&CreditCardSaveManager::OnUserDidAcceptAccountNameFixFlow,
weak_ptr_factory_.GetWeakPtr()));
- } else {
- OnUserDidAcceptUploadHelper(user_provided_card_details);
- }
+ } else {
+ OnUserDidAcceptUploadHelper(user_provided_card_details);
+ }
#else
- OnUserDidAcceptUploadHelper(user_provided_card_details);
+ OnUserDidAcceptUploadHelper(user_provided_card_details);
#endif
+ break;
+
+ case AutofillClient::DECLINED:
+ case AutofillClient::IGNORED:
+ OnUserDidIgnoreOrDeclineSave(upload_request_.card.LastFourDigits());
+ break;
+ }
personal_data_manager_->OnUserAcceptedUpstreamOffer();
}
@@ -828,9 +911,36 @@ void CreditCardSaveManager::SendUploadCardRequest() {
weak_ptr_factory_.GetWeakPtr()));
}
+void CreditCardSaveManager::OnUserDidIgnoreOrDeclineSave(
+ const base::string16& card_last_four_digits) {
+ if (show_save_prompt_.value()) {
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2)) {
+ // If the user rejected or ignored save and the offer-to-save bubble or
+ // infobar was actually shown (NOT just the icon if on desktop), count
+ // that as a strike against offering upload in the future.
+ int nth_strike_added = GetCreditCardSaveStrikeDatabase()->AddStrike(
+ base::UTF16ToUTF8(card_last_four_digits));
+ OnStrikeChangeComplete(nth_strike_added);
+ } else if (base::FeatureList::IsEnabled(
+ features::kAutofillSaveCreditCardUsesStrikeSystem)) {
+ // If the user rejected or ignored save and the offer-to-save bubble or
+ // infobar was actually shown (NOT just the icon if on desktop), count
+ // that as a strike against offering upload in the future.
+ LegacyStrikeDatabase* strike_database =
+ client_->GetLegacyStrikeDatabase();
+ strike_database->AddStrike(
+ strike_database->GetKeyForCreditCardSave(
+ base::UTF16ToUTF8(card_last_four_digits)),
+ base::BindRepeating(&CreditCardSaveManager::OnStrikeChangeComplete,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+ }
+}
+
void CreditCardSaveManager::OnStrikeChangeComplete(const int num_strikes) {
if (observer_for_testing_)
- observer_for_testing_->OnCCSMStrikeChangeComplete();
+ observer_for_testing_->OnStrikeChangeComplete();
}
AutofillMetrics::CardUploadDecisionMetric
diff --git a/chromium/components/autofill/core/browser/credit_card_save_manager.h b/chromium/components/autofill/core/browser/credit_card_save_manager.h
index e851ae8bfab..a1ae70e31ff 100644
--- a/chromium/components/autofill/core/browser/credit_card_save_manager.h
+++ b/chromium/components/autofill/core/browser/credit_card_save_manager.h
@@ -16,6 +16,7 @@
#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/credit_card_save_strike_database.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/payments/payments_client.h"
#include "components/autofill/core/browser/personal_data_manager.h"
@@ -81,7 +82,7 @@ class CreditCardSaveManager {
virtual void OnReceivedGetUploadDetailsResponse() = 0;
virtual void OnSentUploadCardRequest() = 0;
virtual void OnReceivedUploadCardResponse() = 0;
- virtual void OnCCSMStrikeChangeComplete() = 0;
+ virtual void OnStrikeChangeComplete() = 0;
};
// The parameters should outlive the CreditCardSaveManager.
@@ -123,7 +124,11 @@ class CreditCardSaveManager {
private:
friend class CreditCardSaveManagerTest;
friend class CreditCardSaveManagerTestObserverBridge;
- friend class SaveCardBubbleViewsBrowserTestBase;
+ friend class TestCreditCardSaveManager;
+ friend class SaveCardBubbleViewsFullFormBrowserTest;
+
+ // Returns the CreditCardSaveStrikeDatabase for |client_|.
+ CreditCardSaveStrikeDatabase* GetCreditCardSaveStrikeDatabase();
// Sets |show_save_prompt| and moves forward with offering credit card local
// save.
@@ -136,10 +141,9 @@ class CreditCardSaveManager {
// Returns the legal message retrieved from Payments. On failure or not
// meeting Payments's conditions for upload, |legal_message| will contain
// nullptr.
- void OnDidGetUploadDetails(
- AutofillClient::PaymentsRpcResult result,
- const base::string16& context_token,
- std::unique_ptr<base::DictionaryValue> legal_message);
+ void OnDidGetUploadDetails(AutofillClient::PaymentsRpcResult result,
+ const base::string16& context_token,
+ std::unique_ptr<base::Value> legal_message);
// Logs the number of strikes that a card had when save succeeded.
void LogStrikesPresentWhenCardSaved(bool is_local, const int num_strikes);
@@ -169,18 +173,27 @@ class CreditCardSaveManager {
// Autofill StrikeSystem has made its decision.
void OfferCardUploadSave();
- // Clears strikes for the to-be-saved card and has |personal_data_manager_|
- // save the card.
- void OnUserDidAcceptLocalSave();
-
- // Sets |user_did_accept_upload_prompt_| and calls SendUploadCardRequest if
- // the risk data is available. Sets the cardholder name on the upload request
- // if |user_provided_card_details.cardholder_name| is set. Sets the expiration
- // date on the upload request if
- // |user_provided_card_details.expiration_date_month| and
- // |user_provided_card_details.expiration_date_year| are both set.
- void OnUserDidAcceptUpload(const AutofillClient::UserProvidedCardDetails&
- user_provided_card_details);
+ // Called once the user makes a decision with respect to the local credit card
+ // offer-to-save prompt. If accepted, clears strikes for the to-be-saved card
+ // and has |personal_data_manager_| save the card.
+ void OnUserDidDecideOnLocalSave(
+ AutofillClient::SaveCardOfferUserDecision user_decision);
+
+ // Called once the user makes a decision with respect to the credit card
+ // upload offer-to-save prompt.
+ // If accepted:
+ // Sets |user_did_accept_upload_prompt_| and calls SendUploadCardRequest if
+ // the risk data is available. Sets the cardholder name on the upload
+ // request if |user_provided_card_details.cardholder_name| is set. Sets the
+ // expiration date on the upload request if
+ // |user_provided_card_details.expiration_date_month| and
+ // |user_provided_card_details.expiration_date_year| are both set.
+ // If rejected or ignored:
+ // Logs a strike against the current card to deter future offers to save.
+ void OnUserDidDecideOnUploadSave(
+ AutofillClient::SaveCardOfferUserDecision user_decision,
+ const AutofillClient::UserProvidedCardDetails&
+ user_provided_card_details);
#if defined(OS_ANDROID)
// Sets |user_did_accept_upload_prompt_| and calls SendUploadCardRequest if
@@ -204,6 +217,12 @@ class CreditCardSaveManager {
// Finalizes the upload request and calls PaymentsClient::UploadCard().
void SendUploadCardRequest();
+ // Called when the user ignored or declined the credit card save prompt. Logs
+ // a strike for the given card in order to help deter future offers to save,
+ // provided that save was actually offered to the user.
+ void OnUserDidIgnoreOrDeclineSave(
+ const base::string16& card_last_four_digits);
+
// Used for browsertests. Gives the |observer_for_testing_| a notification
// a strike change has been made.
void OnStrikeChangeComplete(const int num_strikes);
@@ -289,6 +308,8 @@ class CreditCardSaveManager {
// The returned legal message from a GetUploadDetails call to Google Payments.
std::unique_ptr<base::DictionaryValue> legal_message_;
+ std::unique_ptr<CreditCardSaveStrikeDatabase> strike_database_;
+
// May be null.
ObserverForTest* observer_for_testing_ = nullptr;
diff --git a/chromium/components/autofill/core/browser/credit_card_save_manager_unittest.cc b/chromium/components/autofill/core/browser/credit_card_save_manager_unittest.cc
index d8706dba442..ef3e151e073 100644
--- a/chromium/components/autofill/core/browser/credit_card_save_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/credit_card_save_manager_unittest.cc
@@ -27,6 +27,7 @@
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/mock_autocomplete_history_manager.h"
#include "components/autofill/core/browser/payments/test_payments_client.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/test_autofill_client.h"
@@ -34,6 +35,7 @@
#include "components/autofill/core/browser/test_autofill_driver.h"
#include "components/autofill/core/browser/test_autofill_manager.h"
#include "components/autofill/core/browser/test_credit_card_save_manager.h"
+#include "components/autofill/core/browser/test_credit_card_save_strike_database.h"
#include "components/autofill/core/browser/test_form_data_importer.h"
#include "components/autofill/core/browser/test_legacy_strike_database.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
@@ -99,12 +101,17 @@ class MockPersonalDataManager : public TestPersonalDataManager {
class CreditCardSaveManagerTest : public testing::Test {
public:
void SetUp() override {
- std::unique_ptr<TestLegacyStrikeDatabase> test_strike_database =
+ std::unique_ptr<TestLegacyStrikeDatabase> test_legacy_strike_database =
std::make_unique<TestLegacyStrikeDatabase>();
- legacy_strike_database_ = test_strike_database.get();
+ legacy_strike_database_ = test_legacy_strike_database.get();
autofill_client_.SetPrefs(test::PrefServiceForTesting());
+ autofill_client_.set_test_legacy_strike_database(
+ std::move(test_legacy_strike_database));
+ std::unique_ptr<TestStrikeDatabase> test_strike_database =
+ std::make_unique<TestStrikeDatabase>();
+ strike_database_ = test_strike_database.get();
autofill_client_.set_test_strike_database(std::move(test_strike_database));
- personal_data_.Init(/*profile_database=*/autofill_client_.GetDatabase(),
+ personal_data_.Init(/*profile_database=*/database_,
/*account_database=*/nullptr,
/*pref_service=*/autofill_client_.GetPrefs(),
/*identity_manager=*/nullptr,
@@ -113,6 +120,9 @@ class CreditCardSaveManagerTest : public testing::Test {
/*cookie_manager_sevice=*/nullptr,
/*is_off_the_record=*/false);
personal_data_.SetSyncServiceForTest(&sync_service_);
+ autocomplete_history_manager_.Init(
+ /*profile_database=*/database_,
+ /*is_off_the_record=*/false);
autofill_driver_.reset(new TestAutofillDriver());
request_context_ = new net::TestURLRequestContextGetter(
base::ThreadTaskRunnerHandle::Get());
@@ -133,8 +143,10 @@ class CreditCardSaveManagerTest : public testing::Test {
&personal_data_, "en-US");
autofill_client_.set_test_form_data_importer(
std::unique_ptr<TestFormDataImporter>(test_form_data_importer));
+ autofill_client_.GetStrikeDatabase();
autofill_manager_.reset(new TestAutofillManager(
- autofill_driver_.get(), &autofill_client_, &personal_data_));
+ autofill_driver_.get(), &autofill_client_, &personal_data_,
+ &autocomplete_history_manager_));
autofill_manager_->SetExpectedObservedSubmission(true);
}
@@ -155,14 +167,14 @@ class CreditCardSaveManagerTest : public testing::Test {
}
void FormSubmitted(const FormData& form) {
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, base::TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
}
void UserHasAcceptedUpload(
AutofillClient::UserProvidedCardDetails user_provided_card_details) {
- credit_card_save_manager_->OnUserDidAcceptUpload(
- user_provided_card_details);
+ credit_card_save_manager_->OnUserDidDecideOnUploadSave(
+ AutofillClient::ACCEPTED, user_provided_card_details);
}
// Populates |form| with data corresponding to a simple credit card form.
@@ -322,7 +334,9 @@ class CreditCardSaveManagerTest : public testing::Test {
std::unique_ptr<TestAutofillDriver> autofill_driver_;
std::unique_ptr<TestAutofillManager> autofill_manager_;
scoped_refptr<net::TestURLRequestContextGetter> request_context_;
+ scoped_refptr<AutofillWebDataService> database_;
MockPersonalDataManager personal_data_;
+ MockAutocompleteHistoryManager autocomplete_history_manager_;
syncer::TestSyncService sync_service_;
base::test::ScopedFeatureList scoped_feature_list_;
// Ends up getting owned (and destroyed) by TestFormDataImporter:
@@ -331,6 +345,8 @@ class CreditCardSaveManagerTest : public testing::Test {
payments::TestPaymentsClient* payments_client_;
// Ends up getting owned (and destroyed) by TestAutofillClient:
TestLegacyStrikeDatabase* legacy_strike_database_;
+ // Ends up getting owned (and destroyed) by TestAutofillClient:
+ TestStrikeDatabase* strike_database_;
private:
int ToHistogramSample(AutofillMetrics::CardUploadDecisionMetric metric) {
@@ -3946,6 +3962,63 @@ TEST_F(CreditCardSaveManagerTest,
EXPECT_TRUE(payments_client_->active_experiments_in_request().empty());
}
+TEST_F(CreditCardSaveManagerTest,
+ UploadCreditCard_ShouldAddUploadCardBillableServiceNumberInRequest) {
+ // 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, true, false);
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+
+ // 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[4].value = ASCIIToUTF16("123");
+
+ // Confirm that the preflight request contained
+ // kUploadCardBillableServiceNumber in the request.
+ FormSubmitted(credit_card_form);
+ EXPECT_EQ(payments::kUploadCardBillableServiceNumber,
+ payments_client_->billable_service_number_in_request());
+}
+
+TEST_F(CreditCardSaveManagerTest,
+ UploadCreditCard_ShouldAddUploadCardSourceInRequest) {
+ // 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, true, false);
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+
+ // 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[4].value = ASCIIToUTF16("123");
+
+ // Confirm that the preflight request contained the correct UploadCardSource.
+ FormSubmitted(credit_card_form);
+ EXPECT_EQ(payments::PaymentsClient::UploadCardSource::UPSTREAM_CHECKOUT_FLOW,
+ payments_client_->upload_card_source_in_request());
+}
+
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_EloDisallowed) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillUpstreamDisallowElo);
@@ -4200,10 +4273,10 @@ TEST_F(CreditCardSaveManagerTest,
"Autofill.StrikeDatabase.StrikesPresentWhenServerCardSaved", 0);
}
-// Tests that a card with some strikes (but not max strikes) should still show
-// the save bubble/infobar.
+// Tests that a card with some strikes using LegacyStrikeDatabase (but not max
+// strikes) should still show the save bubble/infobar.
TEST_F(CreditCardSaveManagerTest,
- LocallySaveCreditCard_NotEnoughStrikesStillShowsOfferToSave) {
+ LocallySaveCreditCard_NotEnoughLegacyStrikesStillShowsOfferToSave) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillSaveCreditCardUsesStrikeSystem);
credit_card_save_manager_->SetCreditCardUploadEnabled(false);
@@ -4241,10 +4314,10 @@ TEST_F(CreditCardSaveManagerTest,
"Autofill.StrikeDatabase.CreditCardSaveNotOfferedDueToMaxStrikes", 0);
}
-// Tests that a card with some strikes (but not max strikes) should still show
-// the save bubble/infobar.
+// Tests that a card with some strikes using LegacyStrikeDatabase (but not max
+// strikes) should still show the save bubble/infobar.
TEST_F(CreditCardSaveManagerTest,
- UploadCreditCard_NotEnoughStrikesStillShowsOfferToSave) {
+ UploadCreditCard_NotEnoughLegacyStrikesStillShowsOfferToSave) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillSaveCreditCardUsesStrikeSystem);
@@ -4292,9 +4365,10 @@ TEST_F(CreditCardSaveManagerTest,
}
#if defined(OS_ANDROID) || defined(OS_IOS)
-// Tests that a card with max strikes does not offer save on mobile at all.
+// Tests that a card with max strikes using LegacyStrikeDatabase does not offer
+// save on mobile at all.
TEST_F(CreditCardSaveManagerTest,
- LocallySaveCreditCard_MaxStrikesDisallowsSave) {
+ LocallySaveCreditCard_MaxLegacyStrikesDisallowsSave) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillSaveCreditCardUsesStrikeSystem);
credit_card_save_manager_->SetCreditCardUploadEnabled(false);
@@ -4330,8 +4404,10 @@ TEST_F(CreditCardSaveManagerTest,
AutofillMetrics::SaveTypeMetric::LOCAL, 1);
}
-// Tests that a card with max strikes does not offer save on mobile at all.
-TEST_F(CreditCardSaveManagerTest, UploadCreditCard_MaxStrikesDisallowsSave) {
+// Tests that a card with max strikes using LegacyStrikeDatabase does not offer
+// save on mobile at all.
+TEST_F(CreditCardSaveManagerTest,
+ UploadCreditCard_MaxLegacyStrikesDisallowsSave) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillSaveCreditCardUsesStrikeSystem);
@@ -4383,10 +4459,11 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_MaxStrikesDisallowsSave) {
}
#else // !defined(OS_ANDROID) && !defined(OS_IOS)
-// Tests that a card with max strikes should still offer to save on Desktop via
-// the omnibox icon, but that the offer-to-save bubble itself is not shown.
+// Tests that a card with max strikes using LegacyStrikeDatabase should still
+// offer to save on Desktop via the omnibox icon, but that the offer-to-save
+// bubble itself is not shown.
TEST_F(CreditCardSaveManagerTest,
- LocallySaveCreditCard_MaxStrikesStillAllowsSave) {
+ LocallySaveCreditCard_MaxLegacyStrikesStillAllowsSave) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillSaveCreditCardUsesStrikeSystem);
credit_card_save_manager_->SetCreditCardUploadEnabled(false);
@@ -4425,9 +4502,11 @@ TEST_F(CreditCardSaveManagerTest,
AutofillMetrics::SaveTypeMetric::LOCAL, 1);
}
-// Tests that a card with max strikes should still offer to save on Desktop via
-// the omnibox icon, but that the offer-to-save bubble itself is not shown.
-TEST_F(CreditCardSaveManagerTest, UploadCreditCard_MaxStrikesStillAllowsSave) {
+// Tests that a card with max strikes using LegacyStrikeDatabase should still
+// offer to save on Desktop via the omnibox icon, but that the offer-to-save
+// bubble itself is not shown.
+TEST_F(CreditCardSaveManagerTest,
+ UploadCreditCard_MaxLegacyStrikesStillAllowsSave) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillSaveCreditCardUsesStrikeSystem);
@@ -4476,8 +4555,10 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_MaxStrikesStillAllowsSave) {
}
#endif
-// Tests that adding a card clears all strikes for that card.
-TEST_F(CreditCardSaveManagerTest, LocallySaveCreditCard_ClearStrikesOnAdd) {
+// Tests that adding a card clears all LegacyStrikeDatabase strikes for that
+// card.
+TEST_F(CreditCardSaveManagerTest,
+ LocallySaveCreditCard_ClearLegacyStrikesOnAdd) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillSaveCreditCardUsesStrikeSystem);
credit_card_save_manager_->SetCreditCardUploadEnabled(false);
@@ -4511,8 +4592,9 @@ TEST_F(CreditCardSaveManagerTest, LocallySaveCreditCard_ClearStrikesOnAdd) {
legacy_strike_database_->GetKeyForCreditCardSave("1111")));
}
-// Tests that adding a card clears all strikes for that card.
-TEST_F(CreditCardSaveManagerTest, UploadCreditCard_ClearStrikesOnAdd) {
+// Tests that adding a card clears all LegacyStrikeDatabase strikes for that
+// card.
+TEST_F(CreditCardSaveManagerTest, UploadCreditCard_ClearLegacyStrikesOnAdd) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillSaveCreditCardUsesStrikeSystem);
@@ -4555,8 +4637,10 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_ClearStrikesOnAdd) {
legacy_strike_database_->GetKeyForCreditCardSave("1111")));
}
-// Tests that adding a card clears all strikes for that card.
-TEST_F(CreditCardSaveManagerTest, LocallySaveCreditCard_NumStrikesLoggedOnAdd) {
+// Tests that adding a card clears all LegacyStrikeDatabase strikes for that
+// card.
+TEST_F(CreditCardSaveManagerTest,
+ LocallySaveCreditCard_NumLegacyStrikesLoggedOnAdd) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillSaveCreditCardUsesStrikeSystem);
credit_card_save_manager_->SetCreditCardUploadEnabled(false);
@@ -4593,8 +4677,10 @@ TEST_F(CreditCardSaveManagerTest, LocallySaveCreditCard_NumStrikesLoggedOnAdd) {
/*sample=*/2, /*count=*/1);
}
-// Tests that adding a card clears all strikes for that card.
-TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NumStrikesLoggedOnAdd) {
+// Tests that adding a card clears all LegacyStrikeDatabase strikes for that
+// card.
+TEST_F(CreditCardSaveManagerTest,
+ UploadCreditCard_NumLegacyStrikesLoggedOnAdd) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillSaveCreditCardUsesStrikeSystem);
@@ -4640,6 +4726,503 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NumStrikesLoggedOnAdd) {
/*sample=*/2, /*count=*/1);
}
+// Tests that one LegacyStrikeDatabase strike is added when upload failed and
+// bubble is shown.
+TEST_F(CreditCardSaveManagerTest,
+ UploadCreditCard_NumLegacyStrikesLoggedOnUploadNotSuccess) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillSaveCreditCardUsesStrikeSystem);
+ const char* const server_id = "InstrumentData:1234";
+ payments_client_->SetServerIdForCardUpload(server_id);
+ EXPECT_EQ(0, legacy_strike_database_->GetStrikesForTesting(
+ legacy_strike_database_->GetKeyForCreditCardSave("1111")));
+
+ // If upload failed and the bubble was shown, strike count should increase
+ // by 1.
+ credit_card_save_manager_->set_show_save_prompt(true);
+ credit_card_save_manager_->set_upload_request_card_number(
+ ASCIIToUTF16("4111111111111111"));
+ credit_card_save_manager_->OnDidUploadCard(AutofillClient::TRY_AGAIN_FAILURE,
+ server_id);
+ EXPECT_EQ(1, legacy_strike_database_->GetStrikesForTesting(
+ legacy_strike_database_->GetKeyForCreditCardSave("1111")));
+}
+
+// Tests that a card with some strikes (but not max strikes) should still show
+// the save bubble/infobar.
+TEST_F(CreditCardSaveManagerTest,
+ LocallySaveCreditCard_NotEnoughStrikesStillShowsOfferToSave) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2);
+ credit_card_save_manager_->SetCreditCardUploadEnabled(false);
+ TestCreditCardSaveStrikeDatabase credit_card_save_strike_database =
+ TestCreditCardSaveStrikeDatabase(strike_database_);
+
+ // Add a single strike for the card to be added.
+ credit_card_save_strike_database.AddStrike("1111");
+ EXPECT_EQ(1, credit_card_save_strike_database.GetStrikes("1111"));
+
+ // Set up our credit card form data.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form, true, false);
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+ ExpectFillableFormParsedUkm(1 /* num_fillable_forms_parsed */);
+
+ // 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[4].value = ASCIIToUTF16("123");
+
+ base::HistogramTester histogram_tester;
+
+ FormSubmitted(credit_card_form);
+ EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
+
+ // Verify that the offer-to-save bubble was still shown because the card did
+ // not have too many strikes.
+ EXPECT_TRUE(
+ autofill_client_.get_offer_to_save_credit_card_bubble_was_shown());
+ // Verify that no histogram entry was logged.
+ histogram_tester.ExpectTotalCount(
+ "Autofill.StrikeDatabase.CreditCardSaveNotOfferedDueToMaxStrikes", 0);
+}
+
+// Tests that a card with some strikes (but not max strikes) should still show
+// the save bubble/infobar.
+TEST_F(CreditCardSaveManagerTest,
+ UploadCreditCard_NotEnoughStrikesStillShowsOfferToSave) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2);
+ TestCreditCardSaveStrikeDatabase credit_card_save_strike_database =
+ TestCreditCardSaveStrikeDatabase(strike_database_);
+
+ // Add a single strike for the card to be added.
+ credit_card_save_strike_database.AddStrike("1111");
+ EXPECT_EQ(1, credit_card_save_strike_database.GetStrikes("1111"));
+
+ // 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));
+ ExpectUniqueFillableFormParsedUkm();
+
+ 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, true, false);
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+ ExpectFillableFormParsedUkm(2 /* num_fillable_forms_parsed */);
+
+ // 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[4].value = ASCIIToUTF16("123");
+
+ base::HistogramTester histogram_tester;
+
+ FormSubmitted(credit_card_form);
+ EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
+
+ // Verify that the offer-to-save bubble was still shown because the card did
+ // not have too many strikes.
+ EXPECT_TRUE(
+ autofill_client_.get_offer_to_save_credit_card_bubble_was_shown());
+ // Verify that no histogram entry was logged.
+ histogram_tester.ExpectTotalCount(
+ "Autofill.StrikeDatabase.CreditCardSaveNotOfferedDueToMaxStrikes", 0);
+}
+
+#if defined(OS_ANDROID) || defined(OS_IOS)
+// Tests that a card with max strikes does not offer save on mobile at all.
+TEST_F(CreditCardSaveManagerTest,
+ LocallySaveCreditCard_MaxStrikesDisallowsSave) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2);
+ credit_card_save_manager_->SetCreditCardUploadEnabled(false);
+ TestCreditCardSaveStrikeDatabase credit_card_save_strike_database =
+ TestCreditCardSaveStrikeDatabase(strike_database_);
+
+ // Max out strikes for the card to be added.
+ credit_card_save_strike_database.AddStrike("1111");
+ credit_card_save_strike_database.AddStrike("1111");
+ credit_card_save_strike_database.AddStrike("1111");
+ EXPECT_EQ(3, credit_card_save_strike_database.GetStrikes("1111"));
+
+ // Set up our credit card form data.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form, true, false);
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+ ExpectFillableFormParsedUkm(1 /* num_fillable_forms_parsed */);
+
+ // 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[4].value = ASCIIToUTF16("123");
+
+ base::HistogramTester histogram_tester;
+
+ // No form of credit card save should be shown.
+ FormSubmitted(credit_card_form);
+ EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
+
+ // Verify that the correct histogram entry was logged.
+ histogram_tester.ExpectBucketCount(
+ "Autofill.StrikeDatabase.CreditCardSaveNotOfferedDueToMaxStrikes",
+ AutofillMetrics::SaveTypeMetric::LOCAL, 1);
+}
+
+// Tests that a card with max strikes does not offer save on mobile at all.
+TEST_F(CreditCardSaveManagerTest, UploadCreditCard_MaxStrikesDisallowsSave) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2);
+ TestCreditCardSaveStrikeDatabase credit_card_save_strike_database =
+ TestCreditCardSaveStrikeDatabase(strike_database_);
+
+ // Max out strikes for the card to be added.
+ credit_card_save_strike_database.AddStrike("1111");
+ credit_card_save_strike_database.AddStrike("1111");
+ credit_card_save_strike_database.AddStrike("1111");
+ EXPECT_EQ(3, credit_card_save_strike_database.GetStrikes("1111"));
+
+ // 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));
+ ExpectUniqueFillableFormParsedUkm();
+
+ 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, true, false);
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+ ExpectFillableFormParsedUkm(2 /* num_fillable_forms_parsed */);
+
+ // 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[4].value = ASCIIToUTF16("123");
+
+ base::HistogramTester histogram_tester;
+
+ // No form of credit card save should be shown.
+ FormSubmitted(credit_card_form);
+ EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
+
+ // Verify that the correct histogram entries were logged.
+ ExpectCardUploadDecision(
+ histogram_tester,
+ AutofillMetrics::UPLOAD_NOT_OFFERED_MAX_STRIKES_ON_MOBILE);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.StrikeDatabase.CreditCardSaveNotOfferedDueToMaxStrikes",
+ AutofillMetrics::SaveTypeMetric::SERVER, 1);
+ // Verify that the correct UKM was logged.
+ ExpectCardUploadDecisionUkm(
+ AutofillMetrics::UPLOAD_NOT_OFFERED_MAX_STRIKES_ON_MOBILE);
+}
+
+#else // !defined(OS_ANDROID) && !defined(OS_IOS)
+// Tests that a card with max strikes should still offer to save on Desktop via
+// the omnibox icon, but that the offer-to-save bubble itself is not shown.
+TEST_F(CreditCardSaveManagerTest,
+ LocallySaveCreditCard_MaxStrikesStillAllowsSave) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2);
+ credit_card_save_manager_->SetCreditCardUploadEnabled(false);
+ TestCreditCardSaveStrikeDatabase credit_card_save_strike_database =
+ TestCreditCardSaveStrikeDatabase(strike_database_);
+
+ // Max out strikes for the card to be added.
+ credit_card_save_strike_database.AddStrike("1111");
+ credit_card_save_strike_database.AddStrike("1111");
+ credit_card_save_strike_database.AddStrike("1111");
+ EXPECT_EQ(3, credit_card_save_strike_database.GetStrikes("1111"));
+
+ // Set up our credit card form data.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form, true, false);
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+ ExpectFillableFormParsedUkm(1 /* num_fillable_forms_parsed */);
+
+ // 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[4].value = ASCIIToUTF16("123");
+
+ base::HistogramTester histogram_tester;
+
+ FormSubmitted(credit_card_form);
+ EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
+
+ // Verify that the offer-to-save bubble was not shown because the card had too
+ // many strikes.
+ EXPECT_FALSE(
+ autofill_client_.get_offer_to_save_credit_card_bubble_was_shown());
+ // Verify that the correct histogram entry was logged.
+ histogram_tester.ExpectBucketCount(
+ "Autofill.StrikeDatabase.CreditCardSaveNotOfferedDueToMaxStrikes",
+ AutofillMetrics::SaveTypeMetric::LOCAL, 1);
+}
+
+// Tests that a card with max strikes should still offer to save on Desktop via
+// the omnibox icon, but that the offer-to-save bubble itself is not shown.
+TEST_F(CreditCardSaveManagerTest, UploadCreditCard_MaxStrikesStillAllowsSave) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2);
+ TestCreditCardSaveStrikeDatabase credit_card_save_strike_database =
+ TestCreditCardSaveStrikeDatabase(strike_database_);
+
+ // Max out strikes for the card to be added.
+ credit_card_save_strike_database.AddStrike("1111");
+ credit_card_save_strike_database.AddStrike("1111");
+ credit_card_save_strike_database.AddStrike("1111");
+ EXPECT_EQ(3, credit_card_save_strike_database.GetStrikes("1111"));
+
+ // 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));
+ ExpectUniqueFillableFormParsedUkm();
+
+ 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, true, false);
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+ ExpectFillableFormParsedUkm(2 /* num_fillable_forms_parsed */);
+
+ // 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[4].value = ASCIIToUTF16("123");
+
+ base::HistogramTester histogram_tester;
+
+ FormSubmitted(credit_card_form);
+ EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
+
+ // Verify that the offer-to-save bubble was not shown because the card had too
+ // many strikes.
+ EXPECT_FALSE(
+ autofill_client_.get_offer_to_save_credit_card_bubble_was_shown());
+ // Verify that the correct histogram entry was logged.
+ histogram_tester.ExpectBucketCount(
+ "Autofill.StrikeDatabase.CreditCardSaveNotOfferedDueToMaxStrikes",
+ AutofillMetrics::SaveTypeMetric::SERVER, 1);
+}
+#endif
+
+// Tests that adding a card clears all strikes for that card.
+TEST_F(CreditCardSaveManagerTest, LocallySaveCreditCard_ClearStrikesOnAdd) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2);
+ credit_card_save_manager_->SetCreditCardUploadEnabled(false);
+ TestCreditCardSaveStrikeDatabase credit_card_save_strike_database =
+ TestCreditCardSaveStrikeDatabase(strike_database_);
+
+ // Add two strikes for the card to be added.
+ credit_card_save_strike_database.AddStrike("1111");
+ credit_card_save_strike_database.AddStrike("1111");
+ EXPECT_EQ(2, credit_card_save_strike_database.GetStrikes("1111"));
+
+ // Set up our credit card form data.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form, true, false);
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+ ExpectFillableFormParsedUkm(1 /* num_fillable_forms_parsed */);
+
+ // 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[4].value = ASCIIToUTF16("123");
+
+ FormSubmitted(credit_card_form);
+ EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
+
+ // Verify that adding the card reset the strike count for that card.
+ EXPECT_EQ(0, credit_card_save_strike_database.GetStrikes("1111"));
+}
+
+// Tests that adding a card clears all strikes for that card.
+TEST_F(CreditCardSaveManagerTest, UploadCreditCard_ClearStrikesOnAdd) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2);
+ TestCreditCardSaveStrikeDatabase credit_card_save_strike_database =
+ TestCreditCardSaveStrikeDatabase(strike_database_);
+
+ // Add two strikes for the card to be added.
+ credit_card_save_strike_database.AddStrike("1111");
+ credit_card_save_strike_database.AddStrike("1111");
+ EXPECT_EQ(2, credit_card_save_strike_database.GetStrikes("1111"));
+
+ // 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));
+ ExpectUniqueFillableFormParsedUkm();
+
+ 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, true, false);
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+ ExpectFillableFormParsedUkm(2 /* num_fillable_forms_parsed */);
+
+ // 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[4].value = ASCIIToUTF16("123");
+
+ FormSubmitted(credit_card_form);
+ EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
+
+ // Verify that adding the card reset the strike count for that card.
+ EXPECT_EQ(0, credit_card_save_strike_database.GetStrikes("1111"));
+}
+
+// Tests that adding a card clears all strikes for that card.
+TEST_F(CreditCardSaveManagerTest, LocallySaveCreditCard_NumStrikesLoggedOnAdd) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2);
+ credit_card_save_manager_->SetCreditCardUploadEnabled(false);
+
+ TestCreditCardSaveStrikeDatabase credit_card_save_strike_database =
+ TestCreditCardSaveStrikeDatabase(strike_database_);
+
+ // Add two strikes for the card to be added.
+ credit_card_save_strike_database.AddStrike("1111");
+ credit_card_save_strike_database.AddStrike("1111");
+ EXPECT_EQ(2, credit_card_save_strike_database.GetStrikes("1111"));
+
+ // Set up our credit card form data.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form, true, false);
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+ ExpectFillableFormParsedUkm(1 /* num_fillable_forms_parsed */);
+
+ // 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[4].value = ASCIIToUTF16("123");
+
+ base::HistogramTester histogram_tester;
+
+ FormSubmitted(credit_card_form);
+ EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
+
+ // Verify that adding the card logged the number of strikes it had previously.
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.StrikeDatabase.StrikesPresentWhenLocalCardSaved",
+ /*sample=*/2, /*count=*/1);
+}
+
+// Tests that adding a card clears all strikes for that card.
+TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NumStrikesLoggedOnAdd) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2);
+ TestCreditCardSaveStrikeDatabase credit_card_save_strike_database =
+ TestCreditCardSaveStrikeDatabase(strike_database_);
+
+ // Add two strikes for the card to be added.
+ credit_card_save_strike_database.AddStrike("1111");
+ credit_card_save_strike_database.AddStrike("1111");
+ EXPECT_EQ(2, credit_card_save_strike_database.GetStrikes("1111"));
+
+ // 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));
+ ExpectUniqueFillableFormParsedUkm();
+
+ 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, true, false);
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+ ExpectFillableFormParsedUkm(2 /* num_fillable_forms_parsed */);
+
+ // 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[4].value = ASCIIToUTF16("123");
+
+ base::HistogramTester histogram_tester;
+
+ FormSubmitted(credit_card_form);
+ EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
+
+ // Verify that adding the card logged the number of strikes it had previously.
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.StrikeDatabase.StrikesPresentWhenServerCardSaved",
+ /*sample=*/2, /*count=*/1);
+}
+
+// Tests that one strike is added when upload failed and
+// bubble is shown.
+TEST_F(CreditCardSaveManagerTest,
+ UploadCreditCard_NumStrikesLoggedOnUploadNotSuccess) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillSaveCreditCardUsesStrikeSystemV2);
+ const char* const server_id = "InstrumentData:1234";
+ payments_client_->SetServerIdForCardUpload(server_id);
+ TestCreditCardSaveStrikeDatabase credit_card_save_strike_database =
+ TestCreditCardSaveStrikeDatabase(strike_database_);
+ EXPECT_EQ(0, credit_card_save_strike_database.GetStrikes("1111"));
+
+ // If upload failed and the bubble was shown, strike count should increase
+ // by 1.
+ credit_card_save_manager_->set_show_save_prompt(true);
+ credit_card_save_manager_->set_upload_request_card_number(
+ ASCIIToUTF16("4111111111111111"));
+ credit_card_save_manager_->OnDidUploadCard(AutofillClient::TRY_AGAIN_FAILURE,
+ server_id);
+ EXPECT_EQ(1, credit_card_save_strike_database.GetStrikes("1111"));
+}
+
// Make sure that the PersonalDataManager gets notified when the user accepts
// an upload offer.
TEST_F(CreditCardSaveManagerTest, OnUserDidAcceptUpload_NotifiesPDM) {
diff --git a/chromium/components/autofill/core/browser/credit_card_save_strike_database.cc b/chromium/components/autofill/core/browser/credit_card_save_strike_database.cc
index aca26ba3589..5df822f385e 100644
--- a/chromium/components/autofill/core/browser/credit_card_save_strike_database.cc
+++ b/chromium/components/autofill/core/browser/credit_card_save_strike_database.cc
@@ -9,8 +9,10 @@
namespace autofill {
CreditCardSaveStrikeDatabase::CreditCardSaveStrikeDatabase(
- const base::FilePath& database_dir)
- : StrikeDatabase(database_dir) {}
+ StrikeDatabase* strike_database)
+ : StrikeDatabaseIntegratorBase(strike_database) {
+ RemoveExpiredStrikes();
+}
CreditCardSaveStrikeDatabase::~CreditCardSaveStrikeDatabase() {}
@@ -22,4 +24,13 @@ int CreditCardSaveStrikeDatabase::GetMaxStrikesLimit() {
return 3;
}
+long long CreditCardSaveStrikeDatabase::GetExpiryTimeMicros() {
+ // Expiry time is 6 months.
+ return (long long)1000000 * 60 * 60 * 24 * 180;
+}
+
+bool CreditCardSaveStrikeDatabase::UniqueIdsRequired() {
+ return true;
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/credit_card_save_strike_database.h b/chromium/components/autofill/core/browser/credit_card_save_strike_database.h
index fab05c64d7f..537682256f1 100644
--- a/chromium/components/autofill/core/browser/credit_card_save_strike_database.h
+++ b/chromium/components/autofill/core/browser/credit_card_save_strike_database.h
@@ -8,18 +8,21 @@
#include <string>
#include "components/autofill/core/browser/strike_database.h"
+#include "components/autofill/core/browser/strike_database_integrator_base.h"
namespace autofill {
-// Implementation of StrikeDatabase for credit card saves (both local and
-// upload).
-class CreditCardSaveStrikeDatabase : public StrikeDatabase {
+// Implementation of StrikeDatabaseIntegratorBase for credit card saves (both
+// local and upload).
+class CreditCardSaveStrikeDatabase : public StrikeDatabaseIntegratorBase {
public:
- CreditCardSaveStrikeDatabase(const base::FilePath& database_dir);
+ CreditCardSaveStrikeDatabase(StrikeDatabase* strike_database);
~CreditCardSaveStrikeDatabase() override;
std::string GetProjectPrefix() override;
int GetMaxStrikesLimit() override;
+ long long GetExpiryTimeMicros() override;
+ bool UniqueIdsRequired() override;
};
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/credit_card_save_strike_database_unittest.cc b/chromium/components/autofill/core/browser/credit_card_save_strike_database_unittest.cc
index cad62581f84..6628663394c 100644
--- a/chromium/components/autofill/core/browser/credit_card_save_strike_database_unittest.cc
+++ b/chromium/components/autofill/core/browser/credit_card_save_strike_database_unittest.cc
@@ -13,14 +13,17 @@
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/autofill/core/browser/proto/strike_data.pb.h"
+#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/browser/test_credit_card_save_strike_database.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace autofill {
class CreditCardSaveStrikeDatabaseTest : public ::testing::Test {
public:
- CreditCardSaveStrikeDatabaseTest() : strike_database_(InitFilePath()) {}
+ CreditCardSaveStrikeDatabaseTest()
+ : strike_database_(new StrikeDatabase(InitFilePath())) {}
protected:
base::HistogramTester* GetHistogramTester() { return &histogram_tester_; }
@@ -102,4 +105,34 @@ TEST_F(CreditCardSaveStrikeDatabaseTest, ClearStrikesForZeroStrikesTest) {
EXPECT_EQ(0, strike_database_.GetStrikes(last_four));
}
+TEST_F(CreditCardSaveStrikeDatabaseTest, RemoveExpiredStrikesTest) {
+ autofill::TestAutofillClock test_clock;
+ test_clock.SetNow(AutofillClock::Now());
+ const std::string last_four1 = "1234";
+ const std::string last_four2 = "9876";
+ strike_database_.AddStrike(last_four1);
+
+ // Advance clock to past the entry for |last_four1|'s expiry time.
+ test_clock.Advance(base::TimeDelta::FromMicroseconds(
+ strike_database_.GetExpiryTimeMicros() + 1));
+
+ strike_database_.AddStrike(last_four2);
+ strike_database_.RemoveExpiredStrikes();
+
+ // |last_four1|'s entry should have its most recent strike expire, but
+ // |last_four2|'s should not.
+ EXPECT_EQ(0, strike_database_.GetStrikes(last_four1));
+ EXPECT_EQ(1, strike_database_.GetStrikes(last_four2));
+
+ // Advance clock to past |last_four2|'s expiry time.
+ test_clock.Advance(base::TimeDelta::FromMicroseconds(
+ strike_database_.GetExpiryTimeMicros() + 1));
+
+ strike_database_.RemoveExpiredStrikes();
+
+ // |last_four1| and |last_four2| should have no more unexpired strikes.
+ EXPECT_EQ(0, strike_database_.GetStrikes(last_four1));
+ EXPECT_EQ(0, strike_database_.GetStrikes(last_four2));
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/credit_card_unittest.cc b/chromium/components/autofill/core/browser/credit_card_unittest.cc
index 0093b822982..9552cae6cd4 100644
--- a/chromium/components/autofill/core/browser/credit_card_unittest.cc
+++ b/chromium/components/autofill/core/browser/credit_card_unittest.cc
@@ -15,7 +15,9 @@
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/browser/validation.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/grit/components_scaled_resources.h"
@@ -578,6 +580,19 @@ TEST(CreditCardTest, Compare) {
b.set_origin("banana");
EXPECT_EQ(0, a.Compare(b));
+ // Different types of server cards don't count.
+ a.set_record_type(MASKED_SERVER_CARD);
+ b.set_record_type(FULL_SERVER_CARD);
+ EXPECT_EQ(0, a.Compare(b));
+
+ // Local is different from server.
+ a.set_record_type(LOCAL_CARD);
+ b.set_record_type(FULL_SERVER_CARD);
+ EXPECT_GT(0, a.Compare(b));
+ a.set_record_type(MASKED_SERVER_CARD);
+ b.set_record_type(LOCAL_CARD);
+ EXPECT_LT(0, a.Compare(b));
+
// Different values produce non-zero results.
test::SetCreditCardInfo(&a, "Jimmy", nullptr, nullptr, nullptr, "");
test::SetCreditCardInfo(&b, "Ringo", nullptr, nullptr, nullptr, "");
@@ -1009,6 +1024,41 @@ TEST(CreditCardTest, CreditCardVerificationCode) {
EXPECT_EQ(base::string16(), card.GetRawInfo(CREDIT_CARD_VERIFICATION_CODE));
}
+// Tests that the card in only deletable if it is expired before the threshold.
+TEST(CreditCardTest, IsDeletable) {
+ // Set up an arbitrary time, as setup the current time to just above the
+ // threshold later than that time. This sets the year to 2007. The code
+ // expects valid expiration years to be between 2000 and 2999. However,
+ // because of the year 2018 problem, we need to pick an earlier year.
+ const base::Time kArbitraryTime = base::Time::FromDoubleT(1000000000);
+ TestAutofillClock test_clock;
+ test_clock.SetNow(kArbitraryTime + kDisusedDataModelDeletionTimeDelta +
+ base::TimeDelta::FromDays(1));
+
+ // Created a card that has not been used since over the deletion threshold.
+ CreditCard card(base::GenerateGUID(), "https://www.example.com/");
+ card.set_use_date(kArbitraryTime);
+
+ // Set the card to be expired before the threshold.
+ base::Time::Exploded now_exploded;
+ AutofillClock::Now().LocalExplode(&now_exploded);
+ card.SetExpirationYear(now_exploded.year - 5);
+ card.SetExpirationMonth(1);
+ ASSERT_TRUE(card.IsExpired(AutofillClock::Now() -
+ kDisusedDataModelDeletionTimeDelta));
+
+ // Make sure the card is deletable.
+ EXPECT_TRUE(card.IsDeletable());
+
+ // Set the card to not be expired.
+ card.SetExpirationYear(now_exploded.year + 5);
+ ASSERT_FALSE(card.IsExpired(AutofillClock::Now() -
+ kDisusedDataModelDeletionTimeDelta));
+
+ // Make sure the card is not deletable.
+ EXPECT_FALSE(card.IsDeletable());
+}
+
struct CreditCardMatchingTypesCase {
CreditCardMatchingTypesCase(const char* value,
const char* card_exp_month,
diff --git a/chromium/components/autofill/core/browser/email_field.cc b/chromium/components/autofill/core/browser/email_field.cc
index 3f4a351dac2..86d507ed74f 100644
--- a/chromium/components/autofill/core/browser/email_field.cc
+++ b/chromium/components/autofill/core/browser/email_field.cc
@@ -4,7 +4,6 @@
#include "components/autofill/core/browser/email_field.h"
-#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_scanner.h"
#include "components/autofill/core/common/autofill_regex_constants.h"
@@ -16,7 +15,7 @@ std::unique_ptr<FormField> EmailField::Parse(AutofillScanner* scanner) {
AutofillField* field;
if (ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kEmailRe),
MATCH_DEFAULT | MATCH_EMAIL, &field)) {
- return base::WrapUnique(new EmailField(field));
+ return std::make_unique<EmailField>(field);
}
return nullptr;
diff --git a/chromium/components/autofill/core/browser/email_field.h b/chromium/components/autofill/core/browser/email_field.h
index c47eb44174c..ea792028365 100644
--- a/chromium/components/autofill/core/browser/email_field.h
+++ b/chromium/components/autofill/core/browser/email_field.h
@@ -16,13 +16,12 @@ namespace autofill {
class EmailField : public FormField {
public:
static std::unique_ptr<FormField> Parse(AutofillScanner* scanner);
+ explicit EmailField(const AutofillField* field);
protected:
void AddClassifications(FieldCandidatesMap* field_candidates) const override;
private:
- explicit EmailField(const AutofillField* field);
-
const AutofillField* field_;
DISALLOW_COPY_AND_ASSIGN(EmailField);
diff --git a/chromium/components/autofill/core/browser/field_filler_unittest.cc b/chromium/components/autofill/core/browser/field_filler_unittest.cc
index b092bfbff40..eb2f698627f 100644
--- a/chromium/components/autofill/core/browser/field_filler_unittest.cc
+++ b/chromium/components/autofill/core/browser/field_filler_unittest.cc
@@ -10,8 +10,8 @@
#include "base/base_paths.h"
#include "base/files/file_path.h"
-#include "base/macros.h"
#include "base/path_service.h"
+#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -1139,10 +1139,10 @@ TEST_F(AutofillFieldFillerTest, FillCreditCardNumberWithEqualSizeSplits) {
test.card_number_ = "5187654321098765";
test.total_splits_ = 4;
int splits[] = {4, 4, 4, 4};
- test.splits_ = std::vector<int>(splits, splits + arraysize(splits));
+ test.splits_ = std::vector<int>(splits, splits + base::size(splits));
std::string results[] = {"5187", "6543", "2109", "8765"};
test.expected_results_ =
- std::vector<std::string>(results, results + arraysize(results));
+ std::vector<std::string>(results, results + base::size(results));
FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
for (size_t i = 0; i < test.total_splits_; ++i) {
@@ -1181,10 +1181,10 @@ TEST_F(AutofillFieldFillerTest, FillCreditCardNumberWithUnequalSizeSplits) {
test.card_number_ = "423456789012345";
test.total_splits_ = 3;
int splits[] = {4, 6, 5};
- test.splits_ = std::vector<int>(splits, splits + arraysize(splits));
+ test.splits_ = std::vector<int>(splits, splits + base::size(splits));
std::string results[] = {"4234", "567890", "12345"};
test.expected_results_ =
- std::vector<std::string>(results, results + arraysize(results));
+ std::vector<std::string>(results, results + base::size(results));
FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
// Start executing test cases to verify parts and full credit card number.
diff --git a/chromium/components/autofill/core/browser/form_data_importer.cc b/chromium/components/autofill/core/browser/form_data_importer.cc
index df485ac887e..03b9216973a 100644
--- a/chromium/components/autofill/core/browser/form_data_importer.cc
+++ b/chromium/components/autofill/core/browser/form_data_importer.cc
@@ -487,10 +487,17 @@ CreditCard FormDataImporter::ExtractCreditCardFromForm(
base::TrimWhitespace(field->value, base::TRIM_ALL, &value);
// If we don't know the type of the field, or the user hasn't entered any
- // information into the field, or the field is non-focusable (hidden), then
- // skip it.
- if (!field->IsFieldFillable() || !field->is_focusable || value.empty())
+ // information into the field, then skip it.
+ if (!field->IsFieldFillable() || value.empty())
continue;
+ // If the field is non-focusable (hidden) after the user entered information
+ // into it, then skip it, unless the experiment to import non-focusable
+ // forms is enabled.
+ if (!field->is_focusable &&
+ !base::FeatureList::IsEnabled(
+ features::kAutofillImportNonFocusableCreditCardForms)) {
+ continue;
+ }
AutofillType field_type = field->Type();
// Field was not identified as a credit card field.
diff --git a/chromium/components/autofill/core/browser/form_data_importer.h b/chromium/components/autofill/core/browser/form_data_importer.h
index 412cf02e709..0a11aeb00a4 100644
--- a/chromium/components/autofill/core/browser/form_data_importer.h
+++ b/chromium/components/autofill/core/browser/form_data_importer.h
@@ -145,13 +145,22 @@ class FormDataImporter {
friend class AutofillMergeTest;
friend class FormDataImporterTest;
friend class FormDataImporterTestBase;
- friend class SaveCardBubbleViewsBrowserTestBase;
+ friend class SaveCardBubbleViewsFullFormBrowserTest;
friend class SaveCardInfobarEGTestHelper;
FRIEND_TEST_ALL_PREFIXES(AutofillMergeTest, MergeProfiles);
FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
AllowDuplicateMaskedServerCardIfFlagEnabled);
FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest, DontDuplicateFullServerCard);
FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest, DontDuplicateMaskedServerCard);
+ FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
+ ImportFormData_AddressesDisabledOneCreditCard);
+ FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
+ ImportFormData_AddressCreditCardDisabled);
+ FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
+ ImportFormData_HiddenCreditCardFormAfterEntered);
+ FRIEND_TEST_ALL_PREFIXES(
+ FormDataImporterTest,
+ ImportFormData_HiddenCreditCardFormAfterEnteredWithExpOff);
FRIEND_TEST_ALL_PREFIXES(
FormDataImporterTest,
ImportFormData_ImportCreditCardRecordType_FullServerCard);
@@ -179,10 +188,6 @@ class FormDataImporter {
FormDataImporterTest,
ImportFormData_SecondImportResetsCreditCardRecordType);
FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
- ImportFormData_AddressesDisabledOneCreditCard);
- FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
- ImportFormData_AddressCreditCardDisabled);
- FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
ImportFormData_TwoAddressesOneCreditCard);
FRIEND_TEST_ALL_PREFIXES(
FormDataImporterTest,
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 51abba7bb0d..a205459df88 100644
--- a/chromium/components/autofill/core/browser/form_data_importer_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_data_importer_unittest.cc
@@ -18,7 +18,6 @@
#include "base/feature_list.h"
#include "base/files/scoped_temp_dir.h"
#include "base/guid.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
@@ -76,6 +75,7 @@ class PersonalDataLoadedObserverMock : public PersonalDataManagerObserver {
~PersonalDataLoadedObserverMock() override {}
MOCK_METHOD0(OnPersonalDataChanged, void());
+ MOCK_METHOD0(OnPersonalDataFinishedProfileTasks, void());
};
template <typename T>
@@ -129,10 +129,7 @@ class FormDataImporterTestBase {
personal_data_manager_->AddObserver(&personal_data_observer_);
personal_data_manager_->OnSyncServiceInitialized(nullptr);
- base::RunLoop run_loop;
- EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
- .WillOnce(QuitMessageLoop(&run_loop));
- run_loop.Run();
+ WaitForOnPersonalDataChanged();
}
void EnableWalletCardImport() {
@@ -173,8 +170,19 @@ class FormDataImporterTestBase {
// Helper methods that simply forward the call to the private member (to avoid
// having to friend every test that needs to access the private
// PersonalDataManager::ImportAddressProfile or ImportCreditCard).
- bool ImportAddressProfiles(const FormStructure& form) {
- return form_data_importer_->ImportAddressProfiles(form);
+ void ImportAddressProfiles(bool extraction_successful,
+ const FormStructure& form) {
+ if (!extraction_successful) {
+ EXPECT_FALSE(form_data_importer_->ImportAddressProfiles(form));
+ return;
+ }
+
+ base::RunLoop run_loop;
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
+ .WillOnce(QuitMessageLoop(&run_loop));
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(1);
+ EXPECT_TRUE(form_data_importer_->ImportAddressProfiles(form));
+ run_loop.Run();
}
bool ImportCreditCard(const FormStructure& form,
@@ -197,11 +205,7 @@ class FormDataImporterTestBase {
personal_data_manager_->OnAcceptedLocalCreditCardSave(
*imported_credit_card);
- base::RunLoop run_loop;
- EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
- .WillOnce(QuitMessageLoop(&run_loop));
- run_loop.Run();
-
+ WaitForOnPersonalDataChanged();
CreditCard expected(base::GenerateGUID(), test::kEmptyOrigin);
test::SetCreditCardInfo(&expected, exp_name, exp_cc_num, exp_cc_month,
exp_cc_year, "");
@@ -213,15 +217,18 @@ class FormDataImporterTestBase {
void WaitForOnPersonalDataChanged() {
base::RunLoop run_loop;
- EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
.WillOnce(QuitMessageLoop(&run_loop));
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .Times(testing::AnyNumber());
run_loop.Run();
}
// The temporary directory should be deleted at the end to ensure that
// files are not used anymore and deletion succeeds.
base::ScopedTempDir temp_dir_;
- base::MessageLoopForUI message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_{
+ base::test::ScopedTaskEnvironment::MainThreadType::UI};
std::unique_ptr<PrefService> prefs_;
scoped_refptr<AutofillWebDataService> autofill_database_service_;
scoped_refptr<WebDatabaseService> web_database_;
@@ -304,9 +311,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles) {
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure);
AutofillProfile expected(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&expected, "George", nullptr, "Washington",
@@ -343,7 +348,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_BadEmail) {
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
- EXPECT_FALSE(ImportAddressProfiles(form_structure));
+ ImportAddressProfiles(/*extraction_success=*/false, form_structure);
ASSERT_EQ(0U, personal_data_manager_->GetProfiles().size());
}
@@ -374,9 +379,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_TwoEmails) {
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure);
ASSERT_EQ(1U, personal_data_manager_->GetProfiles().size());
}
@@ -407,7 +410,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_TwoDifferentEmails) {
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
- EXPECT_FALSE(ImportAddressProfiles(form_structure));
+ ImportAddressProfiles(/*extraction_success=*/false, form_structure);
ASSERT_EQ(0U, personal_data_manager_->GetProfiles().size());
}
@@ -429,7 +432,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_NotEnoughFilledFields) {
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
- EXPECT_FALSE(ImportAddressProfiles(form_structure));
+ ImportAddressProfiles(/*extraction_success=*/false, form_structure);
ASSERT_EQ(0U, personal_data_manager_->GetProfiles().size());
ASSERT_EQ(0U, personal_data_manager_->GetCreditCards().size());
@@ -457,9 +460,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_MinimumAddressUSA) {
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure);
ASSERT_EQ(1U, personal_data_manager_->GetProfiles().size());
}
@@ -486,9 +487,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_MinimumAddressGB) {
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure);
ASSERT_EQ(1U, personal_data_manager_->GetProfiles().size());
}
@@ -510,9 +509,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_MinimumAddressGI) {
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure);
ASSERT_EQ(1U, personal_data_manager_->GetProfiles().size());
}
@@ -552,9 +549,7 @@ TEST_F(FormDataImporterTest,
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure);
AutofillProfile expected(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&expected, "George", nullptr, "Washington", nullptr,
@@ -593,9 +588,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_MultilineAddress) {
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure);
AutofillProfile expected(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&expected, "George", nullptr, "Washington",
@@ -635,9 +628,7 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure1));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure1);
AutofillProfile expected(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&expected, "George", nullptr, "Washington",
@@ -673,9 +664,7 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure2));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure2);
AutofillProfile expected2(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&expected2, "John", nullptr, "Adams", "second@gmail.com",
@@ -732,9 +721,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_TwoValidProfilesSameForm) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure);
AutofillProfile expected(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&expected, "George", nullptr, "Washington",
@@ -808,9 +795,7 @@ TEST_F(FormDataImporterTest,
// Still able to do the import.
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure);
AutofillProfile expected(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&expected, "George", nullptr, "Washington",
@@ -892,9 +877,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_ThreeValidProfilesSameForm) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure);
// Only two are saved.
AutofillProfile expected(base::GenerateGUID(), test::kEmptyOrigin);
@@ -948,9 +931,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_SameProfileWithConflict) {
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure1));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure1);
AutofillProfile expected(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&expected, "George", nullptr, "Washington",
@@ -996,9 +977,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_SameProfileWithConflict) {
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure2));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure2);
const std::vector<AutofillProfile*>& results2 =
personal_data_manager_->GetProfiles();
@@ -1035,9 +1014,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_MissingInfoInOld) {
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure1));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure1);
AutofillProfile expected(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&expected, "George", nullptr, "Washington", nullptr,
@@ -1073,9 +1050,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_MissingInfoInOld) {
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure2));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure2);
const std::vector<AutofillProfile*>& results2 =
personal_data_manager_->GetProfiles();
@@ -1119,9 +1094,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_MissingInfoInNew) {
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure1));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure1);
AutofillProfile expected(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&expected, "George", nullptr, "Washington",
@@ -1159,9 +1132,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_MissingInfoInNew) {
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure2));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure2);
const std::vector<AutofillProfile*>& results2 =
personal_data_manager_->GetProfiles();
@@ -1197,7 +1168,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_InsufficientAddress) {
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes();
- EXPECT_FALSE(ImportAddressProfiles(form_structure1));
+ ImportAddressProfiles(/*extraction_success=*/false, form_structure1);
// Since no refresh is expected, reload the data from the database to make
// sure no changes were written out.
@@ -1220,10 +1191,12 @@ TEST_F(FormDataImporterTest,
"Hollywood", "CA", "91601", "US", "12345678910");
EXPECT_TRUE(profile.IsVerified());
- // Add the profile to the database.
+ base::RunLoop run_loop;
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
+ .WillOnce(QuitMessageLoop(&run_loop));
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(1);
personal_data_manager_->AddProfile(profile);
-
- WaitForOnPersonalDataChanged();
+ run_loop.Run();
// Simulate a form submission with conflicting info.
FormData form;
@@ -1251,10 +1224,7 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure));
-
- // Wait for the refresh, which in this case is a no-op.
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure);
// Expect that no new profile is saved.
const std::vector<AutofillProfile*>& results =
@@ -1272,10 +1242,7 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure2(form);
form_structure2.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure2));
-
- // Wait for the refresh, which in this case is a no-op.
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure2);
// Expect that no new profile is saved.
const std::vector<AutofillProfile*>& results2 =
@@ -1314,7 +1281,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_UnrecognizedCountry) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
- EXPECT_FALSE(ImportAddressProfiles(form_structure));
+ ImportAddressProfiles(/*extraction_success=*/false, form_structure);
// Since no refresh is expected, reload the data from the database to make
// sure no changes were written out.
@@ -1355,9 +1322,7 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
- EXPECT_TRUE(ImportAddressProfiles(form_structure));
-
- WaitForOnPersonalDataChanged();
+ ImportAddressProfiles(/*extraction_success=*/true, form_structure);
AutofillProfile expected(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&expected, "George", nullptr, "Washington",
@@ -1404,7 +1369,7 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
- EXPECT_FALSE(ImportAddressProfiles(form_structure));
+ ImportAddressProfiles(/*extraction_success=*/false, form_structure);
// Since no refresh is expected, reload the data from the database to make
// sure no changes were written out.
@@ -2584,11 +2549,19 @@ TEST_F(FormDataImporterTest, ImportFormData_TwoAddressesOneCreditCard) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
+
+ base::RunLoop run_loop;
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
+ .WillRepeatedly(QuitMessageLoop(&run_loop));
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .Times(testing::AnyNumber());
// 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));
+ run_loop.Run();
+
ASSERT_TRUE(imported_credit_card);
personal_data_manager_->OnAcceptedLocalCreditCardSave(*imported_credit_card);
@@ -2821,6 +2794,101 @@ TEST_F(FormDataImporterTest, DontDuplicateMaskedServerCard) {
ASSERT_FALSE(imported_credit_card);
}
+// Tests that a credit card form that is hidden after receiving input still
+// imports the card.
+TEST_F(FormDataImporterTest, ImportFormData_HiddenCreditCardFormAfterEntered) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillImportNonFocusableCreditCardForms);
+
+ FormData form;
+ form.origin = GURL("https://wwww.foo.com");
+
+ FormFieldData field;
+
+ test::CreateTestFormField("Name on card:", "name_on_card", "Biggie Smalls",
+ "text", &field);
+ field.is_focusable = false;
+ form.fields.push_back(field);
+ test::CreateTestFormField("Card Number:", "card_number", "4111111111111111",
+ "text", &field);
+ field.is_focusable = false;
+ form.fields.push_back(field);
+ test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
+ &field);
+ field.is_focusable = false;
+ form.fields.push_back(field);
+ test::CreateTestFormField("Exp Month:", "exp_month", "01", "text", &field);
+ field.is_focusable = false;
+ form.fields.push_back(field);
+ test::CreateTestFormField("Exp Year:", "exp_year", "2999", "text", &field);
+ field.is_focusable = false;
+ form.fields.push_back(field);
+
+ FormStructure form_structure(form);
+ form_structure.DetermineHeuristicTypes();
+ std::unique_ptr<CreditCard> imported_credit_card;
+ // 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));
+ ASSERT_TRUE(imported_credit_card);
+ personal_data_manager_->OnAcceptedLocalCreditCardSave(*imported_credit_card);
+
+ WaitForOnPersonalDataChanged();
+
+ // Test that the credit card has been saved.
+ CreditCard expected_card(base::GenerateGUID(), test::kEmptyOrigin);
+ test::SetCreditCardInfo(&expected_card, "Biggie Smalls", "4111111111111111",
+ "01", "2999", "");
+ const std::vector<CreditCard*>& results =
+ personal_data_manager_->GetCreditCards();
+ ASSERT_EQ(1U, results.size());
+ EXPECT_EQ(0, expected_card.Compare(*results[0]));
+}
+
+// Tests that a credit card form that is hidden after receiving input does not
+// import the card when the experiment is off.
+TEST_F(FormDataImporterTest,
+ ImportFormData_HiddenCreditCardFormAfterEnteredWithExpOff) {
+ scoped_feature_list_.InitAndDisableFeature(
+ features::kAutofillImportNonFocusableCreditCardForms);
+
+ FormData form;
+ form.origin = GURL("https://wwww.foo.com");
+
+ FormFieldData field;
+
+ test::CreateTestFormField("Name on card:", "name_on_card", "Biggie Smalls",
+ "text", &field);
+ field.is_focusable = false;
+ form.fields.push_back(field);
+ test::CreateTestFormField("Card Number:", "card_number", "4111111111111111",
+ "text", &field);
+ field.is_focusable = false;
+ form.fields.push_back(field);
+ test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
+ &field);
+ field.is_focusable = false;
+ form.fields.push_back(field);
+ test::CreateTestFormField("Exp Month:", "exp_month", "01", "text", &field);
+ field.is_focusable = false;
+ form.fields.push_back(field);
+ test::CreateTestFormField("Exp Year:", "exp_year", "2999", "text", &field);
+ field.is_focusable = false;
+ form.fields.push_back(field);
+
+ FormStructure form_structure(form);
+ form_structure.DetermineHeuristicTypes();
+ std::unique_ptr<CreditCard> imported_credit_card;
+ // Returns false because the credit card import was failed.
+ 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));
+ ASSERT_FALSE(imported_credit_card);
+}
+
TEST_F(FormDataImporterTest, DontDuplicateFullServerCard) {
EnableWalletCardImport();
diff --git a/chromium/components/autofill/core/browser/form_structure.cc b/chromium/components/autofill/core/browser/form_structure.cc
index 3032f4ee662..c715abb098f 100644
--- a/chromium/components/autofill/core/browser/form_structure.cc
+++ b/chromium/components/autofill/core/browser/form_structure.cc
@@ -288,6 +288,32 @@ HtmlFieldType FieldTypeFromAutocompleteAttributeValue(
return HTML_TYPE_UNRECOGNIZED;
}
+// Helper function for explicit conversion between |ButtonTitleType| defined in
+// "button_title_type.h" and "server.proto".
+AutofillUploadContents_ButtonTitle_ButtonTitleType ToServerButtonTitleType(
+ autofill::ButtonTitleType input) {
+ switch (input) {
+ case ButtonTitleType::NONE:
+ return AutofillUploadContents::ButtonTitle::NONE;
+ case ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE:
+ return AutofillUploadContents::ButtonTitle::BUTTON_ELEMENT_SUBMIT_TYPE;
+ case ButtonTitleType::BUTTON_ELEMENT_BUTTON_TYPE:
+ return AutofillUploadContents::ButtonTitle::BUTTON_ELEMENT_BUTTON_TYPE;
+ case ButtonTitleType::INPUT_ELEMENT_SUBMIT_TYPE:
+ return AutofillUploadContents::ButtonTitle::INPUT_ELEMENT_SUBMIT_TYPE;
+ case ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE:
+ return AutofillUploadContents::ButtonTitle::INPUT_ELEMENT_BUTTON_TYPE;
+ case ButtonTitleType::HYPERLINK:
+ return AutofillUploadContents::ButtonTitle::HYPERLINK;
+ case ButtonTitleType::DIV:
+ return AutofillUploadContents::ButtonTitle::DIV;
+ case ButtonTitleType::SPAN:
+ return AutofillUploadContents::ButtonTitle::SPAN;
+ }
+ NOTREACHED();
+ return AutofillUploadContents::ButtonTitle::NONE;
+}
+
std::ostream& operator<<(
std::ostream& out,
const autofill::AutofillQueryResponseContents& response) {
@@ -441,7 +467,7 @@ FormStructure::FormStructure(const FormData& form)
: id_attribute_(form.id_attribute),
name_attribute_(form.name_attribute),
form_name_(form.name),
- button_title_(form.button_title),
+ button_titles_(form.button_titles),
submission_event_(SubmissionIndicatorEvent::NONE),
source_url_(form.origin),
target_url_(form.action),
@@ -529,9 +555,7 @@ void FormStructure::DetermineHeuristicTypes() {
1 << AutofillMetrics::FORM_CONTAINS_UPI_VPA_HINT;
}
- if (base::FeatureList::IsEnabled(
- features::kAutofillRationalizeFieldTypePredictions))
- RationalizeFieldTypePredictions();
+ RationalizeFieldTypePredictions();
AutofillMetrics::LogDetermineHeuristicTypesTiming(
base::TimeTicks::Now() - determine_heuristic_types_start_time);
@@ -551,6 +575,7 @@ bool FormStructure::EncodeUploadRequest(
upload->set_autofill_used(form_was_autofilled);
upload->set_data_present(EncodeFieldTypes(available_field_types));
upload->set_passwords_revealed(passwords_were_revealed_);
+ upload->set_has_form_tag(is_form_tag_);
if (!page_language_.empty() && randomized_encoder_ != nullptr) {
upload->set_language(page_language_);
}
@@ -574,6 +599,11 @@ bool FormStructure::EncodeUploadRequest(
upload->set_action_signature(StrToHash64Bit(target_url_.host()));
if (!form_name().empty())
upload->set_form_name(base::UTF16ToUTF8(form_name()));
+ for (const ButtonTitleInfo& e : button_titles_) {
+ auto* button_title = upload->add_button_title();
+ button_title->set_title(base::UTF16ToUTF8(e.first));
+ button_title->set_type(ToServerButtonTitleType(e.second));
+ }
}
if (!login_form_signature.empty()) {
@@ -720,14 +750,8 @@ void FormStructure::ProcessQueryResponse(
!query_response_has_no_server_data);
form->UpdateAutofillCount();
- if (base::FeatureList::IsEnabled(
- features::kAutofillRationalizeRepeatedServerPredictions))
- form->RationalizeRepeatedFields(form_interactions_ukm_logger);
-
- if (base::FeatureList::IsEnabled(
- features::kAutofillRationalizeFieldTypePredictions))
- form->RationalizeFieldTypePredictions();
-
+ form->RationalizeRepeatedFields(form_interactions_ukm_logger);
+ form->RationalizeFieldTypePredictions();
form->IdentifySections(false);
}
@@ -942,6 +966,7 @@ void FormStructure::LogQualityMetrics(
bool did_autofill_all_possible_fields = true;
bool did_autofill_some_possible_fields = false;
bool is_for_credit_card = IsCompleteCreditCardForm();
+ bool has_upi_vpa_field = false;
// Determine the correct suffix for the metric, depending on whether or
// not a submission was observed.
@@ -952,6 +977,7 @@ void FormStructure::LogQualityMetrics(
for (size_t i = 0; i < field_count(); ++i) {
auto* const field = this->field(i);
if (IsUPIVirtualPaymentAddress(field->value)) {
+ has_upi_vpa_field = true;
AutofillMetrics::LogUserHappinessMetric(
AutofillMetrics::USER_DID_ENTER_UPI_VPA, field->Type().group(),
security_state::SecurityLevel::SECURITY_LEVEL_COUNT);
@@ -1036,8 +1062,8 @@ void FormStructure::LogQualityMetrics(
}
AutofillMetrics::LogAutofillFormSubmittedState(
- state, is_for_credit_card, GetFormTypes(), form_parsed_timestamp_,
- form_signature(), form_interactions_ukm_logger);
+ state, is_for_credit_card, has_upi_vpa_field, GetFormTypes(),
+ form_parsed_timestamp_, form_signature(), form_interactions_ukm_logger);
}
}
diff --git a/chromium/components/autofill/core/browser/form_structure.h b/chromium/components/autofill/core/browser/form_structure.h
index ba04acb0136..218c73ed169 100644
--- a/chromium/components/autofill/core/browser/form_structure.h
+++ b/chromium/components/autofill/core/browser/form_structure.h
@@ -488,8 +488,8 @@ class FormStructure {
// The name of the form.
base::string16 form_name_;
- // The title of form submission button.
- base::string16 button_title_;
+ // The titles of form's buttons.
+ ButtonTitleList button_titles_;
// The type of the event that was taken as an indication that the form has
// been successfully submitted.
diff --git a/chromium/components/autofill/core/browser/form_structure_unittest.cc b/chromium/components/autofill/core/browser/form_structure_unittest.cc
index 0ce878fee0c..cdc3cd526ad 100644
--- a/chromium/components/autofill/core/browser/form_structure_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_structure_unittest.cc
@@ -33,7 +33,6 @@ using base::ASCIIToUTF16;
using autofill::features::kAutofillEnforceMinRequiredFieldsForHeuristics;
using autofill::features::kAutofillEnforceMinRequiredFieldsForQuery;
using autofill::features::kAutofillEnforceMinRequiredFieldsForUpload;
-using autofill::features::kAutofillRationalizeRepeatedServerPredictions;
namespace autofill {
@@ -2445,6 +2444,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithMatchingValidities) {
std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities;
FormData form;
form.origin = GURL("http://www.foo.com/");
+ form.is_form_tag = true;
form_structure = std::make_unique<FormStructure>(form);
form_structure->DetermineHeuristicTypes();
@@ -2538,6 +2538,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithMatchingValidities) {
upload.set_action_signature(15724779818122431245U);
upload.set_submission_event(
AutofillUploadContents_SubmissionIndicatorEvent_NONE);
+ upload.set_has_form_tag(true);
test::FillUploadField(upload.add_field(), 3763331450U, "firstname", "text",
nullptr, 3U, 0);
@@ -2766,6 +2767,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithMultipleValidities) {
std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities;
FormData form;
form.origin = GURL("http://www.foo.com/");
+ form.is_form_tag = true;
form_structure = std::make_unique<FormStructure>(form);
form_structure->DetermineHeuristicTypes();
@@ -2860,6 +2862,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithMultipleValidities) {
upload.set_action_signature(15724779818122431245U);
upload.set_submission_event(
AutofillUploadContents_SubmissionIndicatorEvent_NONE);
+ upload.set_has_form_tag(true);
test::FillUploadField(upload.add_field(), 3763331450U, "firstname", "text",
nullptr, 3U, {0, 2});
@@ -2893,6 +2896,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest) {
std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities;
FormData form;
form.origin = GURL("http://www.foo.com/");
+ form.is_form_tag = true;
form_structure = std::make_unique<FormStructure>(form);
form_structure->DetermineHeuristicTypes();
@@ -2984,6 +2988,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest) {
upload.set_password_has_numeric(true);
upload.set_password_length(10u);
upload.set_action_signature(15724779818122431245U);
+ upload.set_has_form_tag(true);
test::FillUploadField(upload.add_field(), 3763331450U, "firstname", "text",
nullptr, 3U);
@@ -3104,6 +3109,7 @@ TEST_F(FormStructureTest,
std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities;
FormData form;
form.origin = GURL("http://www.foo.com/");
+ form.is_form_tag = true;
form_structure = std::make_unique<FormStructure>(form);
form_structure->DetermineHeuristicTypes();
@@ -3183,6 +3189,7 @@ TEST_F(FormStructureTest,
upload.set_passwords_revealed(false);
upload.set_submission_event(
AutofillUploadContents_SubmissionIndicatorEvent_NONE);
+ upload.set_has_form_tag(true);
AutofillUploadContents::Field* upload_firstname_field = upload.add_field();
test::FillUploadField(upload_firstname_field, 4224610201U, "firstname", "",
@@ -3228,6 +3235,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithAutocomplete) {
std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities;
FormData form;
form.origin = GURL("http://www.foo.com/");
+ form.is_form_tag = true;
form_structure = std::make_unique<FormStructure>(form);
form_structure->DetermineHeuristicTypes();
@@ -3282,6 +3290,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithAutocomplete) {
upload.set_passwords_revealed(false);
upload.set_submission_event(
AutofillUploadContents_SubmissionIndicatorEvent_NONE);
+ upload.set_has_form_tag(true);
test::FillUploadField(upload.add_field(), 3763331450U, "firstname", "text",
"given-name", 3U);
@@ -3310,6 +3319,7 @@ TEST_F(FormStructureTest, EncodeUploadRequestWithPropertiesMask) {
std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities;
FormData form;
form.origin = GURL("http://www.foo.com/");
+ form.is_form_tag = true;
form_structure = std::make_unique<FormStructure>(form);
form_structure->DetermineHeuristicTypes();
@@ -3377,6 +3387,7 @@ TEST_F(FormStructureTest, EncodeUploadRequestWithPropertiesMask) {
upload.set_passwords_revealed(false);
upload.set_submission_event(
AutofillUploadContents_SubmissionIndicatorEvent_NONE);
+ upload.set_has_form_tag(true);
test::FillUploadField(upload.add_field(), 3763331450U, nullptr, nullptr,
nullptr, 3U);
@@ -3408,6 +3419,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_ObservedSubmissionFalse) {
std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities;
FormData form;
form.origin = GURL("http://www.foo.com/");
+ form.is_form_tag = true;
form_structure = std::make_unique<FormStructure>(form);
form_structure->DetermineHeuristicTypes();
@@ -3462,6 +3474,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_ObservedSubmissionFalse) {
upload.set_passwords_revealed(false);
upload.set_submission_event(
AutofillUploadContents_SubmissionIndicatorEvent_NONE);
+ upload.set_has_form_tag(true);
test::FillUploadField(upload.add_field(), 3763331450U, "firstname", "text",
nullptr, 3U);
@@ -3489,6 +3502,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithLabels) {
std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities;
FormData form;
form.origin = GURL("http://www.foo.com/");
+ form.is_form_tag = true;
form_structure = std::make_unique<FormStructure>(form);
form_structure->DetermineHeuristicTypes();
@@ -3536,6 +3550,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithLabels) {
upload.set_passwords_revealed(false);
upload.set_submission_event(
AutofillUploadContents_SubmissionIndicatorEvent_NONE);
+ upload.set_has_form_tag(true);
test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text",
nullptr, 3U);
@@ -3561,6 +3576,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithCssClassesAndIds) {
std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities;
FormData form;
form.origin = GURL("http://www.foo.com/");
+ form.is_form_tag = true;
FormFieldData field;
field.form_control_type = "text";
@@ -3606,6 +3622,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithCssClassesAndIds) {
upload.set_passwords_revealed(false);
upload.set_submission_event(
AutofillUploadContents_SubmissionIndicatorEvent_NONE);
+ upload.set_has_form_tag(true);
AutofillUploadContents::Field* firstname_field = upload.add_field();
test::FillUploadField(firstname_field, 1318412689U, nullptr, "text", nullptr,
@@ -3641,6 +3658,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithFormName) {
std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities;
FormData form;
form.origin = GURL("http://www.foo.com/");
+ form.is_form_tag = true;
// Setting the form name which we expect to see in the upload.
form.name = ASCIIToUTF16("myform");
@@ -3690,6 +3708,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithFormName) {
upload.set_passwords_revealed(false);
upload.set_submission_event(
AutofillUploadContents_SubmissionIndicatorEvent_FRAME_DETACHED);
+ upload.set_has_form_tag(true);
test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text",
nullptr, 3U);
@@ -3716,6 +3735,7 @@ TEST_F(FormStructureTest, EncodeUploadRequestPartialMetadata) {
std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities;
FormData form;
form.origin = GURL("http://www.foo.com/");
+ form.is_form_tag = true;
form_structure = std::make_unique<FormStructure>(form);
form_structure->DetermineHeuristicTypes();
@@ -3770,6 +3790,7 @@ TEST_F(FormStructureTest, EncodeUploadRequestPartialMetadata) {
upload.set_action_signature(15724779818122431245U);
upload.set_submission_event(
AutofillUploadContents_SubmissionIndicatorEvent_NONE);
+ upload.set_has_form_tag(true);
test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text",
nullptr, 3U);
@@ -3799,6 +3820,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_DisabledMetadataTrial) {
std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities;
FormData form;
form.origin = GURL("http://www.foo.com/");
+ form.is_form_tag = true;
form_structure = std::make_unique<FormStructure>(form);
form_structure->DetermineHeuristicTypes();
@@ -3861,6 +3883,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_DisabledMetadataTrial) {
upload.set_passwords_revealed(false);
upload.set_submission_event(
AutofillUploadContents_SubmissionIndicatorEvent_NONE);
+ upload.set_has_form_tag(true);
test::FillUploadField(upload.add_field(), 3763331450U, nullptr, nullptr,
nullptr, 3U);
@@ -3886,6 +3909,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_DisabledMetadataTrial) {
TEST_F(FormStructureTest, CheckDataPresence) {
FormData form;
form.origin = GURL("http://www.foo.com/");
+ form.is_form_tag = true;
FormFieldData field;
field.form_control_type = "text";
@@ -3935,6 +3959,7 @@ TEST_F(FormStructureTest, CheckDataPresence) {
upload.set_action_signature(15724779818122431245U);
upload.set_submission_event(
AutofillUploadContents_SubmissionIndicatorEvent_HTML_FORM_SUBMISSION);
+ upload.set_has_form_tag(true);
test::FillUploadField(upload.add_field(), 1089846351U, "first", "text",
nullptr, 1U);
@@ -4164,6 +4189,7 @@ TEST_F(FormStructureTest, CheckMultipleTypes) {
std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities;
FormData form;
form.origin = GURL("http://www.foo.com/");
+ form.is_form_tag = false;
FormFieldData field;
field.form_control_type = "text";
@@ -4213,6 +4239,7 @@ TEST_F(FormStructureTest, CheckMultipleTypes) {
upload.set_autofill_used(false);
upload.set_data_present("1440000360000008");
upload.set_passwords_revealed(false);
+ upload.set_has_form_tag(false);
upload.set_action_signature(15724779818122431245U);
upload.set_submission_event(
AutofillUploadContents_SubmissionIndicatorEvent_XHR_SUCCEEDED);
@@ -4330,6 +4357,29 @@ TEST_F(FormStructureTest, EncodeUploadRequest_PasswordsRevealed) {
EXPECT_EQ(true, upload.passwords_revealed());
}
+TEST_F(FormStructureTest, EncodeUploadRequest_IsFormTag) {
+ for (bool is_form_tag : {false, true}) {
+ SCOPED_TRACE(testing::Message() << "is_form_tag=" << is_form_tag);
+
+ FormData form;
+ form.origin = GURL("http://www.foo.com/");
+ FormFieldData field;
+ field.name = ASCIIToUTF16("email");
+ form.fields.push_back(field);
+
+ form.is_form_tag = is_form_tag;
+
+ FormStructure form_structure(form);
+ form_structure.set_passwords_were_revealed(true);
+ AutofillUploadContents upload;
+ EXPECT_TRUE(form_structure.EncodeUploadRequest(
+ {{}} /* available_field_types */, false /* form_was_autofilled */,
+ std::string() /* login_form_signature */,
+ true /* observed_submission */, &upload));
+ EXPECT_EQ(is_form_tag, upload.has_form_tag());
+ }
+}
+
TEST_F(FormStructureTest, EncodeUploadRequest_RichMetadata) {
struct FieldMetadata {
const char *id, *name, *label, *placeholder, *aria_label, *aria_description,
@@ -5178,36 +5228,14 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeLoneField) {
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
- // Test that the expiry month field is rationalized away when enabled.
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormStructure::ParseQueryResponse(response_string, forms, nullptr);
- ASSERT_EQ(1U, forms.size());
- ASSERT_EQ(4U, forms[0]->field_count());
- EXPECT_EQ(NAME_FULL, forms[0]->field(0)->Type().GetStorableType());
- EXPECT_EQ(ADDRESS_HOME_LINE1, forms[0]->field(1)->Type().GetStorableType());
- EXPECT_EQ(UNKNOWN_TYPE, forms[0]->field(2)->Type().GetStorableType());
- EXPECT_EQ(EMAIL_ADDRESS, forms[0]->field(3)->Type().GetStorableType());
- }
-
- // Sanity check that the enable/disabled works.
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormStructure::ParseQueryResponse(response_string, forms, nullptr);
- ASSERT_EQ(1U, forms.size());
- ASSERT_EQ(4U, forms[0]->field_count());
- EXPECT_EQ(NAME_FULL, forms[0]->field(0)->Type().GetStorableType());
- EXPECT_EQ(ADDRESS_HOME_LINE1, forms[0]->field(1)->Type().GetStorableType());
- EXPECT_EQ(CREDIT_CARD_EXP_MONTH,
- forms[0]->field(2)->Type().GetStorableType());
- EXPECT_EQ(EMAIL_ADDRESS, forms[0]->field(3)->Type().GetStorableType());
- }
+ // Test that the expiry month field is rationalized away.
+ FormStructure::ParseQueryResponse(response_string, forms, nullptr);
+ ASSERT_EQ(1U, forms.size());
+ ASSERT_EQ(4U, forms[0]->field_count());
+ EXPECT_EQ(NAME_FULL, forms[0]->field(0)->Type().GetStorableType());
+ EXPECT_EQ(ADDRESS_HOME_LINE1, forms[0]->field(1)->Type().GetStorableType());
+ EXPECT_EQ(UNKNOWN_TYPE, forms[0]->field(2)->Type().GetStorableType());
+ EXPECT_EQ(EMAIL_ADDRESS, forms[0]->field(3)->Type().GetStorableType());
}
TEST_F(FormStructureTest, ParseQueryResponse_RationalizeCCName) {
@@ -5240,35 +5268,13 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeCCName) {
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
- // Test that the name fields are rationalized when enabled.
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormStructure::ParseQueryResponse(response_string, forms, nullptr);
- ASSERT_EQ(1U, forms.size());
- ASSERT_EQ(3U, forms[0]->field_count());
- EXPECT_EQ(NAME_FIRST, forms[0]->field(0)->Type().GetStorableType());
- EXPECT_EQ(NAME_LAST, forms[0]->field(1)->Type().GetStorableType());
- EXPECT_EQ(EMAIL_ADDRESS, forms[0]->field(2)->Type().GetStorableType());
- }
-
- // Sanity check that the enable/disabled works.
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormStructure::ParseQueryResponse(response_string, forms, nullptr);
- ASSERT_EQ(1U, forms.size());
- ASSERT_EQ(3U, forms[0]->field_count());
- EXPECT_EQ(CREDIT_CARD_NAME_FIRST,
- forms[0]->field(0)->Type().GetStorableType());
- EXPECT_EQ(CREDIT_CARD_NAME_LAST,
- forms[0]->field(1)->Type().GetStorableType());
- EXPECT_EQ(EMAIL_ADDRESS, forms[0]->field(2)->Type().GetStorableType());
- }
+ // Test that the name fields are rationalized.
+ FormStructure::ParseQueryResponse(response_string, forms, nullptr);
+ ASSERT_EQ(1U, forms.size());
+ ASSERT_EQ(3U, forms[0]->field_count());
+ EXPECT_EQ(NAME_FIRST, forms[0]->field(0)->Type().GetStorableType());
+ EXPECT_EQ(NAME_LAST, forms[0]->field(1)->Type().GetStorableType());
+ EXPECT_EQ(EMAIL_ADDRESS, forms[0]->field(2)->Type().GetStorableType());
}
TEST_F(FormStructureTest, ParseQueryResponse_RationalizeMultiMonth_1) {
@@ -5313,44 +5319,18 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeMultiMonth_1) {
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
- // Test that the extra month field is rationalized away when enabled.
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormStructure::ParseQueryResponse(response_string, forms, nullptr);
- ASSERT_EQ(1U, forms.size());
- ASSERT_EQ(5U, forms[0]->field_count());
- EXPECT_EQ(CREDIT_CARD_NAME_FULL,
- forms[0]->field(0)->Type().GetStorableType());
- EXPECT_EQ(CREDIT_CARD_NUMBER, forms[0]->field(1)->Type().GetStorableType());
- EXPECT_EQ(CREDIT_CARD_EXP_MONTH,
- forms[0]->field(2)->Type().GetStorableType());
- EXPECT_EQ(CREDIT_CARD_EXP_2_DIGIT_YEAR,
- forms[0]->field(3)->Type().GetStorableType());
- EXPECT_EQ(UNKNOWN_TYPE, forms[0]->field(4)->Type().GetStorableType());
- }
-
- // Sanity check that the enable/disabled works.
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
-
- FormStructure::ParseQueryResponse(response_string, forms, nullptr);
- ASSERT_EQ(1U, forms.size());
- ASSERT_EQ(5U, forms[0]->field_count());
- EXPECT_EQ(CREDIT_CARD_NAME_FULL,
- forms[0]->field(0)->Type().GetStorableType());
- EXPECT_EQ(CREDIT_CARD_NUMBER, forms[0]->field(1)->Type().GetStorableType());
- EXPECT_EQ(CREDIT_CARD_EXP_MONTH,
- forms[0]->field(2)->Type().GetStorableType());
- EXPECT_EQ(CREDIT_CARD_EXP_2_DIGIT_YEAR,
- forms[0]->field(3)->Type().GetStorableType());
- EXPECT_EQ(CREDIT_CARD_EXP_MONTH,
- forms[0]->field(4)->Type().GetStorableType());
- }
+ // Test that the extra month field is rationalized away.
+ FormStructure::ParseQueryResponse(response_string, forms, nullptr);
+ ASSERT_EQ(1U, forms.size());
+ ASSERT_EQ(5U, forms[0]->field_count());
+ EXPECT_EQ(CREDIT_CARD_NAME_FULL,
+ forms[0]->field(0)->Type().GetStorableType());
+ EXPECT_EQ(CREDIT_CARD_NUMBER, forms[0]->field(1)->Type().GetStorableType());
+ EXPECT_EQ(CREDIT_CARD_EXP_MONTH,
+ forms[0]->field(2)->Type().GetStorableType());
+ EXPECT_EQ(CREDIT_CARD_EXP_2_DIGIT_YEAR,
+ forms[0]->field(3)->Type().GetStorableType());
+ EXPECT_EQ(UNKNOWN_TYPE, forms[0]->field(4)->Type().GetStorableType());
}
TEST_F(FormStructureTest, ParseQueryResponse_RationalizeMultiMonth_2) {
@@ -5390,38 +5370,16 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeMultiMonth_2) {
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
- // Test that the extra month field is rationalized away when enabled.
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
- FormStructure::ParseQueryResponse(response_string, forms, nullptr);
- ASSERT_EQ(1U, forms.size());
- ASSERT_EQ(4U, forms[0]->field_count());
- EXPECT_EQ(CREDIT_CARD_NAME_FULL,
- forms[0]->field(0)->Type().GetStorableType());
- EXPECT_EQ(CREDIT_CARD_NUMBER, forms[0]->field(1)->Type().GetStorableType());
- EXPECT_EQ(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR,
- forms[0]->field(2)->Type().GetStorableType());
- EXPECT_EQ(UNKNOWN_TYPE, forms[0]->field(3)->Type().GetStorableType());
- }
-
- // Sanity check that the enable/disabled works.
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(
- autofill::features::kAutofillRationalizeFieldTypePredictions);
- FormStructure::ParseQueryResponse(response_string, forms, nullptr);
- ASSERT_EQ(1U, forms.size());
- ASSERT_EQ(4U, forms[0]->field_count());
- EXPECT_EQ(CREDIT_CARD_NAME_FULL,
- forms[0]->field(0)->Type().GetStorableType());
- EXPECT_EQ(CREDIT_CARD_NUMBER, forms[0]->field(1)->Type().GetStorableType());
- EXPECT_EQ(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR,
- forms[0]->field(2)->Type().GetStorableType());
- EXPECT_EQ(CREDIT_CARD_EXP_MONTH,
- forms[0]->field(3)->Type().GetStorableType());
- }
+ // Test that the extra month field is rationalized away.
+ FormStructure::ParseQueryResponse(response_string, forms, nullptr);
+ ASSERT_EQ(1U, forms.size());
+ ASSERT_EQ(4U, forms[0]->field_count());
+ EXPECT_EQ(CREDIT_CARD_NAME_FULL,
+ forms[0]->field(0)->Type().GetStorableType());
+ EXPECT_EQ(CREDIT_CARD_NUMBER, forms[0]->field(1)->Type().GetStorableType());
+ EXPECT_EQ(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR,
+ forms[0]->field(2)->Type().GetStorableType());
+ EXPECT_EQ(UNKNOWN_TYPE, forms[0]->field(3)->Type().GetStorableType());
}
TEST_F(FormStructureTest, FindLongestCommonPrefix) {
@@ -5520,10 +5478,6 @@ TEST_F(FormStructureTest, RationalizePhoneNumber_RunsOncePerSection) {
// Tests that a form that has only one address predicted as
// ADDRESS_HOME_STREET_ADDRESS is not modified by the address rationalization.
TEST_F(FormStructureTest, RationalizeRepeatedFields_OneAddress) {
- base::test::ScopedFeatureList feature_list;
- InitFeature(&feature_list, kAutofillRationalizeRepeatedServerPredictions,
- true);
-
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
@@ -5570,10 +5524,6 @@ TEST_F(FormStructureTest, RationalizeRepeatedFields_OneAddress) {
// ADDRESS_HOME_STREET_ADDRESS is modified by the address rationalization to be
// ADDRESS_HOME_LINE1 and ADDRESS_HOME_LINE2 instead.
TEST_F(FormStructureTest, RationalizeRepreatedFields_TwoAddresses) {
- base::test::ScopedFeatureList feature_list;
- InitFeature(&feature_list, kAutofillRationalizeRepeatedServerPredictions,
- true);
-
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
@@ -5626,10 +5576,6 @@ TEST_F(FormStructureTest, RationalizeRepreatedFields_TwoAddresses) {
// ADDRESS_HOME_STREET_ADDRESS is modified by the address rationalization to be
// ADDRESS_HOME_LINE1, ADDRESS_HOME_LINE2 and ADDRESS_HOME_LINE3 instead.
TEST_F(FormStructureTest, RationalizeRepreatedFields_ThreeAddresses) {
- base::test::ScopedFeatureList feature_list;
- InitFeature(&feature_list, kAutofillRationalizeRepeatedServerPredictions,
- true);
-
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
@@ -5690,9 +5636,6 @@ TEST_F(FormStructureTest, RationalizeRepreatedFields_ThreeAddresses) {
// This doesn't happen in real world, bc four address lines mean multiple
// sections according to the heuristics.
TEST_F(FormStructureTest, RationalizeRepreatedFields_FourAddresses) {
- base::test::ScopedFeatureList feature_list;
- InitFeature(&feature_list, kAutofillRationalizeRepeatedServerPredictions,
- true);
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
@@ -5762,10 +5705,6 @@ TEST_F(FormStructureTest, RationalizeRepreatedFields_FourAddresses) {
// Tests that a form that has only one address in each section predicted as
// ADDRESS_HOME_STREET_ADDRESS is not modified by the address rationalization.
TEST_F(FormStructureTest, RationalizeRepreatedFields_OneAddressEachSection) {
- base::test::ScopedFeatureList feature_list;
- InitFeature(&feature_list, kAutofillRationalizeRepeatedServerPredictions,
- true);
-
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
@@ -5839,15 +5778,11 @@ TEST_F(FormStructureTest, RationalizeRepreatedFields_OneAddressEachSection) {
// Tests a form that has multiple sections with multiple number of address
// fields predicted as ADDRESS_HOME_STREET_ADDRESS. The last section
-// doesn't happen in real world, bc it is in fact two sections according to
+// doesn't happen in real world, because it is in fact two sections according to
// heuristics, and is only made for testing.
TEST_F(
FormStructureTest,
RationalizeRepreatedFields_SectionTwoAddress_SectionThreeAddress_SectionFourAddresses) {
- base::test::ScopedFeatureList feature_list;
- InitFeature(&feature_list, kAutofillRationalizeRepeatedServerPredictions,
- true);
-
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
@@ -6001,10 +5936,6 @@ TEST_F(
// while the sections are previously determined by the heuristics.
TEST_F(FormStructureTest,
RationalizeRepreatedFields_MultipleSectionsByHeuristics_OneAddressEach) {
- base::test::ScopedFeatureList feature_list;
- InitFeature(&feature_list, kAutofillRationalizeRepeatedServerPredictions,
- true);
-
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
@@ -6078,10 +6009,6 @@ TEST_F(FormStructureTest,
TEST_F(
FormStructureTest,
RationalizeRepreatedFields_MultipleSectionsByHeuristics_TwoAddress_ThreeAddress) {
- base::test::ScopedFeatureList feature_list;
- InitFeature(&feature_list, kAutofillRationalizeRepeatedServerPredictions,
- true);
-
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
@@ -6171,10 +6098,6 @@ TEST_F(
TEST_F(FormStructureTest,
RationalizeRepreatedFields_StateCountry_NoRationalization) {
- base::test::ScopedFeatureList feature_list;
- InitFeature(&feature_list, kAutofillRationalizeRepeatedServerPredictions,
- true);
-
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
@@ -6270,10 +6193,6 @@ TEST_F(FormStructureTest,
}
TEST_F(FormStructureTest, RationalizeRepreatedFields_CountryStateNoHeuristics) {
- base::test::ScopedFeatureList feature_list;
- InitFeature(&feature_list, kAutofillRationalizeRepeatedServerPredictions,
- true);
-
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
@@ -6405,10 +6324,6 @@ TEST_F(FormStructureTest, RationalizeRepreatedFields_CountryStateNoHeuristics) {
TEST_F(FormStructureTest,
RationalizeRepreatedFields_StateCountryWithHeuristics) {
- base::test::ScopedFeatureList feature_list;
- InitFeature(&feature_list, kAutofillRationalizeRepeatedServerPredictions,
- true);
-
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
@@ -6540,10 +6455,6 @@ TEST_F(FormStructureTest,
}
TEST_F(FormStructureTest, RationalizeRepreatedFields_FirstFieldRationalized) {
- base::test::ScopedFeatureList feature_list;
- InitFeature(&feature_list, kAutofillRationalizeRepeatedServerPredictions,
- true);
-
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
@@ -6605,10 +6516,6 @@ TEST_F(FormStructureTest, RationalizeRepreatedFields_FirstFieldRationalized) {
}
TEST_F(FormStructureTest, RationalizeRepreatedFields_LastFieldRationalized) {
- base::test::ScopedFeatureList feature_list;
- InitFeature(&feature_list, kAutofillRationalizeRepeatedServerPredictions,
- true);
-
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
@@ -6681,8 +6588,8 @@ TEST_F(FormStructureTest, AllowBigForms) {
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
- // Check that the form with 100 fields are processed correctly.
- for (size_t i = 0; i < 100; ++i) {
+ // Check that the form with 250 fields are processed correctly.
+ for (size_t i = 0; i < 250; ++i) {
field.form_control_type = "text";
field.name = ASCIIToUTF16("text") + base::NumberToString16(i);
form.fields.push_back(field);
diff --git a/chromium/components/autofill/core/browser/legacy_strike_database.cc b/chromium/components/autofill/core/browser/legacy_strike_database.cc
index e6df31e20be..e6fbef3f7d3 100644
--- a/chromium/components/autofill/core/browser/legacy_strike_database.cc
+++ b/chromium/components/autofill/core/browser/legacy_strike_database.cc
@@ -12,7 +12,7 @@
#include "base/task/post_task.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/proto/strike_data.pb.h"
-#include "components/leveldb_proto/proto_database_impl.h"
+#include "components/leveldb_proto/public/proto_database_provider.h"
namespace autofill {
@@ -23,7 +23,7 @@ const char kKeyPrefixForCreditCardSave[] = "creditCardSave";
} // namespace
LegacyStrikeDatabase::LegacyStrikeDatabase(const base::FilePath& database_dir)
- : db_(std::make_unique<leveldb_proto::ProtoDatabaseImpl<StrikeData>>(
+ : db_(leveldb_proto::ProtoDatabaseProvider::CreateUniqueDB<StrikeData>(
base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}))),
diff --git a/chromium/components/autofill/core/browser/legacy_strike_database.h b/chromium/components/autofill/core/browser/legacy_strike_database.h
index 57b0fe4a404..c0aca236581 100644
--- a/chromium/components/autofill/core/browser/legacy_strike_database.h
+++ b/chromium/components/autofill/core/browser/legacy_strike_database.h
@@ -12,7 +12,7 @@
#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "components/leveldb_proto/proto_database.h"
+#include "components/leveldb_proto/public/proto_database.h"
namespace autofill {
class StrikeData;
diff --git a/chromium/components/autofill/core/browser/local_card_migration_manager.cc b/chromium/components/autofill/core/browser/local_card_migration_manager.cc
index a10aee8ff49..764f9159b7f 100644
--- a/chromium/components/autofill/core/browser/local_card_migration_manager.cc
+++ b/chromium/components/autofill/core/browser/local_card_migration_manager.cc
@@ -94,9 +94,10 @@ void LocalCardMigrationManager::AttemptToOfferLocalCardMigration(
base::BindOnce(&LocalCardMigrationManager::OnDidGetUploadDetails,
weak_ptr_factory_.GetWeakPtr(), is_from_settings_page),
payments::kMigrateCardsBillableServiceNumber,
- is_from_settings_page
- ? payments::PaymentsClient::MigrationSource::SETTINGS_PAGE
- : payments::PaymentsClient::MigrationSource::CHECKOUT_FLOW);
+ is_from_settings_page ? payments::PaymentsClient::UploadCardSource::
+ LOCAL_CARD_MIGRATION_SETTINGS_PAGE
+ : payments::PaymentsClient::UploadCardSource::
+ LOCAL_CARD_MIGRATION_CHECKOUT_FLOW);
}
// Callback function when user agrees to migration on the intermediate dialog.
@@ -161,10 +162,10 @@ void LocalCardMigrationManager::OnDidGetUploadDetails(
bool is_from_settings_page,
AutofillClient::PaymentsRpcResult result,
const base::string16& context_token,
- std::unique_ptr<base::DictionaryValue> legal_message) {
+ std::unique_ptr<base::Value> legal_message) {
if (result == AutofillClient::SUCCESS) {
migration_request_.context_token = context_token;
- legal_message_ = std::move(legal_message);
+ 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
@@ -272,7 +273,9 @@ 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_), migratable_credit_cards_,
+ std::move(legal_message_),
+ client_->GetIdentityManager()->GetPrimaryAccountInfo().email,
+ migratable_credit_cards_,
base::BindOnce(
&LocalCardMigrationManager::OnUserAcceptedMainMigrationDialog,
weak_ptr_factory_.GetWeakPtr()));
diff --git a/chromium/components/autofill/core/browser/local_card_migration_manager.h b/chromium/components/autofill/core/browser/local_card_migration_manager.h
index b2a5f9cb94f..06e5ce5832c 100644
--- a/chromium/components/autofill/core/browser/local_card_migration_manager.h
+++ b/chromium/components/autofill/core/browser/local_card_migration_manager.h
@@ -123,7 +123,7 @@ class LocalCardMigrationManager {
bool is_from_settings_page,
AutofillClient::PaymentsRpcResult result,
const base::string16& context_token,
- std::unique_ptr<base::DictionaryValue> legal_message);
+ std::unique_ptr<base::Value> legal_message);
// Callback after successfully getting the migration save results. Map
// migration save result to each card depending on the |save_result|. Will
diff --git a/chromium/components/autofill/core/browser/local_card_migration_manager_unittest.cc b/chromium/components/autofill/core/browser/local_card_migration_manager_unittest.cc
index 341904811fb..6dd9308c48a 100644
--- a/chromium/components/autofill/core/browser/local_card_migration_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/local_card_migration_manager_unittest.cc
@@ -26,6 +26,7 @@
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/mock_autocomplete_history_manager.h"
#include "components/autofill/core/browser/payments/test_payments_client.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/test_autofill_client.h"
@@ -90,7 +91,8 @@ class LocalCardMigrationManagerTest : public testing::Test {
autofill_client_.set_test_form_data_importer(
std::unique_ptr<TestFormDataImporter>(test_form_data_importer));
autofill_manager_.reset(new TestAutofillManager(
- autofill_driver_.get(), &autofill_client_, &personal_data_));
+ autofill_driver_.get(), &autofill_client_, &personal_data_,
+ &autocomplete_history_manager_));
autofill_manager_->SetExpectedObservedSubmission(true);
}
@@ -121,8 +123,8 @@ class LocalCardMigrationManagerTest : public testing::Test {
}
void FormSubmitted(const FormData& form) {
- autofill_manager_->OnFormSubmitted(
- form, false, SubmissionSource::FORM_SUBMISSION, base::TimeTicks::Now());
+ autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
}
void EditCreditCardFrom(FormData& credit_card_form,
@@ -172,6 +174,7 @@ class LocalCardMigrationManagerTest : public testing::Test {
std::unique_ptr<TestAutofillManager> autofill_manager_;
scoped_refptr<net::TestURLRequestContextGetter> request_context_;
TestPersonalDataManager personal_data_;
+ MockAutocompleteHistoryManager autocomplete_history_manager_;
syncer::TestSyncService sync_service_;
base::test::ScopedFeatureList scoped_feature_list_;
// Ends up getting owned (and destroyed) by TestFormDataImporter:
@@ -670,6 +673,99 @@ TEST_F(LocalCardMigrationManagerTest,
CreditCardSaveManager::DetectedValue::HAS_GOOGLE_PAYMENTS_ACCOUNT);
}
+TEST_F(LocalCardMigrationManagerTest,
+ MigrateCreditCard_ShouldAddMigrateCardsBillableServiceNumberInRequest) {
+ EnableAutofillCreditCardLocalCardMigrationExperiment();
+
+ // Set the billing_customer_number Priority Preference to designate
+ // existence of a Payments account.
+ autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
+ 12345);
+ // Add a local credit card whose |TypeAndLastFourDigits| matches what we will
+ // enter below.
+ AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
+ test::NextYear().c_str(), "1", "guid1");
+ // Add another local credit card
+ AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11",
+ test::NextYear().c_str(), "1", "guid2");
+
+ // Set up our credit card form data.
+ FormData credit_card_form;
+ test::CreateTestCreditCardFormData(&credit_card_form, true, false);
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+
+ // Edit the data, and submit.
+ EditCreditCardFrom(credit_card_form, "Flo Master", "4111111111111111", "11",
+ test::NextYear().c_str(), "123");
+ FormSubmitted(credit_card_form);
+ EXPECT_TRUE(local_card_migration_manager_->LocalCardMigrationWasTriggered());
+
+ // Confirm that the preflight request contained
+ // kMigrateCardsBillableServiceNumber in the request.
+ EXPECT_EQ(payments::kMigrateCardsBillableServiceNumber,
+ payments_client_->billable_service_number_in_request());
+}
+
+TEST_F(LocalCardMigrationManagerTest,
+ MigrateCreditCard_ShouldAddUploadCardSourceInRequest_CheckoutFlow) {
+ EnableAutofillCreditCardLocalCardMigrationExperiment();
+
+ // Set the billing_customer_number Priority Preference to designate
+ // existence of a Payments account.
+ autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
+ 12345);
+ // Add a local credit card whose |TypeAndLastFourDigits| matches what we will
+ // enter below.
+ AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
+ test::NextYear().c_str(), "1", "guid1");
+ // Add another local credit card
+ AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11",
+ test::NextYear().c_str(), "1", "guid2");
+
+ // Set up our credit card form data.
+ FormData credit_card_form;
+ test::CreateTestCreditCardFormData(&credit_card_form, true, false);
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+
+ // Edit the data, and submit.
+ EditCreditCardFrom(credit_card_form, "Flo Master", "4111111111111111", "11",
+ test::NextYear().c_str(), "123");
+ FormSubmitted(credit_card_form);
+ EXPECT_TRUE(local_card_migration_manager_->LocalCardMigrationWasTriggered());
+
+ // Confirm that the preflight request contained the correct UploadCardSource.
+ EXPECT_EQ(payments::PaymentsClient::UploadCardSource::
+ LOCAL_CARD_MIGRATION_CHECKOUT_FLOW,
+ payments_client_->upload_card_source_in_request());
+}
+
+TEST_F(LocalCardMigrationManagerTest,
+ MigrateCreditCard_ShouldAddUploadCardSourceInRequest_SettingsPage) {
+ EnableAutofillCreditCardLocalCardMigrationExperiment();
+
+ // Set the billing_customer_number Priority Preference to designate
+ // existence of a Payments account.
+ autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
+ 12345);
+ // Add a local credit card. One migratable credit card will still trigger
+ // migration on settings page.
+ AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
+ test::NextYear().c_str(), "1", "guid1");
+
+ base::HistogramTester histogram_tester;
+ // Do the same operation as we bridge back from the settings page.
+ local_card_migration_manager_->GetMigratableCreditCards();
+ local_card_migration_manager_->AttemptToOfferLocalCardMigration(true);
+
+ EXPECT_FALSE(local_card_migration_manager_->IntermediatePromptWasShown());
+ EXPECT_TRUE(local_card_migration_manager_->MainPromptWasShown());
+
+ // Confirm that the preflight request contained the correct UploadCardSource.
+ EXPECT_EQ(payments::PaymentsClient::UploadCardSource::
+ LOCAL_CARD_MIGRATION_SETTINGS_PAGE,
+ payments_client_->upload_card_source_in_request());
+}
+
// Verify that when triggering from settings page, intermediate prompt will not
// be triggered.
TEST_F(LocalCardMigrationManagerTest,
diff --git a/chromium/components/autofill/core/browser/local_card_migration_strike_database.cc b/chromium/components/autofill/core/browser/local_card_migration_strike_database.cc
new file mode 100644
index 00000000000..6125d447a75
--- /dev/null
+++ b/chromium/components/autofill/core/browser/local_card_migration_strike_database.cc
@@ -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.
+
+#include "components/autofill/core/browser/local_card_migration_strike_database.h"
+
+#include "components/autofill/core/browser/proto/strike_data.pb.h"
+
+namespace autofill {
+
+LocalCardMigrationStrikeDatabase::LocalCardMigrationStrikeDatabase(
+ StrikeDatabase* strike_database)
+ : StrikeDatabaseIntegratorBase(strike_database) {
+ RemoveExpiredStrikes();
+}
+
+LocalCardMigrationStrikeDatabase::~LocalCardMigrationStrikeDatabase() {}
+
+std::string LocalCardMigrationStrikeDatabase::GetProjectPrefix() {
+ return "LocalCardMigration";
+}
+
+int LocalCardMigrationStrikeDatabase::GetMaxStrikesLimit() {
+ return 6;
+}
+
+long long LocalCardMigrationStrikeDatabase::GetExpiryTimeMicros() {
+ // Expiry time is 1 year.
+ return (long long)1000000 * 60 * 60 * 24 * 365;
+}
+
+bool LocalCardMigrationStrikeDatabase::UniqueIdsRequired() {
+ return false;
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/local_card_migration_strike_database.h b/chromium/components/autofill/core/browser/local_card_migration_strike_database.h
new file mode 100644
index 00000000000..ab25114d903
--- /dev/null
+++ b/chromium/components/autofill/core/browser/local_card_migration_strike_database.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_LOCAL_CARD_MIGRATION_STRIKE_DATABASE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_LOCAL_CARD_MIGRATION_STRIKE_DATABASE_H_
+
+#include <string>
+
+#include "components/autofill/core/browser/strike_database.h"
+#include "components/autofill/core/browser/strike_database_integrator_base.h"
+
+namespace autofill {
+
+// Implementation of StrikeDatabaseIntegratorBase for local card migrations.
+class LocalCardMigrationStrikeDatabase : public StrikeDatabaseIntegratorBase {
+ public:
+ LocalCardMigrationStrikeDatabase(StrikeDatabase* strike_database);
+ ~LocalCardMigrationStrikeDatabase() override;
+
+ std::string GetProjectPrefix() override;
+ int GetMaxStrikesLimit() override;
+ long long GetExpiryTimeMicros() override;
+ bool UniqueIdsRequired() override;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_LOCAL_CARD_MIGRATION_STRIKE_DATABASE_H_
diff --git a/chromium/components/autofill/core/browser/local_card_migration_strike_database_unittest.cc b/chromium/components/autofill/core/browser/local_card_migration_strike_database_unittest.cc
new file mode 100644
index 00000000000..c7d3ad022d5
--- /dev/null
+++ b/chromium/components/autofill/core/browser/local_card_migration_strike_database_unittest.cc
@@ -0,0 +1,111 @@
+// 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/local_card_migration_strike_database.h"
+
+#include <utility>
+#include <vector>
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/run_loop.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/autofill/core/browser/proto/strike_data.pb.h"
+#include "components/autofill/core/browser/test_autofill_clock.h"
+#include "components/autofill/core/browser/test_local_card_migration_strike_database.h"
+#include "components/autofill/core/common/autofill_clock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+
+class LocalCardMigrationStrikeDatabaseTest : public ::testing::Test {
+ public:
+ LocalCardMigrationStrikeDatabaseTest()
+ : strike_database_(new StrikeDatabase(InitFilePath())) {}
+
+ protected:
+ base::HistogramTester* GetHistogramTester() { return &histogram_tester_; }
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ TestLocalCardMigrationStrikeDatabase strike_database_;
+
+ private:
+ static const base::FilePath InitFilePath() {
+ base::ScopedTempDir temp_dir_;
+ EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
+ const base::FilePath file_path =
+ temp_dir_.GetPath().AppendASCII("StrikeDatabaseTest");
+ return file_path;
+ }
+
+ base::HistogramTester histogram_tester_;
+};
+
+TEST_F(LocalCardMigrationStrikeDatabaseTest, MaxStrikesLimitReachedTest) {
+ EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached());
+ // 3 strikes added.
+ strike_database_.AddStrikes(3);
+ EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached());
+ // 4 strike added, total strike count is 7.
+ strike_database_.AddStrikes(4);
+ EXPECT_EQ(true, strike_database_.IsMaxStrikesLimitReached());
+}
+
+TEST_F(LocalCardMigrationStrikeDatabaseTest,
+ LocalCardMigrationNthStrikeAddedHistogram) {
+ // 2 strikes logged.
+ strike_database_.AddStrikes(2);
+ strike_database_.RemoveStrikes(2);
+ // 1 strike logged.
+ strike_database_.AddStrike();
+ // 2 strikes logged.
+ strike_database_.AddStrike();
+ std::vector<base::Bucket> buckets = GetHistogramTester()->GetAllSamples(
+ "Autofill.StrikeDatabase.NthStrikeAdded.LocalCardMigration");
+ // There should be two buckets, for strike counts of 1 and 2.
+ ASSERT_EQ(2U, buckets.size());
+ // Bucket for 1 strike should have count of 1.
+ EXPECT_EQ(1, buckets[0].count);
+ // Bucket for 2 strikes should have count of 2.
+ EXPECT_EQ(2, buckets[1].count);
+}
+
+TEST_F(LocalCardMigrationStrikeDatabaseTest,
+ AddStrikeForZeroAndNonZeroStrikesTest) {
+ EXPECT_EQ(0, strike_database_.GetStrikes());
+ strike_database_.AddStrike();
+ EXPECT_EQ(1, strike_database_.GetStrikes());
+ strike_database_.AddStrikes(2);
+ EXPECT_EQ(3, strike_database_.GetStrikes());
+}
+
+TEST_F(LocalCardMigrationStrikeDatabaseTest,
+ ClearStrikesForNonZeroStrikesTest) {
+ strike_database_.AddStrikes(3);
+ EXPECT_EQ(3, strike_database_.GetStrikes());
+ strike_database_.ClearStrikes();
+ EXPECT_EQ(0, strike_database_.GetStrikes());
+}
+
+TEST_F(LocalCardMigrationStrikeDatabaseTest, ClearStrikesForZeroStrikesTest) {
+ strike_database_.ClearStrikes();
+ EXPECT_EQ(0, strike_database_.GetStrikes());
+}
+
+TEST_F(LocalCardMigrationStrikeDatabaseTest, RemoveExpiredStrikesTest) {
+ autofill::TestAutofillClock test_clock;
+ test_clock.SetNow(AutofillClock::Now());
+ strike_database_.AddStrikes(2);
+ EXPECT_EQ(2, strike_database_.GetStrikes());
+
+ // Advance clock to past expiry time.
+ test_clock.Advance(base::TimeDelta::FromMicroseconds(
+ strike_database_.GetExpiryTimeMicros() + 1));
+
+ // One strike should be removed.
+ strike_database_.RemoveExpiredStrikes();
+ EXPECT_EQ(1, strike_database_.GetStrikes());
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/mock_autocomplete_history_manager.cc b/chromium/components/autofill/core/browser/mock_autocomplete_history_manager.cc
new file mode 100644
index 00000000000..38da60e06ef
--- /dev/null
+++ b/chromium/components/autofill/core/browser/mock_autocomplete_history_manager.cc
@@ -0,0 +1,14 @@
+// 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/mock_autocomplete_history_manager.h"
+
+#include "components/autofill/core/browser/autocomplete_history_manager.h"
+
+namespace autofill {
+MockAutocompleteHistoryManager::MockAutocompleteHistoryManager() = default;
+
+MockAutocompleteHistoryManager::~MockAutocompleteHistoryManager() = default;
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/mock_autocomplete_history_manager.h b/chromium/components/autofill/core/browser/mock_autocomplete_history_manager.h
new file mode 100644
index 00000000000..9a87d7fa745
--- /dev/null
+++ b/chromium/components/autofill/core/browser/mock_autocomplete_history_manager.h
@@ -0,0 +1,44 @@
+// 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_MOCK_AUTOCOMPLETE_HISTORY_MANAGER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_MOCK_AUTOCOMPLETE_HISTORY_MANAGER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "components/autofill/core/browser/autocomplete_history_manager.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace autofill {
+
+class MockAutocompleteHistoryManager : public AutocompleteHistoryManager {
+ public:
+ MockAutocompleteHistoryManager();
+ ~MockAutocompleteHistoryManager();
+
+ MOCK_METHOD2(Init, void(scoped_refptr<AutofillWebDataService>, bool));
+ MOCK_METHOD7(
+ OnGetAutocompleteSuggestions,
+ void(int query_id,
+ bool is_autocomplete_enabled,
+ bool autoselect_first_suggestion,
+ const base::string16& name,
+ const base::string16& prefix,
+ const std::string& form_control_type,
+ base::WeakPtr<AutocompleteHistoryManager::SuggestionsHandler>
+ handler));
+ MOCK_METHOD2(OnWillSubmitForm,
+ void(const FormData& form, bool is_autocomplete_enabled));
+ MOCK_METHOD2(OnWebDataServiceRequestDone,
+ void(WebDataServiceBase::Handle,
+ std::unique_ptr<WDTypedResult>));
+ MOCK_METHOD1(CancelPendingQueries,
+ void(const AutocompleteHistoryManager::SuggestionsHandler*));
+ MOCK_METHOD2(OnRemoveAutocompleteEntry,
+ void(const base::string16&, const base::string16&));
+ MOCK_METHOD1(OnAutocompleteEntrySelected, void(const base::string16&));
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_MOCK_AUTOCOMPLETE_HISTORY_MANAGER_H_
diff --git a/chromium/components/autofill/core/browser/name_field.cc b/chromium/components/autofill/core/browser/name_field.cc
index 6bbe3c1bf4f..a6ea9e76ff4 100644
--- a/chromium/components/autofill/core/browser/name_field.cc
+++ b/chromium/components/autofill/core/browser/name_field.cc
@@ -7,7 +7,6 @@
#include <memory>
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_scanner.h"
@@ -23,13 +22,12 @@ namespace {
class FullNameField : public NameField {
public:
static std::unique_ptr<FullNameField> Parse(AutofillScanner* scanner);
+ explicit FullNameField(AutofillField* field);
protected:
void AddClassifications(FieldCandidatesMap* field_candidates) const override;
private:
- explicit FullNameField(AutofillField* field);
-
AutofillField* field_;
DISALLOW_COPY_AND_ASSIGN(FullNameField);
@@ -91,7 +89,7 @@ std::unique_ptr<FullNameField> FullNameField::Parse(AutofillScanner* scanner) {
// "Travel Profile Name".
AutofillField* field = nullptr;
if (ParseField(scanner, UTF8ToUTF16(kNameRe), &field))
- return base::WrapUnique(new FullNameField(field));
+ return std::make_unique<FullNameField>(field);
return nullptr;
}
diff --git a/chromium/components/autofill/core/browser/name_field_unittest.cc b/chromium/components/autofill/core/browser/name_field_unittest.cc
index b575d16410b..e6a3d22680a 100644
--- a/chromium/components/autofill/core/browser/name_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/name_field_unittest.cc
@@ -31,7 +31,7 @@ class NameFieldTest : public testing::Test {
// Downcast for tests.
static std::unique_ptr<NameField> Parse(AutofillScanner* scanner) {
std::unique_ptr<FormField> field = NameField::Parse(scanner);
- return base::WrapUnique(static_cast<NameField*>(field.release()));
+ return std::unique_ptr<NameField>(static_cast<NameField*>(field.release()));
}
private:
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 a71d0211bac..fc4486c4cc6 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
@@ -7,8 +7,8 @@
#include "base/command_line.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
+#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
@@ -115,7 +115,7 @@ class FullCardRequestTest : public testing::Test {
}
private:
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
MockPersonalDataManager personal_data_;
MockResultDelegate result_delegate_;
MockUIDelegate ui_delegate_;
diff --git a/chromium/components/autofill/core/browser/payments/payments_client.cc b/chromium/components/autofill/core/browser/payments/payments_client.cc
index 91e1a848359..ac4803ae4a3 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_client.cc
@@ -90,28 +90,53 @@ GURL GetRequestUrl(const std::string& path) {
return GetBaseSecureUrl().Resolve(path);
}
-base::DictionaryValue BuildCustomerContextDictionary(
- int64_t external_customer_id) {
- base::DictionaryValue customer_context;
- customer_context.SetString("external_customer_id",
- std::to_string(external_customer_id));
+// Tries to get the string |out_value| from the |dictionary| with the given
+// |key|.
+// Returns true if the string value was found, false otherwise.
+bool TryGetString(std::string key,
+ base::Value& dictionary,
+ std::string* out_value) {
+ base::Value* str_ptr = dictionary.FindKey(key);
+ if (str_ptr) {
+ *out_value = str_ptr->GetString();
+ }
+ return str_ptr;
+}
+
+// Tries to get the string |out_value| from the |dictionary| with the given
+// |path|.
+// Returns true if the string value was found, false otherwise.
+bool TryGetStringByPath(std::initializer_list<base::StringPiece> path,
+ base::Value& dictionary,
+ std::string* out_value) {
+ base::Value* str_ptr = dictionary.FindPath(path);
+ if (str_ptr) {
+ *out_value = str_ptr->GetString();
+ }
+ return str_ptr;
+}
+
+base::Value BuildCustomerContextDictionary(int64_t external_customer_id) {
+ base::Value customer_context(base::Value::Type::DICTIONARY);
+ customer_context.SetKey("external_customer_id",
+ base::Value(std::to_string(external_customer_id)));
return customer_context;
}
-base::DictionaryValue BuildRiskDictionary(
- const std::string& encoded_risk_data) {
- base::DictionaryValue risk_data;
+base::Value BuildRiskDictionary(const std::string& encoded_risk_data) {
+ base::Value risk_data(base::Value::Type::DICTIONARY);
#if defined(OS_IOS)
// Browser fingerprinting is not available on iOS. Instead, we generate
// RiskAdvisoryData.
- risk_data.SetString("message_type", "RISK_ADVISORY_DATA");
- risk_data.SetString("encoding_type", "BASE_64_URL");
+ risk_data.SetKey("message_type", base::Value("RISK_ADVISORY_DATA"));
+ risk_data.SetKey("encoding_type", base::Value("BASE_64_URL"));
#else
- risk_data.SetString("message_type", "BROWSER_NATIVE_FINGERPRINTING");
- risk_data.SetString("encoding_type", "BASE_64");
+ risk_data.SetKey("message_type",
+ base::Value("BROWSER_NATIVE_FINGERPRINTING"));
+ risk_data.SetKey("encoding_type", base::Value("BASE_64"));
#endif
- risk_data.SetString("value", encoded_risk_data);
+ risk_data.SetKey("value", base::Value(encoded_risk_data));
return risk_data;
}
@@ -120,65 +145,63 @@ void SetStringIfNotEmpty(const AutofillDataModel& profile,
const ServerFieldType& type,
const std::string& app_locale,
const std::string& path,
- base::DictionaryValue* dictionary) {
+ base::Value& dictionary) {
const base::string16 value = profile.GetInfo(AutofillType(type), app_locale);
if (!value.empty())
- dictionary->SetString(path, value);
+ dictionary.SetKey(path, base::Value(value));
}
void AppendStringIfNotEmpty(const AutofillProfile& profile,
const ServerFieldType& type,
const std::string& app_locale,
- base::ListValue* list) {
+ base::Value& list) {
const base::string16 value = profile.GetInfo(type, app_locale);
if (!value.empty())
- list->AppendString(value);
+ list.GetList().emplace_back(value);
}
// Returns a dictionary with the structure expected by Payments RPCs, containing
// each of the fields in |profile|, formatted according to |app_locale|. If
// |include_non_location_data| is false, the name and phone number in |profile|
// are not included.
-std::unique_ptr<base::DictionaryValue> BuildAddressDictionary(
- const AutofillProfile& profile,
- const std::string& app_locale,
- bool include_non_location_data) {
- std::unique_ptr<base::DictionaryValue> postal_address(
- new base::DictionaryValue());
+base::Value BuildAddressDictionary(const AutofillProfile& profile,
+ const std::string& app_locale,
+ bool include_non_location_data) {
+ base::Value postal_address(base::Value::Type::DICTIONARY);
if (include_non_location_data) {
SetStringIfNotEmpty(profile, NAME_FULL, app_locale,
- PaymentsClient::kRecipientName, postal_address.get());
+ PaymentsClient::kRecipientName, postal_address);
}
- std::unique_ptr<base::ListValue> address_lines(new base::ListValue());
+ base::Value address_lines(base::Value::Type::LIST);
AppendStringIfNotEmpty(profile, ADDRESS_HOME_LINE1, app_locale,
- address_lines.get());
+ address_lines);
AppendStringIfNotEmpty(profile, ADDRESS_HOME_LINE2, app_locale,
- address_lines.get());
+ address_lines);
AppendStringIfNotEmpty(profile, ADDRESS_HOME_LINE3, app_locale,
- address_lines.get());
- if (!address_lines->empty())
- postal_address->Set("address_line", std::move(address_lines));
+ address_lines);
+ if (!address_lines.GetList().empty())
+ postal_address.SetKey("address_line", std::move(address_lines));
SetStringIfNotEmpty(profile, ADDRESS_HOME_CITY, app_locale, "locality_name",
- postal_address.get());
+ postal_address);
SetStringIfNotEmpty(profile, ADDRESS_HOME_STATE, app_locale,
- "administrative_area_name", postal_address.get());
+ "administrative_area_name", postal_address);
SetStringIfNotEmpty(profile, ADDRESS_HOME_ZIP, app_locale,
- "postal_code_number", postal_address.get());
+ "postal_code_number", postal_address);
// Use GetRawInfo to get a country code instead of the country name:
const base::string16 country_code = profile.GetRawInfo(ADDRESS_HOME_COUNTRY);
if (!country_code.empty())
- postal_address->SetString("country_name_code", country_code);
+ postal_address.SetKey("country_name_code", base::Value(country_code));
- std::unique_ptr<base::DictionaryValue> address(new base::DictionaryValue());
- address->Set("postal_address", std::move(postal_address));
+ base::Value address(base::Value::Type::DICTIONARY);
+ address.SetKey("postal_address", std::move(postal_address));
if (include_non_location_data) {
SetStringIfNotEmpty(profile, PHONE_HOME_WHOLE_NUMBER, app_locale,
- PaymentsClient::kPhoneNumber, address.get());
+ PaymentsClient::kPhoneNumber, address);
}
return address;
@@ -189,12 +212,11 @@ std::unique_ptr<base::DictionaryValue> BuildAddressDictionary(
// name (if any) fields in |credit_card|, formatted according to |app_locale|.
// |pan_field_name| is the field name for the encrypted pan. We use each credit
// card's guid as the unique id.
-std::unique_ptr<base::DictionaryValue> BuildCreditCardDictionary(
- const CreditCard& credit_card,
- const std::string& app_locale,
- const std::string& pan_field_name) {
- std::unique_ptr<base::DictionaryValue> card(new base::DictionaryValue());
- card->SetString("unique_id", credit_card.guid());
+base::Value BuildCreditCardDictionary(const CreditCard& credit_card,
+ const std::string& app_locale,
+ const std::string& pan_field_name) {
+ base::Value card(base::Value::Type::DICTIONARY);
+ card.SetKey("unique_id", base::Value(credit_card.guid()));
const base::string16 exp_month =
credit_card.GetInfo(AutofillType(CREDIT_CARD_EXP_MONTH), app_locale);
@@ -202,30 +224,29 @@ std::unique_ptr<base::DictionaryValue> BuildCreditCardDictionary(
AutofillType(CREDIT_CARD_EXP_4_DIGIT_YEAR), app_locale);
int value = 0;
if (base::StringToInt(exp_month, &value))
- card->SetInteger("expiration_month", value);
+ card.SetKey("expiration_month", base::Value(value));
if (base::StringToInt(exp_year, &value))
- card->SetInteger("expiration_year", value);
+ card.SetKey("expiration_year", base::Value(value));
SetStringIfNotEmpty(credit_card, CREDIT_CARD_NAME_FULL, app_locale,
- "cardholder_name", card.get());
+ "cardholder_name", card);
- card->SetString("encrypted_pan", "__param:" + pan_field_name);
+ card.SetKey("encrypted_pan", base::Value("__param:" + pan_field_name));
return card;
}
// Populates the list of active experiments that affect either the data sent in
// payments RPCs or whether the RPCs are sent or not.
void SetActiveExperiments(const std::vector<const char*>& active_experiments,
- base::DictionaryValue* request_dict) {
+ base::Value& request_dict) {
if (active_experiments.empty())
return;
- std::unique_ptr<base::ListValue> active_chrome_experiments(
- std::make_unique<base::ListValue>());
+ base::Value active_chrome_experiments(base::Value::Type::LIST);
for (const char* it : active_experiments)
- active_chrome_experiments->AppendString(it);
+ active_chrome_experiments.GetList().emplace_back(it);
- request_dict->Set("active_chrome_experiments",
- std::move(active_chrome_experiments));
+ request_dict.SetKey("active_chrome_experiments",
+ std::move(active_chrome_experiments));
}
class UnmaskCardRequest : public PaymentsRequest {
@@ -250,32 +271,35 @@ class UnmaskCardRequest : public PaymentsRequest {
}
std::string GetRequestContent() override {
- base::DictionaryValue request_dict;
- request_dict.SetString("encrypted_cvc", "__param:s7e_13_cvc");
- request_dict.SetString("credit_card_id", request_details_.card.server_id());
+ 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()));
request_dict.SetKey("risk_data_encoded",
BuildRiskDictionary(request_details_.risk_data));
- std::unique_ptr<base::DictionaryValue> context(new base::DictionaryValue());
- context->SetInteger("billable_service", kUnmaskCardBillableServiceNumber);
+ base::Value context(base::Value::Type::DICTIONARY);
+ context.SetKey("billable_service",
+ base::Value(kUnmaskCardBillableServiceNumber));
if (request_details_.billing_customer_number != 0) {
- context->SetKey("customer_context",
- BuildCustomerContextDictionary(
- request_details_.billing_customer_number));
+ context.SetKey("customer_context",
+ BuildCustomerContextDictionary(
+ request_details_.billing_customer_number));
}
- request_dict.Set("context", std::move(context));
+ request_dict.SetKey("context", std::move(context));
if (ShouldUseActiveSignedInAccount()) {
- std::unique_ptr<base::DictionaryValue> chrome_user_context(
- new base::DictionaryValue());
- chrome_user_context->SetBoolean("full_sync_enabled", full_sync_enabled_);
- request_dict.Set("chrome_user_context", std::move(chrome_user_context));
+ base::Value chrome_user_context(base::Value::Type::DICTIONARY);
+ chrome_user_context.SetKey("full_sync_enabled",
+ base::Value(full_sync_enabled_));
+ request_dict.SetKey("chrome_user_context",
+ std::move(chrome_user_context));
}
int value = 0;
if (base::StringToInt(request_details_.user_response.exp_month, &value))
- request_dict.SetInteger("expiration_month", value);
+ request_dict.SetKey("expiration_month", base::Value(value));
if (base::StringToInt(request_details_.user_response.exp_year, &value))
- request_dict.SetInteger("expiration_year", value);
+ request_dict.SetKey("expiration_year", base::Value(value));
std::string json_request;
base::JSONWriter::Write(request_dict, &json_request);
@@ -289,8 +313,8 @@ class UnmaskCardRequest : public PaymentsRequest {
return request_content;
}
- void ParseResponse(std::unique_ptr<base::DictionaryValue> response) override {
- response->GetString("pan", &real_pan_);
+ void ParseResponse(base::Value response) override {
+ TryGetString("pan", response, &real_pan_);
}
bool IsResponseComplete() override { return !real_pan_.empty(); }
@@ -318,9 +342,9 @@ class GetUploadDetailsRequest : public PaymentsRequest {
const std::string& app_locale,
base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
const base::string16&,
- std::unique_ptr<base::DictionaryValue>)> callback,
+ std::unique_ptr<base::Value>)> callback,
const int billable_service_number,
- PaymentsClient::MigrationSource migration_source)
+ PaymentsClient::UploadCardSource upload_card_source)
: addresses_(addresses),
detected_values_(detected_values),
active_experiments_(active_experiments),
@@ -328,7 +352,7 @@ class GetUploadDetailsRequest : public PaymentsRequest {
app_locale_(app_locale),
callback_(std::move(callback)),
billable_service_number_(billable_service_number),
- migration_source_(migration_source) {}
+ upload_card_source_(upload_card_source) {}
~GetUploadDetailsRequest() override {}
std::string GetRequestUrlPath() override {
@@ -338,20 +362,21 @@ class GetUploadDetailsRequest : public PaymentsRequest {
std::string GetRequestContentType() override { return "application/json"; }
std::string GetRequestContent() override {
- base::DictionaryValue request_dict;
- std::unique_ptr<base::DictionaryValue> context(new base::DictionaryValue());
- context->SetString("language_code", app_locale_);
- context->SetInteger("billable_service", billable_service_number_);
- request_dict.Set("context", std::move(context));
+ base::Value request_dict(base::Value::Type::DICTIONARY);
+ base::Value context(base::Value::Type::DICTIONARY);
+ context.SetKey("language_code", base::Value(app_locale_));
+ context.SetKey("billable_service", base::Value(billable_service_number_));
+ request_dict.SetKey("context", std::move(context));
if (ShouldUseActiveSignedInAccount()) {
- std::unique_ptr<base::DictionaryValue> chrome_user_context(
- new base::DictionaryValue());
- chrome_user_context->SetBoolean("full_sync_enabled", full_sync_enabled_);
- request_dict.Set("chrome_user_context", std::move(chrome_user_context));
+ base::Value chrome_user_context(base::Value::Type::DICTIONARY);
+ chrome_user_context.SetKey("full_sync_enabled",
+ base::Value(full_sync_enabled_));
+ request_dict.SetKey("chrome_user_context",
+ std::move(chrome_user_context));
}
- std::unique_ptr<base::ListValue> addresses(new base::ListValue());
+ base::Value addresses(base::Value::Type::LIST);
for (const AutofillProfile& profile : addresses_) {
// These addresses are used by Payments to (1) accurately determine the
// user's country in order to show the correct legal documents and (2) to
@@ -360,26 +385,42 @@ 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->Append(BuildAddressDictionary(profile, app_locale_, false));
+ addresses.GetList().push_back(
+ BuildAddressDictionary(profile, app_locale_, false));
}
- request_dict.Set("address", std::move(addresses));
+ request_dict.SetKey("address", std::move(addresses));
// It's possible we may not have found name/address/CVC in the checkout
// flow. The detected_values_ bitmask tells Payments what *was* found, and
// Payments will decide if the provided data is enough to offer upload save.
- request_dict.SetInteger("detected_values", detected_values_);
+ request_dict.SetKey("detected_values", base::Value(detected_values_));
- SetActiveExperiments(active_experiments_, &request_dict);
+ SetActiveExperiments(active_experiments_, request_dict);
- switch (migration_source_) {
- case PaymentsClient::MigrationSource::UNKNOWN_MIGRATION_SOURCE:
- request_dict.SetString("migration_source", "UNKNOWN_MIGRATION_SOURCE");
+ switch (upload_card_source_) {
+ case PaymentsClient::UploadCardSource::UNKNOWN_UPLOAD_CARD_SOURCE:
+ request_dict.SetKey("upload_card_source",
+ base::Value("UNKNOWN_UPLOAD_CARD_SOURCE"));
+ break;
+ case PaymentsClient::UploadCardSource::UPSTREAM_CHECKOUT_FLOW:
+ request_dict.SetKey("upload_card_source",
+ base::Value("UPSTREAM_CHECKOUT_FLOW"));
break;
- case PaymentsClient::MigrationSource::CHECKOUT_FLOW:
- request_dict.SetString("migration_source", "CHECKOUT_FLOW");
+ case PaymentsClient::UploadCardSource::UPSTREAM_SETTINGS_PAGE:
+ request_dict.SetKey("upload_card_source",
+ base::Value("UPSTREAM_SETTINGS_PAGE"));
break;
- case PaymentsClient::MigrationSource::SETTINGS_PAGE:
- request_dict.SetString("migration_source", "SETTINGS_PAGE");
+ case PaymentsClient::UploadCardSource::UPSTREAM_CARD_OCR:
+ request_dict.SetKey("upload_card_source",
+ base::Value("UPSTREAM_CARD_OCR"));
+ break;
+ case PaymentsClient::UploadCardSource::LOCAL_CARD_MIGRATION_CHECKOUT_FLOW:
+ request_dict.SetKey("upload_card_source",
+ base::Value("LOCAL_CARD_MIGRATION_CHECKOUT_FLOW"));
+ break;
+ case PaymentsClient::UploadCardSource::LOCAL_CARD_MIGRATION_SETTINGS_PAGE:
+ request_dict.SetKey("upload_card_source",
+ base::Value("LOCAL_CARD_MIGRATION_SETTINGS_PAGE"));
break;
default:
NOTREACHED();
@@ -391,11 +432,15 @@ class GetUploadDetailsRequest : public PaymentsRequest {
return request_content;
}
- void ParseResponse(std::unique_ptr<base::DictionaryValue> response) override {
- response->GetString("context_token", &context_token_);
- base::DictionaryValue* unowned_legal_message;
- if (response->GetDictionary("legal_message", &unowned_legal_message))
- legal_message_ = unowned_legal_message->CreateDeepCopy();
+ void ParseResponse(base::Value response) override {
+ std::string context_token_utf8;
+ if (TryGetString("context_token", response, &context_token_utf8)) {
+ context_token_ = base::UTF8ToUTF16(context_token_utf8);
+ }
+
+ base::Value* dictionary_value = response.FindKey("legal_message");
+ if (dictionary_value)
+ legal_message_ = std::make_unique<base::Value>(dictionary_value->Clone());
}
bool IsResponseComplete() override {
@@ -414,12 +459,12 @@ class GetUploadDetailsRequest : public PaymentsRequest {
std::string app_locale_;
base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
const base::string16&,
- std::unique_ptr<base::DictionaryValue>)>
+ std::unique_ptr<base::Value>)>
callback_;
base::string16 context_token_;
- std::unique_ptr<base::DictionaryValue> legal_message_;
+ std::unique_ptr<base::Value> legal_message_;
const int billable_service_number_;
- PaymentsClient::MigrationSource migration_source_;
+ PaymentsClient::UploadCardSource upload_card_source_;
};
class UploadCardRequest : public PaymentsRequest {
@@ -440,41 +485,45 @@ class UploadCardRequest : public PaymentsRequest {
}
std::string GetRequestContent() override {
- base::DictionaryValue request_dict;
- request_dict.SetString("encrypted_pan", "__param:s7e_1_pan");
+ base::Value request_dict(base::Value::Type::DICTIONARY);
+ request_dict.SetKey("encrypted_pan", base::Value("__param:s7e_1_pan"));
if (!request_details_.cvc.empty())
- request_dict.SetString("encrypted_cvc", "__param:s7e_13_cvc");
+ request_dict.SetKey("encrypted_cvc", base::Value("__param:s7e_13_cvc"));
request_dict.SetKey("risk_data_encoded",
BuildRiskDictionary(request_details_.risk_data));
const std::string& app_locale = request_details_.app_locale;
- std::unique_ptr<base::DictionaryValue> context(new base::DictionaryValue());
- context->SetString("language_code", app_locale);
- context->SetInteger("billable_service", kUploadCardBillableServiceNumber);
+ base::Value context(base::Value::Type::DICTIONARY);
+ context.SetKey("language_code", base::Value(app_locale));
+ context.SetKey("billable_service",
+ base::Value(kUploadCardBillableServiceNumber));
if (request_details_.billing_customer_number != 0) {
- context->SetKey("customer_context",
- BuildCustomerContextDictionary(
- request_details_.billing_customer_number));
+ context.SetKey("customer_context",
+ BuildCustomerContextDictionary(
+ request_details_.billing_customer_number));
}
- request_dict.Set("context", std::move(context));
+ request_dict.SetKey("context", std::move(context));
if (ShouldUseActiveSignedInAccount()) {
- std::unique_ptr<base::DictionaryValue> chrome_user_context(
- new base::DictionaryValue());
- chrome_user_context->SetBoolean("full_sync_enabled", full_sync_enabled_);
- request_dict.Set("chrome_user_context", std::move(chrome_user_context));
+ base::Value chrome_user_context(base::Value::Type::DICTIONARY);
+ chrome_user_context.SetKey("full_sync_enabled",
+ base::Value(full_sync_enabled_));
+ request_dict.SetKey("chrome_user_context",
+ std::move(chrome_user_context));
}
SetStringIfNotEmpty(request_details_.card, CREDIT_CARD_NAME_FULL,
- app_locale, "cardholder_name", &request_dict);
+ app_locale, "cardholder_name", request_dict);
- std::unique_ptr<base::ListValue> addresses(new base::ListValue());
+ base::Value addresses(base::Value::Type::LIST);
for (const AutofillProfile& profile : request_details_.profiles) {
- addresses->Append(BuildAddressDictionary(profile, app_locale, true));
+ addresses.GetList().push_back(
+ BuildAddressDictionary(profile, app_locale, true));
}
- request_dict.Set("address", std::move(addresses));
+ request_dict.SetKey("address", std::move(addresses));
- request_dict.SetString("context_token", request_details_.context_token);
+ request_dict.SetKey("context_token",
+ base::Value(request_details_.context_token));
int value = 0;
const base::string16 exp_month = request_details_.card.GetInfo(
@@ -482,11 +531,11 @@ class UploadCardRequest : public PaymentsRequest {
const base::string16 exp_year = request_details_.card.GetInfo(
AutofillType(CREDIT_CARD_EXP_4_DIGIT_YEAR), app_locale);
if (base::StringToInt(exp_month, &value))
- request_dict.SetInteger("expiration_month", value);
+ request_dict.SetKey("expiration_month", base::Value(value));
if (base::StringToInt(exp_year, &value))
- request_dict.SetInteger("expiration_year", value);
+ request_dict.SetKey("expiration_year", base::Value(value));
- SetActiveExperiments(request_details_.active_experiments, &request_dict);
+ SetActiveExperiments(request_details_.active_experiments, request_dict);
const base::string16 pan = request_details_.card.GetInfo(
AutofillType(CREDIT_CARD_NUMBER), app_locale);
@@ -511,8 +560,8 @@ class UploadCardRequest : public PaymentsRequest {
return request_content;
}
- void ParseResponse(std::unique_ptr<base::DictionaryValue> response) override {
- response->GetString("credit_card_id", &server_id_);
+ void ParseResponse(base::Value response) override {
+ TryGetString("credit_card_id", response, &server_id_);
}
bool IsResponseComplete() override { return true; }
@@ -549,39 +598,41 @@ class MigrateCardsRequest : public PaymentsRequest {
return "application/x-www-form-urlencoded";
}
- // TODO(crbug.com/877281):Refactor DictionaryValue to base::Value
std::string GetRequestContent() override {
- base::DictionaryValue request_dict;
+ base::Value request_dict(base::Value::Type::DICTIONARY);
request_dict.SetKey("risk_data_encoded",
BuildRiskDictionary(request_details_.risk_data));
const std::string& app_locale = request_details_.app_locale;
- std::unique_ptr<base::DictionaryValue> context(new base::DictionaryValue());
- context->SetString("language_code", app_locale);
- context->SetInteger("billable_service", kMigrateCardsBillableServiceNumber);
+ base::Value context(base::Value::Type::DICTIONARY);
+ context.SetKey("language_code", base::Value(app_locale));
+ context.SetKey("billable_service",
+ base::Value(kMigrateCardsBillableServiceNumber));
if (request_details_.billing_customer_number != 0) {
- context->SetKey("customer_context",
- BuildCustomerContextDictionary(
- request_details_.billing_customer_number));
+ context.SetKey("customer_context",
+ BuildCustomerContextDictionary(
+ request_details_.billing_customer_number));
}
- request_dict.Set("context", std::move(context));
+ request_dict.SetKey("context", std::move(context));
if (ShouldUseActiveSignedInAccount()) {
- std::unique_ptr<base::DictionaryValue> chrome_user_context(
- new base::DictionaryValue());
- chrome_user_context->SetBoolean("full_sync_enabled", full_sync_enabled_);
- request_dict.Set("chrome_user_context", std::move(chrome_user_context));
+ base::Value chrome_user_context(base::Value::Type::DICTIONARY);
+ chrome_user_context.SetKey("full_sync_enabled",
+ base::Value(full_sync_enabled_));
+ request_dict.SetKey("chrome_user_context",
+ std::move(chrome_user_context));
}
- request_dict.SetString("context_token", request_details_.context_token);
+ request_dict.SetKey("context_token",
+ base::Value(request_details_.context_token));
std::string all_pans_data = std::string();
- std::unique_ptr<base::ListValue> migrate_cards(new base::ListValue());
+ base::Value migrate_cards(base::Value::Type::LIST);
for (size_t index = 0; index < migratable_credit_cards_.size(); ++index) {
std::string pan_field_name = GetPanFieldName(index);
// Generate credit card dictionary.
- migrate_cards->Append(BuildCreditCardDictionary(
+ migrate_cards.GetList().push_back(BuildCreditCardDictionary(
migratable_credit_cards_[index].credit_card(), app_locale,
pan_field_name));
// Append pan data to the |all_pans_data|.
@@ -589,7 +640,7 @@ class MigrateCardsRequest : public PaymentsRequest {
GetAppendPan(migratable_credit_cards_[index].credit_card(),
app_locale, pan_field_name);
}
- request_dict.Set("local_card", std::move(migrate_cards));
+ request_dict.SetKey("local_card", std::move(migrate_cards));
std::string json_request;
base::JSONWriter::Write(request_dict, &json_request);
@@ -600,23 +651,26 @@ class MigrateCardsRequest : public PaymentsRequest {
return request_content;
}
- void ParseResponse(std::unique_ptr<base::DictionaryValue> response) override {
- const base::ListValue* save_result_list = nullptr;
- if (!response->GetList("save_result", &save_result_list))
+ void ParseResponse(base::Value response) override {
+ base::Value* list_ptr = response.FindKey("save_result");
+ if (!list_ptr || !list_ptr->is_list())
return;
save_result_ =
std::make_unique<std::unordered_map<std::string, std::string>>();
- for (size_t i = 0; i < save_result_list->GetSize(); ++i) {
- const base::DictionaryValue* single_card_save_result;
- if (save_result_list->GetDictionary(i, &single_card_save_result)) {
+
+ for (base::Value& result : list_ptr->GetList()) {
+ if (result.is_dict()) {
std::string unique_id;
- single_card_save_result->GetString("unique_id", &unique_id);
+ TryGetString("unique_id", result, &unique_id);
+
std::string save_result;
- single_card_save_result->GetString("status", &save_result);
+ TryGetString("status", result, &save_result);
+
save_result_->insert(std::make_pair(unique_id, save_result));
}
}
- response->GetString("value_prop_display_text", &display_text_);
+
+ TryGetString("value_prop_display_text", response, &display_text_);
}
bool IsResponseComplete() override {
@@ -716,14 +770,14 @@ void PaymentsClient::GetUploadDetails(
const std::string& app_locale,
base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
const base::string16&,
- std::unique_ptr<base::DictionaryValue>)> callback,
+ std::unique_ptr<base::Value>)> callback,
const int billable_service_number,
- MigrationSource migration_source) {
+ UploadCardSource upload_card_source) {
IssueRequest(
std::make_unique<GetUploadDetailsRequest>(
addresses, detected_values, active_experiments,
account_info_getter_->IsSyncFeatureEnabled(), app_locale,
- std::move(callback), billable_service_number, migration_source),
+ std::move(callback), billable_service_number, upload_card_source),
false);
}
@@ -815,7 +869,7 @@ void PaymentsClient::OnSimpleLoaderComplete(
void PaymentsClient::OnSimpleLoaderCompleteInternal(int response_code,
const std::string& data) {
- std::unique_ptr<base::DictionaryValue> response_dict;
+ base::Value response_dict(base::Value::Type::DICTIONARY);
VLOG(2) << "Got data: " << data;
AutofillClient::PaymentsRpcResult result = AutofillClient::SUCCESS;
@@ -826,9 +880,9 @@ void PaymentsClient::OnSimpleLoaderCompleteInternal(int response_code,
std::string error_code;
std::unique_ptr<base::Value> message_value = base::JSONReader::Read(data);
if (message_value.get() && message_value->is_dict()) {
- response_dict.reset(
- static_cast<base::DictionaryValue*>(message_value.release()));
- response_dict->GetString("error.code", &error_code);
+ response_dict =
+ base::Value::FromUniquePtrValue(std::move(message_value));
+ TryGetStringByPath({"error", "code"}, response_dict, &error_code);
request_->ParseResponse(std::move(response_dict));
}
diff --git a/chromium/components/autofill/core/browser/payments/payments_client.h b/chromium/components/autofill/core/browser/payments/payments_client.h
index eacd1047834..be0bc533999 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client.h
+++ b/chromium/components/autofill/core/browser/payments/payments_client.h
@@ -111,15 +111,24 @@ class PaymentsClient {
};
// An enum set in the GetUploadDetailsRequest indicating the source of the
- // request. It should stay consistent with the same enum in Google Payments
- // server code.
- enum MigrationSource {
- // Source unknown or unnecessary (such as during single credit card upload).
- UNKNOWN_MIGRATION_SOURCE,
- // Migration request comes from the checkout flow.
- CHECKOUT_FLOW,
- // Migration request comes from settings page.
- SETTINGS_PAGE,
+ // request when uploading a card to Google Payments. It should stay consistent
+ // with the same enum in Google Payments server code.
+ enum UploadCardSource {
+ // Source unknown.
+ UNKNOWN_UPLOAD_CARD_SOURCE,
+ // Single card is being uploaded from the normal credit card offer-to-save
+ // prompt during a checkout flow.
+ UPSTREAM_CHECKOUT_FLOW,
+ // Single card is being uploaded from chrome://settings/payments.
+ UPSTREAM_SETTINGS_PAGE,
+ // Single card is being uploaded after being scanned by OCR.
+ UPSTREAM_CARD_OCR,
+ // 1+ cards are being uploaded from a migration request that started during
+ // a checkout flow.
+ LOCAL_CARD_MIGRATION_CHECKOUT_FLOW,
+ // 1+ cards are being uploaded from a migration request that was initiated
+ // from chrome://settings/payments.
+ LOCAL_CARD_MIGRATION_SETTINGS_PAGE,
};
// |url_loader_factory| is reference counted so it has no lifetime or
@@ -160,7 +169,7 @@ class PaymentsClient {
// billable service number in the GetUploadDetails request. If the conditions
// are met, the legal message will be returned via |callback|.
// |active_experiments| is used by Payments server to track requests that were
- // triggered by enabled features. |migration_source| is used by Payments
+ // triggered by enabled features. |upload_card_source| is used by Payments
// server metrics to track the source of the request.
virtual void GetUploadDetails(
const std::vector<AutofillProfile>& addresses,
@@ -169,10 +178,10 @@ class PaymentsClient {
const std::string& app_locale,
base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
const base::string16&,
- std::unique_ptr<base::DictionaryValue>)> callback,
+ std::unique_ptr<base::Value>)> callback,
const int billable_service_number,
- MigrationSource migration_source =
- MigrationSource::UNKNOWN_MIGRATION_SOURCE);
+ UploadCardSource upload_card_source =
+ UploadCardSource::UNKNOWN_UPLOAD_CARD_SOURCE);
// The user has indicated that they would like to upload a card with the given
// cvc. This request will fail server-side if a successful call to
@@ -197,6 +206,8 @@ class PaymentsClient {
void set_url_loader_factory_for_testing(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+ bool is_off_the_record() { return is_off_the_record_; }
+
private:
friend class PaymentsClientTest;
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 d8bfc91b0a6..1b733047735 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc
@@ -115,10 +115,9 @@ class PaymentsClientTest : public testing::Test {
real_pan_ = real_pan;
}
- void OnDidGetUploadDetails(
- AutofillClient::PaymentsRpcResult result,
- const base::string16& context_token,
- std::unique_ptr<base::DictionaryValue> legal_message) {
+ void OnDidGetUploadDetails(AutofillClient::PaymentsRpcResult result,
+ const base::string16& context_token,
+ std::unique_ptr<base::Value> legal_message) {
result_ = result;
legal_message_ = std::move(legal_message);
}
@@ -156,14 +155,14 @@ class PaymentsClientTest : public testing::Test {
// Issue a GetUploadDetails request.
void StartGettingUploadDetails(
- PaymentsClient::MigrationSource migration_source =
- PaymentsClient::MigrationSource::UNKNOWN_MIGRATION_SOURCE) {
+ PaymentsClient::UploadCardSource upload_card_source =
+ PaymentsClient::UploadCardSource::UNKNOWN_UPLOAD_CARD_SOURCE) {
client_->GetUploadDetails(
BuildTestProfiles(), kAllDetectableValues, std::vector<const char*>(),
"language-LOCALE",
base::BindOnce(&PaymentsClientTest::OnDidGetUploadDetails,
weak_ptr_factory_.GetWeakPtr()),
- /*billable_service_number=*/12345, migration_source);
+ /*billable_service_number=*/12345, upload_card_source);
}
// Issue an UploadCard request. This requires an OAuth token before starting
@@ -233,7 +232,7 @@ class PaymentsClientTest : public testing::Test {
AutofillClient::PaymentsRpcResult result_;
std::string server_id_;
std::string real_pan_;
- std::unique_ptr<base::DictionaryValue> legal_message_;
+ std::unique_ptr<base::Value> legal_message_;
std::vector<MigratableCreditCard> migratable_credit_cards_;
std::unique_ptr<std::unordered_map<std::string, std::string>> save_result_;
std::string display_text_;
@@ -447,26 +446,61 @@ TEST_F(PaymentsClientTest,
}
TEST_F(PaymentsClientTest,
- GetDetailsIncludesCheckoutFlowMigrationSourceInRequest) {
- StartGettingUploadDetails(PaymentsClient::MigrationSource::CHECKOUT_FLOW);
+ GetDetailsIncludesUpstreamCheckoutFlowUploadCardSourceInRequest) {
+ StartGettingUploadDetails(
+ PaymentsClient::UploadCardSource::UPSTREAM_CHECKOUT_FLOW);
+
+ // Verify that the correct upload card source was included in the request.
+ EXPECT_TRUE(GetUploadData().find("UPSTREAM_CHECKOUT_FLOW") !=
+ std::string::npos);
+}
+
+TEST_F(PaymentsClientTest,
+ GetDetailsIncludesUpstreamSettingsPageUploadCardSourceInRequest) {
+ StartGettingUploadDetails(
+ PaymentsClient::UploadCardSource::UPSTREAM_SETTINGS_PAGE);
- // Verify that the correct migration source was included in the request.
- EXPECT_TRUE(GetUploadData().find("CHECKOUT_FLOW") != std::string::npos);
+ // Verify that the correct upload card source was included in the request.
+ EXPECT_TRUE(GetUploadData().find("UPSTREAM_SETTINGS_PAGE") !=
+ std::string::npos);
}
TEST_F(PaymentsClientTest,
- GetDetailsIncludesSettingsPageMigrationSourceInRequest) {
- StartGettingUploadDetails(PaymentsClient::MigrationSource::SETTINGS_PAGE);
+ GetDetailsIncludesUpstreamCardOcrUploadCardSourceInRequest) {
+ StartGettingUploadDetails(
+ PaymentsClient::UploadCardSource::UPSTREAM_CARD_OCR);
- // Verify that the correct migration source was included in the request.
- EXPECT_TRUE(GetUploadData().find("SETTINGS_PAGE") != std::string::npos);
+ // Verify that the correct upload card source was included in the request.
+ EXPECT_TRUE(GetUploadData().find("UPSTREAM_CARD_OCR") != std::string::npos);
+}
+
+TEST_F(
+ PaymentsClientTest,
+ GetDetailsIncludesLocalCardMigrationCheckoutFlowUploadCardSourceInRequest) {
+ StartGettingUploadDetails(
+ PaymentsClient::UploadCardSource::LOCAL_CARD_MIGRATION_CHECKOUT_FLOW);
+
+ // Verify that the correct upload card source was included in the request.
+ EXPECT_TRUE(GetUploadData().find("LOCAL_CARD_MIGRATION_CHECKOUT_FLOW") !=
+ std::string::npos);
+}
+
+TEST_F(
+ PaymentsClientTest,
+ GetDetailsIncludesLocalCardMigrationSettingsPageUploadCardSourceInRequest) {
+ StartGettingUploadDetails(
+ PaymentsClient::UploadCardSource::LOCAL_CARD_MIGRATION_SETTINGS_PAGE);
+
+ // Verify that the correct upload card source was included in the request.
+ EXPECT_TRUE(GetUploadData().find("LOCAL_CARD_MIGRATION_SETTINGS_PAGE") !=
+ std::string::npos);
}
-TEST_F(PaymentsClientTest, GetDetailsIncludesUnknownMigrationSourceInRequest) {
+TEST_F(PaymentsClientTest, GetDetailsIncludesUnknownUploadCardSourceInRequest) {
StartGettingUploadDetails();
- // Verify that the absence of a migration source results in UNKNOWN.
- EXPECT_TRUE(GetUploadData().find("UNKNOWN_MIGRATION_SOURCE") !=
+ // Verify that the absence of an upload card source results in UNKNOWN.
+ EXPECT_TRUE(GetUploadData().find("UNKNOWN_UPLOAD_CARD_SOURCE") !=
std::string::npos);
}
diff --git a/chromium/components/autofill/core/browser/payments/payments_request.h b/chromium/components/autofill/core/browser/payments/payments_request.h
index 184c9275d6d..e71d554d7de 100644
--- a/chromium/components/autofill/core/browser/payments/payments_request.h
+++ b/chromium/components/autofill/core/browser/payments/payments_request.h
@@ -28,8 +28,7 @@ class PaymentsRequest {
virtual std::string GetRequestContent() = 0;
// Parses the required elements of the HTTP response.
- virtual void ParseResponse(
- std::unique_ptr<base::DictionaryValue> response) = 0;
+ virtual void ParseResponse(base::Value response) = 0;
// Returns true if all of the required elements were successfully retrieved by
// a call to ParseResponse.
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 00106156659..8bf0f86a13d 100644
--- a/chromium/components/autofill/core/browser/payments/test_payments_client.cc
+++ b/chromium/components/autofill/core/browser/payments/test_payments_client.cc
@@ -30,18 +30,19 @@ void TestPaymentsClient::GetUploadDetails(
const std::string& app_locale,
base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
const base::string16&,
- std::unique_ptr<base::DictionaryValue>)> callback,
+ std::unique_ptr<base::Value>)> callback,
const int billable_service_number,
- PaymentsClient::MigrationSource migration_source) {
+ PaymentsClient::UploadCardSource upload_card_source) {
upload_details_addresses_ = addresses;
detected_values_ = detected_values;
active_experiments_ = active_experiments;
- migration_source_ = migration_source;
+ billable_service_number_ = billable_service_number;
+ upload_card_source_ = upload_card_source;
std::move(callback).Run(app_locale == "en-US"
? AutofillClient::SUCCESS
: AutofillClient::PERMANENT_FAILURE,
base::ASCIIToUTF16("this is a context token"),
- std::unique_ptr<base::DictionaryValue>(nullptr));
+ std::unique_ptr<base::Value>(nullptr));
}
void TestPaymentsClient::UploadCard(
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 231cf000ce8..01e9d008903 100644
--- a/chromium/components/autofill/core/browser/payments/test_payments_client.h
+++ b/chromium/components/autofill/core/browser/payments/test_payments_client.h
@@ -34,10 +34,10 @@ class TestPaymentsClient : public payments::PaymentsClient {
const std::string& app_locale,
base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
const base::string16&,
- std::unique_ptr<base::DictionaryValue>)> callback,
+ std::unique_ptr<base::Value>)> callback,
const int billable_service_number,
- MigrationSource migration_source =
- MigrationSource::UNKNOWN_MIGRATION_SOURCE) override;
+ UploadCardSource upload_card_source =
+ UploadCardSource::UNKNOWN_UPLOAD_CARD_SOURCE) override;
void UploadCard(
const payments::PaymentsClient::UploadRequestDetails& request_details,
@@ -65,6 +65,12 @@ class TestPaymentsClient : public payments::PaymentsClient {
const std::vector<const char*>& active_experiments_in_request() const {
return active_experiments_;
}
+ int billable_service_number_in_request() const {
+ return billable_service_number_;
+ }
+ PaymentsClient::UploadCardSource upload_card_source_in_request() const {
+ return upload_card_source_;
+ }
private:
std::string server_id_;
@@ -73,7 +79,8 @@ class TestPaymentsClient : public payments::PaymentsClient {
int detected_values_;
std::string pan_first_six_;
std::vector<const char*> active_experiments_;
- PaymentsClient::MigrationSource migration_source_;
+ int billable_service_number_;
+ PaymentsClient::UploadCardSource upload_card_source_;
std::unique_ptr<std::unordered_map<std::string, std::string>> save_result_;
DISALLOW_COPY_AND_ASSIGN(TestPaymentsClient);
diff --git a/chromium/components/autofill/core/browser/personal_data_manager.cc b/chromium/components/autofill/core/browser/personal_data_manager.cc
index acdcabd4a7d..7c66782f7a5 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager.cc
@@ -13,6 +13,7 @@
#include <string>
#include <utility>
+#include "base/callback.h"
#include "base/feature_list.h"
#include "base/i18n/case_conversion.h"
#include "base/i18n/timezone.h"
@@ -68,27 +69,6 @@ using ::i18n::addressinput::STREET_ADDRESS;
// The length of a local profile GUID.
const int LOCAL_GUID_LENGTH = 36;
-constexpr base::TimeDelta kDisusedProfileTimeDelta =
- base::TimeDelta::FromDays(180);
-constexpr base::TimeDelta kDisusedCreditCardTimeDelta =
- base::TimeDelta::FromDays(180);
-constexpr base::TimeDelta kDisusedCreditCardDeletionTimeDelta =
- base::TimeDelta::FromDays(395);
-constexpr base::TimeDelta kDisusedAddressDeletionTimeDelta =
- base::TimeDelta::FromDays(395);
-
-// Time delta to create test data.
-base::TimeDelta DeletableUseDateDelta() {
- static base::TimeDelta delta =
- kDisusedCreditCardDeletionTimeDelta + base::TimeDelta::FromDays(5);
- return delta;
-}
-base::TimeDelta DeletableExpiryDateDelta() {
- static base::TimeDelta delta =
- kDisusedCreditCardDeletionTimeDelta + base::TimeDelta::FromDays(45);
- return delta;
-}
-
template <typename T>
class FormGroupMatchesByGUIDFunctor {
public:
@@ -161,130 +141,6 @@ static bool CompareVotes(const std::pair<std::string, int>& a,
const std::pair<std::string, int>& b) {
return a.second < b.second;
}
-
-AutofillProfile CreateBasicTestAddress(const std::string& locale) {
- const base::Time use_date =
- AutofillClock::Now() - base::TimeDelta::FromDays(20);
- AutofillProfile profile;
- profile.SetInfo(NAME_FULL, base::UTF8ToUTF16("John McTester"), locale);
- profile.SetInfo(COMPANY_NAME, base::UTF8ToUTF16("Test Inc."), locale);
- profile.SetInfo(EMAIL_ADDRESS,
- base::UTF8ToUTF16("jmctester@fake.chromium.org"), locale);
- profile.SetInfo(ADDRESS_HOME_LINE1, base::UTF8ToUTF16("123 Invented Street"),
- locale);
- profile.SetInfo(ADDRESS_HOME_LINE2, base::UTF8ToUTF16("Suite A"), locale);
- profile.SetInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16("Mountain View"),
- locale);
- profile.SetInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("California"), locale);
- profile.SetInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("94043"), locale);
- profile.SetInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16("US"), locale);
- profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16("844-555-0173"),
- locale);
- profile.set_use_date(use_date);
- return profile;
-}
-
-AutofillProfile CreateDisusedTestAddress(const std::string& locale) {
- const base::Time use_date =
- AutofillClock::Now() - base::TimeDelta::FromDays(185);
- AutofillProfile profile;
- profile.SetInfo(NAME_FULL, base::UTF8ToUTF16("Polly Disused"), locale);
- profile.SetInfo(COMPANY_NAME,
- base::UTF8ToUTF16(base::StringPrintf(
- "%lld Inc.", static_cast<long long>(use_date.ToTimeT()))),
- locale);
- profile.SetInfo(EMAIL_ADDRESS,
- base::UTF8ToUTF16("polly.disused@fake.chromium.org"), locale);
- profile.SetInfo(ADDRESS_HOME_LINE1, base::UTF8ToUTF16("456 Disused Lane"),
- locale);
- profile.SetInfo(ADDRESS_HOME_LINE2, base::UTF8ToUTF16("Apt. B"), locale);
- profile.SetInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16("Austin"), locale);
- profile.SetInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Texas"), locale);
- profile.SetInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("73301"), locale);
- profile.SetInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16("US"), locale);
- profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16("844-555-0174"),
- locale);
- profile.set_use_date(use_date);
- return profile;
-}
-
-AutofillProfile CreateDisusedDeletableTestAddress(const std::string& locale) {
- const base::Time use_date =
- AutofillClock::Now() - base::TimeDelta::FromDays(400);
- AutofillProfile profile;
- profile.SetInfo(NAME_FULL, base::UTF8ToUTF16("Polly Deletable"), locale);
- profile.SetInfo(COMPANY_NAME,
- base::UTF8ToUTF16(base::StringPrintf(
- "%lld Inc.", static_cast<long long>(use_date.ToTimeT()))),
- locale);
- profile.SetInfo(EMAIL_ADDRESS,
- base::UTF8ToUTF16("polly.deletable@fake.chromium.org"),
- locale);
- profile.SetInfo(ADDRESS_HOME_LINE1, base::UTF8ToUTF16("459 Deletable Lane"),
- locale);
- profile.SetInfo(ADDRESS_HOME_LINE2, base::UTF8ToUTF16("Apt. B"), locale);
- profile.SetInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16("Austin"), locale);
- profile.SetInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Texas"), locale);
- profile.SetInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("73301"), locale);
- profile.SetInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16("US"), locale);
- profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16("844-555-0274"),
- locale);
- profile.set_use_date(use_date);
- return profile;
-}
-
-// Create a card expiring 500 days from now which was last used 10 days ago.
-CreditCard CreateBasicTestCreditCard(const std::string& locale) {
- const base::Time now = AutofillClock::Now();
- const base::Time use_date = now - base::TimeDelta::FromDays(10);
- base::Time::Exploded expiry_date;
- (now + base::TimeDelta::FromDays(500)).LocalExplode(&expiry_date);
-
- CreditCard credit_card;
- credit_card.SetInfo(CREDIT_CARD_NAME_FULL,
- base::UTF8ToUTF16("Alice Testerson"), locale);
- credit_card.SetInfo(CREDIT_CARD_NUMBER, base::UTF8ToUTF16("4545454545454545"),
- locale);
- credit_card.SetExpirationMonth(expiry_date.month);
- credit_card.SetExpirationYear(expiry_date.year);
- credit_card.set_use_date(use_date);
- return credit_card;
-}
-
-CreditCard CreateDisusedTestCreditCard(const std::string& locale) {
- const base::Time now = AutofillClock::Now();
- const base::Time use_date = now - base::TimeDelta::FromDays(185);
- base::Time::Exploded expiry_date;
- (now - base::TimeDelta::FromDays(200)).LocalExplode(&expiry_date);
-
- CreditCard credit_card;
- credit_card.SetInfo(CREDIT_CARD_NAME_FULL, base::UTF8ToUTF16("Bob Disused"),
- locale);
- credit_card.SetInfo(CREDIT_CARD_NUMBER, base::UTF8ToUTF16("4111111111111111"),
- locale);
- credit_card.SetExpirationMonth(expiry_date.month);
- credit_card.SetExpirationYear(expiry_date.year);
- credit_card.set_use_date(use_date);
- return credit_card;
-}
-
-CreditCard CreateDisusedDeletableTestCreditCard(const std::string& locale) {
- const base::Time now = AutofillClock::Now();
- const base::Time use_date = now - DeletableUseDateDelta();
- base::Time::Exploded expiry_date;
- (now - DeletableExpiryDateDelta()).LocalExplode(&expiry_date);
-
- CreditCard credit_card;
- credit_card.SetInfo(CREDIT_CARD_NAME_FULL,
- base::UTF8ToUTF16("Charlie Deletable"), locale);
- credit_card.SetInfo(CREDIT_CARD_NUMBER, base::UTF8ToUTF16("378282246310005"),
- locale);
- credit_card.SetExpirationMonth(expiry_date.month);
- credit_card.SetExpirationYear(expiry_date.year);
- credit_card.set_use_date(use_date);
- return credit_card;
-}
-
} // namespace
// Helper class to abstract the switching between account and profile storage
@@ -400,7 +256,8 @@ class PersonalDatabaseHelper
};
PersonalDataManager::PersonalDataManager(const std::string& app_locale)
- : app_locale_(app_locale) {
+ : app_locale_(app_locale),
+ test_data_creator_(kDisusedDataModelDeletionTimeDelta, app_locale_) {
database_helper_ = std::make_unique<PersonalDatabaseHelper>(this);
}
@@ -447,6 +304,11 @@ void PersonalDataManager::Init(
if (!database_helper_->GetLocalDatabase()) {
return;
}
+
+ database_helper_->GetLocalDatabase()->SetAutofillProfileChangedCallback(
+ base::BindRepeating(&PersonalDataManager::OnAutofillProfileChanged,
+ weak_factory_.GetWeakPtr()));
+
LoadProfiles();
LoadCreditCards();
LoadPaymentsCustomerData();
@@ -454,7 +316,7 @@ void PersonalDataManager::Init(
// Check if profile cleanup has already been performed this major version.
is_autofill_profile_cleanup_pending_ =
pref_service_->GetInteger(prefs::kAutofillLastVersionDeduped) >=
- atoi(version_info::GetVersionNumber().c_str());
+ CHROME_VERSION_MAJOR;
DVLOG(1) << "Autofill profile cleanup "
<< (is_autofill_profile_cleanup_pending_ ? "needs to be"
: "has already been")
@@ -576,7 +438,7 @@ void PersonalDataManager::OnWebDataServiceRequestDone(
// If the user has a saved unmasked server card and the experiment is
// disabled, force mask all cards back to the unsaved state.
- if (!OfferStoreUnmaskedCards())
+ if (!OfferStoreUnmaskedCards(is_off_the_record_))
ResetFullServerCards();
}
break;
@@ -621,12 +483,16 @@ void PersonalDataManager::OnWebDataServiceRequestDone(
}
is_data_loaded_ = true;
+ // TODO(crbug.com/915229): Remove once the investigation is over.
+ DLOG(WARNING) << this << " refresh is done, notifying PersonalDataChanged";
NotifyPersonalDataChanged();
}
}
void PersonalDataManager::AutofillMultipleChanged() {
has_synced_new_data_ = true;
+ // TODO(crbug.com/915229): Remove once the investigation is over.
+ DLOG(WARNING) << this << " has synced new data, refreshing";
Refresh();
}
@@ -764,18 +630,20 @@ void PersonalDataManager::RecordUseOf(const AutofillDataModel& data_model) {
AutofillProfile* profile = GetProfileByGUID(data_model.guid());
if (profile) {
- profile->RecordAndLogUse();
-
if (profile->record_type() == AutofillProfile::LOCAL_PROFILE) {
- database_helper_->GetLocalDatabase()->UpdateAutofillProfile(*profile);
+ // We can't make the change directly on the web_profiles_, the update
+ // should happen in the database first.
+ AutofillProfile updated_profile(*profile);
+ updated_profile.RecordAndLogUse();
+ UpdateProfileInDB(updated_profile);
} else if (profile->record_type() == AutofillProfile::SERVER_PROFILE) {
+ profile->RecordAndLogUse();
// TODO(crbug.com/864519): Update this once addresses support account
// storage, and also use the server database.
database_helper_->GetLocalDatabase()->UpdateServerAddressMetadata(
*profile);
+ Refresh();
}
-
- Refresh();
}
}
@@ -786,39 +654,16 @@ void PersonalDataManager::AddProfile(const AutofillProfile& profile) {
if (is_off_the_record_)
return;
- if (profile.IsEmpty(app_locale_))
- return;
-
- // Don't add an existing profile.
- if (FindByGUID<AutofillProfile>(web_profiles_, profile.guid()))
- return;
-
if (!database_helper_->GetLocalDatabase())
return;
- // Don't add a duplicate.
- if (FindByContents(web_profiles_, profile))
- return;
-
- // Add the new profile to the web database.
- database_helper_->GetLocalDatabase()->AddAutofillProfile(profile);
-
- // Refresh our local cache and send notifications to observers.
- Refresh();
+ AddProfileToDB(profile);
}
void PersonalDataManager::UpdateProfile(const AutofillProfile& profile) {
if (is_off_the_record_)
return;
- AutofillProfile* existing_profile = GetProfileByGUID(profile.guid());
- if (!existing_profile)
- return;
-
- // Don't overwrite the origin for a profile that is already stored.
- if (existing_profile->EqualsSansOrigin(profile))
- return;
-
if (profile.IsEmpty(app_locale_)) {
RemoveByGUID(profile.guid());
return;
@@ -827,11 +672,7 @@ void PersonalDataManager::UpdateProfile(const AutofillProfile& profile) {
if (!database_helper_->GetLocalDatabase())
return;
- // Make the update.
- database_helper_->GetLocalDatabase()->UpdateAutofillProfile(profile);
-
- // Refresh our local cache and send notifications to observers.
- Refresh();
+ UpdateProfileInDB(profile);
}
AutofillProfile* PersonalDataManager::GetProfileByGUID(
@@ -1065,9 +906,9 @@ void PersonalDataManager::SetSyncServiceForTest(
}
void PersonalDataManager::
- RemoveAutofillProfileByGUIDAndBlankCreditCardReferecne(
+ RemoveAutofillProfileByGUIDAndBlankCreditCardReference(
const std::string& guid) {
- database_helper_->GetLocalDatabase()->RemoveAutofillProfile(guid);
+ RemoveProfileFromDB(guid);
// Reset the billing_address_id of any card that refered to this profile.
for (CreditCard* credit_card : GetCreditCards()) {
@@ -1090,23 +931,17 @@ void PersonalDataManager::RemoveByGUID(const std::string& guid) {
if (is_off_the_record_)
return;
- bool is_credit_card = FindByGUID<CreditCard>(local_credit_cards_, guid);
- bool is_profile =
- !is_credit_card && FindByGUID<AutofillProfile>(web_profiles_, guid);
- if (!is_credit_card && !is_profile)
- return;
-
if (!database_helper_->GetLocalDatabase())
return;
+ bool is_credit_card = FindByGUID<CreditCard>(local_credit_cards_, guid);
if (is_credit_card) {
database_helper_->GetLocalDatabase()->RemoveCreditCard(guid);
+ // Refresh our local cache and send notifications to observers.
+ Refresh();
} else {
- RemoveAutofillProfileByGUIDAndBlankCreditCardReferecne(guid);
+ RemoveAutofillProfileByGUIDAndBlankCreditCardReference(guid);
}
-
- // Refresh our local cache and send notifications to observers.
- Refresh();
}
CreditCard* PersonalDataManager::GetCreditCardByGUID(const std::string& guid) {
@@ -1128,7 +963,7 @@ CreditCard* PersonalDataManager::GetCreditCardByNumber(
}
void PersonalDataManager::GetNonEmptyTypes(
- ServerFieldTypeSet* non_empty_types) {
+ ServerFieldTypeSet* non_empty_types) const {
for (AutofillProfile* profile : GetProfiles())
profile->GetNonEmptyTypes(app_locale_, non_empty_types);
for (CreditCard* card : GetCreditCards())
@@ -1147,11 +982,11 @@ std::vector<AutofillProfile*> PersonalDataManager::GetProfiles() const {
return result;
}
-void PersonalDataManager::UpdateProfilesValidityMapsIfNeeded(
+void PersonalDataManager::UpdateProfilesServerValidityMapsIfNeeded(
const std::vector<AutofillProfile*>& profiles) {
- if (!profile_validities_need_update_)
+ if (!profiles_server_validities_need_update_)
return;
- profile_validities_need_update_ = false;
+ profiles_server_validities_need_update_ = false;
for (auto* profile : profiles) {
profile->UpdateServerValidityMap(GetProfileValidityByGUID(profile->guid()));
}
@@ -1159,6 +994,10 @@ void PersonalDataManager::UpdateProfilesValidityMapsIfNeeded(
void PersonalDataManager::UpdateClientValidityStates(
const std::vector<AutofillProfile*>& profiles) {
+ if (!base::FeatureList::IsEnabled(
+ autofill::features::kAutofillProfileClientValidation))
+ return;
+
if (!client_profile_validator_)
return;
@@ -1166,18 +1005,18 @@ void PersonalDataManager::UpdateClientValidityStates(
// keep up with the validation logic.
bool update_validation =
pref_service_->GetInteger(prefs::kAutofillLastVersionValidated) <
- atoi(version_info::GetVersionNumber().c_str());
+ CHROME_VERSION_MAJOR;
for (const auto* profile : profiles) {
if (!profile->is_client_validity_states_updated() || update_validation) {
client_profile_validator_->StartProfileValidation(
profile, base::BindOnce(&PersonalDataManager::OnValidated,
- base::Unretained(this)));
+ weak_factory_.GetWeakPtr()));
}
}
// Set the pref to the current major version if already not set.
if (update_validation)
pref_service_->SetInteger(prefs::kAutofillLastVersionValidated,
- atoi(version_info::GetVersionNumber().c_str()));
+ CHROME_VERSION_MAJOR);
}
std::vector<AutofillProfile*> PersonalDataManager::GetServerProfiles() const {
@@ -1230,7 +1069,6 @@ void PersonalDataManager::Refresh() {
LoadProfiles();
LoadCreditCards();
LoadPaymentsCustomerData();
- profile_validities_need_update_ = true;
}
std::vector<AutofillProfile*> PersonalDataManager::GetProfilesToSuggest()
@@ -1305,12 +1143,12 @@ std::vector<Suggestion> PersonalDataManager::GetProfileSuggestions(
if (base::FeatureList::IsEnabled(
features::kAutofillSuppressDisusedAddresses)) {
const base::Time min_last_used =
- AutofillClock::Now() - kDisusedProfileTimeDelta;
+ AutofillClock::Now() - kDisusedDataModelTimeDelta;
suggestion_selection::RemoveProfilesNotUsedSinceTimestamp(
min_last_used, &sorted_profiles);
}
// We need the updated information on the validity states of the profiles.
- UpdateProfilesValidityMapsIfNeeded(sorted_profiles);
+ UpdateProfilesServerValidityMapsIfNeeded(sorted_profiles);
MaybeRemoveInvalidSuggestions(type, &sorted_profiles);
}
@@ -1414,7 +1252,7 @@ std::vector<Suggestion> PersonalDataManager::GetCreditCardSuggestions(
base::FeatureList::IsEnabled(
features::kAutofillSuppressDisusedCreditCards)) {
const base::Time min_last_used =
- AutofillClock::Now() - kDisusedCreditCardTimeDelta;
+ AutofillClock::Now() - kDisusedDataModelTimeDelta;
RemoveExpiredCreditCardsNotUsedSinceTimestamp(AutofillClock::Now(),
min_last_used, &cards);
}
@@ -1501,20 +1339,13 @@ void PersonalDataManager::SetPrefService(PrefService* pref_service) {
}
void PersonalDataManager::ClearProfileNonSettingsOrigins() {
- bool has_updated = false;
-
for (AutofillProfile* profile : GetProfiles()) {
if (profile->origin() != kSettingsOrigin && !profile->origin().empty()) {
profile->set_origin(std::string());
- database_helper_->GetLocalDatabase()->UpdateAutofillProfile(*profile);
- has_updated = true;
+ UpdateProfileInDB(*profile);
}
}
- // Refresh the local cache and send notifications to observers if a changed
- // was made.
- if (has_updated)
- Refresh();
}
void PersonalDataManager::ClearCreditCardNonSettingsOrigins() {
@@ -1542,7 +1373,6 @@ void PersonalDataManager::MoveJapanCityToStreetAddress() {
if (pref_service_->GetBoolean(prefs::kAutofillJapanCityFieldMigrated))
return;
- bool has_updated = false;
base::string16 japan_country_code = base::ASCIIToUTF16("JP");
base::string16 line_separator = base::ASCIIToUTF16("\n");
for (AutofillProfile* profile : GetProfiles()) {
@@ -1558,16 +1388,10 @@ void PersonalDataManager::MoveJapanCityToStreetAddress() {
profile->SetRawInfo(ADDRESS_HOME_CITY, base::string16());
// Make the update.
- database_helper_->GetLocalDatabase()->UpdateAutofillProfile(*profile);
- has_updated = true;
+ UpdateProfileInDB(*profile);
}
}
- // Refresh the local cache and send notifications to observers if a change was
- // made.
- if (has_updated)
- Refresh();
-
// Set the pref so that this migration is never run again.
pref_service_->SetBoolean(prefs::kAutofillJapanCityFieldMigrated, true);
}
@@ -1590,7 +1414,7 @@ const ProfileValidityMap& PersonalDataManager::GetProfileValidityByGUID(
const std::string& guid) {
static const ProfileValidityMap& empty_validity_map = ProfileValidityMap();
if (!synced_profile_validity_) {
- profile_validities_need_update_ = true;
+ profiles_server_validities_need_update_ = true;
synced_profile_validity_ = std::make_unique<UserProfileValidityMap>();
if (!synced_profile_validity_->ParseFromString(
::autofill::prefs::GetAllProfilesValidityMapsEncodedString(
@@ -1607,8 +1431,7 @@ const ProfileValidityMap& PersonalDataManager::GetProfileValidityByGUID(
return empty_validity_map;
}
-// TODO(crbug.com/618448): Refactor MergeProfile to not depend on class
-// variables.
+// static
std::string PersonalDataManager::MergeProfile(
const AutofillProfile& new_profile,
std::vector<std::unique_ptr<AutofillProfile>>* existing_profiles,
@@ -1744,31 +1567,25 @@ void PersonalDataManager::DedupeCreditCardToSuggest(
void PersonalDataManager::SetProfiles(std::vector<AutofillProfile>* profiles) {
if (is_off_the_record_)
return;
-
- // Remove empty profiles from input.
- base::EraseIf(*profiles, IsEmptyFunctor<AutofillProfile>(app_locale_));
-
if (!database_helper_->GetLocalDatabase())
return;
+ ClearOnGoingProfileChanges();
+
// Any profiles that are not in the new profile list should be removed from
- // the web database.
+ // the web database
for (const auto& it : web_profiles_) {
if (!FindByGUID<AutofillProfile>(*profiles, it->guid()))
- database_helper_->GetLocalDatabase()->RemoveAutofillProfile(it->guid());
- }
-
- // Update the web database with the existing profiles.
- for (const AutofillProfile& it : *profiles) {
- if (FindByGUID<AutofillProfile>(web_profiles_, it.guid()))
- database_helper_->GetLocalDatabase()->UpdateAutofillProfile(it);
+ RemoveProfileFromDB(it->guid());
}
- // Add the new profiles to the web database. Don't add a duplicate.
+ // Update the web database with the new and existing profiles.
for (const AutofillProfile& it : *profiles) {
- if (!FindByGUID<AutofillProfile>(web_profiles_, it.guid()) &&
- !FindByContents(web_profiles_, it))
- database_helper_->GetLocalDatabase()->AddAutofillProfile(it);
+ if (FindByGUID<AutofillProfile>(web_profiles_, it.guid())) {
+ UpdateProfileInDB(it);
+ } else {
+ AddProfileToDB(it);
+ }
}
// Copy in the new profiles.
@@ -1776,9 +1593,6 @@ void PersonalDataManager::SetProfiles(std::vector<AutofillProfile>* profiles) {
for (const AutofillProfile& it : *profiles) {
web_profiles_.push_back(std::make_unique<AutofillProfile>(it));
}
-
- // Refresh our local cache and send notifications to observers.
- Refresh();
}
void PersonalDataManager::SetCreditCards(
@@ -1914,8 +1728,13 @@ std::string PersonalDataManager::SaveImportedProfile(
}
void PersonalDataManager::NotifyPersonalDataChanged() {
- for (PersonalDataManagerObserver& observer : observers_)
+ bool profile_changes_are_on_going = ProfileChangesAreOnGoing();
+ for (PersonalDataManagerObserver& observer : observers_) {
observer.OnPersonalDataChanged();
+ if (!profile_changes_are_on_going) {
+ observer.OnPersonalDataFinishedProfileTasks();
+ }
+ }
// If new data was synced, try to convert new server profiles and update
// server cards.
@@ -1979,7 +1798,7 @@ void PersonalDataManager::LogStoredProfileMetrics() const {
const base::TimeDelta time_since_last_use = now - profile->use_date();
AutofillMetrics::LogStoredProfileDaysSinceLastUse(
time_since_last_use.InDays());
- if (time_since_last_use > kDisusedProfileTimeDelta)
+ if (time_since_last_use > kDisusedDataModelTimeDelta)
++num_disused_profiles;
}
AutofillMetrics::LogStoredProfileDisusedCount(num_disused_profiles);
@@ -1993,7 +1812,7 @@ void PersonalDataManager::LogStoredProfileMetrics() const {
void PersonalDataManager::LogStoredCreditCardMetrics() const {
if (!has_logged_stored_credit_card_metrics_) {
AutofillMetrics::LogStoredCreditCardMetrics(
- local_credit_cards_, server_credit_cards_, kDisusedProfileTimeDelta);
+ local_credit_cards_, server_credit_cards_, kDisusedDataModelTimeDelta);
// Only log this info once per chrome user profile load.
has_logged_stored_credit_card_metrics_ = true;
@@ -2046,7 +1865,7 @@ void PersonalDataManager::EnableAutofillPrefChanged() {
Refresh();
}
-bool PersonalDataManager::IsKnownCard(const CreditCard& credit_card) {
+bool PersonalDataManager::IsKnownCard(const CreditCard& credit_card) const {
const auto stripped_pan = CreditCard::StripSeparators(credit_card.number());
for (const auto& card : local_credit_cards_) {
if (stripped_pan == CreditCard::StripSeparators(card->number()))
@@ -2131,6 +1950,51 @@ void PersonalDataManager::OnUserAcceptedCardsFromAccountOption() {
/*opted_in=*/true);
}
+void PersonalDataManager::OnAutofillProfileChanged(
+ const AutofillProfileDeepChange& change) {
+ const auto& guid = change.key();
+ const auto& change_type = change.type();
+ const auto& profile = change.profile();
+
+ DCHECK(guid == profile.guid());
+
+ // Happens only in tests.
+ if (!ProfileChangesAreOnGoing(guid)) {
+ DVLOG(1) << "Received an unexpected response from database.";
+ return;
+ }
+
+ const auto* existing_profile = GetProfileByGUID(guid);
+ const bool profile_exists = (existing_profile != nullptr);
+ switch (change_type) {
+ case AutofillProfileChange::ADD:
+ profiles_server_validities_need_update_ = true;
+ if (!profile_exists && !FindByContents(web_profiles_, profile)) {
+ web_profiles_.push_back(std::make_unique<AutofillProfile>(profile));
+ }
+ break;
+ case AutofillProfileChange::UPDATE:
+ profiles_server_validities_need_update_ = true;
+ if (profile_exists &&
+ !existing_profile->EqualsForUpdatePurposes(profile)) {
+ web_profiles_.erase(
+ FindElementByGUID<AutofillProfile>(web_profiles_, guid));
+ web_profiles_.push_back(std::make_unique<AutofillProfile>(profile));
+ }
+ break;
+ case AutofillProfileChange::REMOVE:
+ if (profile_exists) {
+ web_profiles_.erase(
+ FindElementByGUID<AutofillProfile>(web_profiles_, guid));
+ }
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ OnProfileChangeDone(guid);
+}
+
void PersonalDataManager::LogServerCardLinkClicked() const {
AutofillMetrics::LogServerCardLinkClicked(GetSyncSigninState());
}
@@ -2249,33 +2113,39 @@ bool PersonalDataManager::ApplyDedupingRoutine() {
}
// Check if de-duplication has already been performed this major version.
- int current_major_version = atoi(version_info::GetVersionNumber().c_str());
if (pref_service_->GetInteger(prefs::kAutofillLastVersionDeduped) >=
- current_major_version) {
+ CHROME_VERSION_MAJOR) {
DVLOG(1)
<< "Autofill profile de-duplication already performed for this version";
return false;
}
DVLOG(1) << "Starting autofill profile de-duplication.";
- std::unordered_set<AutofillProfile*> profiles_to_delete;
+ std::unordered_set<std::string> profiles_to_delete;
profiles_to_delete.reserve(web_profiles_.size());
// Create the map used to update credit card's billing addresses after the
// dedupe.
std::unordered_map<std::string, std::string> guids_merge_map;
- DedupeProfiles(&web_profiles_, &profiles_to_delete, &guids_merge_map);
+ // The changes can't happen directly on the web_profiles_, but need to be
+ // updated in the database at first, and then updated on the web_profiles_.
+ // Therefore, we need a copy of web_profiles_ to keep track of the changes.
+ std::vector<std::unique_ptr<AutofillProfile>> new_profiles;
+ for (const auto& it : web_profiles_) {
+ new_profiles.push_back(std::make_unique<AutofillProfile>(*(it.get())));
+ }
+
+ DedupeProfiles(&new_profiles, &profiles_to_delete, &guids_merge_map);
// Apply the profile changes to the database.
- for (const auto& profile : web_profiles_) {
- // If the profile was set to be deleted, remove it from the database.
- if (profiles_to_delete.count(profile.get())) {
- database_helper_->GetLocalDatabase()->RemoveAutofillProfile(
- profile->guid());
+ for (const auto& profile : new_profiles) {
+ // If the profile was set to be deleted, remove it from the database,
+ // otherwise update it.
+ if (profiles_to_delete.count(profile->guid())) {
+ RemoveProfileFromDB(profile->guid());
} else {
- // Otherwise, update the profile in the database.
- database_helper_->GetLocalDatabase()->UpdateAutofillProfile(*profile);
+ UpdateProfileInDB(*(profile.get()));
}
}
@@ -2283,17 +2153,13 @@ bool PersonalDataManager::ApplyDedupingRoutine() {
// Set the pref to the current major version.
pref_service_->SetInteger(prefs::kAutofillLastVersionDeduped,
- current_major_version);
-
- // Refresh the local cache and send notifications to observers.
- Refresh();
-
+ CHROME_VERSION_MAJOR);
return true;
}
void PersonalDataManager::DedupeProfiles(
std::vector<std::unique_ptr<AutofillProfile>>* existing_profiles,
- std::unordered_set<AutofillProfile*>* profiles_to_delete,
+ std::unordered_set<std::string>* profiles_to_delete,
std::unordered_map<std::string, std::string>* guids_merge_map) const {
AutofillMetrics::LogNumberOfProfilesConsideredForDedupe(
existing_profiles->size());
@@ -2321,7 +2187,7 @@ void PersonalDataManager::DedupeProfiles(
// If the profile was set to be deleted, skip it. It has already been
// merged into another profile.
- if (profiles_to_delete->count(profile_to_merge))
+ if (profiles_to_delete->count(profile_to_merge->guid()))
continue;
// If we have reached the verified profiles, stop trying to merge. Verified
@@ -2335,7 +2201,7 @@ void PersonalDataManager::DedupeProfiles(
AutofillProfile* existing_profile = (*existing_profiles)[j].get();
// Don't try to merge a profile that was already set for deletion.
- if (profiles_to_delete->count(existing_profile))
+ if (profiles_to_delete->count(existing_profile->guid()))
continue;
// Move on if the profiles are not mergeable.
@@ -2355,7 +2221,7 @@ void PersonalDataManager::DedupeProfiles(
// Since |profile_to_merge| was a duplicate of |existing_profile|
// and was merged successfully, it can now be deleted.
- profiles_to_delete->insert(profile_to_merge);
+ profiles_to_delete->insert(profile_to_merge->guid());
// Now try to merge the new resulting profile with the rest of the
// existing profiles.
@@ -2417,6 +2283,7 @@ void PersonalDataManager::UpdateCardsBillingAddressReference(
*credit_card);
}
}
+ Refresh();
}
void PersonalDataManager::ConvertWalletAddressesAndUpdateWalletCards() {
@@ -2454,7 +2321,9 @@ void PersonalDataManager::ConvertWalletAddressesAndUpdateWalletCards() {
UpdateCardsBillingAddressReference(guids_merge_map);
// Force a reload of the profiles and cards.
- Refresh();
+ // TODO(crbug.com/915229): Remove once the investigation is over.
+ if (has_converted_addresses)
+ DLOG(WARNING) << this << " conversion of addresses done";
}
}
@@ -2465,6 +2334,11 @@ bool PersonalDataManager::ConvertWalletAddressesToLocalProfiles(
// If the full Sync feature isn't enabled, then do NOT convert any Wallet
// addresses to local ones.
if (!IsSyncFeatureEnabled()) {
+ // TODO(crbug.com/915229): Remove once the investigation is over.
+ DLOG(WARNING) << this
+ << " not converting as sync feature is not enabled, probably "
+ "due to sync_service_ being "
+ << sync_service_;
return false;
}
@@ -2478,8 +2352,12 @@ bool PersonalDataManager::ConvertWalletAddressesToLocalProfiles(
if (!wallet_address->has_converted()) {
// Try to merge the server address into a similar local profile, or create
// a new local profile if no similar profile is found.
- std::string address_guid =
- MergeServerAddressesIntoProfiles(*wallet_address, local_profiles);
+ // TODO(crbug.com/864519): Use GetAccountInfoForPaymentsServer instead of
+ // going to IdentityManager directly. This will be necessary to properly
+ // support Wallet addresses with Butter.
+ std::string address_guid = MergeServerAddressesIntoProfiles(
+ *wallet_address, local_profiles, app_locale_,
+ identity_manager_->GetPrimaryAccountInfo().email);
// Update the map to transfer the billing address relationship from the
// server address to the converted/merged local profile.
@@ -2487,6 +2365,8 @@ bool PersonalDataManager::ConvertWalletAddressesToLocalProfiles(
// Update the wallet addresses metadata to record the conversion.
wallet_address->set_has_converted(true);
+ // TODO(crbug.com/915229): Remove once the investigation is over.
+ DLOG(WARNING) << this << " converting address " << *wallet_address;
database_helper_->GetServerDatabase()->UpdateServerAddressMetadata(
*wallet_address);
@@ -2540,16 +2420,19 @@ bool PersonalDataManager::UpdateWalletCardsAlreadyConvertedBillingAddresses(
return should_update_cards;
}
-// TODO(crbug.com/687975): Reuse MergeProfiles in this function.
+// TODO(crbug.com/687975): Reuse MergeProfile in this function.
+// static
std::string PersonalDataManager::MergeServerAddressesIntoProfiles(
const AutofillProfile& server_address,
- std::vector<AutofillProfile>* existing_profiles) const {
+ std::vector<AutofillProfile>* existing_profiles,
+ const std::string& app_locale,
+ const std::string& primary_account_email) {
// If there is already a local profile that is very similar, merge in any
// missing values. Only merge with the first match.
- AutofillProfileComparator comparator(app_locale_);
+ AutofillProfileComparator comparator(app_locale);
for (auto& local_profile : *existing_profiles) {
if (comparator.AreMergeable(server_address, local_profile) &&
- local_profile.SaveAdditionalInfo(server_address, app_locale_)) {
+ local_profile.SaveAdditionalInfo(server_address, app_locale)) {
local_profile.set_modification_date(AutofillClock::Now());
AutofillMetrics::LogWalletAddressConversionType(
AutofillMetrics::CONVERTED_ADDRESS_MERGED);
@@ -2566,11 +2449,7 @@ std::string PersonalDataManager::MergeServerAddressesIntoProfiles(
// Wallet addresses don't have an email address, use the one from the
// currently signed-in account.
- // TODO(crbug.com/864519): Use GetAccountInfoForPaymentsServer instead of
- // going to IdentityManager directly. This will be necessary to properly
- // support Wallet addresses with Butter.
- base::string16 email =
- base::UTF8ToUTF16(identity_manager_->GetPrimaryAccountInfo().email);
+ base::string16 email = base::UTF8ToUTF16(primary_account_email);
if (!email.empty())
existing_profiles->back().SetRawInfo(EMAIL_ADDRESS, email);
@@ -2580,40 +2459,6 @@ std::string PersonalDataManager::MergeServerAddressesIntoProfiles(
return server_address.guid();
}
-void PersonalDataManager::MaybeCreateTestAddresses() {
- if (has_created_test_addresses_)
- return;
-
- has_created_test_addresses_ = true;
- if (!base::FeatureList::IsEnabled(features::kAutofillCreateDataForTest))
- return;
-
- AddProfile(CreateBasicTestAddress(app_locale_));
- AddProfile(CreateDisusedTestAddress(app_locale_));
- AddProfile(CreateDisusedDeletableTestAddress(app_locale_));
-}
-
-void PersonalDataManager::MaybeCreateTestCreditCards() {
- if (has_created_test_credit_cards_)
- return;
-
- has_created_test_credit_cards_ = true;
- if (!base::FeatureList::IsEnabled(features::kAutofillCreateDataForTest))
- return;
-
- AddCreditCard(CreateBasicTestCreditCard(app_locale_));
- AddCreditCard(CreateDisusedTestCreditCard(app_locale_));
- AddCreditCard(CreateDisusedDeletableTestCreditCard(app_locale_));
-}
-
-bool PersonalDataManager::IsCreditCardDeletable(CreditCard* card) {
- const base::Time deletion_threshold =
- AutofillClock::Now() - kDisusedCreditCardDeletionTimeDelta;
-
- return card->use_date() < deletion_threshold &&
- card->IsExpired(deletion_threshold);
-}
-
bool PersonalDataManager::DeleteDisusedCreditCards() {
if (!base::FeatureList::IsEnabled(
features::kAutofillDeleteDisusedCreditCards)) {
@@ -2630,7 +2475,7 @@ bool PersonalDataManager::DeleteDisusedCreditCards() {
std::vector<std::string> guid_to_delete;
for (CreditCard* card : cards) {
- if (IsCreditCardDeletable(card)) {
+ if (card->IsDeletable()) {
guid_to_delete.push_back(card->guid());
}
}
@@ -2650,17 +2495,6 @@ bool PersonalDataManager::DeleteDisusedCreditCards() {
return true;
}
-bool PersonalDataManager::IsAddressDeletable(
- AutofillProfile* profile,
- std::unordered_set<std::string> const& used_billing_address_guids) {
- const base::Time deletion_threshold =
- AutofillClock::Now() - kDisusedAddressDeletionTimeDelta;
-
- return profile->use_date() < deletion_threshold && !profile->IsVerified() &&
- used_billing_address_guids.find(profile->guid()) ==
- used_billing_address_guids.end();
-}
-
bool PersonalDataManager::DeleteDisusedAddresses() {
if (!base::FeatureList::IsEnabled(
features::kAutofillDeleteDisusedAddresses)) {
@@ -2678,14 +2512,15 @@ bool PersonalDataManager::DeleteDisusedAddresses() {
std::unordered_set<std::string> used_billing_address_guids;
for (CreditCard* card : GetCreditCards()) {
- if (!IsCreditCardDeletable(card)) {
+ if (!card->IsDeletable()) {
used_billing_address_guids.insert(card->billing_address_id());
}
}
std::vector<std::string> guids_to_delete;
for (AutofillProfile* profile : profiles) {
- if (IsAddressDeletable(profile, used_billing_address_guids)) {
+ if (profile->IsDeletable() &&
+ !used_billing_address_guids.count(profile->guid())) {
guids_to_delete.push_back(profile->guid());
}
}
@@ -2693,7 +2528,7 @@ bool PersonalDataManager::DeleteDisusedAddresses() {
size_t num_deleted_addresses = guids_to_delete.size();
for (auto const guid : guids_to_delete) {
- RemoveAutofillProfileByGUIDAndBlankCreditCardReferecne(guid);
+ RemoveAutofillProfileByGUIDAndBlankCreditCardReference(guid);
}
if (num_deleted_addresses > 0) {
@@ -2706,23 +2541,156 @@ bool PersonalDataManager::DeleteDisusedAddresses() {
}
void PersonalDataManager::ApplyAddressFixesAndCleanups() {
- RemoveOrphanAutofillTableRows(); // One-time fix, otherwise NOP.
- ApplyDedupingRoutine(); // Once per major version, otherwise NOP.
+ // One-time fix, otherwise NOP.
+ RemoveOrphanAutofillTableRows();
+
+ // Once per major version, otherwise NOP.
+ ApplyDedupingRoutine();
+
DeleteDisusedAddresses();
- MaybeCreateTestAddresses(); // Once per user profile startup.
- ClearProfileNonSettingsOrigins(); // Ran everytime it is called.
- MoveJapanCityToStreetAddress(); // One-time fix, otherwise NOP.
+
+ // If feature AutofillCreateDataForTest is enabled, and once per user profile
+ // startup.
+ test_data_creator_.MaybeAddTestProfiles(base::BindRepeating(
+ &PersonalDataManager::AddProfile, base::Unretained(this)));
+
+ // Ran everytime it is called.
+ ClearProfileNonSettingsOrigins();
+
+ // One-time fix, otherwise NOP.
+ MoveJapanCityToStreetAddress();
}
void PersonalDataManager::ApplyCardFixesAndCleanups() {
DeleteDisusedCreditCards();
- MaybeCreateTestCreditCards(); // Once per user profile startup.
- ClearCreditCardNonSettingsOrigins(); // Ran everytime it is called.
+
+ // If feature AutofillCreateDataForTest is enabled, and once per user profile
+ // startup.
+ test_data_creator_.MaybeAddTestCreditCards(base::BindRepeating(
+ &PersonalDataManager::AddCreditCard, base::Unretained(this)));
+
+ // Ran everytime it is called.
+ ClearCreditCardNonSettingsOrigins();
}
void PersonalDataManager::ResetProfileValidity() {
synced_profile_validity_.reset();
- profile_validities_need_update_ = true;
+ profiles_server_validities_need_update_ = true;
+}
+
+void PersonalDataManager::AddProfileToDB(const AutofillProfile& profile) {
+ // Add the new profile to the web database.
+ if (profile.IsEmpty(app_locale_)) {
+ NotifyPersonalDataChanged();
+ return;
+ }
+
+ if (!ProfileChangesAreOnGoing(profile.guid())) {
+ if (FindByGUID<AutofillProfile>(web_profiles_, profile.guid()) ||
+ FindByContents(web_profiles_, profile)) {
+ NotifyPersonalDataChanged();
+ return;
+ }
+ database_helper_->GetLocalDatabase()->AddAutofillProfile(profile);
+ }
+ ongoing_profile_changes_[profile.guid()].push(
+ AutofillProfileDeepChange(AutofillProfileChange::ADD, profile));
+}
+
+void PersonalDataManager::UpdateProfileInDB(const AutofillProfile& profile) {
+ if (!ProfileChangesAreOnGoing(profile.guid())) {
+ const auto* existing_profile = GetProfileByGUID(profile.guid());
+ bool profile_exists = (existing_profile != nullptr);
+ if (profile_exists && !existing_profile->EqualsForUpdatePurposes(profile)) {
+ database_helper_->GetLocalDatabase()->UpdateAutofillProfile(profile);
+ } else {
+ NotifyPersonalDataChanged();
+ return;
+ }
+ }
+
+ ongoing_profile_changes_[profile.guid()].push(
+ AutofillProfileDeepChange(AutofillProfileChange::UPDATE, profile));
+}
+
+void PersonalDataManager::RemoveProfileFromDB(const std::string& guid) {
+ bool profile_exists = FindByGUID<AutofillProfile>(web_profiles_, guid);
+ if (!profile_exists && !ProfileChangesAreOnGoing(guid)) {
+ NotifyPersonalDataChanged();
+ return;
+ }
+
+ if (!ProfileChangesAreOnGoing(guid))
+ database_helper_->GetLocalDatabase()->RemoveAutofillProfile(guid);
+ ongoing_profile_changes_[guid].push(
+ AutofillProfileDeepChange(AutofillProfileChange::REMOVE, guid));
+}
+
+void PersonalDataManager::HandleNextProfileChange(const std::string& guid) {
+ if (!ProfileChangesAreOnGoing(guid))
+ return;
+
+ const auto& change = ongoing_profile_changes_[guid].front();
+ const auto& change_type = change.type();
+ const auto* existing_profile = GetProfileByGUID(guid);
+ const bool profile_exists = (existing_profile != nullptr);
+ const auto& profile = ongoing_profile_changes_[guid].front().profile();
+
+ DCHECK(guid == profile.guid());
+
+ if (change_type == AutofillProfileChange::REMOVE) {
+ if (!profile_exists) {
+ OnProfileChangeDone(guid);
+ return;
+ }
+ database_helper_->GetLocalDatabase()->RemoveAutofillProfile(guid);
+ return;
+ }
+
+ if (change_type == AutofillProfileChange::ADD) {
+ if (profile_exists || FindByContents(web_profiles_, profile)) {
+ OnProfileChangeDone(guid);
+ return;
+ }
+ database_helper_->GetLocalDatabase()->AddAutofillProfile(profile);
+ return;
+ }
+
+ if (!profile_exists || existing_profile->EqualsForUpdatePurposes(profile)) {
+ OnProfileChangeDone(guid);
+ return;
+ }
+ database_helper_->GetLocalDatabase()->UpdateAutofillProfile(profile);
+}
+
+bool PersonalDataManager::ProfileChangesAreOnGoing(const std::string& guid) {
+ return ongoing_profile_changes_.find(guid) !=
+ ongoing_profile_changes_.end() &&
+ !ongoing_profile_changes_[guid].empty();
+}
+
+bool PersonalDataManager::ProfileChangesAreOnGoing() {
+ for (auto task : ongoing_profile_changes_) {
+ if (ProfileChangesAreOnGoing(task.first)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void PersonalDataManager::OnProfileChangeDone(const std::string& guid) {
+ ongoing_profile_changes_[guid].pop();
+
+ if (!ProfileChangesAreOnGoing()) {
+ Refresh();
+ } else {
+ NotifyPersonalDataChanged();
+ HandleNextProfileChange(guid);
+ }
+}
+
+void PersonalDataManager::ClearOnGoingProfileChanges() {
+ ongoing_profile_changes_.clear();
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/personal_data_manager.h b/chromium/components/autofill/core/browser/personal_data_manager.h
index 5e559bcbbac..754305dd365 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager.h
+++ b/chromium/components/autofill/core/browser/personal_data_manager.h
@@ -27,6 +27,8 @@
#include "components/autofill/core/browser/proto/server.pb.h"
#include "components/autofill/core/browser/suggestion.h"
#include "components/autofill/core/browser/sync_utils.h"
+#include "components/autofill/core/browser/test_data_creator.h"
+#include "components/autofill/core/browser/webdata/autofill_change.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h"
#include "components/history/core/browser/history_service_observer.h"
@@ -125,17 +127,6 @@ class PersonalDataManager : public KeyedService,
bool IsSyncFeatureEnabled() const override;
// GaiaCookieManagerService::Observer:
- void OnAddAccountToCookieCompleted(
- const std::string& account_id,
- const GoogleServiceAuthError& error) override {}
- void OnSetAccountsInCookieCompleted(
- const GoogleServiceAuthError& error) override {}
- void OnLogOutAccountsFromCookieCompleted(
- const GoogleServiceAuthError& error) override {}
- void OnGaiaAccountsInCookieUpdated(
- const std::vector<gaia::ListedAccount>& accounts,
- const std::vector<gaia::ListedAccount>& signed_out_accounts,
- const GoogleServiceAuthError& error) override {}
void OnGaiaCookieDeletedByUserAction() override;
// Returns the current sync status.
@@ -239,7 +230,7 @@ class PersonalDataManager : public KeyedService,
virtual CreditCard* GetCreditCardByNumber(const std::string& number);
// Gets the field types availabe in the stored address and credit card data.
- void GetNonEmptyTypes(ServerFieldTypeSet* non_empty_types);
+ void GetNonEmptyTypes(ServerFieldTypeSet* non_empty_types) const;
// Returns whether the personal data has been loaded from the web database.
virtual bool IsDataLoaded() const;
@@ -261,7 +252,7 @@ class PersonalDataManager : public KeyedService,
virtual PaymentsCustomerData* GetPaymentsCustomerData() const;
// Updates the validity states of |profiles| according to server validity map.
- void UpdateProfilesValidityMapsIfNeeded(
+ void UpdateProfilesServerValidityMapsIfNeeded(
const std::vector<AutofillProfile*>& profiles);
// Updates the validity states of |profiles| according to client side
@@ -336,7 +327,7 @@ class PersonalDataManager : public KeyedService,
// 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.
- std::string MergeProfile(
+ static std::string MergeProfile(
const AutofillProfile& new_profile,
std::vector<std::unique_ptr<AutofillProfile>>* existing_profiles,
const std::string& app_locale,
@@ -369,7 +360,7 @@ class PersonalDataManager : public KeyedService,
// if the card number of |credit_card| is equal to any local card or any
// unmasked server card known by the browser, or |TypeAndLastFourDigits| of
// |credit_card| is equal to any masked server card known by the browser.
- bool IsKnownCard(const CreditCard& credit_card);
+ bool IsKnownCard(const CreditCard& credit_card) const;
// Check whether a card is a server card or has a duplicated server card.
bool IsServerCard(const CreditCard* credit_card) const;
@@ -394,6 +385,9 @@ class PersonalDataManager : public KeyedService,
// Records the sync transport consent if the user is in sync transport mode.
virtual void OnUserAcceptedUpstreamOffer();
+ // Triggered when a profile is added/updated/removed on db.
+ void OnAutofillProfileChanged(const AutofillProfileDeepChange& change);
+
protected:
// Only PersonalDataManagerFactory and certain tests can create instances of
// PersonalDataManager.
@@ -497,15 +491,9 @@ class PersonalDataManager : public KeyedService,
std::vector<AutofillProfile>* profiles);
// Sets |web_profiles_| to the contents of |profiles| and updates the web
- // database by adding, updating and removing profiles.
- // The relationship between this and Refresh is subtle.
- // A call to |SetProfiles| could include out-of-date data that may conflict
- // if we didn't refresh-to-latest before an Autofill window was opened for
- // editing. |SetProfiles| is implemented to make a "best effort" to apply the
- // changes, but in extremely rare edge cases it is possible not all of the
- // updates in |profiles| make it to the DB. This is why SetProfiles will
- // invoke Refresh after finishing, to ensure we get into a
- // consistent state. See Refresh for details.
+ // database by adding, updating and removing profiles. |web_profiles_| need to
+ // be updated at the end of the function, since some tasks cannot tolerate
+ // database delays.
virtual void SetProfiles(std::vector<AutofillProfile>* profiles);
// Sets |credit_cards_| to the contents of |credit_cards| and updates the web
@@ -617,7 +605,7 @@ class PersonalDataManager : public KeyedService,
base::ObserverList<PersonalDataManagerObserver>::Unchecked observers_;
// |profile_valditiies_need_update| whenever the profile validities are out of
- bool profile_validities_need_update_ = true;
+ bool profiles_server_validities_need_update_ = true;
private:
// Saves |imported_credit_card| to the WebDB if it exists. Returns the guid of
@@ -643,10 +631,6 @@ class PersonalDataManager : public KeyedService,
const base::string16& field_contents,
const std::vector<CreditCard*>& cards_to_suggest) const;
- // Returns true if the given credit card can be deleted in a major version
- // upgrade. The card will need to be local and disused, to be deletable.
- bool IsCreditCardDeletable(CreditCard* card);
-
// Runs the routine that removes the orphan rows in the autofill tables if
// it's never been done.
void RemoveOrphanAutofillTableRows();
@@ -668,7 +652,7 @@ class PersonalDataManager : public KeyedService,
// testing purposes.
void DedupeProfiles(
std::vector<std::unique_ptr<AutofillProfile>>* existing_profiles,
- std::unordered_set<AutofillProfile*>* profile_guids_to_delete,
+ std::unordered_set<std::string>* profile_guids_to_delete,
std::unordered_map<std::string, std::string>* guids_merge_map) const;
// Updates the credit cards' billing address reference based on the merges
@@ -709,15 +693,17 @@ class PersonalDataManager : public KeyedService,
// should be sorted by decreasing frecency outside of this method, since this
// will be called multiple times in a row. Returns the guid of the new or
// updated profile.
- std::string MergeServerAddressesIntoProfiles(
+ static std::string MergeServerAddressesIntoProfiles(
const AutofillProfile& server_address,
- std::vector<AutofillProfile>* existing_profiles) const;
+ std::vector<AutofillProfile>* existing_profiles,
+ const std::string& app_locale,
+ const std::string& primary_account_email);
// Removes profile from web database according to |guid| and resets credit
// card's billing address if that address is used by any credit cards.
// The method does not refresh, this allows multiple removal with one
// refreshing in the end.
- void RemoveAutofillProfileByGUIDAndBlankCreditCardReferecne(
+ void RemoveAutofillProfileByGUIDAndBlankCreditCardReference(
const std::string& guid);
// Returns true if an address can be deleted in a major version upgrade.
@@ -727,16 +713,6 @@ class PersonalDataManager : public KeyedService,
AutofillProfile* profile,
const std::unordered_set<std::string>& used_billing_address_guids);
- // If the AutofillCreateDataForTest feature is enabled, this helper creates
- // autofill address data that would otherwise be difficult to create
- // manually using the UI.
- void MaybeCreateTestAddresses();
-
- // If the AutofillCreateDataForTest feature is enabled, this helper creates
- // autofill credit card data that would otherwise be difficult to create
- // manually using the UI.
- void MaybeCreateTestCreditCards();
-
// Applies various fixes and cleanups on autofill addresses.
void ApplyAddressFixesAndCleanups();
@@ -746,6 +722,25 @@ class PersonalDataManager : public KeyedService,
// Resets |synced_profile_validity_|.
void ResetProfileValidity();
+ // Add/Update/Remove profiles on DB.
+ void AddProfileToDB(const AutofillProfile& profile);
+ void UpdateProfileInDB(const AutofillProfile& profile);
+ void RemoveProfileFromDB(const std::string& guid);
+
+ // Look at the next profile change for profile with guid = |guid|, and handle
+ // it.
+ void HandleNextProfileChange(const std::string& guid);
+ // returns true if there is any profile change that's still on going.
+ bool ProfileChangesAreOnGoing();
+ // returns true if there is any ongoing change for profile with guid = |guid|
+ // that's still on going.
+ bool ProfileChangesAreOnGoing(const std::string& guid);
+ // Remove the change from the |ongoing_profile_changes_|, handle next task or
+ // Refresh.
+ void OnProfileChangeDone(const std::string& guid);
+ // Clear |ongoing_profile_changes_|.
+ void ClearOnGoingProfileChanges();
+
const std::string app_locale_;
// The default country code for new addresses.
@@ -772,6 +767,10 @@ class PersonalDataManager : public KeyedService,
// |profile_validities_need_update| whenever this is changed.
std::unique_ptr<UserProfileValidityMap> synced_profile_validity_;
+ // A timely ordered list of on going changes for each profile.
+ std::unordered_map<std::string, std::queue<AutofillProfileDeepChange>>
+ ongoing_profile_changes_;
+
// The client side profile validator.
AutofillProfileValidator* client_profile_validator_ = nullptr;
@@ -806,13 +805,16 @@ class PersonalDataManager : public KeyedService,
// Whether new information was received from the sync server.
bool has_synced_new_data_ = false;
- // True if test data has been created this session.
- bool has_created_test_addresses_ = false;
- bool has_created_test_credit_cards_ = false;
+ // Used to create test data. If the AutofillCreateDataForTest feature is
+ // enabled, this helper creates autofill profiles and credit card data that
+ // would otherwise be difficult to create manually using the UI.
+ TestDataCreator test_data_creator_;
// Whether sync should be considered on in a test.
bool is_syncing_for_test_ = false;
+ base::WeakPtrFactory<PersonalDataManager> weak_factory_{this};
+
DISALLOW_COPY_AND_ASSIGN(PersonalDataManager);
};
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 e948d3ff458..d09bc934f9e 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager_observer.h
+++ b/chromium/components/autofill/core/browser/personal_data_manager_observer.h
@@ -18,6 +18,10 @@ class PersonalDataManagerObserver {
// Called when there is insufficient data to fill a form. Used for testing.
virtual void OnInsufficientFormData() {}
+ // Notifies the observer that the PersonalDataManager has no more tasks to
+ // handle.
+ virtual void OnPersonalDataFinishedProfileTasks() {}
+
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 df1261efc1c..f06c16f345b 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -19,7 +19,6 @@
#include "base/files/scoped_temp_dir.h"
#include "base/guid.h"
#include "base/i18n/time_formatting.h"
-#include "base/message_loop/message_loop.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
@@ -27,6 +26,7 @@
#include "base/synchronization/waitable_event.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -72,8 +72,8 @@ const base::Time kArbitraryTime = base::Time::FromDoubleT(25);
const base::Time kSomeLaterTime = base::Time::FromDoubleT(1000);
const base::Time kMuchLaterTime = base::Time::FromDoubleT(5000);
-ACTION(QuitMainMessageLoop) {
- base::RunLoop::QuitCurrentWhenIdleDeprecated();
+ACTION_P(QuitMessageLoop, loop) {
+ loop->Quit();
}
class PersonalDataLoadedObserverMock : public PersonalDataManagerObserver {
@@ -82,6 +82,7 @@ class PersonalDataLoadedObserverMock : public PersonalDataManagerObserver {
~PersonalDataLoadedObserverMock() override {}
MOCK_METHOD0(OnPersonalDataChanged, void());
+ MOCK_METHOD0(OnPersonalDataFinishedProfileTasks, void());
};
class PersonalDataManagerMock : public PersonalDataManager {
@@ -134,8 +135,10 @@ class PersonalDataManagerTestBase {
PersonalDataManagerTestBase() {
// Enable account storage by default, some tests will override this to be
// false.
- scoped_features_.InitAndEnableFeature(
- features::kAutofillEnableAccountWalletStorage);
+ scoped_features_.InitWithFeatures(
+ /*enabled_features=*/{features::kAutofillEnableAccountWalletStorage,
+ features::kAutofillProfileClientValidation},
+ /*disabled_features=*/{});
}
void SetUpTest() {
@@ -179,8 +182,7 @@ class PersonalDataManagerTestBase {
personal_data_->pref_service_->SetInteger(
prefs::kAutofillLastVersionDeduped, 0);
personal_data_->pref_service_->SetInteger(
- prefs::kAutofillLastVersionValidated,
- atoi(version_info::GetVersionNumber().c_str()));
+ prefs::kAutofillLastVersionValidated, CHROME_VERSION_MAJOR);
}
void TearDownTest() {
@@ -193,6 +195,7 @@ class PersonalDataManagerTestBase {
void ResetPersonalDataManager(UserMode user_mode,
bool use_sync_transport_mode) {
bool is_incognito = (user_mode == USER_MODE_INCOGNITO);
+
personal_data_.reset(new PersonalDataManagerMock("en"));
personal_data_->Init(
scoped_refptr<AutofillWebDataService>(profile_database_service_),
@@ -213,10 +216,7 @@ class PersonalDataManagerTestBase {
personal_data_->OnSyncServiceInitialized(&sync_service_);
personal_data_->OnStateChanged(&sync_service_);
- // Verify that the web database has been updated and the notification sent.
- EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
- .WillRepeatedly(QuitMainMessageLoop());
- base::RunLoop().Run();
+ WaitForOnPersonalDataChangedRepeatedly();
}
void ResetPersonalDataManager(UserMode user_mode) {
@@ -226,6 +226,7 @@ class PersonalDataManagerTestBase {
void ResetProfiles() {
std::vector<AutofillProfile> empty_profiles;
personal_data_->SetProfiles(&empty_profiles);
+ WaitForOnPersonalDataChanged();
}
bool TurnOnSyncFeature() WARN_UNUSED_RESULT {
@@ -253,11 +254,7 @@ class PersonalDataManagerTestBase {
test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
- personal_data_->AddProfile(profile);
-
- EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
- .WillOnce(QuitMainMessageLoop());
- base::RunLoop().Run();
+ AddProfileToPersonalDataManager(profile);
ASSERT_EQ(1U, personal_data_->GetProfiles().size());
}
@@ -298,10 +295,7 @@ class PersonalDataManagerTestBase {
"1");
personal_data_->AddCreditCard(credit_card2);
- EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
- .WillOnce(QuitMainMessageLoop());
- base::RunLoop().Run();
-
+ WaitOnceForOnPersonalDataChanged();
ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
}
@@ -318,9 +312,7 @@ class PersonalDataManagerTestBase {
masked_server_card.set_server_id("masked_id");
masked_server_card.set_use_count(15);
personal_data_->AddFullServerCreditCard(masked_server_card);
- EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
- .WillOnce(QuitMainMessageLoop());
- base::RunLoop().Run();
+ WaitOnceForOnPersonalDataChanged();
ASSERT_EQ(1U, personal_data_->GetCreditCards().size());
// Cards are automatically remasked on Linux since full server cards are not
@@ -349,10 +341,7 @@ class PersonalDataManagerTestBase {
local_card.set_use_count(5);
personal_data_->AddCreditCard(local_card);
- EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
- .WillOnce(QuitMainMessageLoop());
- base::RunLoop().Run();
-
+ WaitOnceForOnPersonalDataChanged();
EXPECT_EQ(3U, personal_data_->GetCreditCards().size());
}
@@ -379,9 +368,8 @@ class PersonalDataManagerTestBase {
AutofillProfile profile0(test::GetFullProfile());
profile0.set_use_date(AutofillClock::Now() -
base::TimeDelta::FromDays(400));
- personal_data_->AddProfile(profile0);
+ AddProfileToPersonalDataManager(profile0);
- WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
}
@@ -390,6 +378,38 @@ class PersonalDataManagerTestBase {
: account_autofill_table_;
}
+ void AddProfileToPersonalDataManager(const AutofillProfile& profile) {
+ base::RunLoop run_loop;
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
+ .WillOnce(QuitMessageLoop(&run_loop));
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .Times(testing::AnyNumber());
+ personal_data_->AddProfile(profile);
+ run_loop.Run();
+ }
+
+ void UpdateProfileOnPersonalDataManager(const AutofillProfile& profile) {
+ base::RunLoop run_loop;
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
+ .WillOnce(QuitMessageLoop(&run_loop));
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .Times(testing::AnyNumber());
+
+ personal_data_->UpdateProfile(profile);
+ run_loop.Run();
+ }
+
+ void RemoveByGUIDFromPersonalDataManager(const std::string& guid) {
+ base::RunLoop run_loop;
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
+ .WillOnce(QuitMessageLoop(&run_loop));
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .Times(testing::AnyNumber());
+
+ personal_data_->RemoveByGUID(guid);
+ run_loop.Run();
+ }
+
void SetServerCards(const std::vector<CreditCard>& server_cards) {
test::SetServerCreditCards(GetServerDataTable(), server_cards);
}
@@ -398,11 +418,53 @@ class PersonalDataManagerTestBase {
GetServerDataTable()->SetServerProfiles(server_profiles);
}
+ void SaveImportedProfileToPersonalDataManager(
+ const AutofillProfile& profile) {
+ base::RunLoop run_loop;
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
+ .WillOnce(QuitMessageLoop(&run_loop));
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(1);
+
+ personal_data_->SaveImportedProfile(profile);
+ run_loop.Run();
+ }
+
+ void ConvertWalletAddressesAndUpdateWalletCards() {
+ base::RunLoop run_loop;
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
+ .WillOnce(QuitMessageLoop(&run_loop));
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(1);
+
+ personal_data_->ConvertWalletAddressesAndUpdateWalletCards();
+ run_loop.Run();
+ }
+
// Verifies that the web database has been updated and the notification sent.
void WaitForOnPersonalDataChanged() {
+ base::RunLoop run_loop;
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
+ .WillOnce(QuitMessageLoop(&run_loop));
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .Times(testing::AnyNumber());
+ run_loop.Run();
+ }
+
+ void WaitOnceForOnPersonalDataChanged() {
+ base::RunLoop run_loop;
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
+ .WillOnce(QuitMessageLoop(&run_loop));
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(1);
+ run_loop.Run();
+ }
+
+ // Verifies that the web database has been updated and the notification sent.
+ void WaitForOnPersonalDataChangedRepeatedly() {
+ base::RunLoop run_loop;
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
+ .WillRepeatedly(QuitMessageLoop(&run_loop));
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
- .WillRepeatedly(QuitMainMessageLoop());
- base::RunLoop().Run();
+ .Times(testing::AnyNumber());
+ run_loop.Run();
}
void ExpectOnValidated(AutofillProfile* profile) {
@@ -435,7 +497,8 @@ class PersonalDataManagerTestBase {
// The temporary directory should be deleted at the end to ensure that
// files are not used anymore and deletion succeeds.
base::ScopedTempDir temp_dir_;
- base::MessageLoopForUI message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_{
+ base::test::ScopedTaskEnvironment::MainThreadType::UI};
std::unique_ptr<PrefService> prefs_;
identity::IdentityTestEnvironment identity_test_env_;
syncer::TestSyncService sync_service_;
@@ -461,11 +524,9 @@ TEST_F(PersonalDataManagerTest, AddProfile) {
// Add profile0 to the database.
AutofillProfile profile0(test::GetFullProfile());
profile0.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("j@s.com"));
- personal_data_->AddProfile(profile0);
-
+ AddProfileToPersonalDataManager(profile0);
// Reload the database.
ResetPersonalDataManager(USER_MODE_NORMAL);
-
// Verify the addition.
const std::vector<AutofillProfile*>& results1 = personal_data_->GetProfiles();
ASSERT_EQ(1U, results1.size());
@@ -474,7 +535,8 @@ TEST_F(PersonalDataManagerTest, AddProfile) {
// Add profile with identical values. Duplicates should not get saved.
AutofillProfile profile0a = profile0;
profile0a.set_guid(base::GenerateGUID());
- personal_data_->AddProfile(profile0a);
+
+ AddProfileToPersonalDataManager(profile0a);
// Reload the database.
ResetPersonalDataManager(USER_MODE_NORMAL);
@@ -492,7 +554,7 @@ TEST_F(PersonalDataManagerTest, AddProfile) {
// Add the different profile. This should save as a separate profile.
// Note that if this same profile was "merged" it would collapse to one
// profile with a multi-valued entry for email.
- personal_data_->AddProfile(profile1);
+ AddProfileToPersonalDataManager(profile1);
// Reload the database.
ResetPersonalDataManager(USER_MODE_NORMAL);
@@ -504,17 +566,35 @@ TEST_F(PersonalDataManagerTest, AddProfile) {
ExpectSameElements(profiles, personal_data_->GetProfiles());
}
-// TODO(crbug.com/909730): If you add a profile and then remove it right away,
-// the profile will not be removed, but it should.
-TEST_F(PersonalDataManagerTest, AddRemoveProfile) {
+// Adding, updating, removing operations without waiting in between.
+TEST_F(PersonalDataManagerTest, AddRemoveUpdateProfileSequence) {
AutofillProfile profile(test::GetFullProfile());
personal_data_->AddProfile(profile);
personal_data_->RemoveByGUID(profile.guid());
-
WaitForOnPersonalDataChanged();
+
auto profiles = personal_data_->GetProfiles();
- ASSERT_EQ(1U, profiles.size()); // the correct size is 0.
+ ASSERT_EQ(0U, profiles.size());
+
+ personal_data_->AddProfile(profile);
+ personal_data_->RemoveByGUID(profile.guid());
+ personal_data_->RemoveByGUID(profile.guid());
+ WaitForOnPersonalDataChanged();
+ profiles = personal_data_->GetProfiles();
+ ASSERT_EQ(0U, profiles.size());
+
+ personal_data_->AddProfile(profile);
+ profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("new@email.com"));
+ personal_data_->UpdateProfile(profile);
+ profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("newer@email.com"));
+ personal_data_->UpdateProfile(profile);
+ WaitForOnPersonalDataChanged();
+
+ profiles = personal_data_->GetProfiles();
+ ASSERT_EQ(1U, profiles.size());
+ EXPECT_EQ(profiles[0]->GetRawInfo(EMAIL_ADDRESS),
+ base::ASCIIToUTF16("newer@email.com"));
}
// Test that a new profile has its basic information set.
@@ -526,7 +606,7 @@ TEST_F(PersonalDataManagerTest, AddProfile_BasicInformation) {
// Add a profile to the database.
AutofillProfile profile(test::GetFullProfile());
profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("j@s.com"));
- personal_data_->AddProfile(profile);
+ AddProfileToPersonalDataManager(profile);
// Reload the database.
ResetPersonalDataManager(USER_MODE_NORMAL);
@@ -685,7 +765,7 @@ TEST_F(PersonalDataManagerTest, AddProfile_Invalid) {
std::vector<AutofillProfile> profiles;
profiles.push_back(with_invalid);
personal_data_->SetProfiles(&profiles);
-
+ WaitForOnPersonalDataChanged();
ASSERT_EQ(1u, personal_data_->GetProfiles().size());
AutofillProfile profile = *personal_data_->GetProfiles()[0];
ASSERT_NE(without_invalid.GetRawInfo(PHONE_HOME_WHOLE_NUMBER),
@@ -697,10 +777,10 @@ TEST_F(PersonalDataManagerTest, SaveImportedProfileSetModificationDate) {
AutofillProfile profile(test::GetFullProfile());
EXPECT_NE(base::Time(), profile.modification_date());
- personal_data_->SaveImportedProfile(profile);
+ SaveImportedProfileToPersonalDataManager(profile);
const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
ASSERT_EQ(1U, profiles.size());
- EXPECT_GT(base::TimeDelta::FromMilliseconds(500),
+ EXPECT_GT(base::TimeDelta::FromMilliseconds(1000),
AutofillClock::Now() - profiles[0]->modification_date());
}
@@ -721,10 +801,8 @@ TEST_F(PersonalDataManagerTest, AddUpdateRemoveProfiles) {
"Orlando", "FL", "32801", "US", "19482937549");
// Add two test profiles to the database.
- personal_data_->AddProfile(profile0);
- personal_data_->AddProfile(profile1);
-
- WaitForOnPersonalDataChanged();
+ AddProfileToPersonalDataManager(profile0);
+ AddProfileToPersonalDataManager(profile1);
std::vector<AutofillProfile*> profiles;
profiles.push_back(&profile0);
@@ -733,11 +811,9 @@ TEST_F(PersonalDataManagerTest, AddUpdateRemoveProfiles) {
// Update, remove, and add.
profile0.SetRawInfo(NAME_FIRST, base::ASCIIToUTF16("John"));
- personal_data_->UpdateProfile(profile0);
- personal_data_->RemoveByGUID(profile1.guid());
- personal_data_->AddProfile(profile2);
-
- WaitForOnPersonalDataChanged();
+ UpdateProfileOnPersonalDataManager(profile0);
+ RemoveByGUIDFromPersonalDataManager(profile1.guid());
+ AddProfileToPersonalDataManager(profile2);
profiles.clear();
profiles.push_back(&profile0);
@@ -783,7 +859,7 @@ TEST_F(PersonalDataManagerTest, AddUpdateRemoveCreditCards) {
// Update, remove, and add.
credit_card0.SetRawInfo(CREDIT_CARD_NAME_FULL, base::ASCIIToUTF16("Joe"));
personal_data_->UpdateCreditCard(credit_card0);
- personal_data_->RemoveByGUID(credit_card1.guid());
+ RemoveByGUIDFromPersonalDataManager(credit_card1.guid());
personal_data_->AddCreditCard(credit_card2);
WaitForOnPersonalDataChanged();
@@ -811,13 +887,8 @@ TEST_F(PersonalDataManagerTest, AddUpdateRemoveCreditCards) {
credit_card3.set_record_type(CreditCard::FULL_SERVER_CARD);
credit_card3.set_server_id("server_id");
- // Verify that the web database has been updated and the notification sent.
- EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
- .WillOnce(QuitMainMessageLoop());
-
personal_data_->AddFullServerCreditCard(credit_card3);
-
- base::RunLoop().Run();
+ WaitForOnPersonalDataChanged();
cards.push_back(&credit_card3);
ExpectSameElements(cards, personal_data_->GetCreditCards());
@@ -956,7 +1027,7 @@ TEST_F(PersonalDataManagerTest, UpdateUnverifiedProfilesAndCreditCards) {
EXPECT_FALSE(credit_card.IsVerified());
// Add the data to the database.
- personal_data_->AddProfile(profile);
+ AddProfileToPersonalDataManager(profile);
personal_data_->AddCreditCard(credit_card);
WaitForOnPersonalDataChanged();
@@ -978,7 +1049,7 @@ TEST_F(PersonalDataManagerTest, UpdateUnverifiedProfilesAndCreditCards) {
EXPECT_TRUE(profile.IsVerified());
EXPECT_TRUE(credit_card.IsVerified());
- personal_data_->UpdateProfile(profile);
+ UpdateProfileOnPersonalDataManager(profile);
personal_data_->UpdateCreditCard(credit_card);
// Note: No refresh, as no update is expected.
@@ -997,7 +1068,7 @@ TEST_F(PersonalDataManagerTest, UpdateUnverifiedProfilesAndCreditCards) {
profile.SetRawInfo(NAME_FIRST, base::ASCIIToUTF16("John"));
credit_card.SetRawInfo(CREDIT_CARD_NAME_FULL, base::ASCIIToUTF16("Joe"));
- personal_data_->UpdateProfile(profile);
+ UpdateProfileOnPersonalDataManager(profile);
personal_data_->UpdateCreditCard(credit_card);
WaitForOnPersonalDataChanged();
@@ -1058,13 +1129,10 @@ TEST_F(PersonalDataManagerTest, AddFullCardAsMaskedCard) {
"378282246310005" /* American Express */, "04",
"2999", "1");
- // Verify that the web database has been updated and the notification sent.
- EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
- .WillOnce(QuitMainMessageLoop());
personal_data_->AddFullServerCreditCard(server_card);
- base::RunLoop().Run();
+ WaitForOnPersonalDataChanged();
ASSERT_EQ(1U, personal_data_->GetCreditCards().size());
EXPECT_EQ(CreditCard::MASKED_SERVER_CARD,
@@ -1078,7 +1146,13 @@ TEST_F(PersonalDataManagerTest, OfferStoreUnmaskedCards) {
#elif defined(OS_LINUX)
bool should_offer = false;
#endif
- EXPECT_EQ(should_offer, OfferStoreUnmaskedCards());
+ EXPECT_EQ(should_offer, OfferStoreUnmaskedCards(/*is_off_the_record=*/false));
+}
+
+// Tests that OfferStoreUnmaskedCards always returns false if the user is off
+// the record.
+TEST_F(PersonalDataManagerTest, OfferStoreUnmaskedCards_OffTheRecord) {
+ EXPECT_EQ(false, OfferStoreUnmaskedCards(/*is_off_the_record=*/true));
}
// Tests that UpdateServerCreditCard can be used to mask or unmask server cards.
@@ -1107,8 +1181,7 @@ TEST_F(PersonalDataManagerTest, UpdateServerCreditCards) {
WaitForOnPersonalDataChanged();
ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
-
- if (!OfferStoreUnmaskedCards()) {
+ if (!OfferStoreUnmaskedCards(/*is_off_the_record=*/false)) {
for (CreditCard* card : personal_data_->GetCreditCards()) {
EXPECT_EQ(CreditCard::MASKED_SERVER_CARD, card->record_type());
}
@@ -1124,8 +1197,6 @@ TEST_F(PersonalDataManagerTest, UpdateServerCreditCards) {
CreditCard* unmasked_card = &server_cards.front();
unmasked_card->set_record_type(CreditCard::FULL_SERVER_CARD);
unmasked_card->SetNumber(base::ASCIIToUTF16("4234567890123456"));
- EXPECT_NE(0, server_cards.front().Compare(
- *personal_data_->GetCreditCards().front()));
personal_data_->UpdateServerCreditCard(*unmasked_card);
WaitForOnPersonalDataChanged();
@@ -1136,8 +1207,6 @@ TEST_F(PersonalDataManagerTest, UpdateServerCreditCards) {
CreditCard* remasked_card = &server_cards.back();
remasked_card->set_record_type(CreditCard::MASKED_SERVER_CARD);
remasked_card->SetNumber(base::ASCIIToUTF16("0005"));
- EXPECT_NE(
- 0, server_cards.back().Compare(*personal_data_->GetCreditCards().back()));
personal_data_->UpdateServerCreditCard(*remasked_card);
WaitForOnPersonalDataChanged();
@@ -1186,10 +1255,8 @@ TEST_F(PersonalDataManagerTest, AddProfilesAndCreditCards) {
"1");
// Add two test profiles to the database.
- personal_data_->AddProfile(profile0);
- personal_data_->AddProfile(profile1);
-
- WaitForOnPersonalDataChanged();
+ AddProfileToPersonalDataManager(profile0);
+ AddProfileToPersonalDataManager(profile1);
std::vector<AutofillProfile*> profiles;
profiles.push_back(&profile0);
@@ -1225,9 +1292,7 @@ TEST_F(PersonalDataManagerTest, PopulateUniqueIDsOnLoad) {
"");
// Add the profile0 to the db.
- personal_data_->AddProfile(profile0);
-
- WaitForOnPersonalDataChanged();
+ AddProfileToPersonalDataManager(profile0);
// Verify that we've loaded the profiles from the web database.
const std::vector<AutofillProfile*>& results2 = personal_data_->GetProfiles();
@@ -1238,9 +1303,7 @@ TEST_F(PersonalDataManagerTest, PopulateUniqueIDsOnLoad) {
AutofillProfile profile1(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&profile1, "z", "", "", "", "", "", "", "", "", "", "",
"");
- personal_data_->AddProfile(profile1);
-
- WaitForOnPersonalDataChanged();
+ AddProfileToPersonalDataManager(profile1);
// Make sure the two profiles have different GUIDs, both valid.
const std::vector<AutofillProfile*>& results3 = personal_data_->GetProfiles();
@@ -1293,9 +1356,7 @@ TEST_F(PersonalDataManagerTest, SetEmptyProfile) {
"");
// Add the empty profile to the database.
- personal_data_->AddProfile(profile0);
-
- // Note: no refresh here.
+ AddProfileToPersonalDataManager(profile0);
// Reset the PersonalDataManager. This tests that the personal data was saved
// to the web database, and that we can load the profiles from the web
@@ -1336,10 +1397,8 @@ TEST_F(PersonalDataManagerTest, Refresh) {
"Orlando", "FL", "32801", "US", "19482937549");
// Add the test profiles to the database.
- personal_data_->AddProfile(profile0);
- personal_data_->AddProfile(profile1);
-
- WaitForOnPersonalDataChanged();
+ AddProfileToPersonalDataManager(profile0);
+ AddProfileToPersonalDataManager(profile1);
std::vector<AutofillProfile*> profiles;
profiles.push_back(&profile0);
@@ -1366,20 +1425,20 @@ TEST_F(PersonalDataManagerTest, Refresh) {
profile_database_service_->RemoveAutofillProfile(profile1.guid());
profile_database_service_->RemoveAutofillProfile(profile2.guid());
- // Before telling the PDM to refresh, simulate an edit to one of the deleted
- // profiles via a SetProfile update (this would happen if the Autofill window
- // was open with a previous snapshot of the profiles, and something
- // [e.g. sync] removed a profile from the browser. In this edge case, we will
- // end up in a consistent state by dropping the write).
+ personal_data_->Refresh();
+ WaitForOnPersonalDataChanged();
+
+ auto results = personal_data_->GetProfiles();
+ ASSERT_EQ(1U, results.size());
+ EXPECT_EQ(profile0, *results[0]);
+
profile0.SetRawInfo(NAME_FIRST, base::ASCIIToUTF16("Mar"));
- profile2.SetRawInfo(NAME_FIRST, base::ASCIIToUTF16("Jo"));
- personal_data_->UpdateProfile(profile0);
- personal_data_->AddProfile(profile1);
- personal_data_->AddProfile(profile2);
+ profile_database_service_->UpdateAutofillProfile(profile0);
+ personal_data_->Refresh();
WaitForOnPersonalDataChanged();
- const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
+ results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(profile0, *results[0]);
}
@@ -1395,10 +1454,9 @@ TEST_F(PersonalDataManagerTest, SaveImportedProfileWithVerifiedData) {
EXPECT_FALSE(profile.IsVerified());
// Add the profile to the database.
- personal_data_->AddProfile(profile);
+ AddProfileToPersonalDataManager(profile);
// Make sure everything is set up correctly.
- WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
AutofillProfile new_verified_profile = profile;
@@ -1408,9 +1466,7 @@ TEST_F(PersonalDataManagerTest, SaveImportedProfileWithVerifiedData) {
base::ASCIIToUTF16("1 234 567-8910"));
EXPECT_TRUE(new_verified_profile.IsVerified());
- personal_data_->SaveImportedProfile(new_verified_profile);
-
- WaitForOnPersonalDataChanged();
+ SaveImportedProfileToPersonalDataManager(new_verified_profile);
// The new profile should be merged into the existing one.
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
@@ -1469,10 +1525,9 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) {
"johnwayne@me.xyz", nullptr, "123 Zoo St.", nullptr,
"Hollywood", "CA", "91601", "US", "14155678910");
- personal_data_->AddProfile(profile0);
+ AddProfileToPersonalDataManager(profile0);
// Make sure everything is set up correctly.
- WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
personal_data_->GetNonEmptyTypes(&non_empty_types);
@@ -1504,10 +1559,9 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) {
"joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
"Orlando", "FL", "32801", "US", "16502937549");
- personal_data_->AddProfile(profile1);
- personal_data_->AddProfile(profile2);
+ AddProfileToPersonalDataManager(profile1);
+ AddProfileToPersonalDataManager(profile2);
- WaitForOnPersonalDataChanged();
EXPECT_EQ(3U, personal_data_->GetProfiles().size());
personal_data_->GetNonEmptyTypes(&non_empty_types);
@@ -1582,7 +1636,7 @@ TEST_F(PersonalDataManagerTest, IncognitoReadOnly) {
test::SetProfileInfo(&steve_jobs, "Steven", "Paul", "Jobs", "sjobs@apple.com",
"Apple Computer, Inc.", "1 Infinite Loop", "",
"Cupertino", "CA", "95014", "US", "(800) 275-2273");
- personal_data_->AddProfile(steve_jobs);
+ AddProfileToPersonalDataManager(steve_jobs);
CreditCard bill_gates(base::GenerateGUID(), test::kEmptyOrigin);
test::SetCreditCardInfo(&bill_gates, "William H. Gates", "5555555555554444",
@@ -1659,10 +1713,9 @@ TEST_F(PersonalDataManagerTest, DefaultCountryCodeIsCached) {
test::SetProfileInfo(&moose, "Moose", "P", "McMahon", "mpm@example.com", "",
"1 Taiga TKTR", "", "Calgary", "AB", "T2B 2K2", "CA",
"(800) 555-9000");
- personal_data_->AddProfile(moose);
+ AddProfileToPersonalDataManager(moose);
// Make sure everything is set up correctly.
- WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
// The value is cached and doesn't change even after adding an address.
@@ -1688,7 +1741,7 @@ TEST_F(PersonalDataManagerTest, DefaultCountryCodeComesFromProfiles) {
test::SetProfileInfo(&moose, "Moose", "P", "McMahon", "mpm@example.com", "",
"1 Taiga TKTR", "", "Calgary", "AB", "T2B 2K2", "CA",
"(800) 555-9000");
- personal_data_->AddProfile(moose);
+ AddProfileToPersonalDataManager(moose);
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_EQ("CA", personal_data_->GetDefaultCountryCodeForNewAddress());
@@ -1701,38 +1754,27 @@ TEST_F(PersonalDataManagerTest, DefaultCountryCodeComesFromProfiles) {
test::SetProfileInfo(&armadillo2, "Armin", "Dill", "Oh", "ado@example.com",
"", "2 Speed Bump", "", "Lubbock", "TX", "77500", "MX",
"(800) 555-9000");
- personal_data_->AddProfile(armadillo);
- personal_data_->AddProfile(armadillo2);
+ AddProfileToPersonalDataManager(armadillo);
+ AddProfileToPersonalDataManager(armadillo2);
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_EQ("MX", personal_data_->GetDefaultCountryCodeForNewAddress());
- personal_data_->RemoveByGUID(armadillo.guid());
- personal_data_->RemoveByGUID(armadillo2.guid());
+ RemoveByGUIDFromPersonalDataManager(armadillo.guid());
+ RemoveByGUIDFromPersonalDataManager(armadillo2.guid());
ResetPersonalDataManager(USER_MODE_NORMAL);
// Verified profiles count more.
armadillo.set_origin("http://randomwebsite.com");
armadillo2.set_origin("http://randomwebsite.com");
- personal_data_->AddProfile(armadillo);
- personal_data_->AddProfile(armadillo2);
+ AddProfileToPersonalDataManager(armadillo);
+ AddProfileToPersonalDataManager(armadillo2);
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_EQ("CA", personal_data_->GetDefaultCountryCodeForNewAddress());
- personal_data_->RemoveByGUID(armadillo.guid());
+ RemoveByGUIDFromPersonalDataManager(armadillo.guid());
ResetPersonalDataManager(USER_MODE_NORMAL);
// But unverified profiles can be a tie breaker.
armadillo.set_origin(kSettingsOrigin);
- personal_data_->AddProfile(armadillo);
- ResetPersonalDataManager(USER_MODE_NORMAL);
- EXPECT_EQ("MX", personal_data_->GetDefaultCountryCodeForNewAddress());
-
- // Invalid country codes are ignored.
- personal_data_->RemoveByGUID(armadillo.guid());
- personal_data_->RemoveByGUID(moose.guid());
- AutofillProfile space_invader(base::GenerateGUID(), kSettingsOrigin);
- test::SetProfileInfo(&space_invader, "Marty", "", "Martian", "mm@example.com",
- "", "1 Flying Object", "", "Valles Marineris", "", "",
- "XX", "");
- personal_data_->AddProfile(moose);
+ AddProfileToPersonalDataManager(armadillo);
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_EQ("MX", personal_data_->GetDefaultCountryCodeForNewAddress());
}
@@ -1742,17 +1784,14 @@ TEST_F(PersonalDataManagerTest, UpdateLanguageCodeInProfile) {
test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
- personal_data_->AddProfile(profile);
+ AddProfileToPersonalDataManager(profile);
// Make sure everything is set up correctly.
- WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
profile.set_language_code("en");
- personal_data_->UpdateProfile(profile);
-
- WaitForOnPersonalDataChanged();
+ UpdateProfileOnPersonalDataManager(profile);
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
@@ -1766,7 +1805,7 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions) {
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
- personal_data_->AddProfile(profile);
+ AddProfileToPersonalDataManager(profile);
ResetPersonalDataManager(USER_MODE_NORMAL);
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
@@ -1783,7 +1822,7 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_PhoneSubstring) {
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
- personal_data_->AddProfile(profile);
+ AddProfileToPersonalDataManager(profile);
ResetPersonalDataManager(USER_MODE_NORMAL);
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
@@ -1817,10 +1856,10 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_HideSubsets) {
// For easier results verification, make sure |profile| is suggested first.
profile.set_use_count(5);
- personal_data_->AddProfile(profile);
- personal_data_->AddProfile(profile1);
- personal_data_->AddProfile(profile2);
- personal_data_->AddProfile(profile3);
+ AddProfileToPersonalDataManager(profile);
+ AddProfileToPersonalDataManager(profile1);
+ AddProfileToPersonalDataManager(profile2);
+ AddProfileToPersonalDataManager(profile3);
ResetPersonalDataManager(USER_MODE_NORMAL);
// Simulate a form with street address, city and state.
@@ -1846,7 +1885,7 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_SuggestionsLimit) {
"Mitchell", "Morrison", "johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
- personal_data_->AddProfile(profile);
+ AddProfileToPersonalDataManager(profile);
profiles.push_back(profile);
}
ResetPersonalDataManager(USER_MODE_NORMAL);
@@ -1880,7 +1919,7 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_ProfilesLimit) {
profile.set_use_count(12);
profile.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(1));
- personal_data_->AddProfile(profile);
+ AddProfileToPersonalDataManager(profile);
profiles.push_back(profile);
}
@@ -1892,7 +1931,7 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_ProfilesLimit) {
"Hollywood", "CA", "91601", "US", "12345678910");
profile.set_use_count(1);
profile.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(7));
- personal_data_->AddProfile(profile);
+ AddProfileToPersonalDataManager(profile);
ResetPersonalDataManager(USER_MODE_NORMAL);
@@ -1918,7 +1957,7 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_Ranking) {
"Hollywood", "CA", "91601", "US", "12345678910");
profile3.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(1));
profile3.set_use_count(5);
- personal_data_->AddProfile(profile3);
+ AddProfileToPersonalDataManager(profile3);
AutofillProfile profile1(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&profile1, "Marion1", "Mitchell", "Morrison",
@@ -1927,7 +1966,7 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_Ranking) {
"Hollywood", "CA", "91601", "US", "12345678910");
profile1.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(1));
profile1.set_use_count(10);
- personal_data_->AddProfile(profile1);
+ AddProfileToPersonalDataManager(profile1);
AutofillProfile profile2(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&profile2, "Marion2", "Mitchell", "Morrison",
@@ -1936,7 +1975,7 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_Ranking) {
"Hollywood", "CA", "91601", "US", "12345678910");
profile2.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(15));
profile2.set_use_count(300);
- personal_data_->AddProfile(profile2);
+ AddProfileToPersonalDataManager(profile2);
ResetPersonalDataManager(USER_MODE_NORMAL);
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
@@ -1956,21 +1995,21 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_NumberOfSuggestions) {
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
- personal_data_->AddProfile(profile1);
+ AddProfileToPersonalDataManager(profile1);
AutofillProfile profile2(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&profile2, "Marion2", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
- personal_data_->AddProfile(profile2);
+ AddProfileToPersonalDataManager(profile2);
AutofillProfile profile3(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&profile3, "Marion3", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
- personal_data_->AddProfile(profile3);
+ AddProfileToPersonalDataManager(profile3);
ResetPersonalDataManager(USER_MODE_NORMAL);
@@ -1992,7 +2031,7 @@ TEST_F(PersonalDataManagerTest,
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
profile1.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(200));
- personal_data_->AddProfile(profile1);
+ AddProfileToPersonalDataManager(profile1);
AutofillProfile profile2(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&profile2, "Marion2", "Mitchell", "Morrison",
@@ -2000,7 +2039,7 @@ TEST_F(PersonalDataManagerTest,
"456 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
profile2.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(20));
- personal_data_->AddProfile(profile2);
+ AddProfileToPersonalDataManager(profile2);
ResetPersonalDataManager(USER_MODE_NORMAL);
@@ -2076,14 +2115,14 @@ TEST_F(PersonalDataManagerTest,
profile1.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillProfile::INVALID,
AutofillProfile::CLIENT);
profile1.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(20));
- personal_data_->AddProfile(profile1);
+ AddProfileToPersonalDataManager(profile1);
AutofillProfile profile2(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&profile2, "Marion2", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"456 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "1234567890");
- personal_data_->AddProfile(profile2);
+ AddProfileToPersonalDataManager(profile2);
ResetPersonalDataManager(USER_MODE_NORMAL);
{
@@ -2143,14 +2182,14 @@ TEST_F(PersonalDataManagerTest,
autofill_profile_validity);
}
profile1.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(20));
- personal_data_->AddProfile(profile1);
+ AddProfileToPersonalDataManager(profile1);
AutofillProfile profile2(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&profile2, "Marion2", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"456 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "NY", "91601", "US", "1234567890");
- personal_data_->AddProfile(profile2);
+ AddProfileToPersonalDataManager(profile2);
ResetPersonalDataManager(USER_MODE_NORMAL);
{
@@ -2198,7 +2237,7 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_ProfileAutofillDisabled) {
test::SetProfileInfo(&local_profile, "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
"Orlando", "FL", "32801", "US", "19482937549");
- personal_data_->AddProfile(local_profile);
+ AddProfileToPersonalDataManager(local_profile);
// Add a different server profile.
std::vector<AutofillProfile> server_profiles;
@@ -2215,7 +2254,7 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_ProfileAutofillDisabled) {
// Disable Profile autofill.
prefs::SetProfileAutofillEnabled(personal_data_->pref_service_, false);
WaitForOnPersonalDataChanged();
- personal_data_->ConvertWalletAddressesAndUpdateWalletCards();
+ ConvertWalletAddressesAndUpdateWalletCards();
// Check that profiles were saved.
EXPECT_EQ(2U, personal_data_->GetProfiles().size());
@@ -2244,7 +2283,7 @@ TEST_F(PersonalDataManagerTest,
test::SetProfileInfo(&local_profile, "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
"Orlando", "FL", "32801", "US", "19482937549");
- personal_data_->AddProfile(local_profile);
+ AddProfileToPersonalDataManager(local_profile);
// Add a different server profile.
std::vector<AutofillProfile> server_profiles;
@@ -2260,7 +2299,7 @@ TEST_F(PersonalDataManagerTest,
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
- personal_data_->ConvertWalletAddressesAndUpdateWalletCards();
+ ConvertWalletAddressesAndUpdateWalletCards();
// Expect 2 autofilled values or suggestions.
EXPECT_EQ(2U, personal_data_->GetProfiles().size());
@@ -2292,7 +2331,7 @@ TEST_F(PersonalDataManagerTest,
test::SetProfileInfo(&local_profile, "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
"Orlando", "FL", "32801", "US", "19482937549");
- personal_data_->AddProfile(local_profile);
+ AddProfileToPersonalDataManager(local_profile);
// Expect no profile values or suggestions were added.
EXPECT_EQ(0U, personal_data_->GetProfiles().size());
@@ -3258,7 +3297,7 @@ TEST_F(PersonalDataManagerTest, RecordUseOf) {
EXPECT_EQ(1U, profile.use_count());
EXPECT_EQ(kArbitraryTime, profile.use_date());
EXPECT_EQ(kArbitraryTime, profile.modification_date());
- personal_data_->AddProfile(profile);
+ AddProfileToPersonalDataManager(profile);
CreditCard credit_card(base::GenerateGUID(), test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card, "John Dillinger",
@@ -3283,8 +3322,16 @@ TEST_F(PersonalDataManagerTest, RecordUseOf) {
EXPECT_EQ(1U, added_profile->use_count());
EXPECT_EQ(kArbitraryTime, added_profile->use_date());
EXPECT_EQ(kArbitraryTime, added_profile->modification_date());
+
+ base::RunLoop run_loop;
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
+ .WillOnce(QuitMessageLoop(&run_loop));
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(1);
+
personal_data_->RecordUseOf(profile);
+ run_loop.Run();
+
CreditCard* added_card =
personal_data_->GetCreditCardByGUID(credit_card.guid());
ASSERT_TRUE(added_card);
@@ -3294,8 +3341,6 @@ TEST_F(PersonalDataManagerTest, RecordUseOf) {
EXPECT_EQ(kArbitraryTime, added_card->modification_date());
personal_data_->RecordUseOf(credit_card);
- WaitForOnPersonalDataChanged();
-
// Verify usage stats are updated.
added_profile = personal_data_->GetProfileByGUID(profile.guid());
ASSERT_TRUE(added_profile);
@@ -3340,7 +3385,7 @@ TEST_F(PersonalDataManagerTest, UpdateServerCreditCardUsageStats) {
WaitForOnPersonalDataChanged();
EXPECT_EQ(3U, personal_data_->GetCreditCards().size());
- if (!OfferStoreUnmaskedCards()) {
+ if (!OfferStoreUnmaskedCards(/*is_off_the_record=*/false)) {
for (CreditCard* card : personal_data_->GetCreditCards()) {
EXPECT_EQ(CreditCard::MASKED_SERVER_CARD, card->record_type());
}
@@ -3356,8 +3401,6 @@ TEST_F(PersonalDataManagerTest, UpdateServerCreditCardUsageStats) {
CreditCard* unmasked_card = &server_cards.front();
unmasked_card->set_record_type(CreditCard::FULL_SERVER_CARD);
unmasked_card->SetNumber(base::ASCIIToUTF16("4234567890123456"));
- EXPECT_NE(0,
- unmasked_card->Compare(*personal_data_->GetCreditCards().front()));
personal_data_->UpdateServerCreditCard(*unmasked_card);
WaitForOnPersonalDataChanged();
@@ -3453,7 +3496,7 @@ TEST_F(PersonalDataManagerTest, ClearAllServerData) {
TEST_F(PersonalDataManagerTest, ClearAllLocalData) {
// Add some local data.
- personal_data_->AddProfile(test::GetFullProfile());
+ AddProfileToPersonalDataManager(test::GetFullProfile());
personal_data_->AddCreditCard(test::GetCreditCard());
personal_data_->Refresh();
@@ -3534,7 +3577,7 @@ TEST_P(SaveImportedProfileTest, SaveImportedProfile) {
base::UTF8ToUTF16(change.field_value));
}
- personal_data_->SaveImportedProfile(profile2);
+ SaveImportedProfileToPersonalDataManager(profile2);
const std::vector<AutofillProfile*>& saved_profiles =
personal_data_->GetProfiles();
@@ -3854,7 +3897,7 @@ TEST_F(PersonalDataManagerTest, MergeProfile_Frecency) {
// Create the |existing_profiles| vector.
std::vector<std::unique_ptr<AutofillProfile>> existing_profiles;
existing_profiles.push_back(std::move(profile1));
- existing_profiles.push_back(base::WrapUnique(profile2));
+ existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile2));
// Create a new imported profile with no company name.
AutofillProfile imported_profile(base::GenerateGUID(), test::kEmptyOrigin);
@@ -3897,7 +3940,7 @@ TEST_F(PersonalDataManagerTest, MAYBE_MergeProfile_UsageStats) {
// Create the |existing_profiles| vector.
std::vector<std::unique_ptr<AutofillProfile>> existing_profiles;
- existing_profiles.push_back(base::WrapUnique(profile));
+ existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile));
// Change the current date.
test_clock.SetNow(kSomeLaterTime);
@@ -3977,18 +4020,18 @@ TEST_F(PersonalDataManagerTest, DedupeProfiles_ProfilesToDelete) {
// Add the profiles.
std::vector<std::unique_ptr<AutofillProfile>> existing_profiles;
- existing_profiles.push_back(base::WrapUnique(profile1));
- existing_profiles.push_back(base::WrapUnique(profile2));
- existing_profiles.push_back(base::WrapUnique(profile3));
- existing_profiles.push_back(base::WrapUnique(profile4));
- existing_profiles.push_back(base::WrapUnique(profile5));
+ existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile1));
+ existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile2));
+ existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile3));
+ existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile4));
+ existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile5));
// Enable the profile cleanup.
EnableAutofillProfileCleanup();
base::HistogramTester histogram_tester;
std::unordered_map<std::string, std::string> guids_merge_map;
- std::unordered_set<AutofillProfile*> profiles_to_delete;
+ std::unordered_set<std::string> profiles_to_delete;
personal_data_->DedupeProfiles(&existing_profiles, &profiles_to_delete,
&guids_merge_map);
// 5 profiles were considered for dedupe.
@@ -4000,11 +4043,11 @@ TEST_F(PersonalDataManagerTest, DedupeProfiles_ProfilesToDelete) {
// Profile1 should be deleted because it was sent as the profile to merge and
// thus was merged into profile3 and then into profile5.
- EXPECT_TRUE(profiles_to_delete.count(profile1));
+ EXPECT_TRUE(profiles_to_delete.count(profile1->guid()));
// Profile3 should be deleted because profile1 was merged into it and the
// resulting profile was then merged into profile5.
- EXPECT_TRUE(profiles_to_delete.count(profile3));
+ EXPECT_TRUE(profiles_to_delete.count(profile3->guid()));
// Only these two profiles should be deleted.
EXPECT_EQ(2U, profiles_to_delete.size());
@@ -4062,17 +4105,18 @@ TEST_F(PersonalDataManagerTest, DedupeProfiles_GuidsMergeMap) {
// Add the profiles.
std::vector<std::unique_ptr<AutofillProfile>> existing_profiles;
- existing_profiles.push_back(base::WrapUnique(profile1));
- existing_profiles.push_back(base::WrapUnique(profile2));
- existing_profiles.push_back(base::WrapUnique(profile3));
- existing_profiles.push_back(base::WrapUnique(profile4));
- existing_profiles.push_back(base::WrapUnique(profile5));
+ existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile1));
+ existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile2));
+ existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile3));
+ existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile4));
+ existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile5));
// Enable the profile cleanup.
EnableAutofillProfileCleanup();
std::unordered_map<std::string, std::string> guids_merge_map;
- std::unordered_set<AutofillProfile*> profiles_to_delete;
+ std::unordered_set<std::string> profiles_to_delete;
+
personal_data_->DedupeProfiles(&existing_profiles, &profiles_to_delete,
&guids_merge_map);
@@ -4121,12 +4165,14 @@ TEST_F(PersonalDataManagerTest, UpdateCardsBillingAddressReference) {
credit_card4->set_billing_address_id("F");
// Add the credit cards to the database.
- personal_data_->local_credit_cards_.push_back(base::WrapUnique(credit_card1));
+ personal_data_->local_credit_cards_.push_back(
+ std::unique_ptr<CreditCard>(credit_card1));
personal_data_->server_credit_cards_.push_back(
- base::WrapUnique(credit_card2));
- personal_data_->local_credit_cards_.push_back(base::WrapUnique(credit_card3));
+ std::unique_ptr<CreditCard>(credit_card2));
+ personal_data_->local_credit_cards_.push_back(
+ std::unique_ptr<CreditCard>(credit_card3));
personal_data_->server_credit_cards_.push_back(
- base::WrapUnique(credit_card4));
+ std::unique_ptr<CreditCard>(credit_card4));
personal_data_->UpdateCardsBillingAddressReference(guids_merge_map);
@@ -4229,12 +4275,12 @@ TEST_F(PersonalDataManagerTest,
// Associate the third card with profile6.
credit_card3.set_billing_address_id(profile6.guid());
- personal_data_->AddProfile(profile1);
- personal_data_->AddProfile(profile2);
- personal_data_->AddProfile(profile3);
- personal_data_->AddProfile(profile4);
- personal_data_->AddProfile(profile5);
- personal_data_->AddProfile(profile6);
+ AddProfileToPersonalDataManager(profile1);
+ AddProfileToPersonalDataManager(profile2);
+ AddProfileToPersonalDataManager(profile3);
+ AddProfileToPersonalDataManager(profile4);
+ AddProfileToPersonalDataManager(profile5);
+ AddProfileToPersonalDataManager(profile6);
personal_data_->AddCreditCard(credit_card1);
personal_data_->AddCreditCard(credit_card2);
personal_data_->AddCreditCard(credit_card3);
@@ -4308,11 +4354,9 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_MergedProfileValues) {
profile3.set_use_count(3);
profile3.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(5));
- personal_data_->AddProfile(profile1);
- personal_data_->AddProfile(profile2);
- personal_data_->AddProfile(profile3);
-
- WaitForOnPersonalDataChanged();
+ AddProfileToPersonalDataManager(profile1);
+ AddProfileToPersonalDataManager(profile2);
+ AddProfileToPersonalDataManager(profile3);
// Make sure the 3 profiles were saved;
EXPECT_EQ(3U, personal_data_->GetProfiles().size());
@@ -4398,11 +4442,9 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_VerifiedProfileFirst) {
profile3.set_use_count(3);
profile3.set_use_date(kArbitraryTime);
- personal_data_->AddProfile(profile1);
- personal_data_->AddProfile(profile2);
- personal_data_->AddProfile(profile3);
-
- WaitForOnPersonalDataChanged();
+ AddProfileToPersonalDataManager(profile1);
+ AddProfileToPersonalDataManager(profile2);
+ AddProfileToPersonalDataManager(profile3);
// Make sure the 3 profiles were saved.
EXPECT_EQ(3U, personal_data_->GetProfiles().size());
@@ -4464,11 +4506,9 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_VerifiedProfileLast) {
profile3.set_use_count(3);
profile3.set_use_date(kArbitraryTime);
- personal_data_->AddProfile(profile1);
- personal_data_->AddProfile(profile2);
- personal_data_->AddProfile(profile3);
-
- WaitForOnPersonalDataChanged();
+ AddProfileToPersonalDataManager(profile1);
+ AddProfileToPersonalDataManager(profile2);
+ AddProfileToPersonalDataManager(profile3);
// Make sure the 3 profiles were saved.
EXPECT_EQ(3U, personal_data_->GetProfiles().size());
@@ -4529,11 +4569,9 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_MultipleVerifiedProfiles) {
profile3.set_use_count(3);
profile3.set_use_date(kArbitraryTime);
- personal_data_->AddProfile(profile1);
- personal_data_->AddProfile(profile2);
- personal_data_->AddProfile(profile3);
-
- WaitForOnPersonalDataChanged();
+ AddProfileToPersonalDataManager(profile1);
+ AddProfileToPersonalDataManager(profile2);
+ AddProfileToPersonalDataManager(profile3);
// Make sure the 3 profiles were saved.
EXPECT_EQ(3U, personal_data_->GetProfiles().size());
@@ -4641,15 +4679,13 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_MultipleDedupes) {
Barney.set_use_count(1);
Barney.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(180));
- personal_data_->AddProfile(Homer1);
- personal_data_->AddProfile(Homer2);
- personal_data_->AddProfile(Homer3);
- personal_data_->AddProfile(Homer4);
- personal_data_->AddProfile(Marge1);
- personal_data_->AddProfile(Marge2);
- personal_data_->AddProfile(Barney);
-
- WaitForOnPersonalDataChanged();
+ AddProfileToPersonalDataManager(Homer1);
+ AddProfileToPersonalDataManager(Homer2);
+ AddProfileToPersonalDataManager(Homer3);
+ AddProfileToPersonalDataManager(Homer4);
+ AddProfileToPersonalDataManager(Marge1);
+ AddProfileToPersonalDataManager(Marge2);
+ AddProfileToPersonalDataManager(Barney);
// Make sure the 7 profiles were saved;
EXPECT_EQ(7U, personal_data_->GetProfiles().size());
@@ -4732,10 +4768,8 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_FeatureDisabled) {
"homer.simpson@abc.com", "Fox", "742 Evergreen Terrace.",
"", "Springfield", "IL", "91601", "", "");
- personal_data_->AddProfile(profile1);
- personal_data_->AddProfile(profile2);
-
- WaitForOnPersonalDataChanged();
+ AddProfileToPersonalDataManager(profile1);
+ AddProfileToPersonalDataManager(profile2);
// Make sure both profiles were saved.
EXPECT_EQ(2U, personal_data_->GetProfiles().size());
@@ -4760,9 +4794,8 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_NopIfOneProfile) {
"homer.simpson@abc.com", "", "742. Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "");
- personal_data_->AddProfile(profile);
+ AddProfileToPersonalDataManager(profile);
- WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
// Enable the profile cleanup now. Otherwise it would be triggered by the
@@ -4786,10 +4819,9 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_OncePerVersion) {
"homer.simpson@abc.com", "Fox", "742 Evergreen Terrace.",
"", "Springfield", "IL", "91601", "", "");
- personal_data_->AddProfile(profile1);
- personal_data_->AddProfile(profile2);
+ AddProfileToPersonalDataManager(profile1);
+ AddProfileToPersonalDataManager(profile2);
- WaitForOnPersonalDataChanged();
EXPECT_EQ(2U, personal_data_->GetProfiles().size());
// Enable the profile cleanup now. Otherwise it would be triggered by the
@@ -4811,8 +4843,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_OncePerVersion) {
"homer.simpson@abc.com", "Fox", "742 Evergreen Terrace.",
"", "Springfield", "IL", "91601", "", "");
- personal_data_->AddProfile(profile3);
- WaitForOnPersonalDataChanged();
+ AddProfileToPersonalDataManager(profile3);
// Make sure |profile3| was saved.
EXPECT_EQ(2U, personal_data_->GetProfiles().size());
@@ -4861,7 +4892,7 @@ TEST_F(PersonalDataManagerTest,
"1234 Evergreen Terrace", "Bld. 6", "Springfield", "IL",
"32801", "US", "15151231234");
profile0.set_use_date(now - base::TimeDelta::FromDays(400));
- personal_data_->AddProfile(profile0);
+ AddProfileToPersonalDataManager(profile0);
// Create unverified/disused/used-by-expired-credit-card address(deletable).
AutofillProfile profile1(base::GenerateGUID(), test::kEmptyOrigin);
@@ -4875,9 +4906,9 @@ TEST_F(PersonalDataManagerTest,
"1");
credit_card0.set_use_date(now - base::TimeDelta::FromDays(400));
credit_card0.set_billing_address_id(profile1.guid());
- personal_data_->AddProfile(profile1);
+ AddProfileToPersonalDataManager(profile1);
personal_data_->AddCreditCard(credit_card0);
-
+ WaitForOnPersonalDataChanged();
// Create verified/disused/not-used-by-valid-credit-card address(not
// deletable).
AutofillProfile profile2(base::GenerateGUID(), test::kEmptyOrigin);
@@ -4886,7 +4917,7 @@ TEST_F(PersonalDataManagerTest,
"32801", "US", "15151231234");
profile2.set_origin(kSettingsOrigin);
profile2.set_use_date(now - base::TimeDelta::FromDays(400));
- personal_data_->AddProfile(profile2);
+ AddProfileToPersonalDataManager(profile2);
// Create unverified/recently-used/not-used-by-valid-credit-card address(not
// deletable).
@@ -4895,7 +4926,7 @@ TEST_F(PersonalDataManagerTest,
"1234 Evergreen Terrace", "Bld. 9", "Springfield", "IL",
"32801", "US", "15151231234");
profile3.set_use_date(now - base::TimeDelta::FromDays(4));
- personal_data_->AddProfile(profile3);
+ AddProfileToPersonalDataManager(profile3);
// Create unverified/disused/used-by-valid-credit-card address(not deletable).
AutofillProfile profile4(base::GenerateGUID(), test::kEmptyOrigin);
@@ -4908,7 +4939,7 @@ TEST_F(PersonalDataManagerTest,
credit_card1.SetNetworkForMaskedCard(kVisaCard);
credit_card1.set_billing_address_id(profile4.guid());
credit_card1.set_use_date(now - base::TimeDelta::FromDays(1));
- personal_data_->AddProfile(profile4);
+ AddProfileToPersonalDataManager(profile4);
personal_data_->AddCreditCard(credit_card1);
WaitForOnPersonalDataChanged();
@@ -5105,7 +5136,7 @@ TEST_F(PersonalDataManagerTest,
"joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
"Orlando", "FL", "32801", "US", "19482937549");
local_profile.set_use_count(1);
- personal_data_->AddProfile(local_profile);
+ AddProfileToPersonalDataManager(local_profile);
// Add a different server profile.
std::vector<AutofillProfile> server_profiles;
@@ -5146,15 +5177,7 @@ TEST_F(PersonalDataManagerTest,
ASSERT_EQ(1U, personal_data_->GetServerProfiles().size());
ASSERT_EQ(2U, personal_data_->GetCreditCards().size());
- ///////////////////////////////////////////////////////////////////////
- // Tested method.
- ///////////////////////////////////////////////////////////////////////
- personal_data_->ConvertWalletAddressesAndUpdateWalletCards();
-
- ///////////////////////////////////////////////////////////////////////
- // Validation.
- ///////////////////////////////////////////////////////////////////////
- WaitForOnPersonalDataChanged();
+ ConvertWalletAddressesAndUpdateWalletCards();
// The Wallet address should have been added as a new local profile.
EXPECT_EQ(2U, personal_data_->GetProfiles().size());
@@ -5211,7 +5234,7 @@ TEST_F(PersonalDataManagerTest,
"1212 Center.", "Bld. 5", "Orlando", "FL", "32801", "US",
"19482937549");
local_profile.set_use_count(1);
- personal_data_->AddProfile(local_profile);
+ AddProfileToPersonalDataManager(local_profile);
// Add a different server profile.
std::vector<AutofillProfile> server_profiles;
@@ -5251,15 +5274,7 @@ TEST_F(PersonalDataManagerTest,
EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
- ///////////////////////////////////////////////////////////////////////
- // Tested method.
- ///////////////////////////////////////////////////////////////////////
- personal_data_->ConvertWalletAddressesAndUpdateWalletCards();
-
- ///////////////////////////////////////////////////////////////////////
- // Validation.
- ///////////////////////////////////////////////////////////////////////
- WaitForOnPersonalDataChanged();
+ ConvertWalletAddressesAndUpdateWalletCards();
// The Wallet address should have been merged with the existing local profile.
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
@@ -5368,7 +5383,7 @@ TEST_F(
"1212 Center.", "Bld. 5", "Orlando", "FL", "32801", "US",
"19482937549");
local_profile.set_use_count(1);
- personal_data_->AddProfile(local_profile);
+ AddProfileToPersonalDataManager(local_profile);
// Add a server profile.
std::vector<AutofillProfile> server_profiles;
@@ -5420,15 +5435,7 @@ TEST_F(
EXPECT_EQ(2U, personal_data_->GetServerProfiles().size());
EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
- ///////////////////////////////////////////////////////////////////////
- // Tested method.
- ///////////////////////////////////////////////////////////////////////
- personal_data_->ConvertWalletAddressesAndUpdateWalletCards();
-
- ///////////////////////////////////////////////////////////////////////
- // Validation.
- ///////////////////////////////////////////////////////////////////////
- WaitForOnPersonalDataChanged();
+ ConvertWalletAddressesAndUpdateWalletCards();
// The first Wallet address should have been added as a new local profile and
// the second one should have merged with the first.
@@ -5513,10 +5520,7 @@ TEST_F(
EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
- // Run the conversion.
- personal_data_->ConvertWalletAddressesAndUpdateWalletCards();
-
- WaitForOnPersonalDataChanged();
+ ConvertWalletAddressesAndUpdateWalletCards();
// The Wallet address should have been converted to a new local profile.
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
@@ -5547,15 +5551,7 @@ TEST_F(
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
- ///////////////////////////////////////////////////////////////////////
- // Tested method.
- ///////////////////////////////////////////////////////////////////////
- personal_data_->ConvertWalletAddressesAndUpdateWalletCards();
-
- ///////////////////////////////////////////////////////////////////////
- // Validation.
- ///////////////////////////////////////////////////////////////////////
- WaitForOnPersonalDataChanged();
+ ConvertWalletAddressesAndUpdateWalletCards();
// The conversion should still be recorded in the Wallet address.
EXPECT_TRUE(personal_data_->GetServerProfiles().back()->has_converted());
@@ -5591,7 +5587,7 @@ TEST_F(PersonalDataManagerTest, DoNotConvertWalletAddressesInEphemeralStorage) {
AutofillProfile local_profile(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&local_profile, "Josephine", "Alicia", "Saenz", "",
"Fox", "1212 Center.", "Bld. 5", "", "", "", "", "");
- personal_data_->AddProfile(local_profile);
+ AddProfileToPersonalDataManager(local_profile);
// Add two server profiles: The first is unique, the second is similar to the
// local one but has some additional info.
@@ -5684,8 +5680,8 @@ TEST_F(PersonalDataManagerTest, RemoveByGUID_ResetsBillingAddress) {
server_cards.push_back(server_card1);
// Add the data to the database.
- personal_data_->AddProfile(profile0);
- personal_data_->AddProfile(profile1);
+ AddProfileToPersonalDataManager(profile0);
+ AddProfileToPersonalDataManager(profile1);
personal_data_->AddCreditCard(local_card0);
personal_data_->AddCreditCard(local_card1);
SetServerCards(server_cards);
@@ -5701,14 +5697,14 @@ TEST_F(PersonalDataManagerTest, RemoveByGUID_ResetsBillingAddress) {
///////////////////////////////////////////////////////////////////////
// Tested method.
///////////////////////////////////////////////////////////////////////
- personal_data_->RemoveByGUID(profile0.guid());
+ RemoveByGUIDFromPersonalDataManager(profile0.guid());
///////////////////////////////////////////////////////////////////////
// Validation.
///////////////////////////////////////////////////////////////////////
// Wait for the data to be refreshed.
- WaitForOnPersonalDataChanged();
+ // WaitForOnPersonalDataChanged();
// Make sure only profile0 was deleted.
ASSERT_EQ(1U, personal_data_->GetProfiles().size());
@@ -5746,7 +5742,7 @@ TEST_F(PersonalDataManagerTest, LogStoredProfileMetrics) {
test::SetProfileInfo(&profile0, "Bob", "", "Doe", "", "Fox", "1212 Center.",
"Bld. 5", "Orlando", "FL", "32801", "US", "19482937549");
profile0.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(3));
- personal_data_->AddProfile(profile0);
+ AddProfileToPersonalDataManager(profile0);
// Add a profile used a long time (200 days) ago.
AutofillProfile profile1(base::GenerateGUID(), test::kEmptyOrigin);
@@ -5754,7 +5750,7 @@ TEST_F(PersonalDataManagerTest, LogStoredProfileMetrics) {
"1234 Evergreen Terrace", "Bld. 5", "Springfield", "IL",
"32801", "US", "15151231234");
profile1.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(200));
- personal_data_->AddProfile(profile1);
+ AddProfileToPersonalDataManager(profile1);
// Reload the database, which will log the stored profile counts.
base::HistogramTester histogram_tester;
@@ -6028,6 +6024,7 @@ TEST_F(PersonalDataManagerTest, CreateDataForTest) {
// Reloading the test profile should result in test data being created.
ResetPersonalDataManager(USER_MODE_NORMAL);
+
const std::vector<AutofillProfile*> addresses = personal_data_->GetProfiles();
const std::vector<CreditCard*> credit_cards =
personal_data_->GetCreditCards();
@@ -6363,7 +6360,7 @@ TEST_F(PersonalDataManagerTest, ClearProfileNonSettingsOrigins) {
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
profile0.set_use_count(10000);
- personal_data_->AddProfile(profile0);
+ AddProfileToPersonalDataManager(profile0);
AutofillProfile profile1(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&profile1, "Marion1", "Mitchell", "Morrison",
@@ -6371,7 +6368,7 @@ TEST_F(PersonalDataManagerTest, ClearProfileNonSettingsOrigins) {
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
profile1.set_use_count(1000);
- personal_data_->AddProfile(profile1);
+ AddProfileToPersonalDataManager(profile1);
AutofillProfile profile2(base::GenerateGUID(), "1234");
test::SetProfileInfo(&profile2, "Marion2", "Mitchell", "Morrison",
@@ -6379,7 +6376,7 @@ TEST_F(PersonalDataManagerTest, ClearProfileNonSettingsOrigins) {
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
profile2.set_use_count(100);
- personal_data_->AddProfile(profile2);
+ AddProfileToPersonalDataManager(profile2);
// Create a profile with a settings origin.
AutofillProfile profile3(base::GenerateGUID(), kSettingsOrigin);
@@ -6388,14 +6385,19 @@ TEST_F(PersonalDataManagerTest, ClearProfileNonSettingsOrigins) {
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
profile3.set_use_count(10);
- personal_data_->AddProfile(profile3);
+ AddProfileToPersonalDataManager(profile3);
- WaitForOnPersonalDataChanged();
ASSERT_EQ(4U, personal_data_->GetProfiles().size());
+ base::RunLoop run_loop;
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
+ .WillRepeatedly(QuitMessageLoop(&run_loop));
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .Times(2); // The setting of profiles 0 and 2 will be cleared.
+
personal_data_->ClearProfileNonSettingsOrigins();
+ run_loop.Run();
- WaitForOnPersonalDataChanged();
ASSERT_EQ(4U, personal_data_->GetProfiles().size());
// The first three profiles' origin should be cleared and the fourth one still
@@ -6470,7 +6472,7 @@ TEST_F(PersonalDataManagerTest, MoveJapanCityToStreetAddress) {
test::SetProfileInfo(&profile0, "Homer", "J", "Simpson",
"homer.simpson@abc.com", "", "742. Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "");
- personal_data_->AddProfile(profile0);
+ AddProfileToPersonalDataManager(profile0);
}
// A JP profile with both street address and a city.
@@ -6480,7 +6482,7 @@ TEST_F(PersonalDataManagerTest, MoveJapanCityToStreetAddress) {
test::SetProfileInfo(&profile1, "Homer", "J", "Simpson",
"homer.simpson@abc.com", "", "742. Evergreen Terrace",
"", "Springfield", "IL", "91601", "JP", "");
- personal_data_->AddProfile(profile1);
+ AddProfileToPersonalDataManager(profile1);
}
// A JP profile with only a city.
@@ -6490,7 +6492,7 @@ TEST_F(PersonalDataManagerTest, MoveJapanCityToStreetAddress) {
test::SetProfileInfo(&profile2, "Homer", "J", "Simpson",
"homer.simpson@abc.com", "", "", "", "Springfield",
"IL", "91601", "JP", "");
- personal_data_->AddProfile(profile2);
+ AddProfileToPersonalDataManager(profile2);
}
// A JP profile with only a street address.
@@ -6500,7 +6502,7 @@ TEST_F(PersonalDataManagerTest, MoveJapanCityToStreetAddress) {
test::SetProfileInfo(&profile3, "Homer", "J", "Simpson",
"homer.simpson@abc.com", "", "742. Evergreen Terrace",
"", "", "IL", "91601", "JP", "");
- personal_data_->AddProfile(profile3);
+ AddProfileToPersonalDataManager(profile3);
}
// A JP profile with neither a street address nor a city.
@@ -6510,14 +6512,16 @@ TEST_F(PersonalDataManagerTest, MoveJapanCityToStreetAddress) {
test::SetProfileInfo(&profile4, "Homer", "J", "Simpson",
"homer.simpson@abc.com", "", "", "", "", "IL", "91601",
"JP", "");
- personal_data_->AddProfile(profile4);
+ AddProfileToPersonalDataManager(profile4);
}
- WaitForOnPersonalDataChanged();
-
+ base::RunLoop run_loop;
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
+ .WillRepeatedly(QuitMessageLoop(&run_loop));
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .Times(2); // For the Japan profiles where the city is not empty.
personal_data_->MoveJapanCityToStreetAddress();
-
- WaitForOnPersonalDataChanged();
+ run_loop.Run();
{
AutofillProfile* profile0 = personal_data_->GetProfileByGUID(guid0);
@@ -6570,8 +6574,7 @@ TEST_F(
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
- personal_data_->AddProfile(profile);
- WaitForOnPersonalDataChanged();
+ AddProfileToPersonalDataManager(profile);
// Turn off autofill profile sync.
auto model_type_set = sync_service_.GetActiveDataTypes();
@@ -6730,9 +6733,7 @@ TEST_F(PersonalDataManagerTest, UseCorrectStorageForDifferentCards) {
test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
- personal_data_->AddProfile(profile);
-
- WaitForOnPersonalDataChanged();
+ AddProfileToPersonalDataManager(profile);
std::vector<std::unique_ptr<AutofillProfile>> profiles;
// Expect that a profile is stored in the profile autofill table.
@@ -6825,8 +6826,9 @@ TEST_F(PersonalDataManagerTest, RequestProfileValidity) {
TEST_F(PersonalDataManagerTest, UpdateClientValidityStates) {
// Create three profiles and add them to personal_data_.
AutofillProfile valid_profile(test::GetFullValidProfileForCanada());
+ valid_profile.set_use_date(AutofillClock::Now());
valid_profile.set_guid("00000000-0000-0000-0000-000000000001");
- personal_data_->AddProfile(valid_profile);
+ AddProfileToPersonalDataManager(valid_profile);
AutofillProfile profile_invalid_phone_email(
test::GetFullValidProfileForChina());
@@ -6834,8 +6836,10 @@ TEST_F(PersonalDataManagerTest, UpdateClientValidityStates) {
PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16("invalid phone number!"));
profile_invalid_phone_email.SetRawInfo(EMAIL_ADDRESS,
base::UTF8ToUTF16("invalid email!"));
+ profile_invalid_phone_email.set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(10));
profile_invalid_phone_email.set_guid("00000000-0000-0000-0000-000000000002");
- personal_data_->AddProfile(profile_invalid_phone_email);
+ AddProfileToPersonalDataManager(profile_invalid_phone_email);
AutofillProfile profile_invalid_province(base::GenerateGUID(),
test::kEmptyOrigin);
@@ -6843,9 +6847,10 @@ TEST_F(PersonalDataManagerTest, UpdateClientValidityStates) {
"alice@munro.ca", "Fox", "123 Zoo St", "unit 5",
"Montreal", "CA", "H3C 2A3", "CA", "15142343254");
profile_invalid_province.set_guid("00000000-0000-0000-0000-000000000003");
- personal_data_->AddProfile(profile_invalid_province);
+ profile_invalid_province.set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(100));
+ AddProfileToPersonalDataManager(profile_invalid_province);
- WaitForOnPersonalDataChanged();
ASSERT_EQ(3U, personal_data_->GetProfiles().size());
// Validate the profiles through the client validation API.
@@ -6939,12 +6944,11 @@ TEST_F(PersonalDataManagerTest, UpdateClientValidityStates) {
TEST_F(PersonalDataManagerTest, UpdateClientValidityStates_UpdatedFlag) {
// Create two profiles and add them to personal_data_.
AutofillProfile profile1(test::GetFullValidProfileForCanada());
- personal_data_->AddProfile(profile1);
+ AddProfileToPersonalDataManager(profile1);
AutofillProfile profile2(test::GetFullValidProfileForChina());
- personal_data_->AddProfile(profile2);
+ AddProfileToPersonalDataManager(profile2);
- WaitForOnPersonalDataChanged();
ASSERT_EQ(2U, personal_data_->GetProfiles().size());
// Validate the profiles through the client validation API.
@@ -6987,13 +6991,11 @@ TEST_F(PersonalDataManagerTest, UpdateClientValidityStates_AlreadyUpdated) {
// Create two profiles and add them to personal_data_.
AutofillProfile profile1(test::GetFullValidProfileForCanada());
profile1.SetRawInfo(EMAIL_ADDRESS, base::UTF8ToUTF16("invalid email!"));
- personal_data_->AddProfile(profile1);
+ AddProfileToPersonalDataManager(profile1);
AutofillProfile profile2(test::GetFullValidProfileForChina());
profile2.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("invalid state!"));
- personal_data_->AddProfile(profile2);
-
- WaitForOnPersonalDataChanged();
+ AddProfileToPersonalDataManager(profile2);
EXPECT_CALL(*personal_data_, OnValidated(testing::_)).Times(0);
@@ -7030,14 +7032,13 @@ TEST_F(PersonalDataManagerTest, UpdateClientValidityStates_Version) {
AutofillProfile profile1(test::GetFullValidProfileForCanada());
profile1.SetRawInfo(EMAIL_ADDRESS, base::UTF8ToUTF16("invalid email!"));
profile1.set_guid("00000000-0000-0000-0000-000000000001");
- personal_data_->AddProfile(profile1);
+ AddProfileToPersonalDataManager(profile1);
AutofillProfile profile2(test::GetFullValidProfileForChina());
profile2.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("invalid state!"));
profile2.set_guid("00000000-0000-0000-0000-000000000002");
- personal_data_->AddProfile(profile2);
+ AddProfileToPersonalDataManager(profile2);
- WaitForOnPersonalDataChanged();
auto profiles = personal_data_->GetProfiles();
// Pretend that the validity states are updated.
@@ -7071,8 +7072,7 @@ TEST_F(PersonalDataManagerTest, UpdateClientValidityStates_Version) {
AutofillProfile::CLIENT));
// Verify that the version of the last update is set to this version.
- EXPECT_EQ(atoi(version_info::GetVersionNumber().c_str()),
- GetLastVersionValidatedUpdate());
+ EXPECT_EQ(CHROME_VERSION_MAJOR, GetLastVersionValidatedUpdate());
// Update should not update any validity state, because both the validity
// state flag and the version are up to date.
@@ -7086,6 +7086,26 @@ TEST_F(PersonalDataManagerTest, UpdateClientValidityStates_Version) {
AutofillProfile::CLIENT));
}
+// The validation should not happen when the feature is disabled.
+TEST_F(PersonalDataManagerTest, UpdateClientValidityStates_Disabled) {
+ base::test::ScopedFeatureList scoped_features;
+ scoped_features.InitAndDisableFeature(
+ features::kAutofillProfileClientValidation);
+
+ AutofillProfile profile1(test::GetFullValidProfileForCanada());
+ AddProfileToPersonalDataManager(profile1);
+
+ auto profiles = personal_data_->GetProfiles();
+ EXPECT_FALSE(profiles[0]->is_client_validity_states_updated());
+
+ personal_data_->UpdateClientValidityStates(profiles);
+
+ EXPECT_FALSE(profiles[0]->is_client_validity_states_updated());
+ EXPECT_EQ(AutofillProfile::UNVALIDATED,
+ profiles[0]->GetValidityState(ADDRESS_HOME_COUNTRY,
+ AutofillProfile::CLIENT));
+}
+
TEST_F(PersonalDataManagerTest, GetAccountInfoForPaymentsServer) {
const std::string kIdentityManagerAccountEmail = "identity_account@email.com";
const std::string kSyncServiceAccountEmail = "active_sync_account@email.com";
diff --git a/chromium/components/autofill/core/browser/phone_field.cc b/chromium/components/autofill/core/browser/phone_field.cc
index 7c19aabc528..343504b5d1b 100644
--- a/chromium/components/autofill/core/browser/phone_field.cc
+++ b/chromium/components/autofill/core/browser/phone_field.cc
@@ -10,7 +10,7 @@
#include <utility>
#include "base/logging.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -139,12 +139,12 @@ std::unique_ptr<FormField> PhoneField::Parse(AutofillScanner* scanner) {
// The form owns the following variables, so they should not be deleted.
AutofillField* parsed_fields[FIELD_MAX];
- for (size_t i = 0; i < arraysize(kPhoneFieldGrammars); ++i) {
+ for (size_t i = 0; i < base::size(kPhoneFieldGrammars); ++i) {
memset(parsed_fields, 0, sizeof(parsed_fields));
size_t saved_cursor = scanner->SaveCursor();
// Attempt to parse according to the next grammar.
- for (; i < arraysize(kPhoneFieldGrammars) &&
+ for (; i < base::size(kPhoneFieldGrammars) &&
kPhoneFieldGrammars[i].regex != REGEX_SEPARATOR;
++i) {
if (!ParsePhoneField(scanner, GetRegExp(kPhoneFieldGrammars[i].regex),
@@ -158,7 +158,7 @@ std::unique_ptr<FormField> PhoneField::Parse(AutofillScanner* scanner) {
}
}
- if (i >= arraysize(kPhoneFieldGrammars)) {
+ if (i >= base::size(kPhoneFieldGrammars)) {
scanner->RewindTo(saved_cursor);
return nullptr; // Parsing failed.
}
@@ -168,11 +168,11 @@ std::unique_ptr<FormField> PhoneField::Parse(AutofillScanner* scanner) {
// Proceed to the next grammar.
do {
++i;
- } while (i < arraysize(kPhoneFieldGrammars) &&
+ } while (i < base::size(kPhoneFieldGrammars) &&
kPhoneFieldGrammars[i].regex != REGEX_SEPARATOR);
scanner->RewindTo(saved_cursor);
- if (i + 1 == arraysize(kPhoneFieldGrammars)) {
+ if (i + 1 == base::size(kPhoneFieldGrammars)) {
return nullptr; // Tried through all the possibilities - did not match.
}
}
diff --git a/chromium/components/autofill/core/browser/phone_field_unittest.cc b/chromium/components/autofill/core/browser/phone_field_unittest.cc
index d8374d09c43..96ee9c85b43 100644
--- a/chromium/components/autofill/core/browser/phone_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/phone_field_unittest.cc
@@ -38,7 +38,8 @@ class PhoneFieldTest : public testing::Test {
// Downcast for tests.
static std::unique_ptr<PhoneField> Parse(AutofillScanner* scanner) {
std::unique_ptr<FormField> field = PhoneField::Parse(scanner);
- return base::WrapUnique(static_cast<PhoneField*>(field.release()));
+ return std::unique_ptr<PhoneField>(
+ static_cast<PhoneField*>(field.release()));
}
void Clear() {
diff --git a/chromium/components/autofill/core/browser/phone_number_i18n.cc b/chromium/components/autofill/core/browser/phone_number_i18n.cc
index 03b9bedfefa..f4e7e3ba8fb 100644
--- a/chromium/components/autofill/core/browser/phone_number_i18n.cc
+++ b/chromium/components/autofill/core/browser/phone_number_i18n.cc
@@ -108,7 +108,7 @@ bool IsPrintable(base::StringPiece str) {
namespace i18n {
-const size_t kMaxPhoneNumberSize = 1000u;
+const size_t kMaxPhoneNumberSize = 40u;
// Returns true if |phone_number| is a possible number.
bool IsPossiblePhoneNumber(
diff --git a/chromium/components/autofill/core/browser/proto/server.proto b/chromium/components/autofill/core/browser/proto/server.proto
index 01b3a6527ec..079c9449ffc 100644
--- a/chromium/components/autofill/core/browser/proto/server.proto
+++ b/chromium/components/autofill/core/browser/proto/server.proto
@@ -185,7 +185,7 @@ message AutofillRandomizedFieldMetadata {
// This message contains information about the field types in a single form.
// It is sent by the toolbar to contribute to the field type statistics.
-// Next available id: 36
+// Next available id: 38
message AutofillUploadContents {
required string client_version = 1;
required fixed64 form_signature = 2;
@@ -370,6 +370,32 @@ message AutofillUploadContents {
// Form-level metadata observed by the client, randomized.
optional AutofillRandomizedFormMetadata randomized_form_metadata = 32;
+
+ // Information about a button's title.
+ message ButtonTitle {
+ // Text showed on the button.
+ optional string title = 1;
+
+ // Describes how the button is implemented in HTML source. Corresponds to
+ // components/autofill/core/common/button_title_type.h
+ enum ButtonTitleType {
+ NONE = 0;
+ BUTTON_ELEMENT_SUBMIT_TYPE = 1; // <button type='submit'>
+ BUTTON_ELEMENT_BUTTON_TYPE = 2; // <button type='button'>
+ INPUT_ELEMENT_SUBMIT_TYPE = 3; // <input type='submit'>
+ INPUT_ELEMENT_BUTTON_TYPE = 4; // <input type='button'>
+ HYPERLINK = 5; // e.g. <a class='button'>
+ DIV = 6; // e.g. <div id='submit'>
+ SPAN = 7; // e.g. <span name='btn'>
+ }
+ optional ButtonTitleType type = 2;
+ }
+ // Titles of form's buttons.
+ // TODO(850606): Deprecate once randomized metadata is launched.
+ repeated ButtonTitle button_title = 36;
+
+ // Whether the fields are enclosed by a <form> tag or are unowned elements.
+ optional bool has_form_tag = 37;
}
// This proto contains information about the validity of each field in an
diff --git a/chromium/components/autofill/core/browser/randomized_encoder_unittest.cc b/chromium/components/autofill/core/browser/randomized_encoder_unittest.cc
index dcbc1e5989d..d034c86cae0 100644
--- a/chromium/components/autofill/core/browser/randomized_encoder_unittest.cc
+++ b/chromium/components/autofill/core/browser/randomized_encoder_unittest.cc
@@ -4,7 +4,8 @@
#include "components/autofill/core/browser/randomized_encoder.h"
-#include "base/time/time.h"
+#include "base/strings/stringprintf.h"
+#include "net/base/hex_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
@@ -106,7 +107,7 @@ TEST_P(RandomizedEncoderTest, Encode) {
EXPECT_LT(value.length(), kMaxLengthInBytes);
- TestRandomizedEncoder encoder("this is a secret", params.encoding_type);
+ TestRandomizedEncoder encoder("this is the seed", params.encoding_type);
// Encode the output string.
std::string actual_result =
@@ -135,10 +136,10 @@ TEST_P(RandomizedEncoderTest, EncodeLarge) {
const std::string value(
"This is some text for testing purposes. It exceeds the maximum encoding "
"size. This serves to validate that truncation is performed. Lots and "
- " or text. Yay!");
+ "lots of text. Yay!");
EXPECT_GT(value.length(), kMaxLengthInBytes);
- TestRandomizedEncoder encoder("this is a secret", params.encoding_type);
+ TestRandomizedEncoder encoder("this is the seed", params.encoding_type);
// Encode the output string.
std::string actual_result =
@@ -162,3 +163,164 @@ TEST_P(RandomizedEncoderTest, EncodeLarge) {
INSTANTIATE_TEST_CASE_P(All,
RandomizedEncoderTest,
::testing::ValuesIn(kEncodeParams));
+
+namespace {
+
+// Data structure used to drive the decoding test cases.
+struct DecodeParams {
+ // The number of samples for this test.
+ size_t num_votes;
+
+ // The lower and upper bound of the confidence interval given |num_votes|
+ // samples. If fewer than (lower_bound * num_votes) samples are one then the
+ // bit is a zero. If more than (upper_bound * num_votes) samples are one then
+ // the bit is a one.
+ double lower_bound;
+ double upper_bound;
+};
+
+// The fundamental idea of this algorithm is to count the number of reported 1s
+// and 0s from a crowdsourced set of votes and look for a threshold that gives
+// us confidence that we have seen enough 1s or 0s to assume that the actual
+// value is a 1 or 0.
+//
+// Due to the symmetriy of the problem, we can conveniently choose the following
+// null-hypothesis:
+//
+// N0: The true value of a bit is random on each pageload.
+//
+// In this case, we expect a binomial distribution B(n, 0.5), for which we can
+// find a confidence interval that a sample of size n ends up in this interval.
+// If a sample is outside of this interval, we can assume with the given
+// confidence that we can reject the null-hypothesis and assume that the actual
+// value is 0 or 1.
+//
+// For the confidence interval, we use the Wilson Score interval.
+// https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson_score_interval
+//
+// The confidence intervals are calculate as:
+//
+// import scipy.stats as st
+// import math
+//
+// def ConfidenceInterval(ph, n, confidence):
+// """
+// Args:
+// confidence: e.g. 0.95 for a 95% confidence
+// ph = p hat (see Wilson Score inverval link above)
+// n = number of samples
+// """
+// alpha = 1 - confidence
+// # for the 95% confidence interval this gives 1.96.
+// z = st.norm.ppf(1 - alpha/2)
+//
+// base = (ph + z*z/(2*n)) / (1 + z*z/n)
+// offset = z / (1 + z*z/n) * math.sqrt(ph*(1-ph)/n + z*z/(4*n*n))
+//
+// return [base - offset, base + offset]
+//
+// Note: The string being encoded/decoded for each "sample" consists of a common
+// prefix followed by the decimal value of the sample number (i.e., "foo 25").
+// Avoid test cases that skew the distribution of the appended noise to far
+// from random (for example, using 0-199, more than 55% of the appended noise
+// starts with the ASCII digit '1').
+const DecodeParams kDecodeParams[] = {
+ // 99.0 % confidence interval
+ {150, 0.39709349666174232, 0.60290650333825768},
+ {256, 0.42052859913480434, 0.57947140086519566},
+
+ // 99.5% confidence interval
+ {150, 0.38829956746162475, 0.61170043253837525},
+ {256, 0.41359977651950797, 0.58640022348049203},
+};
+
+using RandomizedDecoderTest = ::testing::TestWithParam<DecodeParams>;
+
+// Generate a hex string representing the 128 bit value where each byte has
+// value |i|. This lets us spread the seeds across the 128 bit space.
+std::string Make128BitSeed(size_t i) {
+ EXPECT_LT(i, 256u);
+ return net::HexDump(
+ std::string(128 / kBitsPerByte, static_cast<char>(i & 0xFF)));
+}
+
+} // namespace
+
+TEST_P(RandomizedDecoderTest, Decode) {
+ static const autofill::FormSignature form_signature = 0x8765432187654321;
+ static const autofill::FieldSignature field_signature = 0xDEADBEEF;
+ static const char data_type[] = "data_type";
+ static const base::StringPiece common_prefix(
+ "This is the common prefix to encode and recover ");
+
+ const size_t num_votes = GetParam().num_votes;
+ const double lower_bound = GetParam().lower_bound;
+ const double upper_bound = GetParam().upper_bound;
+
+ // This vector represents the aggregate counts of the number of times a
+ // separate encoding of out sample string had a given bit encoded as a one.
+ std::vector<size_t> num_times_bit_is_1(/*count=*/kMaxLengthInBits,
+ /*value=*/0);
+
+ // Perform |num_votes| independent encoding operations, with seeds (somewhat)
+ // evenly spread out across a 128-bit space.
+ for (size_t i = 0; i < num_votes; ++i) {
+ // Create a new encoder with a different secret each time.
+ TestRandomizedEncoder encoder(
+ Make128BitSeed(i),
+ autofill::AutofillRandomizedValue_EncodingType_ALL_BITS);
+
+ // Encode the common prefix plus some non-constant data.
+ std::string encoded =
+ encoder.Encode(form_signature, field_signature, data_type,
+ base::StringPrintf("%s%zu", common_prefix.data(), i));
+
+ // Update |num_times_bit_is_1| for each bit in the encoded string.
+ for (size_t b = 0; b < kMaxLengthInBits; ++b) {
+ num_times_bit_is_1[b] += GetBit(encoded, b);
+ }
+ }
+
+ // Use |num_times_bit_is_1| to reconstruct the encoded string, bit by bit,
+ // as well as a record of whether or not each bit in the reconstruction
+ // buffer was validated with sufficient confidence.
+ std::string output(kMaxLengthInBytes, static_cast<char>(0));
+ std::vector<bool> bit_is_valid(kMaxLengthInBits);
+ const double threshold_for_zero = lower_bound * num_votes;
+ const double threshold_for_one = upper_bound * num_votes;
+ for (size_t b = 0; b < kMaxLengthInBits; ++b) {
+ if (num_times_bit_is_1[b] < threshold_for_zero) {
+ // bit it already zero, just mark it as valid
+ bit_is_valid[b] = true;
+ } else if (num_times_bit_is_1[b] > threshold_for_one) {
+ output[b / kBitsPerByte] |= (1 << (b % kBitsPerByte));
+ bit_is_valid[b] = true;
+ }
+ }
+
+ // Validation: All bits overlapping the constant prefix should be valid.
+ for (size_t b = 0; b < common_prefix.length() * kBitsPerByte; ++b) {
+ EXPECT_TRUE(bit_is_valid[b]) << "True bit found to be noise at " << b;
+ }
+
+ // Validation: All of the recovered prefix bits should match the prefix.
+ for (size_t i = 0; i < common_prefix.length(); ++i) {
+ EXPECT_EQ(common_prefix[i], output[i]) << "Incorrect char at offset " << i;
+ }
+
+ // Validation: Most noise bits should be invalid, but we may get some false
+ // positives. Instead, we expect that no noise byte will have all of its
+ // bits turn up as valid.
+ for (size_t i = common_prefix.length(); i < kMaxLengthInBytes; ++i) {
+ size_t num_valid_bits = 0;
+ for (size_t b = 0; b < kBitsPerByte; ++b) {
+ num_valid_bits += bit_is_valid[i * kBitsPerByte + b];
+ }
+ EXPECT_LT(num_valid_bits, kBitsPerByte)
+ << "Noise byte at offset " << i << " decoded as " << output[i];
+ }
+}
+
+INSTANTIATE_TEST_CASE_P(All,
+ RandomizedDecoderTest,
+ ::testing::ValuesIn(kDecodeParams));
diff --git a/chromium/components/autofill/core/browser/search_field_unittest.cc b/chromium/components/autofill/core/browser/search_field_unittest.cc
index 4c65cb00fc0..f24235145f6 100644
--- a/chromium/components/autofill/core/browser/search_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/search_field_unittest.cc
@@ -32,7 +32,8 @@ class SearchFieldTest : public testing::Test {
// Downcast for tests.
static std::unique_ptr<SearchField> Parse(AutofillScanner* scanner) {
std::unique_ptr<FormField> field = SearchField::Parse(scanner);
- return base::WrapUnique(static_cast<SearchField*>(field.release()));
+ return std::unique_ptr<SearchField>(
+ static_cast<SearchField*>(field.release()));
}
private:
diff --git a/chromium/components/autofill/core/browser/strike_database.cc b/chromium/components/autofill/core/browser/strike_database.cc
index 6e0e8b8c36f..0e247e7d2e3 100644
--- a/chromium/components/autofill/core/browser/strike_database.cc
+++ b/chromium/components/autofill/core/browser/strike_database.cc
@@ -14,18 +14,18 @@
#include "base/task/post_task.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/proto/strike_data.pb.h"
-#include "components/leveldb_proto/proto_database_impl.h"
+#include "components/autofill/core/common/autofill_clock.h"
+#include "components/leveldb_proto/public/proto_database_provider.h"
namespace autofill {
namespace {
const char kDatabaseClientName[] = "StrikeService";
-const char kKeyDeliminator[] = "__";
const int kMaxInitAttempts = 3;
} // namespace
StrikeDatabase::StrikeDatabase(const base::FilePath& database_dir)
- : db_(std::make_unique<leveldb_proto::ProtoDatabaseImpl<StrikeData>>(
+ : db_(leveldb_proto::ProtoDatabaseProvider::CreateUniqueDB<StrikeData>(
base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}))),
@@ -39,36 +39,35 @@ StrikeDatabase::StrikeDatabase(const base::FilePath& database_dir)
StrikeDatabase::~StrikeDatabase() {}
-bool StrikeDatabase::IsMaxStrikesLimitReached(const std::string id) {
- return GetStrikes(id) >= GetMaxStrikesLimit();
+int StrikeDatabase::AddStrikes(int strikes_increase, const std::string key) {
+ DCHECK(strikes_increase > 0);
+ int num_strikes =
+ strike_map_cache_.count(key) // Cache has entry for |key|.
+ ? strike_map_cache_[key].num_strikes() + strikes_increase
+ : strikes_increase;
+ SetStrikeData(key, num_strikes);
+ return num_strikes;
}
-int StrikeDatabase::AddStrike(const std::string id) {
- std::string key = GetKey(id);
- int num_strikes = strike_map_cache_.count(key) // Cache has entry for |key|.
- ? strike_map_cache_[key].num_strikes() + 1
- : 1;
- StrikeData data;
- data.set_num_strikes(num_strikes);
- data.set_last_update_timestamp(
- base::Time::Now().ToDeltaSinceWindowsEpoch().InMicroseconds());
- UpdateCache(key, data);
- SetProtoStrikeData(key, data, base::DoNothing());
- base::UmaHistogramCounts1000(
- "Autofill.StrikeDatabase.NthStrikeAdded." + GetProjectPrefix(),
- num_strikes);
+int StrikeDatabase::RemoveStrikes(int strikes_decrease, const std::string key) {
+ DCHECK(strikes_decrease > 0);
+ DCHECK(strike_map_cache_.count(key));
+ int num_strikes = strike_map_cache_[key].num_strikes() - strikes_decrease;
+ if (num_strikes < 1) {
+ ClearStrikes(key);
+ return 0;
+ }
+ SetStrikeData(key, num_strikes);
return num_strikes;
}
-int StrikeDatabase::GetStrikes(const std::string id) {
- std::string key = GetKey(id);
+int StrikeDatabase::GetStrikes(const std::string key) {
return strike_map_cache_.count(key) // Cache contains entry for |key|.
? strike_map_cache_[key].num_strikes()
: 0;
}
-void StrikeDatabase::ClearStrikes(const std::string id) {
- std::string key = GetKey(id);
+void StrikeDatabase::ClearStrikes(const std::string key) {
strike_map_cache_.erase(key);
ClearAllProtoStrikesForKey(key, base::DoNothing());
}
@@ -107,8 +106,13 @@ void StrikeDatabase::OnDatabaseLoadKeysAndEntries(
strike_map_cache_.insert(entries->begin(), entries->end());
}
-std::string StrikeDatabase::GetKey(const std::string id) {
- return GetProjectPrefix() + kKeyDeliminator + id;
+void StrikeDatabase::SetStrikeData(const std::string key, int num_strikes) {
+ StrikeData data;
+ data.set_num_strikes(num_strikes);
+ data.set_last_update_timestamp(
+ AutofillClock::Now().ToDeltaSinceWindowsEpoch().InMicroseconds());
+ UpdateCache(key, data);
+ SetProtoStrikeData(key, data, base::DoNothing());
}
void StrikeDatabase::GetProtoStrikes(const std::string key,
diff --git a/chromium/components/autofill/core/browser/strike_database.h b/chromium/components/autofill/core/browser/strike_database.h
index 5c69ace7f95..bea6da0aa80 100644
--- a/chromium/components/autofill/core/browser/strike_database.h
+++ b/chromium/components/autofill/core/browser/strike_database.h
@@ -13,7 +13,7 @@
#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "components/leveldb_proto/proto_database.h"
+#include "components/leveldb_proto/public/proto_database.h"
namespace autofill {
class StrikeData;
@@ -22,6 +22,10 @@ class StrikeData;
// the user. Projects can earn strikes in a number of ways; for instance, if a
// user ignores or declines a prompt, or if a user accepts a prompt but the task
// fails.
+// This class is a Singleton which contains StrikeData information for all
+// projects. It should not be used directly, but rather by implementing the
+// StrikeDatabaseIntegratorBase (which contains a pointer to StrikeDatabase)
+// for specific projects.
class StrikeDatabase : public KeyedService {
public:
using ClearStrikesCallback = base::RepeatingCallback<void(bool success)>;
@@ -43,19 +47,23 @@ class StrikeDatabase : public KeyedService {
explicit StrikeDatabase(const base::FilePath& database_dir);
~StrikeDatabase() override;
- bool IsMaxStrikesLimitReached(const std::string id);
+ // Increases in-memory cache by |strikes_increase| and updates underlying
+ // ProtoDatabase.
+ int AddStrikes(int strikes_increase, const std::string key);
- // Increments in-memory cache and updates underlying ProtoDatabase.
- int AddStrike(const std::string id);
+ // Removes |strikes_decrease| in-memory cache strikes, updates
+ // last_update_timestamp, and updates underlying ProtoDatabase.
+ int RemoveStrikes(int strikes_decrease, const std::string key);
// Returns strike count from in-memory cache.
- int GetStrikes(const std::string id);
+ int GetStrikes(const std::string key);
// Removes all database entries from in-memory cache and underlying
// ProtoDatabase.
- void ClearStrikes(const std::string id);
+ void ClearStrikes(const std::string key);
protected:
+ friend class StrikeDatabaseIntegratorBase;
// Constructor for testing that does not initialize a ProtoDatabase.
StrikeDatabase();
@@ -80,6 +88,10 @@ class StrikeDatabase : public KeyedService {
StrikeDatabaseEmptyOnAutofillRemoveEverything);
FRIEND_TEST_ALL_PREFIXES(CreditCardSaveStrikeDatabaseTest,
GetKeyForCreditCardSaveTest);
+ FRIEND_TEST_ALL_PREFIXES(CreditCardSaveStrikeDatabaseTest,
+ GetIdForCreditCardSaveTest);
+ FRIEND_TEST_ALL_PREFIXES(CreditCardSaveStrikeDatabaseTest,
+ RemoveExpiredStrikesOnLoadTest);
friend class StrikeDatabaseTest;
friend class StrikeDatabaseTester;
@@ -89,16 +101,9 @@ class StrikeDatabase : public KeyedService {
bool success,
std::unique_ptr<std::map<std::string, StrikeData>> entries);
- // Returns a prefix unique to each project, which will be used to create
- // database key.
- virtual std::string GetProjectPrefix() = 0;
-
- // Returns the maximum number of strikes after which the project's Autofill
- // opportunity stops being offered.
- virtual int GetMaxStrikesLimit() = 0;
-
- // Generates key based on project-specific string identifier.
- std::string GetKey(const std::string id);
+ // Updates the StrikeData for |key| in the cache and ProtoDatabase to have
+ // |num_stikes|, and the current time as timestamp.
+ void SetStrikeData(const std::string key, int num_strikes);
// Passes the number of strikes for |key| to |outer_callback|. In the case
// that the database fails to retrieve the strike update or if no entry is
diff --git a/chromium/components/autofill/core/browser/strike_database_integrator_base.cc b/chromium/components/autofill/core/browser/strike_database_integrator_base.cc
new file mode 100644
index 00000000000..f6438197ffd
--- /dev/null
+++ b/chromium/components/autofill/core/browser/strike_database_integrator_base.cc
@@ -0,0 +1,92 @@
+// 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/strike_database_integrator_base.h"
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/task/post_task.h"
+#include "base/time/time.h"
+#include "components/autofill/core/browser/proto/strike_data.pb.h"
+#include "components/autofill/core/common/autofill_clock.h"
+#include "components/leveldb_proto/public/proto_database_provider.h"
+
+namespace autofill {
+
+namespace {
+const char kKeyDeliminator[] = "__";
+} // namespace
+
+StrikeDatabaseIntegratorBase::StrikeDatabaseIntegratorBase(
+ StrikeDatabase* strike_database)
+ : strike_database_(strike_database) {}
+
+StrikeDatabaseIntegratorBase::~StrikeDatabaseIntegratorBase() {}
+
+bool StrikeDatabaseIntegratorBase::IsMaxStrikesLimitReached(
+ const std::string id) {
+ CheckIdUniqueness(id);
+ return GetStrikes(id) >= GetMaxStrikesLimit();
+}
+
+int StrikeDatabaseIntegratorBase::AddStrike(const std::string id) {
+ CheckIdUniqueness(id);
+ return AddStrikes(1, id);
+}
+
+int StrikeDatabaseIntegratorBase::AddStrikes(int strikes_increase,
+ const std::string id) {
+ CheckIdUniqueness(id);
+ int num_strikes = strike_database_->AddStrikes(strikes_increase, GetKey(id));
+ base::UmaHistogramCounts1000(
+ "Autofill.StrikeDatabase.NthStrikeAdded." + GetProjectPrefix(),
+ num_strikes);
+ return num_strikes;
+}
+
+int StrikeDatabaseIntegratorBase::RemoveStrike(const std::string id) {
+ CheckIdUniqueness(id);
+ return strike_database_->RemoveStrikes(1, GetKey(id));
+}
+
+int StrikeDatabaseIntegratorBase::RemoveStrikes(int strikes_decrease,
+ const std::string id) {
+ CheckIdUniqueness(id);
+ return strike_database_->RemoveStrikes(strikes_decrease, GetKey(id));
+}
+
+int StrikeDatabaseIntegratorBase::GetStrikes(const std::string id) {
+ CheckIdUniqueness(id);
+ return strike_database_->GetStrikes(GetKey(id));
+}
+
+void StrikeDatabaseIntegratorBase::ClearStrikes(const std::string id) {
+ CheckIdUniqueness(id);
+ strike_database_->ClearStrikes(GetKey(id));
+}
+
+void StrikeDatabaseIntegratorBase::RemoveExpiredStrikes() {
+ std::vector<std::string> expired_keys;
+ for (auto entry : strike_database_->strike_map_cache_) {
+ if (AutofillClock::Now().ToDeltaSinceWindowsEpoch().InMicroseconds() -
+ entry.second.last_update_timestamp() >
+ GetExpiryTimeMicros()) {
+ if (strike_database_->GetStrikes(entry.first) > 0)
+ expired_keys.push_back(entry.first);
+ }
+ }
+ for (std::string key : expired_keys)
+ strike_database_->RemoveStrikes(1, key);
+}
+
+std::string StrikeDatabaseIntegratorBase::GetKey(const std::string id) {
+ return GetProjectPrefix() + kKeyDeliminator + id;
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/strike_database_integrator_base.h b/chromium/components/autofill/core/browser/strike_database_integrator_base.h
new file mode 100644
index 00000000000..9f207da9d94
--- /dev/null
+++ b/chromium/components/autofill/core/browser/strike_database_integrator_base.h
@@ -0,0 +1,102 @@
+// 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_STRIKE_DATABASE_INTEGRATOR_BASE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_INTEGRATOR_BASE_H_
+
+#include "components/autofill/core/browser/strike_database.h"
+
+namespace autofill {
+
+namespace {
+static const char kSharedId[] = "shared_id";
+} // namespace
+
+// Contains virtual functions for per-project implementations of StrikeDatabase
+// to interface from, as well as a pointer to StrikeDatabase. This class is
+// seperated from StrikeDatabase since we only want StrikeDatabase's cache to
+// be loaded once per browser session.
+class StrikeDatabaseIntegratorBase {
+ public:
+ StrikeDatabaseIntegratorBase(StrikeDatabase* strike_database);
+ virtual ~StrikeDatabaseIntegratorBase();
+
+ // Returns whether or not strike count for |id| has reached the strike limit
+ // set by GetMaxStrikesLimit().
+ bool IsMaxStrikesLimitReached(const std::string id = kSharedId);
+
+ // Increments in-memory cache and updates underlying ProtoDatabase.
+ int AddStrike(const std::string id = kSharedId);
+
+ // Increases in-memory cache by |strikes_increase| and updates underlying
+ // ProtoDatabase.
+ int AddStrikes(int strikes_increase, const std::string id = kSharedId);
+
+ // Removes an in-memory cache strike, updates last_update_timestamp, and
+ // updates underlying ProtoDatabase.
+ int RemoveStrike(const std::string id = kSharedId);
+
+ // Removes |strikes_decrease| in-memory cache strikes, updates
+ // |last_update_timestamp|, and updates underlying ProtoDatabase.
+ int RemoveStrikes(int strikes_decrease, const std::string id = kSharedId);
+
+ // Returns strike count from in-memory cache.
+ int GetStrikes(const std::string id = kSharedId);
+
+ // Removes all database entries from in-memory cache and underlying
+ // ProtoDatabase.
+ void ClearStrikes(const std::string id = kSharedId);
+
+ protected:
+ // Removes all strikes in which it has been longer than GetExpiryTimeMicros()
+ // past |last_update_timestamp|.
+ void RemoveExpiredStrikes();
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(ChromeBrowsingDataRemoverDelegateTest,
+ StrikeDatabaseEmptyOnAutofillRemoveEverything);
+ FRIEND_TEST_ALL_PREFIXES(CreditCardSaveStrikeDatabaseTest,
+ GetKeyForCreditCardSaveTest);
+ FRIEND_TEST_ALL_PREFIXES(CreditCardSaveStrikeDatabaseTest,
+ GetIdForCreditCardSaveTest);
+ FRIEND_TEST_ALL_PREFIXES(CreditCardSaveStrikeDatabaseTest,
+ RemoveExpiredStrikesTest);
+ FRIEND_TEST_ALL_PREFIXES(LocalCardMigrationStrikeDatabaseTest,
+ RemoveExpiredStrikesTest);
+ friend class StrikeDatabaseTest;
+ friend class StrikeDatabaseTester;
+
+ StrikeDatabase* strike_database_;
+
+ // For projects in which strikes don't have unique identifiers, the
+ // id suffix is set to |kSharedId|. This makes sure that projects requiring
+ // unique IDs always specify |id| instead of relying on the default shared
+ // value, while projects where unique IDs are unnecessary always fall back to
+ // the default shared value.
+ void CheckIdUniqueness(std::string id) {
+ DCHECK(UniqueIdsRequired() == (id != kSharedId));
+ }
+
+ // Generates key based on project-specific string identifier.
+ std::string GetKey(const std::string id);
+
+ // Returns a prefix unique to each project, which will be used to create
+ // database key.
+ virtual std::string GetProjectPrefix() = 0;
+
+ // Returns the maximum number of strikes after which the project's Autofill
+ // opportunity stops being offered.
+ virtual int GetMaxStrikesLimit() = 0;
+
+ // Returns the time after which the most recent strike should expire.
+ virtual long long GetExpiryTimeMicros() = 0;
+
+ // Returns whether or not a unique string identifier is required for every
+ // strike in this project.
+ virtual bool UniqueIdsRequired() = 0;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_INTEGRATOR_BASE_H_
diff --git a/chromium/components/autofill/core/browser/strike_database_unittest.cc b/chromium/components/autofill/core/browser/strike_database_unittest.cc
index 07ea6bbe91a..57075bb0bac 100644
--- a/chromium/components/autofill/core/browser/strike_database_unittest.cc
+++ b/chromium/components/autofill/core/browser/strike_database_unittest.cc
@@ -45,20 +45,6 @@ class TestStrikeDatabase : public StrikeDatabase {
private:
DISALLOW_COPY_AND_ASSIGN(TestStrikeDatabase);
-
- // Do not use. This virtual function needed to be implemented but
- // TestStrikeDatabase is not a project class.
- std::string GetProjectPrefix() override {
- NOTIMPLEMENTED();
- return " ";
- }
-
- // Do not use. This virtual function needed to be implemented but
- // TestStrikeDatabase is not a project class.
- int GetMaxStrikesLimit() override {
- NOTIMPLEMENTED();
- return 0;
- }
};
} // anonymous namespace
diff --git a/chromium/components/autofill/core/browser/suggestion_selection.cc b/chromium/components/autofill/core/browser/suggestion_selection.cc
index ca3daa9691a..354c174d5b0 100644
--- a/chromium/components/autofill/core/browser/suggestion_selection.cc
+++ b/chromium/components/autofill/core/browser/suggestion_selection.cc
@@ -51,11 +51,11 @@ base::string16 GetInfoInOneLine(const AutofillProfile* profile,
// As of November 2018, 50 profiles should be more than enough to cover at least
// 99% of all times the dropdown is shown.
-extern const size_t kMaxSuggestedProfilesCount = 50;
+constexpr size_t kMaxSuggestedProfilesCount = 50;
// As of November 2018, displaying 10 suggestions cover at least 99% of the
// indices clicked by our users. The suggestions will also refine as they type.
-extern const size_t kMaxUniqueSuggestionsCount = 10;
+constexpr size_t kMaxUniqueSuggestionsCount = 10;
std::vector<Suggestion> GetPrefixMatchedSuggestions(
const AutofillType& type,
@@ -201,4 +201,4 @@ void RemoveProfilesNotUsedSinceTimestamp(
}
} // namespace suggestion_selection
-} // namespace autofill \ No newline at end of file
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/test_autofill_async_observer.cc b/chromium/components/autofill/core/browser/test_autofill_async_observer.cc
new file mode 100644
index 00000000000..d0f3133ad93
--- /dev/null
+++ b/chromium/components/autofill/core/browser/test_autofill_async_observer.cc
@@ -0,0 +1,28 @@
+// Copyright (c) 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_async_observer.h"
+
+#include "base/run_loop.h"
+
+namespace autofill {
+namespace test {
+
+TestAutofillAsyncObserver::TestAutofillAsyncObserver(
+ NotificationType notification_type,
+ bool detach_on_notify)
+ : AutofillObserver(notification_type, detach_on_notify), run_loop_() {}
+
+TestAutofillAsyncObserver::~TestAutofillAsyncObserver() = default;
+
+void TestAutofillAsyncObserver::OnNotify() {
+ run_loop_.Quit();
+}
+
+void TestAutofillAsyncObserver::Wait() {
+ run_loop_.Run();
+}
+
+} // namespace test
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/test_autofill_async_observer.h b/chromium/components/autofill/core/browser/test_autofill_async_observer.h
new file mode 100644
index 00000000000..17afb414084
--- /dev/null
+++ b/chromium/components/autofill/core/browser/test_autofill_async_observer.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_ASYNC_OBSERVER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_ASYNC_OBSERVER_H_
+
+#include "base/observer_list_types.h"
+#include "base/run_loop.h"
+#include "components/autofill/core/browser/autofill_observer.h"
+
+namespace autofill {
+namespace test {
+
+// Observer which allows to block a thread (wait) until it gets notified with a
+// specific NotificationType. Blocks the thread via a base::RunLoop.
+// This is a very useful mechanism for browsers tests.
+class TestAutofillAsyncObserver : public AutofillObserver {
+ public:
+ // |notification_type| is the notification type that this observer observes.
+ // |detach_on_notify| will let the AutofillSubject know that this
+ // observer only wants to watch for the first notification of that type.
+ TestAutofillAsyncObserver(NotificationType notification_type,
+ bool detach_on_notify = false);
+
+ ~TestAutofillAsyncObserver() override;
+
+ // Invoked by the watched AutofillSubject, this will effectively quit the
+ // current run loop.
+ void OnNotify() override;
+
+ // Blocks the thread until the expected notification occurs.
+ void Wait();
+
+ private:
+ base::RunLoop run_loop_;
+};
+
+} // namespace test
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_ASYNC_OBSERVER_H_
diff --git a/chromium/components/autofill/core/browser/test_autofill_client.cc b/chromium/components/autofill/core/browser/test_autofill_client.cc
index acf9c148bf2..b26056019a3 100644
--- a/chromium/components/autofill/core/browser/test_autofill_client.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_client.cc
@@ -21,8 +21,9 @@ PersonalDataManager* TestAutofillClient::GetPersonalDataManager() {
return &test_personal_data_manager_;
}
-scoped_refptr<AutofillWebDataService> TestAutofillClient::GetDatabase() {
- return scoped_refptr<AutofillWebDataService>(nullptr);
+AutocompleteHistoryManager*
+TestAutofillClient::GetAutocompleteHistoryManager() {
+ return &mock_autocomplete_history_manager_;
}
PrefService* TestAutofillClient::GetPrefs() {
@@ -49,6 +50,10 @@ LegacyStrikeDatabase* TestAutofillClient::GetLegacyStrikeDatabase() {
return test_legacy_strike_database_.get();
}
+StrikeDatabase* TestAutofillClient::GetStrikeDatabase() {
+ return test_strike_database_.get();
+}
+
ukm::UkmRecorder* TestAutofillClient::GetUkmRecorder() {
return ukm::UkmRecorder::Get();
}
@@ -61,10 +66,6 @@ ukm::SourceId TestAutofillClient::GetUkmSourceId() {
return source_id_;
}
-void TestAutofillClient::InitializeUKMSources() {
- UpdateSourceURL(GetUkmRecorder(), source_id_, form_origin_);
-}
-
AddressNormalizer* TestAutofillClient::GetAddressNormalizer() {
return &test_address_normalizer_;
}
@@ -92,6 +93,7 @@ void TestAutofillClient::ShowLocalCardMigrationDialog(
void TestAutofillClient::ConfirmMigrateLocalCardToCloud(
std::unique_ptr<base::DictionaryValue> legal_message,
+ const std::string& user_email,
const std::vector<MigratableCreditCard>& migratable_credit_cards,
LocalCardMigrationCallback start_migrating_cards_callback) {
// If |migration_card_selection_| hasn't been preset by tests, default to
@@ -120,10 +122,10 @@ void TestAutofillClient::ConfirmSaveAutofillProfile(
void TestAutofillClient::ConfirmSaveCreditCardLocally(
const CreditCard& card,
bool show_prompt,
- base::OnceClosure callback) {
+ LocalSaveCardPromptCallback callback) {
confirm_save_credit_card_locally_called_ = true;
offer_to_save_credit_card_bubble_was_shown_ = show_prompt;
- std::move(callback).Run();
+ std::move(callback).Run(AutofillClient::ACCEPTED);
}
#if defined(OS_ANDROID)
@@ -140,9 +142,9 @@ void TestAutofillClient::ConfirmSaveCreditCardToCloud(
bool should_request_name_from_user,
bool should_request_expiration_date_from_user,
bool show_prompt,
- UserAcceptedUploadCallback callback) {
+ UploadSaveCardPromptCallback callback) {
offer_to_save_credit_card_bubble_was_shown_ = show_prompt;
- std::move(callback).Run({});
+ std::move(callback).Run(AutofillClient::ACCEPTED, {});
}
void TestAutofillClient::ConfirmCreditCardFillAssist(
@@ -151,11 +153,6 @@ void TestAutofillClient::ConfirmCreditCardFillAssist(
std::move(callback).Run();
}
-void TestAutofillClient::LoadRiskData(
- base::OnceCallback<void(const std::string&)> callback) {
- std::move(callback).Run("some risk data");
-}
-
bool TestAutofillClient::HasCreditCardScanFeature() {
return false;
}
@@ -193,8 +190,6 @@ void TestAutofillClient::DidFillOrPreviewField(
const base::string16& profile_full_name) {
}
-void TestAutofillClient::DidInteractWithNonsecureCreditCardInput() {}
-
bool TestAutofillClient::IsContextSecure() {
// Simplified secure context check for tests.
return form_origin_.SchemeIs("https");
@@ -204,12 +199,21 @@ bool TestAutofillClient::ShouldShowSigninPromo() {
return false;
}
-void TestAutofillClient::ExecuteCommand(int id) {}
-
bool TestAutofillClient::AreServerCardsSupported() {
return true;
}
+void TestAutofillClient::ExecuteCommand(int id) {}
+
+void TestAutofillClient::LoadRiskData(
+ base::OnceCallback<void(const std::string&)> callback) {
+ std::move(callback).Run("some risk data");
+}
+
+void TestAutofillClient::InitializeUKMSources() {
+ UpdateSourceURL(GetUkmRecorder(), source_id_, form_origin_);
+}
+
void TestAutofillClient::set_form_origin(const GURL& url) {
form_origin_ = url;
// Also reset source_id_.
diff --git a/chromium/components/autofill/core/browser/test_autofill_client.h b/chromium/components/autofill/core/browser/test_autofill_client.h
index 656a2732e1b..c2237b15534 100644
--- a/chromium/components/autofill/core/browser/test_autofill_client.h
+++ b/chromium/components/autofill/core/browser/test_autofill_client.h
@@ -15,11 +15,13 @@
#include "base/macros.h"
#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/test_payments_client.h"
#include "components/autofill/core/browser/test_address_normalizer.h"
#include "components/autofill/core/browser/test_form_data_importer.h"
#include "components/autofill/core/browser/test_legacy_strike_database.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
+#include "components/autofill/core/browser/test_strike_database.h"
#include "components/prefs/pref_service.h"
#include "components/ukm/test_ukm_recorder.h"
#include "services/identity/public/cpp/identity_test_environment.h"
@@ -32,15 +34,16 @@ class TestAutofillClient : public AutofillClient {
TestAutofillClient();
~TestAutofillClient() override;
- // AutofillClient implementation.
+ // AutofillClient:
PersonalDataManager* GetPersonalDataManager() override;
- scoped_refptr<AutofillWebDataService> GetDatabase() override;
+ AutocompleteHistoryManager* GetAutocompleteHistoryManager() override;
PrefService* GetPrefs() override;
syncer::SyncService* GetSyncService() override;
identity::IdentityManager* GetIdentityManager() override;
FormDataImporter* GetFormDataImporter() override;
payments::PaymentsClient* GetPaymentsClient() override;
LegacyStrikeDatabase* GetLegacyStrikeDatabase() override;
+ StrikeDatabase* GetStrikeDatabase() override;
ukm::UkmRecorder* GetUkmRecorder() override;
ukm::SourceId GetUkmSourceId() override;
AddressNormalizer* GetAddressNormalizer() override;
@@ -54,6 +57,7 @@ class TestAutofillClient : public AutofillClient {
base::OnceClosure show_migration_dialog_closure) override;
void ConfirmMigrateLocalCardToCloud(
std::unique_ptr<base::DictionaryValue> legal_message,
+ const std::string& user_email,
const std::vector<MigratableCreditCard>& migratable_credit_cards,
LocalCardMigrationCallback start_migrating_cards_callback) override;
void ShowLocalCardMigrationResults(
@@ -63,25 +67,23 @@ class TestAutofillClient : public AutofillClient {
MigrationDeleteCardCallback delete_local_card_callback) override;
void ConfirmSaveAutofillProfile(const AutofillProfile& profile,
base::OnceClosure callback) override;
- void ConfirmSaveCreditCardLocally(const CreditCard& card,
- bool show_prompt,
- base::OnceClosure callback) override;
+ void ConfirmSaveCreditCardLocally(
+ const CreditCard& card,
+ bool show_prompt,
+ LocalSaveCardPromptCallback callback) override;
#if defined(OS_ANDROID)
void ConfirmAccountNameFixFlow(
base::OnceCallback<void(const base::string16&)> callback) override;
#endif // defined(OS_ANDROID)
-
void ConfirmSaveCreditCardToCloud(
const CreditCard& card,
std::unique_ptr<base::DictionaryValue> legal_message,
bool should_request_name_from_user,
bool should_request_expiration_date_from_user,
bool show_prompt,
- UserAcceptedUploadCallback callback) override;
+ UploadSaveCardPromptCallback callback) override;
void ConfirmCreditCardFillAssist(const CreditCard& card,
base::OnceClosure callback) override;
- void LoadRiskData(
- base::OnceCallback<void(const std::string&)> callback) override;
bool HasCreditCardScanFeature() override;
void ScanCreditCard(const CreditCardScanCallback& callback) override;
void ShowAutofillPopup(
@@ -100,7 +102,6 @@ class TestAutofillClient : public AutofillClient {
const std::vector<autofill::FormStructure*>& forms) override;
void DidFillOrPreviewField(const base::string16& autofilled_value,
const base::string16& profile_full_name) override;
- void DidInteractWithNonsecureCreditCardInput() override;
// By default, TestAutofillClient will report that the context is
// secure. This can be adjusted by calling set_form_origin() with an
// http:// URL.
@@ -108,6 +109,11 @@ class TestAutofillClient : public AutofillClient {
bool ShouldShowSigninPromo() override;
bool AreServerCardsSupported() override;
void ExecuteCommand(int id) override;
+
+ // RiskDataLoader:
+ void LoadRiskData(
+ base::OnceCallback<void(const std::string&)> callback) override;
+
// Initializes UKM source from form_origin_. This needs to be called
// in unittests after calling Purge for ukm recorder to re-initialize
// sources.
@@ -117,9 +123,14 @@ class TestAutofillClient : public AutofillClient {
prefs_ = std::move(prefs);
}
+ void set_test_legacy_strike_database(
+ std::unique_ptr<TestLegacyStrikeDatabase> test_legacy_strike_database) {
+ test_legacy_strike_database_ = std::move(test_legacy_strike_database);
+ }
+
void set_test_strike_database(
- std::unique_ptr<TestLegacyStrikeDatabase> test_strike_database) {
- test_legacy_strike_database_ = std::move(test_strike_database);
+ std::unique_ptr<TestStrikeDatabase> test_strike_database) {
+ test_strike_database_ = std::move(test_strike_database);
}
void set_test_payments_client(
@@ -150,6 +161,10 @@ class TestAutofillClient : public AutofillClient {
return offer_to_save_credit_card_bubble_was_shown_.value();
}
+ MockAutocompleteHistoryManager* GetMockAutocompleteHistoryManager() {
+ return &mock_autocomplete_history_manager_;
+ }
+
void set_migration_card_selections(
const std::vector<std::string>& migration_card_selection) {
migration_card_selection_ = migration_card_selection;
@@ -166,10 +181,12 @@ class TestAutofillClient : public AutofillClient {
syncer::SyncService* test_sync_service_ = nullptr;
TestAddressNormalizer test_address_normalizer_;
TestPersonalDataManager test_personal_data_manager_;
+ MockAutocompleteHistoryManager mock_autocomplete_history_manager_;
// NULL by default.
std::unique_ptr<PrefService> prefs_;
std::unique_ptr<TestLegacyStrikeDatabase> test_legacy_strike_database_;
+ std::unique_ptr<TestStrikeDatabase> test_strike_database_;
std::unique_ptr<payments::PaymentsClient> payments_client_;
std::unique_ptr<FormDataImporter> form_data_importer_;
GURL form_origin_;
diff --git a/chromium/components/autofill/core/browser/test_autofill_driver.cc b/chromium/components/autofill/core/browser/test_autofill_driver.cc
index 4ffa86aed6f..23e869b9916 100644
--- a/chromium/components/autofill/core/browser/test_autofill_driver.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_driver.cc
@@ -78,18 +78,6 @@ gfx::RectF TestAutofillDriver::TransformBoundingBoxToViewportCoordinates(
return bounding_box;
}
-void TestAutofillDriver::DidInteractWithCreditCardForm() {
- did_interact_with_credit_card_form_ = true;
-}
-
-void TestAutofillDriver::ClearDidInteractWithCreditCardForm() {
- did_interact_with_credit_card_form_ = false;
-}
-
-bool TestAutofillDriver::GetDidInteractWithCreditCardForm() const {
- return did_interact_with_credit_card_form_;
-}
-
void TestAutofillDriver::SetIsIncognito(bool is_incognito) {
is_incognito_ = is_incognito;
}
diff --git a/chromium/components/autofill/core/browser/test_autofill_driver.h b/chromium/components/autofill/core/browser/test_autofill_driver.h
index dd742de0c38..e04c11db813 100644
--- a/chromium/components/autofill/core/browser/test_autofill_driver.h
+++ b/chromium/components/autofill/core/browser/test_autofill_driver.h
@@ -44,15 +44,10 @@ class TestAutofillDriver : public AutofillDriver {
void PopupHidden() override;
gfx::RectF TransformBoundingBoxToViewportCoordinates(
const gfx::RectF& bounding_box) override;
- void DidInteractWithCreditCardForm() override;
// Methods unique to TestAutofillDriver that tests can use to specialize
// functionality.
- void ClearDidInteractWithCreditCardForm();
-
- bool GetDidInteractWithCreditCardForm() const;
-
void SetIsIncognito(bool is_incognito);
void SetIsInMainFrame(bool is_in_main_frame);
@@ -68,7 +63,6 @@ class TestAutofillDriver : public AutofillDriver {
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
bool is_incognito_ = false;
bool is_in_main_frame_ = false;
- bool did_interact_with_credit_card_form_ = false;
DISALLOW_COPY_AND_ASSIGN(TestAutofillDriver);
};
diff --git a/chromium/components/autofill/core/browser/test_autofill_manager.cc b/chromium/components/autofill/core/browser/test_autofill_manager.cc
index 8898d9326bf..a398f1f92e7 100644
--- a/chromium/components/autofill/core/browser/test_autofill_manager.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_manager.cc
@@ -7,6 +7,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/mock_autocomplete_history_manager.h"
#include "components/autofill/core/browser/test_form_structure.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -14,10 +15,15 @@
namespace autofill {
-TestAutofillManager::TestAutofillManager(AutofillDriver* driver,
- AutofillClient* client,
- TestPersonalDataManager* personal_data)
- : AutofillManager(driver, client, personal_data),
+TestAutofillManager::TestAutofillManager(
+ AutofillDriver* driver,
+ AutofillClient* client,
+ TestPersonalDataManager* personal_data,
+ MockAutocompleteHistoryManager* autocomplete_history_manager)
+ : AutofillManager(driver,
+ client,
+ personal_data,
+ autocomplete_history_manager),
personal_data_(personal_data) {}
TestAutofillManager::~TestAutofillManager() {}
@@ -44,11 +50,10 @@ void TestAutofillManager::UploadFormData(const FormStructure& submitted_form,
bool TestAutofillManager::MaybeStartVoteUploadProcess(
std::unique_ptr<FormStructure> form_structure,
- const base::TimeTicks& timestamp,
bool observed_submission) {
run_loop_ = std::make_unique<base::RunLoop>();
- if (AutofillManager::MaybeStartVoteUploadProcess(
- std::move(form_structure), timestamp, observed_submission)) {
+ if (AutofillManager::MaybeStartVoteUploadProcess(std::move(form_structure),
+ observed_submission)) {
run_loop_->Run();
return true;
}
diff --git a/chromium/components/autofill/core/browser/test_autofill_manager.h b/chromium/components/autofill/core/browser/test_autofill_manager.h
index 64e00d905bc..edd6ad02f0e 100644
--- a/chromium/components/autofill/core/browser/test_autofill_manager.h
+++ b/chromium/components/autofill/core/browser/test_autofill_manager.h
@@ -22,12 +22,15 @@ class AutofillClient;
class AutofillDriver;
class FormStructure;
class TestPersonalDataManager;
+class MockAutocompleteHistoryManager;
class TestAutofillManager : public AutofillManager {
public:
- TestAutofillManager(AutofillDriver* driver,
- AutofillClient* client,
- TestPersonalDataManager* personal_data);
+ TestAutofillManager(
+ AutofillDriver* driver,
+ AutofillClient* client,
+ TestPersonalDataManager* personal_data,
+ MockAutocompleteHistoryManager* autocomplete_history_manager);
~TestAutofillManager() override;
// AutofillManager overrides.
@@ -38,7 +41,6 @@ class TestAutofillManager : public AutofillManager {
bool observed_submission) override;
bool MaybeStartVoteUploadProcess(
std::unique_ptr<FormStructure> form_structure,
- const base::TimeTicks& timestamp,
bool observed_submission) override;
void UploadFormDataAsyncCallback(const FormStructure* submitted_form,
const base::TimeTicks& interaction_time,
diff --git a/chromium/components/autofill/core/browser/test_autofill_provider.h b/chromium/components/autofill/core/browser/test_autofill_provider.h
index a9e620793c3..8c69b47e99e 100644
--- a/chromium/components/autofill/core/browser/test_autofill_provider.h
+++ b/chromium/components/autofill/core/browser/test_autofill_provider.h
@@ -36,8 +36,7 @@ class TestAutofillProvider : public AutofillProvider {
void OnFormSubmitted(AutofillHandlerProxy* handler,
const FormData& form,
bool known_success,
- SubmissionSource source,
- base::TimeTicks timestamp) override {}
+ SubmissionSource source) override {}
void OnFocusNoLongerOnForm(AutofillHandlerProxy* handler) override;
void OnFocusOnFormField(AutofillHandlerProxy* handler,
const FormData& form,
diff --git a/chromium/components/autofill/core/browser/test_credit_card_save_manager.cc b/chromium/components/autofill/core/browser/test_credit_card_save_manager.cc
index ab8a64099d2..21007fe0eb0 100644
--- a/chromium/components/autofill/core/browser/test_credit_card_save_manager.cc
+++ b/chromium/components/autofill/core/browser/test_credit_card_save_manager.cc
@@ -33,6 +33,15 @@ bool TestCreditCardSaveManager::CreditCardWasUploaded() {
return credit_card_was_uploaded_;
}
+void TestCreditCardSaveManager::set_show_save_prompt(bool show_save_prompt) {
+ show_save_prompt_ = show_save_prompt;
+}
+
+void TestCreditCardSaveManager::set_upload_request_card_number(
+ const base::string16& credit_card_number) {
+ upload_request_.card.SetNumber(credit_card_number);
+}
+
void TestCreditCardSaveManager::OnDidUploadCard(
AutofillClient::PaymentsRpcResult result,
const std::string& server_id) {
diff --git a/chromium/components/autofill/core/browser/test_credit_card_save_manager.h b/chromium/components/autofill/core/browser/test_credit_card_save_manager.h
index cc157fc47fa..c01c302f7b8 100644
--- a/chromium/components/autofill/core/browser/test_credit_card_save_manager.h
+++ b/chromium/components/autofill/core/browser/test_credit_card_save_manager.h
@@ -34,6 +34,10 @@ class TestCreditCardSaveManager : public CreditCardSaveManager {
// Returns whether OnDidUploadCard() was called.
bool CreditCardWasUploaded();
+ void set_show_save_prompt(bool show_save_prompt);
+
+ void set_upload_request_card_number(const base::string16& credit_card_number);
+
private:
void OnDidUploadCard(AutofillClient::PaymentsRpcResult result,
const std::string& server_id) override;
@@ -41,6 +45,12 @@ class TestCreditCardSaveManager : public CreditCardSaveManager {
bool credit_card_upload_enabled_ = false;
bool credit_card_was_uploaded_ = false;
+ FRIEND_TEST_ALL_PREFIXES(
+ CreditCardSaveManagerTest,
+ UploadCreditCard_NumLegacyStrikesLoggedOnUploadNotSuccess);
+ FRIEND_TEST_ALL_PREFIXES(CreditCardSaveManagerTest,
+ UploadCreditCard_NumStrikesLoggedOnUploadNotSuccess);
+
DISALLOW_COPY_AND_ASSIGN(TestCreditCardSaveManager);
};
diff --git a/chromium/components/autofill/core/browser/test_credit_card_save_strike_database.cc b/chromium/components/autofill/core/browser/test_credit_card_save_strike_database.cc
index da24bb69ed9..ebeb05ae93c 100644
--- a/chromium/components/autofill/core/browser/test_credit_card_save_strike_database.cc
+++ b/chromium/components/autofill/core/browser/test_credit_card_save_strike_database.cc
@@ -7,9 +7,7 @@
namespace autofill {
TestCreditCardSaveStrikeDatabase::TestCreditCardSaveStrikeDatabase(
- const base::FilePath& database_dir)
- : CreditCardSaveStrikeDatabase(database_dir) {
- database_initialized_ = true;
-}
+ StrikeDatabase* strike_database)
+ : CreditCardSaveStrikeDatabase(strike_database) {}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/test_credit_card_save_strike_database.h b/chromium/components/autofill/core/browser/test_credit_card_save_strike_database.h
index 21c33a52404..070337c3510 100644
--- a/chromium/components/autofill/core/browser/test_credit_card_save_strike_database.h
+++ b/chromium/components/autofill/core/browser/test_credit_card_save_strike_database.h
@@ -11,7 +11,7 @@ namespace autofill {
class TestCreditCardSaveStrikeDatabase : public CreditCardSaveStrikeDatabase {
public:
- TestCreditCardSaveStrikeDatabase(const base::FilePath& database_dir);
+ TestCreditCardSaveStrikeDatabase(StrikeDatabase* strike_database);
};
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/test_data_creator.cc b/chromium/components/autofill/core/browser/test_data_creator.cc
new file mode 100644
index 00000000000..5ef889268d5
--- /dev/null
+++ b/chromium/components/autofill/core/browser/test_data_creator.cc
@@ -0,0 +1,204 @@
+// 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/test_data_creator.h"
+
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/common/autofill_clock.h"
+#include "components/autofill/core/common/autofill_features.h"
+
+namespace autofill {
+
+namespace {
+// Time delta to create test data.
+base::TimeDelta DeletableUseDateDelta(
+ const base::TimeDelta& cc_deletion_delta) {
+ static base::TimeDelta delta =
+ cc_deletion_delta + base::TimeDelta::FromDays(5);
+ return delta;
+}
+base::TimeDelta DeletableExpiryDateDelta(
+ const base::TimeDelta& cc_deletion_delta) {
+ static base::TimeDelta delta =
+ cc_deletion_delta + base::TimeDelta::FromDays(45);
+ return delta;
+}
+} // namespace
+
+TestDataCreator::TestDataCreator(base::TimeDelta cc_deletion_delta,
+ std::string app_locale)
+ : cc_deletion_delta_(cc_deletion_delta), app_locale_(app_locale) {}
+
+void TestDataCreator::MaybeAddTestProfiles(
+ const base::RepeatingCallback<void(const AutofillProfile&)>&
+ add_profile_callback) {
+ if (has_created_test_addresses_ ||
+ !base::FeatureList::IsEnabled(features::kAutofillCreateDataForTest))
+ return;
+
+ has_created_test_addresses_ = true;
+
+ for (const auto& profile : GetTestProfiles()) {
+ add_profile_callback.Run(profile);
+ }
+
+ DLOG(WARNING) << this << " added fake autofill profiles.";
+}
+
+void TestDataCreator::MaybeAddTestCreditCards(
+ const base::RepeatingCallback<void(const CreditCard&)>& add_cc_callback) {
+ if (has_created_test_credit_cards_ ||
+ !base::FeatureList::IsEnabled(features::kAutofillCreateDataForTest))
+ return;
+
+ has_created_test_credit_cards_ = true;
+
+ for (const auto& credit_card : GetTestCreditCards()) {
+ add_cc_callback.Run(credit_card);
+ }
+
+ DLOG(WARNING) << this << " added fake credit cards.";
+}
+
+std::vector<AutofillProfile> TestDataCreator::GetTestProfiles() {
+ return {CreateBasicTestAddress(), CreateDisusedTestAddress(),
+ CreateDisusedDeletableTestAddress()};
+}
+
+std::vector<CreditCard> TestDataCreator::GetTestCreditCards() {
+ return {CreateBasicTestCreditCard(), CreateDisusedTestCreditCard(),
+ CreateDisusedDeletableTestCreditCard()};
+}
+
+AutofillProfile TestDataCreator::CreateBasicTestAddress() {
+ const base::Time use_date =
+ AutofillClock::Now() - base::TimeDelta::FromDays(20);
+ AutofillProfile profile;
+ profile.SetInfo(NAME_FULL, base::UTF8ToUTF16("John McTester"), app_locale_);
+ profile.SetInfo(COMPANY_NAME, base::UTF8ToUTF16("Test Inc."), app_locale_);
+ profile.SetInfo(EMAIL_ADDRESS,
+ base::UTF8ToUTF16("jmctester@fake.chromium.org"),
+ app_locale_);
+ profile.SetInfo(ADDRESS_HOME_LINE1, base::UTF8ToUTF16("123 Invented Street"),
+ app_locale_);
+ profile.SetInfo(ADDRESS_HOME_LINE2, base::UTF8ToUTF16("Suite A"),
+ app_locale_);
+ profile.SetInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16("Mountain View"),
+ app_locale_);
+ profile.SetInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("California"),
+ app_locale_);
+ profile.SetInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("94043"), app_locale_);
+ profile.SetInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16("US"), app_locale_);
+ profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16("844-555-0173"),
+ app_locale_);
+ profile.set_use_date(use_date);
+ return profile;
+}
+
+AutofillProfile TestDataCreator::CreateDisusedTestAddress() {
+ const base::Time use_date =
+ AutofillClock::Now() - base::TimeDelta::FromDays(185);
+ AutofillProfile profile;
+ profile.SetInfo(NAME_FULL, base::UTF8ToUTF16("Polly Disused"), app_locale_);
+ profile.SetInfo(COMPANY_NAME,
+ base::UTF8ToUTF16(base::StringPrintf(
+ "%lld Inc.", static_cast<long long>(use_date.ToTimeT()))),
+ app_locale_);
+ profile.SetInfo(EMAIL_ADDRESS,
+ base::UTF8ToUTF16("polly.disused@fake.chromium.org"),
+ app_locale_);
+ profile.SetInfo(ADDRESS_HOME_LINE1, base::UTF8ToUTF16("456 Disused Lane"),
+ app_locale_);
+ profile.SetInfo(ADDRESS_HOME_LINE2, base::UTF8ToUTF16("Apt. B"), app_locale_);
+ profile.SetInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16("Austin"), app_locale_);
+ profile.SetInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Texas"), app_locale_);
+ profile.SetInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("73301"), app_locale_);
+ profile.SetInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16("US"), app_locale_);
+ profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16("844-555-0174"),
+ app_locale_);
+ profile.set_use_date(use_date);
+ return profile;
+}
+
+AutofillProfile TestDataCreator::CreateDisusedDeletableTestAddress() {
+ const base::Time use_date =
+ AutofillClock::Now() - base::TimeDelta::FromDays(400);
+ AutofillProfile profile;
+ profile.SetInfo(NAME_FULL, base::UTF8ToUTF16("Polly Deletable"), app_locale_);
+ profile.SetInfo(COMPANY_NAME,
+ base::UTF8ToUTF16(base::StringPrintf(
+ "%lld Inc.", static_cast<long long>(use_date.ToTimeT()))),
+ app_locale_);
+ profile.SetInfo(EMAIL_ADDRESS,
+ base::UTF8ToUTF16("polly.deletable@fake.chromium.org"),
+ app_locale_);
+ profile.SetInfo(ADDRESS_HOME_LINE1, base::UTF8ToUTF16("459 Deletable Lane"),
+ app_locale_);
+ profile.SetInfo(ADDRESS_HOME_LINE2, base::UTF8ToUTF16("Apt. B"), app_locale_);
+ profile.SetInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16("Austin"), app_locale_);
+ profile.SetInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Texas"), app_locale_);
+ profile.SetInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("73301"), app_locale_);
+ profile.SetInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16("US"), app_locale_);
+ profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16("844-555-0274"),
+ app_locale_);
+ profile.set_use_date(use_date);
+ return profile;
+}
+
+// Create a card expiring 500 days from now which was last used 10 days ago.
+CreditCard TestDataCreator::CreateBasicTestCreditCard() {
+ const base::Time now = AutofillClock::Now();
+ const base::Time use_date = now - base::TimeDelta::FromDays(10);
+ base::Time::Exploded expiry_date;
+ (now + base::TimeDelta::FromDays(500)).LocalExplode(&expiry_date);
+
+ CreditCard credit_card;
+ credit_card.SetInfo(CREDIT_CARD_NAME_FULL,
+ base::UTF8ToUTF16("Alice Testerson"), app_locale_);
+ credit_card.SetInfo(CREDIT_CARD_NUMBER, base::UTF8ToUTF16("4545454545454545"),
+ app_locale_);
+ credit_card.SetExpirationMonth(expiry_date.month);
+ credit_card.SetExpirationYear(expiry_date.year);
+ credit_card.set_use_date(use_date);
+ return credit_card;
+}
+
+CreditCard TestDataCreator::CreateDisusedTestCreditCard() {
+ const base::Time now = AutofillClock::Now();
+ const base::Time use_date = now - base::TimeDelta::FromDays(185);
+ base::Time::Exploded expiry_date;
+ (now - base::TimeDelta::FromDays(200)).LocalExplode(&expiry_date);
+
+ CreditCard credit_card;
+ credit_card.SetInfo(CREDIT_CARD_NAME_FULL, base::UTF8ToUTF16("Bob Disused"),
+ app_locale_);
+ credit_card.SetInfo(CREDIT_CARD_NUMBER, base::UTF8ToUTF16("4111111111111111"),
+ app_locale_);
+ credit_card.SetExpirationMonth(expiry_date.month);
+ credit_card.SetExpirationYear(expiry_date.year);
+ credit_card.set_use_date(use_date);
+ return credit_card;
+}
+
+CreditCard TestDataCreator::CreateDisusedDeletableTestCreditCard() {
+ const base::Time now = AutofillClock::Now();
+ const base::Time use_date = now - DeletableUseDateDelta(cc_deletion_delta_);
+ base::Time::Exploded expiry_date;
+ (now - DeletableExpiryDateDelta(cc_deletion_delta_))
+ .LocalExplode(&expiry_date);
+
+ CreditCard credit_card;
+ credit_card.SetInfo(CREDIT_CARD_NAME_FULL,
+ base::UTF8ToUTF16("Charlie Deletable"), app_locale_);
+ credit_card.SetInfo(CREDIT_CARD_NUMBER, base::UTF8ToUTF16("378282246310005"),
+ app_locale_);
+ credit_card.SetExpirationMonth(expiry_date.month);
+ credit_card.SetExpirationYear(expiry_date.year);
+ credit_card.set_use_date(use_date);
+ return credit_card;
+}
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/test_data_creator.h b/chromium/components/autofill/core/browser/test_data_creator.h
new file mode 100644
index 00000000000..5a34c163b56
--- /dev/null
+++ b/chromium/components/autofill/core/browser/test_data_creator.h
@@ -0,0 +1,52 @@
+// 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_TEST_DATA_CREATOR_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_DATA_CREATOR_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.h"
+
+namespace autofill {
+
+class TestDataCreator {
+ public:
+ TestDataCreator(base::TimeDelta cc_deletion_delta, std::string app_locale);
+
+ void MaybeAddTestProfiles(
+ const base::RepeatingCallback<void(const AutofillProfile&)>&
+ add_profile_callback);
+ void MaybeAddTestCreditCards(
+ const base::RepeatingCallback<void(const CreditCard&)>& add_cc_callback);
+
+ private:
+ std::vector<AutofillProfile> GetTestProfiles();
+ std::vector<CreditCard> GetTestCreditCards();
+
+ AutofillProfile CreateBasicTestAddress();
+ AutofillProfile CreateDisusedTestAddress();
+ AutofillProfile CreateDisusedDeletableTestAddress();
+
+ CreditCard CreateBasicTestCreditCard();
+ CreditCard CreateDisusedTestCreditCard();
+ CreditCard CreateDisusedDeletableTestCreditCard();
+
+ // Minimum amount of time since last use for a credit card to be considered
+ // "disused".
+ base::TimeDelta cc_deletion_delta_;
+
+ std::string app_locale_;
+
+ // True if test data has been created this session.
+ bool has_created_test_addresses_ = false;
+ bool has_created_test_credit_cards_ = false;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_DATA_CREATOR_H_ \ No newline at end of file
diff --git a/chromium/components/autofill/core/browser/test_local_card_migration_manager.cc b/chromium/components/autofill/core/browser/test_local_card_migration_manager.cc
index ef295c9693d..cc72aed5cf6 100644
--- a/chromium/components/autofill/core/browser/test_local_card_migration_manager.cc
+++ b/chromium/components/autofill/core/browser/test_local_card_migration_manager.cc
@@ -62,7 +62,7 @@ void TestLocalCardMigrationManager::OnDidGetUploadDetails(
bool is_from_settings_page,
AutofillClient::PaymentsRpcResult result,
const base::string16& context_token,
- std::unique_ptr<base::DictionaryValue> legal_message) {
+ std::unique_ptr<base::Value> legal_message) {
if (result == AutofillClient::SUCCESS) {
local_card_migration_was_triggered_ = true;
LocalCardMigrationManager::OnDidGetUploadDetails(
diff --git a/chromium/components/autofill/core/browser/test_local_card_migration_manager.h b/chromium/components/autofill/core/browser/test_local_card_migration_manager.h
index 7daa8c6b388..97e4518eb15 100644
--- a/chromium/components/autofill/core/browser/test_local_card_migration_manager.h
+++ b/chromium/components/autofill/core/browser/test_local_card_migration_manager.h
@@ -55,7 +55,7 @@ class TestLocalCardMigrationManager : public LocalCardMigrationManager {
bool is_from_settings_page,
AutofillClient::PaymentsRpcResult result,
const base::string16& context_token,
- std::unique_ptr<base::DictionaryValue> legal_message) override;
+ std::unique_ptr<base::Value> legal_message) override;
bool local_card_migration_was_triggered_ = false;
diff --git a/chromium/components/autofill/core/browser/test_local_card_migration_strike_database.cc b/chromium/components/autofill/core/browser/test_local_card_migration_strike_database.cc
new file mode 100644
index 00000000000..cc212712538
--- /dev/null
+++ b/chromium/components/autofill/core/browser/test_local_card_migration_strike_database.cc
@@ -0,0 +1,13 @@
+// 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_local_card_migration_strike_database.h"
+
+namespace autofill {
+
+TestLocalCardMigrationStrikeDatabase::TestLocalCardMigrationStrikeDatabase(
+ StrikeDatabase* strike_database)
+ : LocalCardMigrationStrikeDatabase(strike_database) {}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/test_local_card_migration_strike_database.h b/chromium/components/autofill/core/browser/test_local_card_migration_strike_database.h
new file mode 100644
index 00000000000..c1cac181ceb
--- /dev/null
+++ b/chromium/components/autofill/core/browser/test_local_card_migration_strike_database.h
@@ -0,0 +1,20 @@
+// 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_LOCAL_CARD_MIGRATION_STRIKE_DATABASE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_LOCAL_CARD_MIGRATION_STRIKE_DATABASE_H_
+
+#include "components/autofill/core/browser/local_card_migration_strike_database.h"
+
+namespace autofill {
+
+class TestLocalCardMigrationStrikeDatabase
+ : public LocalCardMigrationStrikeDatabase {
+ public:
+ TestLocalCardMigrationStrikeDatabase(StrikeDatabase* strike_database);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_LOCAL_CARD_MIGRATION_STRIKE_DATABASE_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 664b6904b4b..9a6e5c35765 100644
--- a/chromium/components/autofill/core/browser/test_personal_data_manager.cc
+++ b/chromium/components/autofill/core/browser/test_personal_data_manager.cc
@@ -14,6 +14,11 @@ TestPersonalDataManager::TestPersonalDataManager()
TestPersonalDataManager::~TestPersonalDataManager() {}
+void TestPersonalDataManager::OnSyncServiceInitialized(
+ syncer::SyncService* sync_service) {
+ sync_service_initialized_ = true;
+}
+
void TestPersonalDataManager::RecordUseOf(const AutofillDataModel& data_model) {
CreditCard* credit_card = GetCreditCardWithGUID(data_model.guid().c_str());
if (credit_card)
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 86ea84a5c10..ae3a7cdb449 100644
--- a/chromium/components/autofill/core/browser/test_personal_data_manager.h
+++ b/chromium/components/autofill/core/browser/test_personal_data_manager.h
@@ -27,7 +27,7 @@ class TestPersonalDataManager : public PersonalDataManager {
// PersonalDataManager overrides. These functions are overridden as needed
// for various tests, whether to skip calls to uncreated databases/services,
// or to make things easier in general to toggle.
- void OnSyncServiceInitialized(syncer::SyncService* sync_service) override {}
+ void OnSyncServiceInitialized(syncer::SyncService* sync_service) override;
void RecordUseOf(const AutofillDataModel& data_model) override;
std::string SaveImportedProfile(
const AutofillProfile& imported_profile) override;
@@ -90,6 +90,8 @@ class TestPersonalDataManager : public PersonalDataManager {
return num_times_save_imported_credit_card_called_;
}
+ bool sync_service_initialized() const { return sync_service_initialized_; }
+
void SetAutofillEnabled(bool autofill_enabled) {
autofill_enabled_ = autofill_enabled;
}
@@ -127,6 +129,7 @@ class TestPersonalDataManager : public PersonalDataManager {
base::Optional<bool> autofill_credit_card_enabled_;
base::Optional<bool> autofill_wallet_import_enabled_;
bool sync_feature_enabled_ = false;
+ bool sync_service_initialized_ = false;
AccountInfo account_info_;
DISALLOW_COPY_AND_ASSIGN(TestPersonalDataManager);
diff --git a/chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl.cc b/chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl.cc
index 69818085c4a..7a3c321db04 100644
--- a/chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl.cc
+++ b/chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl.cc
@@ -205,7 +205,7 @@ bool CardUnmaskPromptControllerImpl::CanStoreLocally() const {
return false;
if (card_.record_type() == CreditCard::LOCAL_CARD)
return false;
- return OfferStoreUnmaskedCards();
+ return OfferStoreUnmaskedCards(is_off_the_record_);
}
bool CardUnmaskPromptControllerImpl::GetStoreLocallyStartState() const {
diff --git a/chromium/components/autofill/core/browser/ui/local_card_migration_dialog_controller.h b/chromium/components/autofill/core/browser/ui/local_card_migration_dialog_controller.h
index 03e7b7bca96..f2dcc17dd9c 100644
--- a/chromium/components/autofill/core/browser/ui/local_card_migration_dialog_controller.h
+++ b/chromium/components/autofill/core/browser/ui/local_card_migration_dialog_controller.h
@@ -29,6 +29,7 @@ class LocalCardMigrationDialogController {
virtual const std::vector<MigratableCreditCard>& GetCardList() const = 0;
virtual const LegalMessageLines& GetLegalMessageLines() const = 0;
virtual const base::string16& GetTipMessage() const = 0;
+ virtual const std::string& GetUserEmail() const = 0;
virtual void OnSaveButtonClicked(
const std::vector<std::string>& selected_cards_guids) = 0;
virtual void OnCancelButtonClicked() = 0;
diff --git a/chromium/components/autofill/core/browser/validation.cc b/chromium/components/autofill/core/browser/validation.cc
index 299fe00083c..bce4371b0de 100644
--- a/chromium/components/autofill/core/browser/validation.cc
+++ b/chromium/components/autofill/core/browser/validation.cc
@@ -43,6 +43,13 @@ bool IsValidCreditCardExpirationDate(int year,
return true;
}
+bool IsValidCreditCardExpirationYear(int year, const base::Time& now) {
+ base::Time::Exploded now_exploded;
+ now.LocalExplode(&now_exploded);
+
+ return year >= now_exploded.year;
+}
+
bool IsValidCreditCardNumber(const base::string16& text) {
base::string16 number = CreditCard::StripSeparators(text);
diff --git a/chromium/components/autofill/core/browser/validation.h b/chromium/components/autofill/core/browser/validation.h
index 65873edfb4a..5c7dccf1a65 100644
--- a/chromium/components/autofill/core/browser/validation.h
+++ b/chromium/components/autofill/core/browser/validation.h
@@ -40,6 +40,10 @@ bool IsValidCreditCardExpirationDate(int year,
int month,
const base::Time& now);
+// Returns true if |year| describes a year later than or equal to |now|'s year.
+// |year| must have 4 digits.
+bool IsValidCreditCardExpirationYear(int year, const base::Time& now);
+
// Returns true if |text| looks like a valid credit card number.
// Uses the Luhn formula to validate the number.
bool IsValidCreditCardNumber(const base::string16& text);
diff --git a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc
index 664b9e74879..1eebf032d16 100644
--- a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc
@@ -17,6 +17,7 @@
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/common/autofill_features.h"
#include "components/sync/model/entity_data.h"
#include "components/sync/model/model_type_change_processor.h"
#include "components/sync/model/mutable_data_batch.h"
@@ -337,7 +338,14 @@ Optional<syncer::ModelError> AutocompleteSyncBridge::MergeSyncData(
RETURN_IF_ERROR(tracker.FlushToLocal(web_data_backend_));
RETURN_IF_ERROR(tracker.FlushToSync(true, std::move(metadata_change_list),
change_processor()));
- web_data_backend_->RemoveExpiredFormElements();
+
+ // TODO(crbug.com/920214) Deprecated, clean-up as part of the
+ // Autocomplete Retention Policy flag cleanup.
+ if (!base::FeatureList::IsEnabled(
+ autofill::features::kAutocompleteRetentionPolicyEnabled)) {
+ web_data_backend_->RemoveExpiredFormElements();
+ }
+
web_data_backend_->NotifyThatSyncHasStarted(syncer::AUTOFILL);
return {};
}
@@ -361,7 +369,13 @@ Optional<ModelError> AutocompleteSyncBridge::ApplySyncChanges(
RETURN_IF_ERROR(tracker.FlushToLocal(web_data_backend_));
RETURN_IF_ERROR(tracker.FlushToSync(false, std::move(metadata_change_list),
change_processor()));
- web_data_backend_->RemoveExpiredFormElements();
+
+ // TODO(crbug.com/920214) Deprecated, clean-up as part of the
+ // Autocomplete Retention Policy flag cleanup.
+ if (!base::FeatureList::IsEnabled(
+ autofill::features::kAutocompleteRetentionPolicyEnabled)) {
+ web_data_backend_->RemoveExpiredFormElements();
+ }
return {};
}
@@ -438,6 +452,21 @@ void AutocompleteSyncBridge::ActOnLocalChanges(
change_processor()->Delete(storage_key, metadata_change_list.get());
break;
}
+ case AutofillChange::EXPIRE: {
+ // For expired entries, unlink and delete the sync metadata.
+ // That way we are not sending tombstone updates to the sync servers.
+ bool success = GetAutofillTable()->ClearSyncMetadata(syncer::AUTOFILL,
+ storage_key);
+ if (!success) {
+ change_processor()->ReportError(
+ {FROM_HERE,
+ "Failed to clear sync metadata for an expired autofill entry "
+ "from WebDatabase."});
+ return;
+ }
+
+ change_processor()->UntrackEntityForStorageKey(storage_key);
+ }
}
}
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 d5a0700e746..d7dfa2eff27 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
@@ -17,12 +17,14 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#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/autofill/core/common/autofill_features.h"
#include "components/sync/base/hash_util.h"
#include "components/sync/model/data_batch.h"
#include "components/sync/model/data_type_activation_request.h"
@@ -445,6 +447,34 @@ TEST_F(AutocompleteSyncBridgeTest, ApplySyncChangesSimple) {
VerifyAllData({specifics2});
}
+// Tests that the function RemoveExpiredFormElements is called when the
+// Autocomplete Retention Policy feature flag is disabled.
+TEST_F(AutocompleteSyncBridgeTest,
+ ApplySyncChangesSimple_FlagOff_Calls_RemoveExpiredFormElements) {
+ base::test::ScopedFeatureList scoped_features;
+ scoped_features.InitAndDisableFeature(
+ features::kAutocompleteRetentionPolicyEnabled);
+
+ EXPECT_CALL(*backend(), RemoveExpiredFormElements);
+
+ AutofillSpecifics specifics1 = CreateSpecifics(1);
+ ApplyAdds({specifics1});
+}
+
+// Tests that the function RemoveExpiredFormElements is not called when the
+// Autocomplete Retention Policy feature flag is enabled.
+TEST_F(AutocompleteSyncBridgeTest,
+ ApplySyncChangesSimple_FlagOn_Not_Calls_RemoveExpiredFormElements) {
+ base::test::ScopedFeatureList scoped_features;
+ scoped_features.InitAndEnableFeature(
+ features::kAutocompleteRetentionPolicyEnabled);
+
+ EXPECT_CALL(*backend(), RemoveExpiredFormElements).Times(0);
+
+ AutofillSpecifics specifics1 = CreateSpecifics(1);
+ ApplyAdds({specifics1});
+}
+
// Should be resilient to deleting and updating non-existent things, and adding
// existing ones.
TEST_F(AutocompleteSyncBridgeTest, ApplySyncChangesWrongChangeType) {
@@ -592,6 +622,33 @@ TEST_F(AutocompleteSyncBridgeTest, LocalEntryDeleted) {
{AutofillChange(AutofillChange::REMOVE, deleted_entry.key())});
}
+// Tests that AutofillEntry marked with AutofillChange::EXPIRE are unlinked from
+// sync, and their sync metadata is deleted in this client.
+TEST_F(AutocompleteSyncBridgeTest, LocalEntryExpired) {
+ StartSyncing();
+ const AutofillSpecifics expired_specifics = CreateSpecifics(1, {2, 3});
+ const AutofillEntry expired_entry = CreateAutofillEntry(expired_specifics);
+ const std::string storage_key = GetStorageKey(expired_specifics);
+
+ // Let's add the sync metadata
+ ASSERT_TRUE(table()->UpdateSyncMetadata(syncer::AUTOFILL, storage_key,
+ EntityMetadata()));
+
+ // Validate that it was added.
+ syncer::MetadataBatch batch;
+ ASSERT_TRUE(table()->GetAllSyncMetadata(syncer::AUTOFILL, &batch));
+ ASSERT_EQ(1U, batch.TakeAllMetadata().size());
+
+ EXPECT_CALL(mock_processor(), UntrackEntityForStorageKey(storage_key));
+
+ bridge()->AutofillEntriesChanged(
+ {AutofillChange(AutofillChange::EXPIRE, expired_entry.key())});
+
+ // Expect metadata to have been cleaned up.
+ EXPECT_TRUE(table()->GetAllSyncMetadata(syncer::AUTOFILL, &batch));
+ EXPECT_EQ(0U, batch.TakeAllMetadata().size());
+}
+
TEST_F(AutocompleteSyncBridgeTest, LoadMetadataCalled) {
ModelTypeState model_type_state;
model_type_state.set_initial_sync_done(true);
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_change.h b/chromium/components/autofill/core/browser/webdata/autofill_change.h
index 6212c6079c5..16c6290fa60 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_change.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_change.h
@@ -9,11 +9,11 @@
#include <vector>
#include "base/logging.h"
+#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/webdata/autofill_entry.h"
namespace autofill {
-class AutofillProfile;
class CreditCard;
// For classic Autofill form fields, the KeyType is AutofillKey.
@@ -21,11 +21,7 @@ class CreditCard;
template <typename KeyType>
class GenericAutofillChange {
public:
- enum Type {
- ADD,
- UPDATE,
- REMOVE
- };
+ enum Type { ADD, UPDATE, REMOVE, EXPIRE };
virtual ~GenericAutofillChange() {}
@@ -56,8 +52,9 @@ typedef std::vector<AutofillChange> AutofillChangeList;
template <typename DataType>
class AutofillDataModelChange : public GenericAutofillChange<std::string> {
public:
- // The |type| input specifies the change type. The |key| input is the key,
- // which is expected to be the GUID identifying the |data_model|.
+ // The |type| input specifies the change type. The |key| input is the key
+ // that identifies the |data_model|; it is the GUID of the entry for local
+ // data and server_id of the entry for server data from GPay.
// When |type| == ADD, |data_model| should be non-NULL.
// When |type| == UPDATE, |data_model| should be non-NULL.
// When |type| == REMOVE, |data_model| should be NULL.
@@ -66,7 +63,8 @@ class AutofillDataModelChange : public GenericAutofillChange<std::string> {
const DataType* data_model)
: GenericAutofillChange<std::string>(type, key), data_model_(data_model) {
DCHECK(type == REMOVE ? !data_model
- : data_model && data_model->guid() == key);
+ : data_model && (data_model->guid() == key ||
+ data_model->server_id() == key));
}
~AutofillDataModelChange() override {}
@@ -86,6 +84,25 @@ class AutofillDataModelChange : public GenericAutofillChange<std::string> {
typedef AutofillDataModelChange<AutofillProfile> AutofillProfileChange;
typedef AutofillDataModelChange<CreditCard> CreditCardChange;
+class AutofillProfileDeepChange : public AutofillProfileChange {
+ public:
+ AutofillProfileDeepChange(Type type, const AutofillProfile& profile)
+ : AutofillProfileChange(type, profile.guid(), &profile),
+ profile_(profile) {}
+
+ AutofillProfileDeepChange(Type type, const std::string& guid)
+ : AutofillProfileChange(type, guid, nullptr), profile_(guid, "") {
+ DCHECK(type == GenericAutofillChange::REMOVE);
+ }
+
+ ~AutofillProfileDeepChange() override {}
+
+ AutofillProfile profile() const { return profile_; }
+
+ private:
+ AutofillProfile profile_;
+};
+
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_CHANGE_H__
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.cc b/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.cc
index 080e6be3b32..f05cd1227fd 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.cc
@@ -25,18 +25,19 @@ namespace browser_sync {
AutofillProfileDataTypeController::AutofillProfileDataTypeController(
scoped_refptr<base::SingleThreadTaskRunner> db_thread,
const base::Closure& dump_stack,
+ syncer::SyncService* sync_service,
syncer::SyncClient* sync_client,
const scoped_refptr<autofill::AutofillWebDataService>& web_data_service)
: AsyncDirectoryTypeController(syncer::AUTOFILL_PROFILE,
dump_stack,
+ sync_service,
sync_client,
syncer::GROUP_DB,
std::move(db_thread)),
- sync_client_(sync_client),
web_data_service_(web_data_service),
callback_registered_(false),
currently_enabled_(IsEnabled()) {
- pref_registrar_.Init(sync_client_->GetPrefService());
+ pref_registrar_.Init(sync_client->GetPrefService());
pref_registrar_.Add(
autofill::prefs::kAutofillProfileEnabled,
base::Bind(&AutofillProfileDataTypeController::OnUserPrefChanged,
@@ -52,7 +53,7 @@ void AutofillProfileDataTypeController::OnPersonalDataChanged() {
DCHECK(CalledOnValidThread());
DCHECK_EQ(state(), MODEL_STARTING);
- sync_client_->GetPersonalDataManager()->RemoveObserver(this);
+ sync_client()->GetPersonalDataManager()->RemoveObserver(this);
if (!web_data_service_)
return;
@@ -78,7 +79,7 @@ bool AutofillProfileDataTypeController::StartModels() {
return false;
}
autofill::PersonalDataManager* personal_data =
- sync_client_->GetPersonalDataManager();
+ sync_client()->GetPersonalDataManager();
// Make sure PDM has the sync service. This is needed because in the account
// wallet data mode, PDM uses the service to determine whether to use the
@@ -88,7 +89,7 @@ bool AutofillProfileDataTypeController::StartModels() {
// one single call in a more general place.
if (base::FeatureList::IsEnabled(
autofill::features::kAutofillEnableAccountWalletStorage)) {
- personal_data->OnSyncServiceInitialized(sync_client_->GetSyncService());
+ personal_data->OnSyncServiceInitialized(sync_service());
}
// Waiting for the personal data is subtle: we do this as the PDM resets
@@ -117,7 +118,7 @@ bool AutofillProfileDataTypeController::StartModels() {
void AutofillProfileDataTypeController::StopModels() {
DCHECK(CalledOnValidThread());
- sync_client_->GetPersonalDataManager()->RemoveObserver(this);
+ sync_client()->GetPersonalDataManager()->RemoveObserver(this);
}
bool AutofillProfileDataTypeController::ReadyForStart() const {
@@ -136,8 +137,7 @@ void AutofillProfileDataTypeController::OnUserPrefChanged() {
if (currently_enabled_) {
// The preference was just enabled. Trigger a reconfiguration. This will do
// nothing if the type isn't preferred.
- syncer::SyncService* sync_service = sync_client_->GetSyncService();
- sync_service->ReenableDatatype(type());
+ sync_service()->ReenableDatatype(type());
} else {
DisableForPolicy();
}
@@ -148,7 +148,7 @@ bool AutofillProfileDataTypeController::IsEnabled() {
// Require the user-visible pref to be enabled to sync Autofill Profile data.
return autofill::prefs::IsProfileAutofillEnabled(
- sync_client_->GetPrefService());
+ sync_client()->GetPrefService());
}
void AutofillProfileDataTypeController::DisableForPolicy() {
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h b/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h
index d981239acbd..b2886eea632 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h
@@ -18,6 +18,11 @@ namespace autofill {
class AutofillWebDataService;
} // namespace autofill
+namespace syncer {
+class SyncClient;
+class SyncService;
+} // namespace syncer
+
namespace browser_sync {
// Controls syncing of the AUTOFILL_PROFILE data type.
@@ -29,6 +34,7 @@ class AutofillProfileDataTypeController
AutofillProfileDataTypeController(
scoped_refptr<base::SingleThreadTaskRunner> db_thread,
const base::Closure& dump_stack,
+ syncer::SyncService* sync_service,
syncer::SyncClient* sync_client,
const scoped_refptr<autofill::AutofillWebDataService>& web_data_service);
~AutofillProfileDataTypeController() override;
@@ -55,9 +61,6 @@ class AutofillProfileDataTypeController
// Report an error (which will stop the datatype asynchronously).
void DisableForPolicy();
- // A pointer to the sync client.
- syncer::SyncClient* const sync_client_;
-
// A reference to the AutofillWebDataService for this controller.
scoped_refptr<autofill::AutofillWebDataService> web_data_service_;
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 db2726ee0bf..8385d72a5fb 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
@@ -9,19 +9,20 @@
#include "base/bind.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/prefs/pref_service.h"
-#include "components/sync/driver/sync_client.h"
#include "components/sync/driver/sync_service.h"
namespace browser_sync {
AutofillProfileModelTypeController::AutofillProfileModelTypeController(
std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk,
- syncer::SyncClient* sync_client)
+ PrefService* pref_service,
+ syncer::SyncService* sync_service)
: ModelTypeController(syncer::AUTOFILL_PROFILE,
std::move(delegate_on_disk)),
- sync_client_(sync_client),
+ pref_service_(pref_service),
+ sync_service_(sync_service),
currently_enabled_(IsEnabled()) {
- pref_registrar_.Init(sync_client_->GetPrefService());
+ pref_registrar_.Init(pref_service_);
pref_registrar_.Add(
autofill::prefs::kAutofillProfileEnabled,
base::BindRepeating(
@@ -45,15 +46,14 @@ void AutofillProfileModelTypeController::OnUserPrefChanged() {
return;
currently_enabled_ = new_enabled;
- sync_client_->GetSyncService()->ReadyForStartChanged(type());
+ sync_service_->ReadyForStartChanged(type());
}
bool AutofillProfileModelTypeController::IsEnabled() {
DCHECK(CalledOnValidThread());
// Require the user-visible pref to be enabled to sync Autofill Profile data.
- return autofill::prefs::IsProfileAutofillEnabled(
- sync_client_->GetPrefService());
+ return autofill::prefs::IsProfileAutofillEnabled(pref_service_);
}
} // namespace browser_sync
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 2a6a4095acd..38aafd7d8d2 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
@@ -11,9 +11,11 @@
#include "components/prefs/pref_change_registrar.h"
#include "components/sync/driver/model_type_controller.h"
+class PrefService;
+
namespace syncer {
class ModelTypeControllerDelegate;
-class SyncClient;
+class SyncService;
} // namespace syncer
namespace browser_sync {
@@ -23,7 +25,8 @@ class AutofillProfileModelTypeController : public syncer::ModelTypeController {
public:
AutofillProfileModelTypeController(
std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk,
- syncer::SyncClient* sync_client);
+ PrefService* pref_service,
+ syncer::SyncService* sync_service);
~AutofillProfileModelTypeController() override;
// DataTypeController overrides.
@@ -36,7 +39,8 @@ class AutofillProfileModelTypeController : public syncer::ModelTypeController {
// Returns true if the pref is set such that autofill sync should be enabled.
bool IsEnabled();
- syncer::SyncClient* const sync_client_;
+ PrefService* const pref_service_;
+ syncer::SyncService* const sync_service_;
// Registrar for listening to prefs::kAutofillProfileEnabled.
PrefChangeRegistrar pref_registrar_;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc
index d5bc7624172..4ee20ea6814 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc
@@ -232,6 +232,10 @@ void AutofillProfileSyncBridge::ActOnLocalChange(
// here.
change_processor()->Delete(change.key(), metadata_change_list.get());
break;
+ case AutofillProfileChange::EXPIRE:
+ // EXPIRE changes are not being issued for profiles.
+ NOTREACHED();
+ break;
}
if (Optional<ModelError> error = metadata_change_list->TakeError()) {
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 ca84bff0f37..552c2dabef6 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
@@ -15,7 +15,7 @@
#include "base/guid.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_task_environment.h"
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc b/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc
index cd6d49216a8..51d3cb7ee83 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc
@@ -76,8 +76,8 @@ void AutofillProfileSyncableService::CreateForWebDataServiceAndBackend(
const std::string& app_locale) {
web_data_service->GetDBUserData()->SetUserData(
AutofillProfileSyncableServiceUserDataKey(),
- base::WrapUnique(
- new AutofillProfileSyncableService(webdata_backend, app_locale)));
+ std::make_unique<AutofillProfileSyncableService>(webdata_backend,
+ app_locale));
}
// static
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h b/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h
index ce6efa43404..079ff91ee41 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h
@@ -50,6 +50,9 @@ class AutofillProfileSyncableService
public syncer::SyncableService,
public AutofillWebDataServiceObserverOnDBSequence {
public:
+ AutofillProfileSyncableService(AutofillWebDataBackend* webdata_backend,
+ const std::string& app_locale);
+
~AutofillProfileSyncableService() override;
// Creates a new AutofillProfileSyncableService and hangs it off of
@@ -87,9 +90,6 @@ class AutofillProfileSyncableService
const syncer::SyncableService::StartSyncFlare& flare);
protected:
- AutofillProfileSyncableService(AutofillWebDataBackend* webdata_backend,
- const std::string& app_locale);
-
// A convenience wrapper of a bunch of state we pass around while
// associating models, and send to the WebDatabase for persistence.
// We do this so we hold the write lock for only a small period.
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc
index 199e53f7c24..b4dc3f5db51 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc
@@ -11,8 +11,8 @@
#include "base/location.h"
#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_task_environment.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/country_names.h"
#include "components/autofill/core/browser/webdata/autofill_change.h"
@@ -262,7 +262,7 @@ class AutofillProfileSyncableServiceTest : public testing::Test {
}
protected:
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
MockAutofillProfileSyncableService autofill_syncable_service_;
std::unique_ptr<MockSyncChangeProcessor> sync_processor_;
};
@@ -1502,7 +1502,7 @@ class SyncUpdatesUsageStatsTest
}
protected:
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
MockAutofillProfileSyncableService autofill_syncable_service_;
std::unique_ptr<MockSyncChangeProcessor> sync_processor_;
};
@@ -1604,7 +1604,7 @@ TEST_F(AutofillProfileSyncableServiceTest, ClientOverwritesUsageStats) {
.WillOnce(Return(true));
autofill_syncable_service_.MergeDataAndStartSyncing(
syncer::AUTOFILL_PROFILE, data_list,
- base::WrapUnique(sync_change_processor),
+ std::unique_ptr<TestSyncChangeProcessor>(sync_change_processor),
std::unique_ptr<syncer::SyncErrorFactory>(
new syncer::SyncErrorFactoryMock()));
@@ -1640,7 +1640,7 @@ TEST_F(AutofillProfileSyncableServiceTest, IgnoreServerProfileUpdate) {
.WillOnce(Return(true));
autofill_syncable_service_.MergeDataAndStartSyncing(
syncer::AUTOFILL_PROFILE, syncer::SyncDataList(),
- base::WrapUnique(new TestSyncChangeProcessor),
+ std::make_unique<TestSyncChangeProcessor>(),
std::unique_ptr<syncer::SyncErrorFactory>(
new syncer::SyncErrorFactoryMock()));
AutofillProfile server_profile(AutofillProfile::SERVER_PROFILE, "server-id");
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc
index dfbede05b0c..d0647c4bf0e 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc
@@ -5,6 +5,7 @@
#include "components/autofill/core/browser/webdata/autofill_sync_bridge_util.h"
#include "base/base64.h"
+#include "base/pickle.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_data_util.h"
@@ -113,67 +114,107 @@ CreditCard::CardType CardTypeFromWalletCardClass(
}
}
-} // namespace
+// Creates an AutofillProfile from the specified |address| specifics.
+AutofillProfile ProfileFromSpecifics(
+ const sync_pb::WalletPostalAddress& address) {
+ AutofillProfile profile(AutofillProfile::SERVER_PROFILE, std::string());
-std::string GetBase64EncodedServerId(const std::string& server_id) {
- std::string encoded_id;
- base::Base64Encode(server_id, &encoded_id);
- return encoded_id;
-}
+ // AutofillProfile stores multi-line addresses with newline separators.
+ std::vector<base::StringPiece> street_address(
+ address.street_address().begin(), address.street_address().end());
+ profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS,
+ base::UTF8ToUTF16(base::JoinString(street_address, "\n")));
+
+ profile.SetRawInfo(COMPANY_NAME, base::UTF8ToUTF16(address.company_name()));
+ profile.SetRawInfo(ADDRESS_HOME_STATE,
+ base::UTF8ToUTF16(address.address_1()));
+ profile.SetRawInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16(address.address_2()));
+ profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
+ base::UTF8ToUTF16(address.address_3()));
+ // AutofillProfile doesn't support address_4 ("sub dependent locality").
+ profile.SetRawInfo(ADDRESS_HOME_ZIP,
+ base::UTF8ToUTF16(address.postal_code()));
+ profile.SetRawInfo(ADDRESS_HOME_SORTING_CODE,
+ base::UTF8ToUTF16(address.sorting_code()));
+ profile.SetRawInfo(ADDRESS_HOME_COUNTRY,
+ base::UTF8ToUTF16(address.country_code()));
+ profile.set_language_code(address.language_code());
+
+ // SetInfo instead of SetRawInfo so the constituent pieces will be parsed
+ // for these data types.
+ profile.SetInfo(NAME_FULL, base::UTF8ToUTF16(address.recipient_name()),
+ profile.language_code());
+ profile.SetInfo(PHONE_HOME_WHOLE_NUMBER,
+ base::UTF8ToUTF16(address.phone_number()),
+ profile.language_code());
+
+ profile.GenerateServerProfileIdentifier();
-std::string GetSpecificsIdForEntryServerId(const std::string& server_id) {
- // TODO(jkrcal): This specifics id for wallet_data probably should not be
- // base64 encoded - this function is only used in printing debug data; should
- // the storage key for wallet_data below be encoded? (probably yes, as this is
- // already launched).
- return GetBase64EncodedServerId(server_id);
+ return profile;
}
-std::string GetSpecificsIdForMetadataId(const std::string& metadata_id) {
- return GetBase64EncodedServerId(metadata_id);
+// Creates an AutofillProfile from the specified |card| specifics.
+CreditCard CardFromSpecifics(const sync_pb::WalletMaskedCreditCard& card) {
+ CreditCard result(CreditCard::MASKED_SERVER_CARD, card.id());
+ result.SetNumber(base::UTF8ToUTF16(card.last_four()));
+ result.SetServerStatus(ServerToLocalStatus(card.status()));
+ result.SetNetworkForMaskedCard(CardNetworkFromWalletCardType(card.type()));
+ result.set_card_type(CardTypeFromWalletCardClass(card.card_class()));
+ result.SetRawInfo(CREDIT_CARD_NAME_FULL,
+ base::UTF8ToUTF16(card.name_on_card()));
+ result.SetExpirationMonth(card.exp_month());
+ result.SetExpirationYear(card.exp_year());
+ result.set_billing_address_id(card.billing_address_id());
+ result.set_bank_name(card.bank_name());
+ return result;
}
-std::string GetStorageKeyForSpecificsId(const std::string& specifics_id) {
- // We use the base64 encoded |specifics_id| directly as the storage key, this
- // function only hides this definition from all its call sites.
- return specifics_id;
+// Creates a PaymentCustomerData object corresponding to the sync datatype
+// |customer_data|.
+PaymentsCustomerData CustomerDataFromSpecifics(
+ const sync_pb::PaymentsCustomerData& customer_data) {
+ return PaymentsCustomerData{/*customer_id=*/customer_data.id()};
}
-std::string GetStorageKeyForEntryServerId(const std::string& server_id) {
- // TODO(jkrcal): This probably needs to stay base64 encoded while specifics id
- // should not. Fix.
- return GetStorageKeyForSpecificsId(GetSpecificsIdForEntryServerId(server_id));
+} // namespace
+
+std::string GetBase64EncodedId(const std::string& id) {
+ std::string encoded_id;
+ base::Base64Encode(id, &encoded_id);
+ return encoded_id;
}
-std::string GetStorageKeyForMetadataId(const std::string& metadata_id) {
- return GetStorageKeyForSpecificsId(GetSpecificsIdForMetadataId(metadata_id));
+std::string GetBase64DecodedId(const std::string& id) {
+ std::string decoded_id;
+ base::Base64Decode(id, &decoded_id);
+ return decoded_id;
}
-std::string GetClientTagForSpecificsId(
- AutofillWalletSpecifics::WalletInfoType type,
- const std::string& wallet_data_specifics_id) {
- switch (type) {
- case AutofillWalletSpecifics::POSTAL_ADDRESS:
- return "address-" + wallet_data_specifics_id;
- case AutofillWalletSpecifics::MASKED_CREDIT_CARD:
- return "card-" + wallet_data_specifics_id;
- case sync_pb::AutofillWalletSpecifics::CUSTOMER_DATA:
- return "customer-" + wallet_data_specifics_id;
- case AutofillWalletSpecifics::UNKNOWN:
- NOTREACHED();
- return "";
- }
+std::string GetStorageKeyForWalletMetadataTypeAndSpecificsId(
+ sync_pb::WalletMetadataSpecifics::Type type,
+ const std::string& specifics_id) {
+ base::Pickle pickle;
+ pickle.WriteInt(static_cast<int>(type));
+ // We use the (base64-encoded) |specifics_id| here.
+ pickle.WriteString(specifics_id);
+ return std::string(static_cast<const char*>(pickle.data()), pickle.size());
}
void SetAutofillWalletSpecificsFromServerProfile(
const AutofillProfile& address,
- AutofillWalletSpecifics* wallet_specifics) {
+ AutofillWalletSpecifics* wallet_specifics,
+ bool enforce_utf8) {
wallet_specifics->set_type(AutofillWalletSpecifics::POSTAL_ADDRESS);
sync_pb::WalletPostalAddress* wallet_address =
wallet_specifics->mutable_address();
- wallet_address->set_id(address.server_id());
+ if (enforce_utf8) {
+ wallet_address->set_id(GetBase64EncodedId(address.server_id()));
+ } else {
+ wallet_address->set_id(address.server_id());
+ }
+
wallet_address->set_language_code(TruncateUTF8(address.language_code()));
if (address.HasRawInfo(NAME_FULL)) {
@@ -218,69 +259,30 @@ void SetAutofillWalletSpecificsFromServerProfile(
}
}
-std::unique_ptr<EntityData> CreateEntityDataFromAutofillServerProfile(
- const AutofillProfile& address) {
- auto entity_data = std::make_unique<EntityData>();
-
- std::string specifics_id =
- GetSpecificsIdForEntryServerId(address.server_id());
- entity_data->non_unique_name = GetClientTagForSpecificsId(
- AutofillWalletSpecifics::POSTAL_ADDRESS, specifics_id);
-
- AutofillWalletSpecifics* wallet_specifics =
- entity_data->specifics.mutable_autofill_wallet();
-
- SetAutofillWalletSpecificsFromServerProfile(address, wallet_specifics);
-
- return entity_data;
-}
-
-AutofillProfile ProfileFromSpecifics(
- const sync_pb::WalletPostalAddress& address) {
- AutofillProfile profile(AutofillProfile::SERVER_PROFILE, std::string());
-
- // AutofillProfile stores multi-line addresses with newline separators.
- std::vector<base::StringPiece> street_address(
- address.street_address().begin(), address.street_address().end());
- profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS,
- base::UTF8ToUTF16(base::JoinString(street_address, "\n")));
-
- profile.SetRawInfo(COMPANY_NAME, base::UTF8ToUTF16(address.company_name()));
- profile.SetRawInfo(ADDRESS_HOME_STATE,
- base::UTF8ToUTF16(address.address_1()));
- profile.SetRawInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16(address.address_2()));
- profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
- base::UTF8ToUTF16(address.address_3()));
- // AutofillProfile doesn't support address_4 ("sub dependent locality").
- profile.SetRawInfo(ADDRESS_HOME_ZIP,
- base::UTF8ToUTF16(address.postal_code()));
- profile.SetRawInfo(ADDRESS_HOME_SORTING_CODE,
- base::UTF8ToUTF16(address.sorting_code()));
- profile.SetRawInfo(ADDRESS_HOME_COUNTRY,
- base::UTF8ToUTF16(address.country_code()));
- profile.set_language_code(address.language_code());
-
- // SetInfo instead of SetRawInfo so the constituent pieces will be parsed
- // for these data types.
- profile.SetInfo(NAME_FULL, base::UTF8ToUTF16(address.recipient_name()),
- profile.language_code());
- profile.SetInfo(PHONE_HOME_WHOLE_NUMBER,
- base::UTF8ToUTF16(address.phone_number()),
- profile.language_code());
-
- profile.GenerateServerProfileIdentifier();
-
- return profile;
-}
-
void SetAutofillWalletSpecificsFromServerCard(
const CreditCard& card,
- AutofillWalletSpecifics* wallet_specifics) {
+ AutofillWalletSpecifics* wallet_specifics,
+ bool enforce_utf8) {
wallet_specifics->set_type(AutofillWalletSpecifics::MASKED_CREDIT_CARD);
sync_pb::WalletMaskedCreditCard* wallet_card =
wallet_specifics->mutable_masked_card();
- wallet_card->set_id(card.server_id());
+
+ if (enforce_utf8) {
+ wallet_card->set_id(GetBase64EncodedId(card.server_id()));
+ // The billing address id might refer to a local profile guid which doesn't
+ // need to be encoded.
+ if (base::IsStringUTF8(card.billing_address_id())) {
+ wallet_card->set_billing_address_id(card.billing_address_id());
+ } else {
+ wallet_card->set_billing_address_id(
+ GetBase64EncodedId(card.billing_address_id()));
+ }
+ } else {
+ wallet_card->set_id(card.server_id());
+ wallet_card->set_billing_address_id(card.billing_address_id());
+ }
+
wallet_card->set_status(LocalToServerStatus(card));
if (card.HasRawInfo(CREDIT_CARD_NAME_FULL)) {
wallet_card->set_name_on_card(TruncateUTF8(
@@ -290,57 +292,10 @@ void SetAutofillWalletSpecificsFromServerCard(
wallet_card->set_last_four(base::UTF16ToUTF8(card.LastFourDigits()));
wallet_card->set_exp_month(card.expiration_month());
wallet_card->set_exp_year(card.expiration_year());
- wallet_card->set_billing_address_id(card.billing_address_id());
wallet_card->set_card_class(WalletCardClassFromCardType(card.card_type()));
wallet_card->set_bank_name(card.bank_name());
}
-std::unique_ptr<EntityData> CreateEntityDataFromCard(const CreditCard& card) {
- std::string specifics_id = GetSpecificsIdForEntryServerId(card.server_id());
-
- auto entity_data = std::make_unique<EntityData>();
- entity_data->non_unique_name = GetClientTagForSpecificsId(
- AutofillWalletSpecifics::MASKED_CREDIT_CARD, specifics_id);
-
- AutofillWalletSpecifics* wallet_specifics =
- entity_data->specifics.mutable_autofill_wallet();
-
- SetAutofillWalletSpecificsFromServerCard(card, wallet_specifics);
-
- return entity_data;
-}
-
-CreditCard CardFromSpecifics(const sync_pb::WalletMaskedCreditCard& card) {
- CreditCard result(CreditCard::MASKED_SERVER_CARD, card.id());
- result.SetNumber(base::UTF8ToUTF16(card.last_four()));
- result.SetServerStatus(ServerToLocalStatus(card.status()));
- result.SetNetworkForMaskedCard(CardNetworkFromWalletCardType(card.type()));
- result.set_card_type(CardTypeFromWalletCardClass(card.card_class()));
- result.SetRawInfo(CREDIT_CARD_NAME_FULL,
- base::UTF8ToUTF16(card.name_on_card()));
- result.SetExpirationMonth(card.exp_month());
- result.SetExpirationYear(card.exp_year());
- result.set_billing_address_id(card.billing_address_id());
- result.set_bank_name(card.bank_name());
- return result;
-}
-
-std::unique_ptr<EntityData> CreateEntityDataFromPaymentsCustomerData(
- const PaymentsCustomerData& customer_data) {
- // We use customer_id as a storage key here.
- auto entity_data = std::make_unique<EntityData>();
- entity_data->non_unique_name = GetClientTagForSpecificsId(
- AutofillWalletSpecifics::CUSTOMER_DATA, customer_data.customer_id);
-
- AutofillWalletSpecifics* wallet_specifics =
- entity_data->specifics.mutable_autofill_wallet();
-
- SetAutofillWalletSpecificsFromPaymentsCustomerData(customer_data,
- wallet_specifics);
-
- return entity_data;
-}
-
void SetAutofillWalletSpecificsFromPaymentsCustomerData(
const PaymentsCustomerData& customer_data,
AutofillWalletSpecifics* wallet_specifics) {
@@ -351,11 +306,6 @@ void SetAutofillWalletSpecificsFromPaymentsCustomerData(
mutable_customer_data->set_id(customer_data.customer_id);
}
-PaymentsCustomerData CustomerDataFromSpecifics(
- const sync_pb::PaymentsCustomerData& customer_data) {
- return PaymentsCustomerData{/*customer_id=*/customer_data.id()};
-}
-
void CopyRelevantWalletMetadataFromDisk(
const AutofillTable& table,
std::vector<CreditCard>* cards_from_server) {
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.h b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.h
index 07861d45969..fc6812fc600 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.h
@@ -18,61 +18,29 @@ class AutofillTable;
class CreditCard;
struct PaymentsCustomerData;
-// Returns the specified |server_id| encoded in base 64.
-std::string GetBase64EncodedServerId(const std::string& server_id);
+// Returns the specified |id| encoded in / decoded from base 64.
+std::string GetBase64EncodedId(const std::string& id);
+std::string GetBase64DecodedId(const std::string& id);
-// Returns the wallet data specifics id for the specified |server_id|.
-std::string GetSpecificsIdForEntryServerId(const std::string& server_id);
-
-// Returns the wallet metadata specifics id for the specified |metadata_id|.
-std::string GetSpecificsIdForMetadataId(const std::string& metadata_id);
-
-// Returns the storage key for the specified |specifics_id|.
-std::string GetStorageKeyForSpecificsId(const std::string& specifics_id);
-
-// Returns the wallet data specifics storage key for the specified
-// |server_id|.
-std::string GetStorageKeyForEntryServerId(const std::string& server_id);
-
-// Returns the wallet metadata specifics storage key for the specified
-// |metadata_id|.
-std::string GetStorageKeyForMetadataId(const std::string& metadata_id);
-
-// Returns the client tag for the specified wallet |type| and
-// |wallet_data_specifics_id|.
-std::string GetClientTagForSpecificsId(
- sync_pb::AutofillWalletSpecifics::WalletInfoType type,
- const std::string& wallet_data_specifics_id);
+// Returns the storage key to be used for wallet metadata for the specified
+// wallet metadata |type| and |specifics_id|.
+std::string GetStorageKeyForWalletMetadataTypeAndSpecificsId(
+ sync_pb::WalletMetadataSpecifics::Type type,
+ const std::string& specifics_id);
// Sets the fields of the |wallet_specifics| based on the the specified
-// |address|.
+// |address|. If |enforce_utf8|, ids are encoded into UTF-8.
void SetAutofillWalletSpecificsFromServerProfile(
const AutofillProfile& address,
- sync_pb::AutofillWalletSpecifics* wallet_specifics);
-
-// Creates a EntityData object corresponding to the specified |address|.
-std::unique_ptr<syncer::EntityData> CreateEntityDataFromAutofillServerProfile(
- const AutofillProfile& address);
-
-// Creates an AutofillProfile from the specified |address| specifics.
-AutofillProfile ProfileFromSpecifics(
- const sync_pb::WalletPostalAddress& address);
+ sync_pb::AutofillWalletSpecifics* wallet_specifics,
+ bool enforce_utf8 = false);
// Sets the fields of the |wallet_specifics| based on the the specified |card|.
+// If |enforce_utf8|, ids are encoded into UTF-8.
void SetAutofillWalletSpecificsFromServerCard(
const CreditCard& card,
- sync_pb::AutofillWalletSpecifics* wallet_specifics);
-
-// Creates a EntityData object corresponding to the specified |card|.
-std::unique_ptr<syncer::EntityData> CreateEntityDataFromCard(
- const CreditCard& card);
-
-// Creates an AutofillProfile from the specified |card| specifics.
-CreditCard CardFromSpecifics(const sync_pb::WalletMaskedCreditCard& card);
-
-// Creates a EntityData object corresponding to the specified |customer_data|.
-std::unique_ptr<syncer::EntityData> CreateEntityDataFromPaymentsCustomerData(
- const PaymentsCustomerData& customer_data);
+ sync_pb::AutofillWalletSpecifics* wallet_specifics,
+ bool enforce_utf8 = false);
// Sets the fields of the |wallet_specifics| based on the specified
// |customer_data|.
@@ -80,11 +48,6 @@ void SetAutofillWalletSpecificsFromPaymentsCustomerData(
const PaymentsCustomerData& customer_data,
sync_pb::AutofillWalletSpecifics* wallet_specifics);
-// Creates a PaymentCustomerData object corresponding to the sync datatype
-// |customer_data|.
-PaymentsCustomerData CustomerDataFromSpecifics(
- const sync_pb::PaymentsCustomerData& customer_data);
-
// TODO(sebsg): This should probably copy the converted state for the address
// too.
// Copies the metadata from the local cards (if present) to the corresponding
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table.cc b/chromium/components/autofill/core/browser/webdata/autofill_table.cc
index a13ca78d12f..44741c86d84 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table.cc
@@ -34,6 +34,8 @@
#include "components/autofill/core/browser/webdata/autofill_table_encryptor.h"
#include "components/autofill/core/browser/webdata/autofill_table_encryptor_factory.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/autofill_switches.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_field_data.h"
@@ -503,22 +505,28 @@ bool AutofillTable::AddFormFieldValue(const FormFieldData& element,
bool AutofillTable::GetFormValuesForElementName(
const base::string16& name,
const base::string16& prefix,
- std::vector<base::string16>* values,
+ std::vector<AutofillEntry>* entries,
int limit) {
- DCHECK(values);
+ DCHECK(entries);
bool succeeded = false;
if (prefix.empty()) {
sql::Statement s;
- s.Assign(
- db_->GetUniqueStatement("SELECT value FROM autofill WHERE name = ? "
- "ORDER BY count DESC LIMIT ?"));
+ s.Assign(db_->GetUniqueStatement(
+ "SELECT name, value, date_created, date_last_used FROM autofill "
+ "WHERE name = ? "
+ "ORDER BY count DESC LIMIT ?"));
s.BindString16(0, name);
s.BindInt(1, limit);
- values->clear();
- while (s.Step())
- values->push_back(s.ColumnString16(0));
+ entries->clear();
+ while (s.Step()) {
+ entries->push_back(AutofillEntry(
+ AutofillKey(/*name=*/s.ColumnString16(0),
+ /*value=*/s.ColumnString16(1)),
+ /*date_created=*/base::Time::FromTimeT(s.ColumnInt64(2)),
+ /*date_last_used=*/base::Time::FromTimeT(s.ColumnInt64(3))));
+ }
succeeded = s.Succeeded();
} else {
@@ -527,28 +535,33 @@ bool AutofillTable::GetFormValuesForElementName(
next_prefix.back()++;
sql::Statement s1;
- s1.Assign(
- db_->GetUniqueStatement("SELECT value FROM autofill "
- "WHERE name = ? AND "
- "value_lower >= ? AND "
- "value_lower < ? "
- "ORDER BY count DESC "
- "LIMIT ?"));
+ s1.Assign(db_->GetUniqueStatement(
+ "SELECT name, value, date_created, date_last_used FROM autofill "
+ "WHERE name = ? AND "
+ "value_lower >= ? AND "
+ "value_lower < ? "
+ "ORDER BY count DESC "
+ "LIMIT ?"));
s1.BindString16(0, name);
s1.BindString16(1, prefix_lower);
s1.BindString16(2, next_prefix);
s1.BindInt(3, limit);
- values->clear();
- while (s1.Step())
- values->push_back(s1.ColumnString16(0));
+ entries->clear();
+ while (s1.Step()) {
+ entries->push_back(AutofillEntry(
+ AutofillKey(/*name=*/s1.ColumnString16(0),
+ /*value=*/s1.ColumnString16(1)),
+ /*date_created=*/base::Time::FromTimeT(s1.ColumnInt64(2)),
+ /*date_last_used=*/base::Time::FromTimeT(s1.ColumnInt64(3))));
+ }
succeeded = s1.Succeeded();
if (IsFeatureSubstringMatchEnabled()) {
sql::Statement s2;
s2.Assign(db_->GetUniqueStatement(
- "SELECT value FROM autofill "
+ "SELECT name, value, date_created, date_last_used FROM autofill "
"WHERE name = ? AND ("
" value LIKE '% ' || :prefix || '%' ESCAPE '!' OR "
" value LIKE '%.' || :prefix || '%' ESCAPE '!' OR "
@@ -564,8 +577,13 @@ bool AutofillTable::GetFormValuesForElementName(
s2.BindString16(1,
Substitute(prefix_lower, base::ASCIIToUTF16("_%"), 0x21));
s2.BindInt(2, limit);
- while (s2.Step())
- values->push_back(s2.ColumnString16(0));
+ while (s2.Step()) {
+ entries->push_back(AutofillEntry(
+ AutofillKey(/*name=*/s2.ColumnString16(0),
+ /*value=*/s2.ColumnString16(1)),
+ /*date_created=*/base::Time::FromTimeT(s2.ColumnInt64(2)),
+ /*date_last_used=*/base::Time::FromTimeT(s2.ColumnInt64(3))));
+ }
succeeded &= s2.Succeeded();
}
@@ -681,8 +699,17 @@ bool AutofillTable::RemoveFormElementsAddedBetween(
bool AutofillTable::RemoveExpiredFormElements(
std::vector<AutofillChange>* changes) {
+ int64_t period = kExpirationPeriodInDays;
+ auto change_type = AutofillChange::REMOVE;
+
+ if (base::FeatureList::IsEnabled(
+ autofill::features::kAutocompleteRetentionPolicyEnabled)) {
+ period = kAutocompleteRetentionPolicyPeriodInDays;
+ change_type = AutofillChange::EXPIRE;
+ }
+
base::Time expiration_time =
- AutofillClock::Now() - base::TimeDelta::FromDays(kExpirationPeriodInDays);
+ AutofillClock::Now() - base::TimeDelta::FromDays(period);
// Query for the name and value of all form elements that were last used
// before the |expiration_time|.
@@ -694,7 +721,7 @@ bool AutofillTable::RemoveExpiredFormElements(
base::string16 name = select_for_delete.ColumnString16(0);
base::string16 value = select_for_delete.ColumnString16(1);
tentative_changes.push_back(
- AutofillChange(AutofillChange::REMOVE, AutofillKey(name, value)));
+ AutofillChange(change_type, AutofillKey(name, value)));
}
if (!select_for_delete.Succeeded())
@@ -1342,6 +1369,24 @@ bool AutofillTable::UpdateServerCardMetadata(const CreditCard& credit_card) {
return db_->GetLastChangeCount() > 0;
}
+bool AutofillTable::UpdateServerCardMetadata(
+ const AutofillMetadata& card_metadata) {
+ // Do not check if there was a record that got deleted. Inserting a new one is
+ // also fine.
+ RemoveServerCardMetadata(card_metadata.id);
+ sql::Statement s(
+ db_->GetUniqueStatement("INSERT INTO server_card_metadata(use_count, "
+ "use_date, billing_address_id, id)"
+ "VALUES (?,?,?,?)"));
+ s.BindInt64(0, card_metadata.use_count);
+ s.BindInt64(1, card_metadata.use_date.ToInternalValue());
+ s.BindString(2, card_metadata.billing_address_id);
+ s.BindString(3, card_metadata.id);
+ s.Run();
+
+ return db_->GetLastChangeCount() > 0;
+}
+
bool AutofillTable::RemoveServerCardMetadata(const std::string& id) {
sql::Statement remove(
db_->GetUniqueStatement("DELETE FROM server_card_metadata WHERE id = ?"));
@@ -1418,6 +1463,24 @@ bool AutofillTable::UpdateServerAddressMetadata(
return db_->GetLastChangeCount() > 0;
}
+bool AutofillTable::UpdateServerAddressMetadata(
+ const AutofillMetadata& address_metadata) {
+ // Do not check if there was a record that got deleted. Inserting a new one is
+ // also fine.
+ RemoveServerAddressMetadata(address_metadata.id);
+ sql::Statement s(
+ db_->GetUniqueStatement("INSERT INTO server_address_metadata(use_count, "
+ "use_date, has_converted, id)"
+ "VALUES (?,?,?,?)"));
+ s.BindInt64(0, address_metadata.use_count);
+ s.BindInt64(1, address_metadata.use_date.ToInternalValue());
+ s.BindBool(2, address_metadata.has_converted);
+ s.BindString(3, address_metadata.id);
+ s.Run();
+
+ return db_->GetLastChangeCount() > 0;
+}
+
bool AutofillTable::RemoveServerAddressMetadata(const std::string& id) {
sql::Statement remove(db_->GetUniqueStatement(
"DELETE FROM server_address_metadata WHERE id = ?"));
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table.h b/chromium/components/autofill/core/browser/webdata/autofill_table.h
index 4c47232d7c5..ae7114f18b4 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table.h
@@ -306,7 +306,7 @@ class AutofillTable : public WebDatabaseTable,
// |prefix|. The comparison of the prefix is case insensitive.
bool GetFormValuesForElementName(const base::string16& name,
const base::string16& prefix,
- std::vector<base::string16>* values,
+ std::vector<AutofillEntry>* entries,
int limit);
// Removes rows from the autofill table if they were created on or after
@@ -409,11 +409,13 @@ class AutofillTable : public WebDatabaseTable,
// addresses.
bool AddServerCardMetadata(const AutofillMetadata& card_metadata);
bool UpdateServerCardMetadata(const CreditCard& credit_card);
+ bool UpdateServerCardMetadata(const AutofillMetadata& card_metadata);
bool RemoveServerCardMetadata(const std::string& id);
bool GetServerCardsMetadata(
std::map<std::string, AutofillMetadata>* cards_metadata) const;
bool AddServerAddressMetadata(const AutofillMetadata& address_metadata);
bool UpdateServerAddressMetadata(const AutofillProfile& profile);
+ bool UpdateServerAddressMetadata(const AutofillMetadata& address_metadata);
bool RemoveServerAddressMetadata(const std::string& id);
bool GetServerAddressesMetadata(
std::map<std::string, AutofillMetadata>* addresses_metadata) const;
@@ -558,6 +560,12 @@ class AutofillTable : public WebDatabaseTable,
FRIEND_TEST_ALL_PREFIXES(
AutofillTableTest,
Autofill_RemoveFormElementsAddedBetween_OlderThan30Days);
+ FRIEND_TEST_ALL_PREFIXES(AutofillTableTest,
+ RemoveExpiredFormElements_FlagOff_Removes);
+ FRIEND_TEST_ALL_PREFIXES(AutofillTableTest,
+ RemoveExpiredFormElements_FlagOn_Expires);
+ FRIEND_TEST_ALL_PREFIXES(AutofillTableTest,
+ RemoveExpiredFormElements_FlagOn_NotOldEnough);
FRIEND_TEST_ALL_PREFIXES(AutofillTableTest, Autofill_AddFormFieldValues);
FRIEND_TEST_ALL_PREFIXES(AutofillTableTest, AutofillProfile);
FRIEND_TEST_ALL_PREFIXES(AutofillTableTest, UpdateAutofillProfile);
@@ -573,6 +581,7 @@ class AutofillTable : public WebDatabaseTable,
Autofill_GetAllAutofillEntries_TwoDistinct);
FRIEND_TEST_ALL_PREFIXES(AutofillTableTest,
Autofill_GetAllAutofillEntries_TwoSame);
+ FRIEND_TEST_ALL_PREFIXES(AutofillTableTest, Autofill_GetEntry_Populated);
// Methods for adding autofill entries at a specified time. For
// testing only.
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 6b20deb05ee..14d9f4ec53d 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
@@ -13,11 +13,11 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/guid.h"
-#include "base/macros.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_metadata.h"
@@ -28,7 +28,9 @@
#include "components/autofill/core/browser/payments/payments_customer_data.h"
#include "components/autofill/core/browser/webdata/autofill_change.h"
#include "components/autofill/core/browser/webdata/autofill_entry.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/autofill_switches.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_field_data.h"
@@ -37,6 +39,7 @@
#include "components/sync/protocol/model_type_state.pb.h"
#include "components/webdata/common/web_database.h"
#include "sql/statement.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::ASCIIToUTF16;
@@ -46,6 +49,7 @@ using sync_pb::EntityMetadata;
using sync_pb::ModelTypeState;
using syncer::EntityMetadataMap;
using syncer::MetadataBatch;
+using testing::ElementsAre;
namespace autofill {
@@ -70,6 +74,10 @@ std::ostream& operator<<(std::ostream& os, const AutofillChange& change) {
os << "REMOVE";
break;
}
+ case AutofillChange::EXPIRE: {
+ os << "EXPIRED";
+ break;
+ }
}
return os << " " << change.key();
}
@@ -145,6 +153,7 @@ class AutofillTableTest : public testing::Test {
base::ScopedTempDir temp_dir_;
std::unique_ptr<AutofillTable> table_;
std::unique_ptr<WebDatabase> db_;
+ base::test::ScopedFeatureList scoped_feature_list_;
private:
DISALLOW_COPY_AND_ASSIGN(AutofillTableTest);
@@ -162,7 +171,7 @@ TEST_F(AutofillTableTest, Autofill) {
base::Time now = base::Time::Now();
base::TimeDelta two_seconds = base::TimeDelta::FromSeconds(2);
EXPECT_TRUE(table_->AddFormFieldValue(field, &changes));
- std::vector<base::string16> v;
+ std::vector<AutofillEntry> v;
for (int i = 0; i < 5; ++i) {
field.value = ASCIIToUTF16("Clark Kent");
EXPECT_TRUE(table_->AddFormFieldValueTime(field, &changes,
@@ -200,9 +209,9 @@ TEST_F(AutofillTableTest, Autofill) {
ASCIIToUTF16("Name"), base::string16(), &v, 6));
EXPECT_EQ(3U, v.size());
if (v.size() == 3) {
- EXPECT_EQ(ASCIIToUTF16("Clark Kent"), v[0]);
- EXPECT_EQ(ASCIIToUTF16("Clark Sutter"), v[1]);
- EXPECT_EQ(ASCIIToUTF16("Superman"), v[2]);
+ EXPECT_EQ(ASCIIToUTF16("Clark Kent"), v[0].key().value());
+ EXPECT_EQ(ASCIIToUTF16("Clark Sutter"), v[1].key().value());
+ EXPECT_EQ(ASCIIToUTF16("Superman"), v[2].key().value());
}
// If we query again limiting the list size to 1, we should only get the most
@@ -211,7 +220,7 @@ TEST_F(AutofillTableTest, Autofill) {
ASCIIToUTF16("Name"), base::string16(), &v, 1));
EXPECT_EQ(1U, v.size());
if (v.size() == 1) {
- EXPECT_EQ(ASCIIToUTF16("Clark Kent"), v[0]);
+ EXPECT_EQ(ASCIIToUTF16("Clark Kent"), v[0].key().value());
}
// Querying for suggestions given a prefix is case-insensitive, so the prefix
@@ -220,8 +229,8 @@ TEST_F(AutofillTableTest, Autofill) {
ASCIIToUTF16("Name"), ASCIIToUTF16("cLa"), &v, 6));
EXPECT_EQ(2U, v.size());
if (v.size() == 2) {
- EXPECT_EQ(ASCIIToUTF16("Clark Kent"), v[0]);
- EXPECT_EQ(ASCIIToUTF16("Clark Sutter"), v[1]);
+ EXPECT_EQ(ASCIIToUTF16("Clark Kent"), v[0].key().value());
+ EXPECT_EQ(ASCIIToUTF16("Clark Sutter"), v[1].key().value());
}
// Removing all elements since the beginning of this function should remove
@@ -243,8 +252,8 @@ TEST_F(AutofillTableTest, Autofill) {
AutofillKey(ASCIIToUTF16("Favorite Color"),
ASCIIToUTF16("Green"))),
};
- EXPECT_EQ(arraysize(kExpectedChanges), changes.size());
- for (size_t i = 0; i < arraysize(kExpectedChanges); ++i) {
+ EXPECT_EQ(base::size(kExpectedChanges), changes.size());
+ for (size_t i = 0; i < base::size(kExpectedChanges); ++i) {
EXPECT_EQ(kExpectedChanges[i], changes[i]);
}
@@ -278,6 +287,43 @@ TEST_F(AutofillTableTest, Autofill) {
EXPECT_EQ(4U, v.size());
}
+TEST_F(AutofillTableTest, Autofill_GetEntry_Populated) {
+ AutofillChangeList changes;
+ FormFieldData field;
+ field.name = ASCIIToUTF16("Name");
+ field.value = ASCIIToUTF16("Superman");
+ base::Time now = base::Time::FromDoubleT(1546889367);
+
+ EXPECT_TRUE(table_->AddFormFieldValueTime(field, &changes, now));
+
+ std::vector<AutofillEntry> prefix_v;
+ EXPECT_TRUE(table_->GetFormValuesForElementName(
+ field.name, ASCIIToUTF16("Super"), &prefix_v, 10));
+
+ std::vector<AutofillEntry> no_prefix_v;
+ EXPECT_TRUE(table_->GetFormValuesForElementName(field.name, ASCIIToUTF16(""),
+ &no_prefix_v, 10));
+
+ AutofillEntry expected_entry(AutofillKey(field.name, field.value), now, now);
+
+ EXPECT_THAT(prefix_v, ElementsAre(expected_entry));
+ EXPECT_THAT(no_prefix_v, ElementsAre(expected_entry));
+
+ // Update date_last_used.
+ base::Time new_time = now + base::TimeDelta::FromSeconds(1000);
+ EXPECT_TRUE(table_->AddFormFieldValueTime(field, &changes, new_time));
+ EXPECT_TRUE(table_->GetFormValuesForElementName(
+ field.name, ASCIIToUTF16("Super"), &prefix_v, 10));
+ EXPECT_TRUE(table_->GetFormValuesForElementName(field.name, ASCIIToUTF16(""),
+ &no_prefix_v, 10));
+
+ expected_entry =
+ AutofillEntry(AutofillKey(field.name, field.value), now, new_time);
+
+ EXPECT_THAT(prefix_v, ElementsAre(expected_entry));
+ EXPECT_THAT(no_prefix_v, ElementsAre(expected_entry));
+}
+
TEST_F(AutofillTableTest, Autofill_GetCountOfValuesContainedBetween) {
AutofillChangeList changes;
// This test makes time comparisons that are precise to a microsecond, but the
@@ -468,7 +514,7 @@ TEST_F(AutofillTableTest, Autofill_UpdateNullTerminated) {
const char kName[] = "foo";
const char kValue[] = "bar";
// A value which contains terminating character.
- std::string value(kValue, arraysize(kValue));
+ std::string value(kValue, base::size(kValue));
AutofillEntry entry0(MakeAutofillEntry(kName, kValue, 1, -1));
AutofillEntry entry1(MakeAutofillEntry(kName, value, 2, 3));
@@ -772,6 +818,70 @@ TEST_F(AutofillTableTest,
changes.clear();
}
+// Tests that we set the change type to REMOVE for expired elements when the
+// Autocomplete Retention Policy feature flag is off.
+TEST_F(AutofillTableTest, RemoveExpiredFormElements_FlagOff_Removes) {
+ scoped_feature_list_.InitAndDisableFeature(
+ features::kAutocompleteRetentionPolicyEnabled);
+ auto kNow = AutofillClock::Now();
+ auto k4MonthsOld = kNow - base::TimeDelta::FromDays(4 * 30);
+
+ AutofillChangeList changes;
+ FormFieldData field;
+ field.name = ASCIIToUTF16("Name");
+ field.value = ASCIIToUTF16("Superman");
+ EXPECT_TRUE(table_->AddFormFieldValueTime(field, &changes, k4MonthsOld));
+ changes.clear();
+
+ EXPECT_TRUE(table_->RemoveExpiredFormElements(&changes));
+
+ EXPECT_EQ(AutofillChange(AutofillChange::REMOVE,
+ AutofillKey(field.name, field.value)),
+ changes[0]);
+}
+
+// Tests that we set the change type to EXPIRE for expired elements when the
+// Autocomplete Retention Policy feature flag is on.
+TEST_F(AutofillTableTest, RemoveExpiredFormElements_FlagOn_Expires) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutocompleteRetentionPolicyEnabled);
+ auto kNow = AutofillClock::Now();
+ auto k2YearsOld = kNow - base::TimeDelta::FromDays(
+ 2 * kAutocompleteRetentionPolicyPeriodInDays);
+
+ AutofillChangeList changes;
+ FormFieldData field;
+ field.name = ASCIIToUTF16("Name");
+ field.value = ASCIIToUTF16("Superman");
+ EXPECT_TRUE(table_->AddFormFieldValueTime(field, &changes, k2YearsOld));
+ changes.clear();
+
+ EXPECT_TRUE(table_->RemoveExpiredFormElements(&changes));
+
+ EXPECT_EQ(AutofillChange(AutofillChange::EXPIRE,
+ AutofillKey(field.name, field.value)),
+ changes[0]);
+}
+
+// Tests that, with the Autocomplete Retention Policy feature flag on, we don't
+// delete non-expired entries' data from the SQLite table.
+TEST_F(AutofillTableTest, RemoveExpiredFormElements_FlagOn_NotOldEnough) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutocompleteRetentionPolicyEnabled);
+ auto kNow = AutofillClock::Now();
+ auto k2DaysOld = kNow - base::TimeDelta::FromDays(2);
+
+ AutofillChangeList changes;
+ FormFieldData field;
+ field.name = ASCIIToUTF16("Name");
+ field.value = ASCIIToUTF16("Superman");
+ EXPECT_TRUE(table_->AddFormFieldValueTime(field, &changes, k2DaysOld));
+ changes.clear();
+
+ EXPECT_TRUE(table_->RemoveExpiredFormElements(&changes));
+ EXPECT_TRUE(changes.empty());
+}
+
TEST_F(AutofillTableTest, AutofillProfile) {
// Add a 'Home' profile with non-default data. The specific values are not
// important.
@@ -1979,6 +2089,133 @@ TEST_F(AutofillTableTest, SetGetRemoveServerAddressMetadata) {
EXPECT_EQ(0U, outputs.size());
}
+TEST_F(AutofillTableTest, AddUpdateServerAddressMetadata) {
+ // Create and set the metadata.
+ AutofillMetadata input;
+ input.id = "server id";
+ input.use_count = 50;
+ input.use_date = Time::Now();
+ input.has_converted = true;
+ ASSERT_TRUE(table_->AddServerAddressMetadata(input));
+
+ // Make sure it was added correctly.
+ std::map<std::string, AutofillMetadata> outputs;
+ ASSERT_TRUE(table_->GetServerAddressesMetadata(&outputs));
+ ASSERT_EQ(1U, outputs.size());
+ ASSERT_EQ(input, outputs[input.id]);
+
+ // Update the metadata in the table.
+ input.use_count = 51;
+ EXPECT_TRUE(table_->UpdateServerAddressMetadata(input));
+
+ // Make sure it was updated correctly.
+ ASSERT_TRUE(table_->GetServerAddressesMetadata(&outputs));
+ ASSERT_EQ(1U, outputs.size());
+ EXPECT_EQ(input, outputs[input.id]);
+
+ // Insert a new entry using update - that should also be legal.
+ input.id = "another server id";
+ EXPECT_TRUE(table_->UpdateServerAddressMetadata(input));
+ ASSERT_TRUE(table_->GetServerAddressesMetadata(&outputs));
+ ASSERT_EQ(2U, outputs.size());
+}
+
+TEST_F(AutofillTableTest, AddUpdateServerCardMetadata) {
+ // Create and set the metadata.
+ AutofillMetadata input;
+ input.id = "server id";
+ input.use_count = 50;
+ input.use_date = Time::Now();
+ input.billing_address_id = "billing id";
+ ASSERT_TRUE(table_->AddServerCardMetadata(input));
+
+ // Make sure it was added correctly.
+ std::map<std::string, AutofillMetadata> outputs;
+ ASSERT_TRUE(table_->GetServerCardsMetadata(&outputs));
+ ASSERT_EQ(1U, outputs.size());
+ ASSERT_EQ(input, outputs[input.id]);
+
+ // Update the metadata in the table.
+ input.use_count = 51;
+ EXPECT_TRUE(table_->UpdateServerCardMetadata(input));
+
+ // Make sure it was updated correctly.
+ ASSERT_TRUE(table_->GetServerCardsMetadata(&outputs));
+ ASSERT_EQ(1U, outputs.size());
+ EXPECT_EQ(input, outputs[input.id]);
+
+ // Insert a new entry using update - that should also be legal.
+ input.id = "another server id";
+ EXPECT_TRUE(table_->UpdateServerCardMetadata(input));
+ ASSERT_TRUE(table_->GetServerCardsMetadata(&outputs));
+ ASSERT_EQ(2U, outputs.size());
+}
+
+TEST_F(AutofillTableTest, UpdateServerAddressMetadataDoesNotChangeData) {
+ AutofillProfile one(AutofillProfile::SERVER_PROFILE, "a123");
+ std::vector<AutofillProfile> inputs;
+ inputs.push_back(one);
+ table_->SetServerProfiles(inputs);
+
+ std::vector<std::unique_ptr<AutofillProfile>> outputs;
+ table_->GetServerProfiles(&outputs);
+ ASSERT_EQ(1u, outputs.size());
+ EXPECT_EQ(one.server_id(), outputs[0]->server_id());
+
+ // Update metadata in the profile.
+ ASSERT_NE(outputs[0]->use_count(), 51u);
+ outputs[0]->set_use_count(51);
+
+ AutofillMetadata input_metadata = outputs[0]->GetMetadata();
+ EXPECT_TRUE(table_->UpdateServerAddressMetadata(input_metadata));
+
+ // Make sure it was updated correctly.
+ std::map<std::string, AutofillMetadata> output_metadata;
+ ASSERT_TRUE(table_->GetServerAddressesMetadata(&output_metadata));
+ ASSERT_EQ(1U, output_metadata.size());
+ EXPECT_EQ(input_metadata, output_metadata[input_metadata.id]);
+
+ // Make sure nothing else got updated.
+ std::vector<std::unique_ptr<AutofillProfile>> outputs2;
+ table_->GetServerProfiles(&outputs2);
+ ASSERT_EQ(1u, outputs2.size());
+ EXPECT_TRUE(outputs[0]->EqualsForSyncPurposes(*outputs2[0]));
+}
+
+TEST_F(AutofillTableTest, UpdateServerCardMetadataDoesNotChangeData) {
+ std::vector<CreditCard> inputs;
+ inputs.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "a123"));
+ inputs[0].SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("Paul F. Tompkins"));
+ inputs[0].SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("1"));
+ inputs[0].SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2020"));
+ inputs[0].SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111"));
+ test::SetServerCreditCards(table_.get(), inputs);
+
+ std::vector<std::unique_ptr<CreditCard>> outputs;
+ ASSERT_TRUE(table_->GetServerCreditCards(&outputs));
+ ASSERT_EQ(1u, outputs.size());
+ EXPECT_EQ(inputs[0].server_id(), outputs[0]->server_id());
+
+ // Update metadata in the profile.
+ ASSERT_NE(outputs[0]->use_count(), 51u);
+ outputs[0]->set_use_count(51);
+
+ AutofillMetadata input_metadata = outputs[0]->GetMetadata();
+ EXPECT_TRUE(table_->UpdateServerCardMetadata(input_metadata));
+
+ // Make sure it was updated correctly.
+ std::map<std::string, AutofillMetadata> output_metadata;
+ ASSERT_TRUE(table_->GetServerCardsMetadata(&output_metadata));
+ ASSERT_EQ(1U, output_metadata.size());
+ EXPECT_EQ(input_metadata, output_metadata[input_metadata.id]);
+
+ // Make sure nothing else got updated.
+ std::vector<std::unique_ptr<CreditCard>> outputs2;
+ table_->GetServerCreditCards(&outputs2);
+ ASSERT_EQ(1u, outputs2.size());
+ EXPECT_EQ(0, outputs[0]->Compare(*outputs2[0]));
+}
+
TEST_F(AutofillTableTest, RemoveWrongServerCardMetadata) {
// Crete and set some metadata.
AutofillMetadata input;
@@ -2580,13 +2817,14 @@ TEST_P(GetFormValuesTest, GetFormValuesForElementName_SubstringMatchEnabled) {
table_->AddFormFieldValue(field, &changes);
}
- std::vector<base::string16> v;
+ std::vector<AutofillEntry> v;
table_->GetFormValuesForElementName(
ASCIIToUTF16("Name"), ASCIIToUTF16(test_case.field_contents), &v, 6);
EXPECT_EQ(test_case.expected_suggestion_count, v.size());
for (size_t j = 0; j < test_case.expected_suggestion_count; ++j) {
- EXPECT_EQ(ASCIIToUTF16(test_case.expected_suggestion[j]), v[j]);
+ EXPECT_EQ(ASCIIToUTF16(test_case.expected_suggestion[j]),
+ v[j].key().value());
}
changes.clear();
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
index c04756fd18c..98721d9d598 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
@@ -10,6 +10,7 @@
#include "base/base64.h"
#include "base/logging.h"
#include "base/optional.h"
+#include "base/pickle.h"
#include "components/autofill/core/browser/autofill_metadata.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/credit_card.h"
@@ -17,6 +18,7 @@
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/common/autofill_util.h"
#include "components/sync/model/entity_data.h"
#include "components/sync/model/mutable_data_batch.h"
#include "components/sync/model_impl/client_tag_based_model_type_processor.h"
@@ -27,6 +29,8 @@ namespace autofill {
namespace {
using sync_pb::WalletMetadataSpecifics;
+using syncer::EntityChange;
+using syncer::EntityChangeList;
using syncer::EntityData;
using syncer::MetadataChangeList;
@@ -46,10 +50,53 @@ std::string GetClientTagForSpecificsId(WalletMetadataSpecifics::Type type,
}
}
+// Returns the wallet metadata specifics id for the specified |metadata_id|.
+std::string GetSpecificsIdForMetadataId(const std::string& metadata_id) {
+ // Metadata id is in the raw format (like profiles/cards from WalletData)
+ // whereas the specifics id is base64-encoded.
+ return GetBase64EncodedId(metadata_id);
+}
+
+// Returns the wallet metadata id for the specified |specifics_id|.
+std::string GetMetadataIdForSpecificsId(const std::string& specifics_id) {
+ // The specifics id is base64-encoded whereas the metadata id is in the raw
+ // format (like profiles/cards from WalletData).
+ return GetBase64DecodedId(specifics_id);
+}
+
+// Returns the wallet metadata specifics storage key for the specified |type|
+// and |metadata_id|.
+std::string GetStorageKeyForWalletMetadataTypeAndId(
+ WalletMetadataSpecifics::Type type,
+ const std::string& metadata_id) {
+ return GetStorageKeyForWalletMetadataTypeAndSpecificsId(
+ type, GetSpecificsIdForMetadataId(metadata_id));
+}
+
+struct TypeAndMetadataId {
+ WalletMetadataSpecifics::Type type;
+ std::string metadata_id;
+};
+
+TypeAndMetadataId ParseWalletMetadataStorageKey(
+ const std::string& storage_key) {
+ TypeAndMetadataId parsed;
+
+ base::Pickle pickle(storage_key.data(), storage_key.size());
+ base::PickleIterator iterator(pickle);
+ int type_int;
+ if (!iterator.ReadInt(&type_int) ||
+ !iterator.ReadString(&parsed.metadata_id)) {
+ NOTREACHED() << "Unsupported storage_key provided " << storage_key;
+ }
+ parsed.type = static_cast<WalletMetadataSpecifics::Type>(type_int);
+ return parsed;
+}
+
// Returns EntityData for wallet_metadata for |local_metadata| and |type|.
std::unique_ptr<EntityData> CreateEntityDataFromAutofillMetadata(
- const AutofillMetadata& local_metadata,
- WalletMetadataSpecifics::Type type) {
+ WalletMetadataSpecifics::Type type,
+ const AutofillMetadata& local_metadata) {
auto entity_data = std::make_unique<EntityData>();
std::string specifics_id = GetSpecificsIdForMetadataId(local_metadata.id);
entity_data->non_unique_name = GetClientTagForSpecificsId(type, specifics_id);
@@ -69,10 +116,8 @@ std::unique_ptr<EntityData> CreateEntityDataFromAutofillMetadata(
}
case WalletMetadataSpecifics::CARD: {
// The strings must be in valid UTF-8 to sync.
- std::string billing_address_id;
- base::Base64Encode(local_metadata.billing_address_id,
- &billing_address_id);
- remote_metadata->set_card_billing_address_id(billing_address_id);
+ remote_metadata->set_card_billing_address_id(
+ GetBase64EncodedId(local_metadata.billing_address_id));
break;
}
case WalletMetadataSpecifics::UNKNOWN: {
@@ -84,18 +129,156 @@ std::unique_ptr<EntityData> CreateEntityDataFromAutofillMetadata(
return entity_data;
}
-// Returns EntityData for wallet_metadata for |local_profile|.
-std::unique_ptr<EntityData> CreateMetadataEntityDataFromAutofillServerProfile(
- const AutofillProfile& local_profile) {
- return CreateEntityDataFromAutofillMetadata(local_profile.GetMetadata(),
- WalletMetadataSpecifics::ADDRESS);
+// Returns AutofillMetadata for |specifics|.
+AutofillMetadata CreateAutofillMetadataFromWalletMetadataSpecifics(
+ const WalletMetadataSpecifics& specifics) {
+ AutofillMetadata metadata;
+ metadata.id = GetMetadataIdForSpecificsId(specifics.id());
+ metadata.use_count = specifics.use_count();
+ metadata.use_date = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(specifics.use_date()));
+
+ switch (specifics.type()) {
+ case WalletMetadataSpecifics::ADDRESS:
+ metadata.has_converted = specifics.address_has_converted();
+ break;
+ case WalletMetadataSpecifics::CARD:
+ metadata.billing_address_id =
+ GetBase64DecodedId(specifics.card_billing_address_id());
+ break;
+ case WalletMetadataSpecifics::UNKNOWN:
+ break;
+ }
+
+ return metadata;
+}
+
+bool HasLocalBillingAddress(const AutofillMetadata& metadata) {
+ return metadata.billing_address_id.size() == kLocalGuidSize;
+}
+
+bool IsRemoteBillingAddressEqualOrBetter(const AutofillMetadata& local,
+ const AutofillMetadata& remote) {
+ // If local is empty, remote is better (or equal). Otherwise, if remote is
+ // empty, local is better.
+ if (local.billing_address_id.empty()) {
+ return true;
+ } else if (remote.billing_address_id.empty()) {
+ return false;
+ }
+ // Now we need to decide between non-empty profiles. Prefer id's pointing to
+ // local profiles over ids of non-local profiles.
+ if (HasLocalBillingAddress(local) != HasLocalBillingAddress(remote)) {
+ return HasLocalBillingAddress(remote);
+ }
+ // For both local / both remote, we prefer the more recently used.
+ return remote.use_date >= local.use_date;
+}
+
+AutofillMetadata MergeMetadata(WalletMetadataSpecifics::Type type,
+ const AutofillMetadata& local,
+ const AutofillMetadata& remote) {
+ AutofillMetadata merged;
+ DCHECK_EQ(local.id, remote.id);
+ merged.id = local.id;
+
+ switch (type) {
+ case WalletMetadataSpecifics::ADDRESS:
+ merged.has_converted = local.has_converted || remote.has_converted;
+ break;
+ case WalletMetadataSpecifics::CARD:
+ if (IsRemoteBillingAddressEqualOrBetter(local, remote)) {
+ merged.billing_address_id = remote.billing_address_id;
+ } else {
+ merged.billing_address_id = local.billing_address_id;
+ }
+ break;
+ case WalletMetadataSpecifics::UNKNOWN:
+ NOTREACHED();
+ break;
+ }
+
+ // Special case for local models with a use_count of one. This means the local
+ // model was only created, never used. The remote model should always be
+ // preferred.
+ // This situation can happen for new Chromium instances where there is no data
+ // yet on disk, making the use_date artificially high. Once the metadata sync
+ // kicks in, we should use that value.
+ if (local.use_count == 1) {
+ merged.use_count = remote.use_count;
+ merged.use_date = remote.use_date;
+ } else {
+ merged.use_count = std::max(local.use_count, remote.use_count);
+ merged.use_date = std::max(local.use_date, remote.use_date);
+ }
+ return merged;
+}
+
+// Metadata is worth updating if its value is "newer" then before; here "newer"
+// is the ordering of legal state transitions that metadata can take that is
+// defined below.
+bool IsMetadataWorthUpdating(AutofillMetadata existing_entry,
+ AutofillMetadata new_entry) {
+ if (existing_entry.use_count < new_entry.use_count &&
+ existing_entry.use_date < new_entry.use_date) {
+ return true;
+ }
+ // For the following type-specific fields, we don't have to distinguish the
+ // type of metadata as both entries must be of the same type and therefore
+ // irrelevant values are default, thus equal.
+
+ // It is only legal to move from non-converted to converted. Do not accept
+ // the other transition.
+ if (!existing_entry.has_converted && new_entry.has_converted) {
+ return true;
+ }
+ if (existing_entry.billing_address_id != new_entry.billing_address_id) {
+ return true;
+ }
+ return false;
+}
+
+bool AddServerMetadata(AutofillTable* table,
+ WalletMetadataSpecifics::Type type,
+ const AutofillMetadata& metadata) {
+ switch (type) {
+ case WalletMetadataSpecifics::ADDRESS:
+ return table->AddServerAddressMetadata(metadata);
+ case WalletMetadataSpecifics::CARD:
+ return table->AddServerCardMetadata(metadata);
+ case WalletMetadataSpecifics::UNKNOWN:
+ NOTREACHED();
+ return false;
+ }
+}
+
+bool RemoveServerMetadata(AutofillTable* table,
+ WalletMetadataSpecifics::Type type,
+ const std::string& id) {
+ switch (type) {
+ case WalletMetadataSpecifics::ADDRESS:
+ return table->RemoveServerAddressMetadata(id);
+ case WalletMetadataSpecifics::CARD:
+ return table->RemoveServerCardMetadata(id);
+ case WalletMetadataSpecifics::UNKNOWN:
+ NOTREACHED();
+ return false;
+ }
}
-// Returns EntityData for wallet_metadata for |local_card|.
-std::unique_ptr<EntityData> CreateMetadataEntityDataFromCard(
- const CreditCard& local_card) {
- return CreateEntityDataFromAutofillMetadata(local_card.GetMetadata(),
- WalletMetadataSpecifics::CARD);
+bool UpdateServerMetadata(AutofillTable* table,
+ WalletMetadataSpecifics::Type type,
+ const AutofillMetadata& metadata) {
+ // TODO: Create UpdateServerAddressMetadata() that takes metadata as arg.
+ switch (type) {
+ case WalletMetadataSpecifics::ADDRESS:
+ return table->UpdateServerAddressMetadata(metadata);
+ case WalletMetadataSpecifics::CARD:
+ return table->UpdateServerCardMetadata(metadata);
+ case WalletMetadataSpecifics::UNKNOWN:
+ NOTREACHED();
+ return false;
+ }
}
} // namespace
@@ -155,16 +338,19 @@ base::Optional<syncer::ModelError>
AutofillWalletMetadataSyncBridge::MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) {
- NOTIMPLEMENTED();
- return base::nullopt;
+ // First upload local entities that are not mentioned in |entity_data|.
+ UploadInitialLocalData(metadata_change_list.get(), entity_data);
+
+ return MergeRemoteChanges(std::move(metadata_change_list),
+ std::move(entity_data));
}
base::Optional<syncer::ModelError>
AutofillWalletMetadataSyncBridge::ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) {
- NOTIMPLEMENTED();
- return base::nullopt;
+ return MergeRemoteChanges(std::move(metadata_change_list),
+ std::move(entity_data));
}
void AutofillWalletMetadataSyncBridge::GetData(StorageKeyList storage_keys,
@@ -191,70 +377,25 @@ std::string AutofillWalletMetadataSyncBridge::GetClientTag(
std::string AutofillWalletMetadataSyncBridge::GetStorageKey(
const syncer::EntityData& entity_data) {
- return GetStorageKeyForSpecificsId(
+ return GetStorageKeyForWalletMetadataTypeAndSpecificsId(
+ entity_data.specifics.wallet_metadata().type(),
entity_data.specifics.wallet_metadata().id());
}
void AutofillWalletMetadataSyncBridge::AutofillProfileChanged(
const AutofillProfileChange& change) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- const AutofillProfile* changed = change.data_model();
- if (!changed || changed->record_type() != AutofillProfile::SERVER_PROFILE) {
+ // Skip local profiles (if possible, i.e. if it is not a deletion where
+ // data_model() is not set).
+ if (change.data_model() &&
+ change.data_model()->record_type() != AutofillProfile::SERVER_PROFILE) {
return;
}
-
- // The only legal change on a server profile is that its use count or use date
- // or has-converted status gets updated. Other changes (adding, deleting) are
- // only done by the AutofillWalletSyncBridge and result only in the
- // AutofillMultipleChanged() notification.
- DCHECK(change.type() == AutofillProfileChange::UPDATE);
- SyncUpUpdatedEntity(
- CreateMetadataEntityDataFromAutofillServerProfile(*changed));
+ LocalMetadataChanged(WalletMetadataSpecifics::ADDRESS, change);
}
void AutofillWalletMetadataSyncBridge::CreditCardChanged(
const CreditCardChange& change) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- const CreditCard* changed = change.data_model();
- if (!changed || changed->record_type() == CreditCard::LOCAL_CARD) {
- return;
- }
-
- // The only legal change on a server card is that its use count or use date or
- // billing address id gets updated. Other changes (adding, deleting) are only
- // done by the AutofillWalletSyncBridge and result only in the
- // AutofillMultipleChanged() notification.
- DCHECK(change.type() == CreditCardChange::UPDATE);
- SyncUpUpdatedEntity(CreateMetadataEntityDataFromCard(*changed));
-}
-
-void AutofillWalletMetadataSyncBridge::AutofillMultipleChanged() {
- NOTIMPLEMENTED();
-}
-
-void AutofillWalletMetadataSyncBridge::SyncUpUpdatedEntity(
- std::unique_ptr<EntityData> entity_after_change) {
- std::string storage_key = GetStorageKey(*entity_after_change);
- auto it = cache_.find(storage_key);
-
- // This *changed* entity should already be in the cache, ignore otherwise.
- if (it == cache_.end())
- return;
-
- const WalletMetadataSpecifics& specifics_before = it->second;
- const WalletMetadataSpecifics& specifics_after =
- entity_after_change->specifics.wallet_metadata();
-
- if (specifics_before.use_count() < specifics_after.use_count() &&
- specifics_before.use_date() < specifics_after.use_date()) {
- std::unique_ptr<MetadataChangeList> metadata_change_list =
- CreateMetadataChangeList();
- cache_[storage_key] = specifics_after;
- change_processor()->Put(storage_key, std::move(entity_after_change),
- metadata_change_list.get());
- }
+ LocalMetadataChanged(WalletMetadataSpecifics::CARD, change);
}
AutofillTable* AutofillWalletMetadataSyncBridge::GetAutofillTable() {
@@ -269,23 +410,23 @@ void AutofillWalletMetadataSyncBridge::LoadDataCacheAndMetadata() {
return;
}
- // Load the data cache.
- std::vector<std::unique_ptr<AutofillProfile>> profiles;
- std::vector<std::unique_ptr<CreditCard>> cards;
- if (!GetAutofillTable()->GetServerProfiles(&profiles) ||
- !GetAutofillTable()->GetServerCreditCards(&cards)) {
+ // Load the data cache (both addresses and cards into the same cache, the keys
+ // in the cache never overlap).
+ std::map<std::string, AutofillMetadata> addresses_metadata;
+ std::map<std::string, AutofillMetadata> cards_metadata;
+ if (!GetAutofillTable()->GetServerAddressesMetadata(&addresses_metadata) ||
+ !GetAutofillTable()->GetServerCardsMetadata(&cards_metadata)) {
change_processor()->ReportError(
{FROM_HERE, "Failed reading autofill data from WebDatabase."});
return;
}
- for (const std::unique_ptr<AutofillProfile>& entry : profiles) {
- cache_[GetStorageKeyForMetadataId(entry->GetMetadata().id)] =
- CreateMetadataEntityDataFromAutofillServerProfile(*entry)
- ->specifics.wallet_metadata();
+ for (const auto& it : addresses_metadata) {
+ cache_[GetStorageKeyForWalletMetadataTypeAndId(
+ WalletMetadataSpecifics::ADDRESS, it.first)] = it.second;
}
- for (const std::unique_ptr<CreditCard>& entry : cards) {
- cache_[GetStorageKeyForMetadataId(entry->GetMetadata().id)] =
- CreateMetadataEntityDataFromCard(*entry)->specifics.wallet_metadata();
+ for (const auto& it : cards_metadata) {
+ cache_[GetStorageKeyForWalletMetadataTypeAndId(
+ WalletMetadataSpecifics::CARD, it.first)] = it.second;
}
// Load the metadata and send to the processor.
@@ -305,32 +446,166 @@ void AutofillWalletMetadataSyncBridge::GetDataImpl(
DataCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- std::vector<std::unique_ptr<AutofillProfile>> profiles;
- std::vector<std::unique_ptr<CreditCard>> cards;
- if (!GetAutofillTable()->GetServerProfiles(&profiles) ||
- !GetAutofillTable()->GetServerCreditCards(&cards)) {
- change_processor()->ReportError(
- {FROM_HERE, "Failed to load entries from table."});
- return;
- }
-
auto batch = std::make_unique<syncer::MutableDataBatch>();
- for (const std::unique_ptr<AutofillProfile>& entry : profiles) {
- std::string key = GetStorageKeyForMetadataId(entry->GetMetadata().id);
- if (!storage_keys_set || base::ContainsKey(*storage_keys_set, key)) {
- batch->Put(key,
- CreateMetadataEntityDataFromAutofillServerProfile(*entry));
+ for (const auto& pair : cache_) {
+ const std::string& storage_key = pair.first;
+ const AutofillMetadata& metadata = pair.second;
+ TypeAndMetadataId parsed_storage_key =
+ ParseWalletMetadataStorageKey(storage_key);
+ if (!storage_keys_set ||
+ base::ContainsKey(*storage_keys_set, storage_key)) {
+ batch->Put(storage_key, CreateEntityDataFromAutofillMetadata(
+ parsed_storage_key.type, metadata));
}
}
- for (const std::unique_ptr<CreditCard>& entry : cards) {
- std::string key = GetStorageKeyForMetadataId(entry->GetMetadata().id);
- if (!storage_keys_set || base::ContainsKey(*storage_keys_set, key)) {
- batch->Put(key, CreateMetadataEntityDataFromCard(*entry));
+
+ std::move(callback).Run(std::move(batch));
+}
+
+void AutofillWalletMetadataSyncBridge::UploadInitialLocalData(
+ syncer::MetadataChangeList* metadata_change_list,
+ const syncer::EntityChangeList& entity_data) {
+ // First, make a copy of all local storage keys.
+ std::set<std::string> local_keys_to_upload;
+ for (const auto& it : cache_) {
+ local_keys_to_upload.insert(it.first);
+ }
+ // Strip |local_keys_to_upload| of the keys of data provided by the server.
+ for (const EntityChange& change : entity_data) {
+ DCHECK_EQ(change.type(), EntityChange::ACTION_ADD)
+ << "Illegal change; can only be called during initial MergeSyncData()";
+ local_keys_to_upload.erase(change.storage_key());
+ }
+ // Upload the remaining storage keys
+ for (const std::string& storage_key : local_keys_to_upload) {
+ TypeAndMetadataId parsed_storage_key =
+ ParseWalletMetadataStorageKey(storage_key);
+ change_processor()->Put(storage_key,
+ CreateEntityDataFromAutofillMetadata(
+ parsed_storage_key.type, cache_[storage_key]),
+ metadata_change_list);
+ }
+}
+
+base::Optional<syncer::ModelError>
+AutofillWalletMetadataSyncBridge::MergeRemoteChanges(
+ std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+ syncer::EntityChangeList entity_data) {
+ bool is_any_local_modified = false;
+
+ AutofillTable* table = GetAutofillTable();
+
+ for (const EntityChange& change : entity_data) {
+ TypeAndMetadataId parsed_storage_key =
+ ParseWalletMetadataStorageKey(change.storage_key());
+ switch (change.type()) {
+ case EntityChange::ACTION_ADD:
+ case EntityChange::ACTION_UPDATE: {
+ const WalletMetadataSpecifics& specifics =
+ change.data().specifics.wallet_metadata();
+ AutofillMetadata remote =
+ CreateAutofillMetadataFromWalletMetadataSpecifics(specifics);
+ auto it = cache_.find(change.storage_key());
+ base::Optional<AutofillMetadata> local = base::nullopt;
+ if (it != cache_.end()) {
+ local = it->second;
+ }
+
+ if (!local) {
+ cache_[change.storage_key()] = remote;
+ is_any_local_modified |= AddServerMetadata(
+ GetAutofillTable(), parsed_storage_key.type, remote);
+ continue;
+ }
+
+ // Resolve the conflict between the local and the newly received remote.
+ AutofillMetadata merged =
+ MergeMetadata(parsed_storage_key.type, *local, remote);
+ if (merged != *local) {
+ cache_[change.storage_key()] = merged;
+ is_any_local_modified |=
+ UpdateServerMetadata(table, parsed_storage_key.type, merged);
+ }
+ if (merged != remote) {
+ change_processor()->Put(change.storage_key(),
+ CreateEntityDataFromAutofillMetadata(
+ parsed_storage_key.type, merged),
+ metadata_change_list.get());
+ }
+ break;
+ }
+ case EntityChange::ACTION_DELETE: {
+ cache_.erase(change.storage_key());
+ is_any_local_modified |= RemoveServerMetadata(
+ table, parsed_storage_key.type, parsed_storage_key.metadata_id);
+ break;
+ }
}
}
- std::move(callback).Run(std::move(batch));
+ if (is_any_local_modified) {
+ web_data_backend_->NotifyOfMultipleAutofillChanges();
+ }
+ return base::nullopt;
+}
+
+template <class DataType>
+void AutofillWalletMetadataSyncBridge::LocalMetadataChanged(
+ WalletMetadataSpecifics::Type type,
+ AutofillDataModelChange<DataType> change) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ const std::string& metadata_id = change.key();
+ std::string storage_key =
+ GetStorageKeyForWalletMetadataTypeAndId(type, metadata_id);
+ std::unique_ptr<MetadataChangeList> metadata_change_list =
+ CreateMetadataChangeList();
+
+ switch (change.type()) {
+ case AutofillProfileChange::EXPIRE:
+ NOTREACHED() << "EXPIRE change is not allowed for wallet entities";
+ return;
+ case AutofillProfileChange::REMOVE:
+ if (RemoveServerMetadata(GetAutofillTable(), type, metadata_id)) {
+ cache_.erase(storage_key);
+ // Send up deletion only if we had this entry in the DB. It is not there
+ // if (i) it was previously deleted by a remote deletion or (ii) this is
+ // notification for a LOCAL_PROFILE (which have non-overlapping
+ // storage_keys).
+ change_processor()->Delete(storage_key, metadata_change_list.get());
+ }
+ return;
+ case AutofillProfileChange::ADD:
+ case AutofillProfileChange::UPDATE:
+ DCHECK(change.data_model());
+
+ AutofillMetadata new_entry = change.data_model()->GetMetadata();
+ auto it = cache_.find(storage_key);
+ base::Optional<AutofillMetadata> existing_entry = base::nullopt;
+ if (it != cache_.end()) {
+ existing_entry = it->second;
+ }
+
+ if (existing_entry &&
+ !IsMetadataWorthUpdating(*existing_entry, new_entry)) {
+ // Skip changes that are outdated, etc. (changes that would result in
+ // inferior metadata compared to what we have now).
+ return;
+ }
+
+ cache_[storage_key] = new_entry;
+ if (existing_entry) {
+ UpdateServerMetadata(GetAutofillTable(), type, new_entry);
+ } else {
+ AddServerMetadata(GetAutofillTable(), type, new_entry);
+ }
+
+ change_processor()->Put(
+ storage_key, CreateEntityDataFromAutofillMetadata(type, new_entry),
+ metadata_change_list.get());
+ return;
+ }
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h
index 59241199da3..16feaf2dd78 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h
@@ -78,18 +78,14 @@ class AutofillWalletMetadataSyncBridge
// AutofillWebDataServiceObserverOnDBSequence implementation.
void AutofillProfileChanged(const AutofillProfileChange& change) override;
void CreditCardChanged(const CreditCardChange& change) override;
- void AutofillMultipleChanged() override;
private:
- // Syncs up an updated entity |entity_after_change| (if needed).
- void SyncUpUpdatedEntity(
- std::unique_ptr<syncer::EntityData> entity_after_change);
-
// Returns the table associated with the |web_data_backend_|.
AutofillTable* GetAutofillTable();
- // Synchronously load |cache_| and sync metadata from the autofill table
- // and pass the latter to the processor so that it can start tracking changes.
+ // Synchronously load the sync data into |cache_| and sync metadata from the
+ // autofill table and pass the latter to the processor so that it can start
+ // tracking changes.
void LoadDataCacheAndMetadata();
// Reads local wallet metadata from the database and passes them into
@@ -99,6 +95,23 @@ class AutofillWalletMetadataSyncBridge
base::Optional<std::unordered_set<std::string>> storage_keys_set,
DataCallback callback);
+ // Uploads local data that is not part of |entity_data| sent from the server
+ // during initial MergeSyncData().
+ void UploadInitialLocalData(syncer::MetadataChangeList* metadata_change_list,
+ const syncer::EntityChangeList& entity_data);
+
+ // Merges remote changes, specified in |entity_data|, with the local DB and,
+ // potentially, writes changes to the local DB and/or commits updates of
+ // entities from |entity_data| up to sync.
+ base::Optional<syncer::ModelError> MergeRemoteChanges(
+ std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+ syncer::EntityChangeList entity_data);
+
+ // Reacts to a local |change| of an entry of type |type|.
+ template <class DataType>
+ void LocalMetadataChanged(sync_pb::WalletMetadataSpecifics::Type type,
+ AutofillDataModelChange<DataType> change);
+
// AutofillWalletMetadataSyncBridge is owned by |web_data_backend_| through
// SupportsUserData, so it's guaranteed to outlive |this|.
AutofillWebDataBackend* const web_data_backend_;
@@ -106,10 +119,9 @@ class AutofillWalletMetadataSyncBridge
ScopedObserver<AutofillWebDataBackend, AutofillWalletMetadataSyncBridge>
scoped_observer_;
- // Cache of the data (local data + data that hasn't synced down yet); keyed by
- // storage keys. Needed for figuring out what to sync up when larger changes
- // happen in the local database.
- std::unordered_map<std::string, sync_pb::WalletMetadataSpecifics> cache_;
+ // Cache of the local data that allows figuring out the diff for local
+ // changes; keyed by storage keys.
+ std::map<std::string, AutofillMetadata> cache_;
// Indicates whether we should rely on wallet data being actively synced. If
// true, the bridge will prune metadata entries without corresponding wallet
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 2b0de491dcb..4306ae52280 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
@@ -6,6 +6,7 @@
#include <stddef.h>
+#include <algorithm>
#include <memory>
#include <sstream>
#include <utility>
@@ -14,7 +15,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_task_environment.h"
#include "base/time/time.h"
@@ -23,6 +24,7 @@
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.h"
+#include "components/autofill/core/browser/webdata/autofill_sync_bridge_util.h"
#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"
@@ -48,6 +50,7 @@ using syncer::MockModelTypeChangeProcessor;
using syncer::ModelType;
using testing::_;
using testing::ElementsAre;
+using testing::ElementsAreArray;
using testing::IsEmpty;
using testing::Return;
using testing::UnorderedElementsAre;
@@ -65,6 +68,15 @@ const char kAddr2SpecificsId[] = "YWRkcjLvv74=";
const char kCard1SpecificsId[] = "Y2FyZDHvv74=";
const char kCard2SpecificsId[] = "Y2FyZDLvv74=";
+const std::string kAddr1StorageKey =
+ GetStorageKeyForWalletMetadataTypeAndSpecificsId(
+ WalletMetadataSpecifics::ADDRESS,
+ kAddr1SpecificsId);
+const std::string kCard1StorageKey =
+ GetStorageKeyForWalletMetadataTypeAndSpecificsId(
+ WalletMetadataSpecifics::CARD,
+ kCard1SpecificsId);
+
// Unique sync tags for the server IDs.
const char kAddr1SyncTag[] = "address-YWRkcjHvv74=";
const char kCard1SyncTag[] = "card-Y2FyZDHvv74=";
@@ -81,6 +93,16 @@ int64_t UseDateToProtoValue(base::Time use_date) {
return use_date.ToDeltaSinceWindowsEpoch().InMicroseconds();
}
+std::string GetAddressStorageKey(const std::string& specifics_id) {
+ return GetStorageKeyForWalletMetadataTypeAndSpecificsId(
+ WalletMetadataSpecifics::ADDRESS, specifics_id);
+}
+
+std::string GetCardStorageKey(const std::string& specifics_id) {
+ return GetStorageKeyForWalletMetadataTypeAndSpecificsId(
+ WalletMetadataSpecifics::CARD, specifics_id);
+}
+
WalletMetadataSpecifics CreateWalletMetadataSpecificsForAddressWithUseStats(
const std::string& specifics_id,
size_t use_count,
@@ -173,6 +195,16 @@ std::string WalletMetadataSpecificsAsDebugString(
return output.str();
}
+std::vector<std::string> GetSortedSerializedSpecifics(
+ const std::vector<WalletMetadataSpecifics>& specifics) {
+ std::vector<std::string> serialized;
+ for (const WalletMetadataSpecifics& entry : specifics) {
+ serialized.push_back(entry.SerializeAsString());
+ }
+ std::sort(serialized.begin(), serialized.end());
+ return serialized;
+}
+
MATCHER_P(EqualsSpecifics, expected, "") {
if (arg.SerializeAsString() != expected.SerializeAsString()) {
*result_listener << "entry\n"
@@ -250,6 +282,18 @@ class AutofillWalletMetadataSyncBridgeTest : public testing::Test {
return data;
}
+ // Like GetAllData() but it also checks that cache is consistent with the disk
+ // content.
+ std::vector<WalletMetadataSpecifics> GetAllLocalDataInclRestart() {
+ std::vector<WalletMetadataSpecifics> data_before = GetAllLocalData();
+ ResetProcessor();
+ ResetBridge();
+ std::vector<WalletMetadataSpecifics> data_after = GetAllLocalData();
+ EXPECT_THAT(GetSortedSerializedSpecifics(data_before),
+ ElementsAreArray(GetSortedSerializedSpecifics(data_after)));
+ return data_after;
+ }
+
std::vector<WalletMetadataSpecifics> GetLocalData(
AutofillWalletMetadataSyncBridge::StorageKeyList storage_keys) {
std::vector<WalletMetadataSpecifics> data;
@@ -313,7 +357,7 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest, GetStorageKeyForAddress) {
WalletMetadataSpecifics specifics =
CreateWalletMetadataSpecificsForAddress(kAddr1SpecificsId);
EXPECT_EQ(bridge()->GetStorageKey(SpecificsToEntity(specifics)),
- kAddr1SpecificsId);
+ GetAddressStorageKey(kAddr1SpecificsId));
}
TEST_F(AutofillWalletMetadataSyncBridgeTest, GetStorageKeyForCard) {
@@ -321,7 +365,7 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest, GetStorageKeyForCard) {
WalletMetadataSpecifics specifics =
CreateWalletMetadataSpecificsForCard(kCard1SpecificsId);
EXPECT_EQ(bridge()->GetStorageKey(SpecificsToEntity(specifics)),
- kCard1SpecificsId);
+ GetCardStorageKey(kCard1SpecificsId));
}
TEST_F(AutofillWalletMetadataSyncBridgeTest,
@@ -348,7 +392,8 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest,
TEST_F(AutofillWalletMetadataSyncBridgeTest,
GetData_ShouldNotReturnNonexistentData) {
ResetBridge();
- EXPECT_THAT(GetLocalData({kAddr1SpecificsId}), IsEmpty());
+ EXPECT_THAT(GetLocalData({GetAddressStorageKey(kAddr1SpecificsId)}),
+ IsEmpty());
}
TEST_F(AutofillWalletMetadataSyncBridgeTest, GetData_ShouldReturnSelectedData) {
@@ -358,7 +403,8 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest, GetData_ShouldReturnSelectedData) {
CreateServerCreditCard(kCard2ServerId)});
ResetBridge();
- EXPECT_THAT(GetLocalData({kAddr1SpecificsId, kCard1SpecificsId}),
+ EXPECT_THAT(GetLocalData({GetAddressStorageKey(kAddr1SpecificsId),
+ GetCardStorageKey(kCard1SpecificsId)}),
UnorderedElementsAre(
EqualsSpecifics(CreateWalletMetadataSpecificsForAddress(
kAddr1SpecificsId)),
@@ -393,7 +439,8 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest, GetData_ShouldReturnCompleteData) {
card_specifics.set_use_date(3);
card_specifics.set_card_billing_address_id(kAddr1SpecificsId);
- EXPECT_THAT(GetLocalData({kAddr1SpecificsId, kCard1SpecificsId}),
+ EXPECT_THAT(GetLocalData({GetAddressStorageKey(kAddr1SpecificsId),
+ GetCardStorageKey(kCard1SpecificsId)}),
UnorderedElementsAre(EqualsSpecifics(profile_specifics),
EqualsSpecifics(card_specifics)));
}
@@ -401,7 +448,7 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest, GetData_ShouldReturnCompleteData) {
// Verify that lower values of metadata are not sent to the sync server when
// local metadata is updated.
TEST_F(AutofillWalletMetadataSyncBridgeTest,
- DontSendLowerValueToServerOnSingleChange) {
+ DontSendLowerValueToServerOnUpdate) {
table()->SetServerProfiles({CreateServerProfileWithUseStats(
kAddr1ServerId, /*use_count=*/2, /*use_date=*/5)});
table()->SetServerCreditCards({CreateServerCreditCardWithUseStats(
@@ -415,48 +462,103 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest,
EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
- bridge()->AutofillProfileChanged(AutofillProfileChange(
- AutofillProfileChange::UPDATE, updated_profile.guid(), &updated_profile));
+ bridge()->AutofillProfileChanged(
+ AutofillProfileChange(AutofillProfileChange::UPDATE,
+ updated_profile.server_id(), &updated_profile));
bridge()->CreditCardChanged(CreditCardChange(
- CreditCardChange::UPDATE, updated_card.guid(), &updated_card));
+ CreditCardChange::UPDATE, updated_card.server_id(), &updated_card));
+
+ // Check that also the local metadata did not get updated.
+ EXPECT_THAT(
+ GetAllLocalDataInclRestart(),
+ UnorderedElementsAre(
+ EqualsSpecifics(CreateWalletMetadataSpecificsForAddressWithUseStats(
+ kAddr1SpecificsId, /*use_count=*/2, /*use_date=*/5)),
+ EqualsSpecifics(CreateWalletMetadataSpecificsForCardWithUseStats(
+ kCard1SpecificsId, /*use_count=*/3, /*use_date=*/6))));
}
-// Verify that one-off addition of metadata is not sent to the sync
-// server. Metadata add and delete trigger multiple changes notification
-// instead.
-TEST_F(AutofillWalletMetadataSyncBridgeTest, DontAddToServerOnSingleChange) {
+// Verify that higher values of metadata are sent to the sync server when local
+// metadata is updated.
+TEST_F(AutofillWalletMetadataSyncBridgeTest,
+ SendHigherValuesToServerOnLocalUpdate) {
table()->SetServerProfiles({CreateServerProfileWithUseStats(
kAddr1ServerId, /*use_count=*/1, /*use_date=*/2)});
table()->SetServerCreditCards({CreateServerCreditCardWithUseStats(
kCard1ServerId, /*use_count=*/3, /*use_date=*/4)});
ResetBridge();
+ AutofillProfile updated_profile = CreateServerProfileWithUseStats(
+ kAddr1ServerId, /*use_count=*/10, /*use_date=*/20);
+ CreditCard updated_card = CreateServerCreditCardWithUseStats(
+ kCard1ServerId, /*use_count=*/30, /*use_date=*/40);
+
+ WalletMetadataSpecifics expected_profile_specifics =
+ CreateWalletMetadataSpecificsForAddressWithUseStats(
+ kAddr1SpecificsId, /*use_count=*/10, /*use_date=*/20);
+ WalletMetadataSpecifics expected_card_specifics =
+ CreateWalletMetadataSpecificsForCardWithUseStats(
+ kCard1SpecificsId, /*use_count=*/30, /*use_date=*/40);
+
+ EXPECT_CALL(
+ mock_processor(),
+ Put(kAddr1StorageKey, HasSpecifics(expected_profile_specifics), _));
+ EXPECT_CALL(mock_processor(),
+ Put(kCard1StorageKey, HasSpecifics(expected_card_specifics), _));
+
+ bridge()->AutofillProfileChanged(
+ AutofillProfileChange(AutofillProfileChange::UPDATE,
+ updated_profile.server_id(), &updated_profile));
+ bridge()->CreditCardChanged(CreditCardChange(
+ CreditCardChange::UPDATE, updated_card.server_id(), &updated_card));
+
+ // Check that the local metadata got update as well.
+ EXPECT_THAT(GetAllLocalDataInclRestart(),
+ UnorderedElementsAre(EqualsSpecifics(expected_profile_specifics),
+ EqualsSpecifics(expected_card_specifics)));
+}
+
+// Verify that one-off addition of metadata is sent to the sync server.
+TEST_F(AutofillWalletMetadataSyncBridgeTest,
+ SendNewDataToServerOnLocalAddition) {
+ ResetBridge();
AutofillProfile new_profile = CreateServerProfileWithUseStats(
- kAddr2ServerId, /*use_count=*/10, /*use_date=*/20);
+ kAddr1ServerId, /*use_count=*/10, /*use_date=*/20);
CreditCard new_card = CreateServerCreditCardWithUseStats(
- kCard2ServerId, /*use_count=*/30, /*use_date=*/40);
+ kCard1ServerId, /*use_count=*/30, /*use_date=*/40);
- EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
+ WalletMetadataSpecifics expected_profile_specifics =
+ CreateWalletMetadataSpecificsForAddressWithUseStats(
+ kAddr1SpecificsId, /*use_count=*/10, /*use_date=*/20);
+ WalletMetadataSpecifics expected_card_specifics =
+ CreateWalletMetadataSpecificsForCardWithUseStats(
+ kCard1SpecificsId, /*use_count=*/30, /*use_date=*/40);
+
+ EXPECT_CALL(
+ mock_processor(),
+ Put(kAddr1StorageKey, HasSpecifics(expected_profile_specifics), _));
+ EXPECT_CALL(mock_processor(),
+ Put(kCard1StorageKey, HasSpecifics(expected_card_specifics), _));
bridge()->AutofillProfileChanged(AutofillProfileChange(
- AutofillProfileChange::UPDATE, new_profile.guid(), &new_profile));
+ AutofillProfileChange::ADD, new_profile.server_id(), &new_profile));
bridge()->CreditCardChanged(
- CreditCardChange(CreditCardChange::UPDATE, new_card.guid(), &new_card));
+ CreditCardChange(CreditCardChange::ADD, new_card.server_id(), &new_card));
+
+ // Check that the new metadata got created as well.
+ EXPECT_THAT(GetAllLocalDataInclRestart(),
+ UnorderedElementsAre(EqualsSpecifics(expected_profile_specifics),
+ EqualsSpecifics(expected_card_specifics)));
}
-// Verify that higher values of metadata are sent to the sync server when local
-// metadata is updated.
-TEST_F(AutofillWalletMetadataSyncBridgeTest,
- SendHigherValuesToServerOnLocalSingleChange) {
- table()->SetServerProfiles({CreateServerProfileWithUseStats(
- kAddr1ServerId, /*use_count=*/1, /*use_date=*/2)});
- table()->SetServerCreditCards({CreateServerCreditCardWithUseStats(
- kCard1ServerId, /*use_count=*/3, /*use_date=*/4)});
+// Verify that one-off addition of metadata is sent to the sync server (even
+// though it is notified as an update). This tests that the bridge is robust and
+// recreates metadata that may get deleted in the mean-time).
+TEST_F(AutofillWalletMetadataSyncBridgeTest, SendNewDataToServerOnLocalUpdate) {
ResetBridge();
-
- AutofillProfile updated_profile = CreateServerProfileWithUseStats(
+ AutofillProfile new_profile = CreateServerProfileWithUseStats(
kAddr1ServerId, /*use_count=*/10, /*use_date=*/20);
- CreditCard updated_card = CreateServerCreditCardWithUseStats(
+ CreditCard new_card = CreateServerCreditCardWithUseStats(
kCard1ServerId, /*use_count=*/30, /*use_date=*/40);
WalletMetadataSpecifics expected_profile_specifics =
@@ -468,14 +570,69 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest,
EXPECT_CALL(
mock_processor(),
- Put(kAddr1SpecificsId, HasSpecifics(expected_profile_specifics), _));
+ Put(kAddr1StorageKey, HasSpecifics(expected_profile_specifics), _));
EXPECT_CALL(mock_processor(),
- Put(kCard1SpecificsId, HasSpecifics(expected_card_specifics), _));
+ Put(kCard1StorageKey, HasSpecifics(expected_card_specifics), _));
bridge()->AutofillProfileChanged(AutofillProfileChange(
- AutofillProfileChange::UPDATE, updated_profile.guid(), &updated_profile));
+ AutofillProfileChange::UPDATE, new_profile.server_id(), &new_profile));
bridge()->CreditCardChanged(CreditCardChange(
- CreditCardChange::UPDATE, updated_card.guid(), &updated_card));
+ CreditCardChange::UPDATE, new_card.server_id(), &new_card));
+
+ // Check that the new metadata got created as well.
+ EXPECT_THAT(GetAllLocalDataInclRestart(),
+ UnorderedElementsAre(EqualsSpecifics(expected_profile_specifics),
+ EqualsSpecifics(expected_card_specifics)));
+}
+
+// Verify that one-off deletion of existing metadata is sent to the sync server.
+TEST_F(AutofillWalletMetadataSyncBridgeTest,
+ DeleteExistingDataFromServerOnLocalDeletion) {
+ AutofillProfile existing_profile = CreateServerProfileWithUseStats(
+ kAddr1ServerId, /*use_count=*/10, /*use_date=*/20);
+ CreditCard existing_card = CreateServerCreditCardWithUseStats(
+ kCard1ServerId, /*use_count=*/30, /*use_date=*/40);
+ table()->SetServerProfiles({existing_profile});
+ table()->SetServerCreditCards({existing_card});
+ ResetBridge();
+
+ EXPECT_CALL(mock_processor(), Delete(kAddr1StorageKey, _));
+ EXPECT_CALL(mock_processor(), Delete(kCard1StorageKey, _));
+
+ bridge()->AutofillProfileChanged(AutofillProfileChange(
+ AutofillProfileChange::REMOVE, existing_profile.server_id(), nullptr));
+ bridge()->CreditCardChanged(CreditCardChange(
+ CreditCardChange::REMOVE, existing_card.server_id(), nullptr));
+
+ // Check that there is no metadata anymore.
+ EXPECT_THAT(GetAllLocalDataInclRestart(), IsEmpty());
+}
+
+// Verify that deletion of non-existing metadata is not sent to the sync server.
+TEST_F(AutofillWalletMetadataSyncBridgeTest,
+ DoNotDeleteNonExistingDataFromServerOnLocalDeletion) {
+ AutofillProfile existing_profile = CreateServerProfileWithUseStats(
+ kAddr1ServerId, /*use_count=*/10, /*use_date=*/20);
+ CreditCard existing_card = CreateServerCreditCardWithUseStats(
+ kCard1ServerId, /*use_count=*/30, /*use_date=*/40);
+ // Save only data and not metadata.
+ table()->SetServerAddressesData({existing_profile});
+ table()->SetServerCardsData({existing_card});
+ ResetBridge();
+
+ // Check that there is no metadata, from start on.
+ ASSERT_THAT(GetAllLocalDataInclRestart(), IsEmpty());
+
+ EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0);
+ EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0);
+
+ bridge()->AutofillProfileChanged(AutofillProfileChange(
+ AutofillProfileChange::REMOVE, existing_profile.server_id(), nullptr));
+ bridge()->CreditCardChanged(CreditCardChange(
+ CreditCardChange::REMOVE, existing_card.server_id(), nullptr));
+
+ // Check that there is also no metadata at the end.
+ EXPECT_THAT(GetAllLocalDataInclRestart(), IsEmpty());
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
index 40ef9b40ee7..86fd8a07dff 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
@@ -511,6 +511,8 @@ syncer::SyncError AutofillWalletMetadataSyncableService::ProcessSyncChanges(
// get rid of this hack.
DCHECK(!ignore_multiple_changed_notification_);
ignore_multiple_changed_notification_ = true;
+ // TODO(crbug.com/915229): Remove once the investigation is over.
+ DLOG(WARNING) << this << " ProcessSyncChanges notify the PDM";
web_data_backend_->NotifyOfMultipleAutofillChanges();
ignore_multiple_changed_notification_ = false;
}
@@ -539,8 +541,13 @@ void AutofillWalletMetadataSyncableService::AutofillProfileChanged(
it->GetSpecifics().wallet_metadata();
const AutofillProfile& local = *change.data_model();
+ // TODO(crbug.com/915229): Remove once the investigation is over.
+ DLOG(WARNING) << this << " AutofillProfileChanged " << local;
+
if (!AreLocalUseStatsUpdated(remote, local) &&
!IsLocalHasConvertedStatusUpdated(remote, local)) {
+ // TODO(crbug.com/915229): Remove once the investigation is over.
+ DLOG(WARNING) << this << " Nothing has changed, not syncing up.";
return;
}
@@ -604,8 +611,8 @@ void AutofillWalletMetadataSyncableService::CreateForWebDataServiceAndBackend(
const std::string& app_locale) {
web_data_service->GetDBUserData()->SetUserData(
AutofillWalletMetadataSyncableServiceUserDataKey(),
- base::WrapUnique(new AutofillWalletMetadataSyncableService(
- web_data_backend, app_locale)));
+ std::make_unique<AutofillWalletMetadataSyncableService>(web_data_backend,
+ app_locale));
}
// static
@@ -655,6 +662,8 @@ bool AutofillWalletMetadataSyncableService::GetLocalData(
bool AutofillWalletMetadataSyncableService::UpdateAddressStats(
const AutofillProfile& profile) {
+ // TODO(crbug.com/915229): Remove once the investigation is over.
+ DLOG(WARNING) << this << " Applying change from sync " << profile;
return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase())
->UpdateServerAddressMetadata(profile);
}
@@ -754,6 +763,8 @@ syncer::SyncMergeResult AutofillWalletMetadataSyncableService::MergeData(
// get rid of this hack.
DCHECK(!ignore_multiple_changed_notification_);
ignore_multiple_changed_notification_ = true;
+ // TODO(crbug.com/915229): Remove once the investigation is over.
+ DLOG(WARNING) << this << " MergeData notify the PDM";
web_data_backend_->NotifyOfMultipleAutofillChanges();
ignore_multiple_changed_notification_ = false;
}
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h
index 4df82f02c7b..0169b0deb07 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h
@@ -49,6 +49,10 @@ class AutofillWalletMetadataSyncableService
public syncer::SyncableService,
public AutofillWebDataServiceObserverOnDBSequence {
public:
+ AutofillWalletMetadataSyncableService(
+ AutofillWebDataBackend* web_data_backend,
+ const std::string& app_locale);
+
~AutofillWalletMetadataSyncableService() override;
// Determines whether this bridge should be monitoring the Wallet data. This
@@ -91,10 +95,6 @@ class AutofillWalletMetadataSyncableService
AutofillWebDataService* web_data_service);
protected:
- AutofillWalletMetadataSyncableService(
- AutofillWebDataBackend* web_data_backend,
- const std::string& app_locale);
-
// Populates the provided |profiles| and |cards| with mappings from server ID
// to server profiles and server cards read from disk. This data contains the
// usage stats. Returns true on success.
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
index eb9f740f4f6..8631ea78944 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/base64.h"
+#include "base/feature_list.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
@@ -20,6 +21,7 @@
#include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/autofill/core/common/autofill_util.h"
+#include "components/sync/driver/sync_driver_switches.h"
#include "components/sync/model/entity_data.h"
#include "components/sync/model/mutable_data_batch.h"
#include "components/sync/model/sync_merge_result.h"
@@ -51,6 +53,23 @@ std::string GetSpecificsIdFromAutofillWalletSpecifics(
return std::string();
}
+std::string GetSpecificsIdFromAutofillProfile(const AutofillProfile& profile) {
+ // Both server_id and specifics_id are _not_ base64 encoded.
+ return profile.server_id();
+}
+
+std::string GetSpecificsIdFromCreditCard(const CreditCard& card) {
+ // Both server_id and specifics_id are _not_ base64 encoded.
+ return card.server_id();
+}
+
+std::string GetSpecificsIdFromPaymentsCustomerData(
+ const PaymentsCustomerData& customer_data) {
+ // Both customer_id and specifics_id are _not_ base64 encoded.
+ return customer_data.customer_id;
+}
+
+// Returns the client tag for wallet data specifics id.
std::string GetClientTagForWalletDataSpecificsId(
const std::string& specifics_id) {
// Unlike for the wallet_metadata model type, the wallet_data expects
@@ -58,6 +77,64 @@ std::string GetClientTagForWalletDataSpecificsId(
return specifics_id;
}
+// Returns the storage key to be used for wallet data for the specified wallet
+// data |specifics_id|.
+std::string GetStorageKeyForWalletDataSpecificsId(
+ const std::string& specifics_id) {
+ // We use the (non-base64-encoded) |specifics_id| directly as the storage key,
+ // this function only hides this definition from all its call sites.
+ return specifics_id;
+}
+
+// Creates a EntityData object corresponding to the specified |address|.
+std::unique_ptr<EntityData> CreateEntityDataFromAutofillServerProfile(
+ const AutofillProfile& address,
+ bool enforce_utf8) {
+ auto entity_data = std::make_unique<EntityData>();
+ entity_data->non_unique_name =
+ "Server profile " +
+ GetBase64EncodedId(GetSpecificsIdFromAutofillProfile(address));
+
+ AutofillWalletSpecifics* wallet_specifics =
+ entity_data->specifics.mutable_autofill_wallet();
+ SetAutofillWalletSpecificsFromServerProfile(address, wallet_specifics,
+ enforce_utf8);
+
+ return entity_data;
+}
+
+// Creates a EntityData object corresponding to the specified |card|.
+std::unique_ptr<EntityData> CreateEntityDataFromCard(const CreditCard& card,
+ bool enforce_utf8) {
+ auto entity_data = std::make_unique<EntityData>();
+ entity_data->non_unique_name =
+ "Server card " + GetBase64EncodedId(GetSpecificsIdFromCreditCard(card));
+
+ AutofillWalletSpecifics* wallet_specifics =
+ entity_data->specifics.mutable_autofill_wallet();
+ SetAutofillWalletSpecificsFromServerCard(card, wallet_specifics,
+ enforce_utf8);
+
+ return entity_data;
+}
+
+// Creates a EntityData object corresponding to the specified |customer_data|.
+std::unique_ptr<EntityData> CreateEntityDataFromPaymentsCustomerData(
+ const PaymentsCustomerData& customer_data) {
+ auto entity_data = std::make_unique<EntityData>();
+ entity_data->non_unique_name =
+ "Payments customer data " +
+ GetBase64EncodedId(GetSpecificsIdFromPaymentsCustomerData(customer_data));
+
+ AutofillWalletSpecifics* wallet_specifics =
+ entity_data->specifics.mutable_autofill_wallet();
+
+ SetAutofillWalletSpecificsFromPaymentsCustomerData(customer_data,
+ wallet_specifics);
+
+ return entity_data;
+}
+
} // namespace
// static
@@ -111,6 +188,15 @@ AutofillWalletSyncBridge::CreateMetadataChangeList() {
base::Optional<syncer::ModelError> AutofillWalletSyncBridge::MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) {
+ // All metadata changes have been already written, return early for an error.
+ base::Optional<syncer::ModelError> error =
+ static_cast<syncer::SyncMetadataStoreChangeList*>(
+ metadata_change_list.get())
+ ->TakeError();
+ if (error) {
+ return error;
+ }
+
SetSyncData(entity_data);
// After the first sync, we are sure that initial sync is done.
@@ -118,6 +204,8 @@ base::Optional<syncer::ModelError> AutofillWalletSyncBridge::MergeSyncData(
initial_sync_done_ = true;
active_callback_.Run(true);
}
+ // TODO(crbug.com/853688): Update the AutofillTable API to know about write
+ // errors and report them here.
return base::nullopt;
}
@@ -137,54 +225,7 @@ void AutofillWalletSyncBridge::GetData(StorageKeyList storage_keys,
}
void AutofillWalletSyncBridge::GetAllDataForDebugging(DataCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- std::vector<std::unique_ptr<AutofillProfile>> profiles;
- std::vector<std::unique_ptr<CreditCard>> cards;
- std::unique_ptr<PaymentsCustomerData> customer_data;
- if (!GetAutofillTable()->GetServerProfiles(&profiles) ||
- !GetAutofillTable()->GetServerCreditCards(&cards) ||
- !GetAutofillTable()->GetPaymentsCustomerData(&customer_data)) {
- change_processor()->ReportError(
- {FROM_HERE, "Failed to load entries from table."});
- return;
- }
-
- // Convert all non base 64 strings so that they can be displayed properly.
- auto batch = std::make_unique<syncer::MutableDataBatch>();
- for (const std::unique_ptr<AutofillProfile>& entry : profiles) {
- std::unique_ptr<EntityData> entity_data =
- CreateEntityDataFromAutofillServerProfile(*entry);
- sync_pb::WalletPostalAddress* wallet_address =
- entity_data->specifics.mutable_autofill_wallet()->mutable_address();
-
- wallet_address->set_id(GetBase64EncodedServerId(wallet_address->id()));
-
- batch->Put(GetStorageKeyForEntryServerId(entry->server_id()),
- std::move(entity_data));
- }
- for (const std::unique_ptr<CreditCard>& entry : cards) {
- std::unique_ptr<EntityData> entity_data = CreateEntityDataFromCard(*entry);
- sync_pb::WalletMaskedCreditCard* wallet_card =
- entity_data->specifics.mutable_autofill_wallet()->mutable_masked_card();
-
- wallet_card->set_id(GetBase64EncodedServerId(wallet_card->id()));
- // The billing address id might refer to a local profile guid which doesn't
- // need to be encoded.
- if (!base::IsStringUTF8(wallet_card->billing_address_id())) {
- wallet_card->set_billing_address_id(
- GetBase64EncodedServerId(wallet_card->billing_address_id()));
- }
-
- batch->Put(GetStorageKeyForEntryServerId(entry->server_id()),
- std::move(entity_data));
- }
-
- if (customer_data) {
- batch->Put(GetStorageKeyForEntryServerId(customer_data->customer_id),
- CreateEntityDataFromPaymentsCustomerData(*customer_data));
- }
- std::move(callback).Run(std::move(batch));
+ GetAllDataImpl(std::move(callback), /*enforce_utf8=*/true);
}
std::string AutofillWalletSyncBridge::GetClientTag(
@@ -199,8 +240,9 @@ std::string AutofillWalletSyncBridge::GetClientTag(
std::string AutofillWalletSyncBridge::GetStorageKey(
const syncer::EntityData& entity_data) {
DCHECK(entity_data.specifics.has_autofill_wallet());
- return GetStorageKeyForSpecificsId(GetSpecificsIdFromAutofillWalletSpecifics(
- entity_data.specifics.autofill_wallet()));
+ return GetStorageKeyForWalletDataSpecificsId(
+ GetSpecificsIdFromAutofillWalletSpecifics(
+ entity_data.specifics.autofill_wallet()));
}
bool AutofillWalletSyncBridge::SupportsIncrementalUpdates() const {
@@ -228,6 +270,11 @@ AutofillWalletSyncBridge::ApplyStopSyncChanges(
}
void AutofillWalletSyncBridge::GetAllDataForTesting(DataCallback callback) {
+ GetAllDataImpl(std::move(callback), /*enforce_utf8=*/false);
+}
+
+void AutofillWalletSyncBridge::GetAllDataImpl(DataCallback callback,
+ bool enforce_utf8) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::vector<std::unique_ptr<AutofillProfile>> profiles;
@@ -243,16 +290,19 @@ void AutofillWalletSyncBridge::GetAllDataForTesting(DataCallback callback) {
auto batch = std::make_unique<syncer::MutableDataBatch>();
for (const std::unique_ptr<AutofillProfile>& entry : profiles) {
- batch->Put(GetStorageKeyForEntryServerId(entry->server_id()),
- CreateEntityDataFromAutofillServerProfile(*entry));
+ batch->Put(GetStorageKeyForWalletDataSpecificsId(
+ GetSpecificsIdFromAutofillProfile(*entry)),
+ CreateEntityDataFromAutofillServerProfile(*entry, enforce_utf8));
}
for (const std::unique_ptr<CreditCard>& entry : cards) {
- batch->Put(GetStorageKeyForEntryServerId(entry->server_id()),
- CreateEntityDataFromCard(*entry));
+ batch->Put(GetStorageKeyForWalletDataSpecificsId(
+ GetSpecificsIdFromCreditCard(*entry)),
+ CreateEntityDataFromCard(*entry, enforce_utf8));
}
if (customer_data) {
- batch->Put(GetStorageKeyForEntryServerId(customer_data->customer_id),
+ batch->Put(GetStorageKeyForWalletDataSpecificsId(
+ GetSpecificsIdFromPaymentsCustomerData(*customer_data)),
CreateEntityDataFromPaymentsCustomerData(*customer_data));
}
std::move(callback).Run(std::move(batch));
@@ -301,15 +351,20 @@ bool AutofillWalletSyncBridge::SetWalletCards(
ComputeAutofillWalletDiff(existing_cards, wallet_cards);
if (log_diff) {
- UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCards.Added", diff.items_added);
- UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCards.Removed",
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCards2.Added", diff.items_added);
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCards2.Removed",
diff.items_removed);
- UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCards.AddedOrRemoved",
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCards2.AddedOrRemoved",
diff.items_added + diff.items_removed);
}
if (!diff.IsEmpty()) {
- table->SetServerCreditCards(wallet_cards);
+ if (base::FeatureList::IsEnabled(
+ ::switches::kSyncUSSAutofillWalletMetadata)) {
+ table->SetServerCardsData(wallet_cards);
+ } else {
+ table->SetServerCreditCards(wallet_cards);
+ }
for (const CreditCardChange& change : diff.changes)
web_data_backend_->NotifyOfCreditCardChanged(change);
return true;
@@ -331,16 +386,21 @@ bool AutofillWalletSyncBridge::SetWalletAddresses(
ComputeAutofillWalletDiff(existing_addresses, wallet_addresses);
if (log_diff) {
- UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddresses.Added",
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddresses2.Added",
diff.items_added);
- UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddresses.Removed",
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddresses2.Removed",
diff.items_removed);
- UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddresses.AddedOrRemoved",
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddresses2.AddedOrRemoved",
diff.items_added + diff.items_removed);
}
if (!diff.IsEmpty()) {
- table->SetServerProfiles(wallet_addresses);
+ if (base::FeatureList::IsEnabled(
+ ::switches::kSyncUSSAutofillWalletMetadata)) {
+ table->SetServerAddressesData(wallet_addresses);
+ } else {
+ table->SetServerProfiles(wallet_addresses);
+ }
for (const AutofillProfileChange& change : diff.changes)
web_data_backend_->NotifyOfAutofillProfileChanged(change);
return true;
@@ -427,7 +487,7 @@ AutofillWalletSyncBridge::ComputeAutofillWalletDiff(
if (cmp < 0) {
++result.items_removed;
result.changes.emplace_back(AutofillDataModelChange<Item>::REMOVE,
- (*old_it)->guid(), nullptr);
+ (*old_it)->server_id(), nullptr);
++old_it;
} else if (cmp == 0) {
++old_it;
@@ -435,7 +495,7 @@ AutofillWalletSyncBridge::ComputeAutofillWalletDiff(
} else {
++result.items_added;
result.changes.emplace_back(AutofillDataModelChange<Item>::ADD,
- (*new_it)->guid(), *new_it);
+ (*new_it)->server_id(), *new_it);
++new_it;
}
}
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
index 46d91c27fef..17ea21c91bb 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
@@ -71,7 +71,7 @@ class AutofillWalletSyncBridge : public base::SupportsUserData::Data,
override;
// Sends all Wallet Data to the |callback| and keeps all the strings in their
- // original format.
+ // original format (whereas GetAllDataForDebugging() has to make them UTF-8).
void GetAllDataForTesting(DataCallback callback);
private:
@@ -84,6 +84,10 @@ class AutofillWalletSyncBridge : public base::SupportsUserData::Data,
bool IsEmpty() const { return items_added == 0 && items_removed == 0; }
};
+ // Sends all Wallet Data to the |callback|. If |enforce_utf8|, the string
+ // fields that are in non-UTF-8 get encoded so that they conform to UTF-8.
+ void GetAllDataImpl(DataCallback callback, bool enforce_utf8);
+
// Sets the wallet data from |entity_data| to this client and records metrics
// about added/deleted data.
void SetSyncData(const syncer::EntityChangeList& entity_data);
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 84edb01afb9..97c9520760b 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
@@ -12,12 +12,14 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "base/time/time.h"
+#include "components/autofill/core/browser/autofill_metadata.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/country_names.h"
@@ -31,6 +33,7 @@
#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/driver/sync_driver_switches.h"
#include "components/sync/model/entity_data.h"
#include "components/sync/model/mock_model_type_change_processor.h"
#include "components/sync/model/sync_data.h"
@@ -187,9 +190,33 @@ MATCHER_P2(AddChange, key, data, "") {
return true;
}
+// Class that enables or disables USS based on test parameter. Must be the first
+// base class of the test fixture.
+// TODO(jkrcal): When the new implementation fully launches, remove this class,
+// convert all tests from *_P back to *_F and remove the instance at the end.
+class UssSwitchToggler : public testing::WithParamInterface<bool> {
+ public:
+ UssSwitchToggler() {
+ if (IsWalletMetadataOnUSS()) {
+ override_features_.InitAndEnableFeature(
+ ::switches::kSyncUSSAutofillWalletMetadata);
+ } else {
+ override_features_.InitAndDisableFeature(
+ ::switches::kSyncUSSAutofillWalletMetadata);
+ }
+ }
+
+ protected:
+ bool IsWalletMetadataOnUSS() { return GetParam(); }
+
+ private:
+ base::test::ScopedFeatureList override_features_;
+};
+
} // namespace
-class AutofillWalletSyncBridgeTest : public testing::Test {
+class AutofillWalletSyncBridgeTest : public UssSwitchToggler,
+ public testing::Test {
public:
AutofillWalletSyncBridgeTest() {}
~AutofillWalletSyncBridgeTest() override {}
@@ -253,44 +280,55 @@ class AutofillWalletSyncBridgeTest : public testing::Test {
}
void ExpectAddressesDiffInHistograms(int added, int removed) {
- histogram_tester_.ExpectUniqueSample("Autofill.WalletAddresses.Added",
+ histogram_tester_.ExpectUniqueSample("Autofill.WalletAddresses2.Added",
/*bucket=*/added,
/*count=*/1);
- histogram_tester_.ExpectUniqueSample("Autofill.WalletAddresses.Removed",
+ histogram_tester_.ExpectUniqueSample("Autofill.WalletAddresses2.Removed",
/*bucket=*/removed,
/*count=*/1);
histogram_tester_.ExpectUniqueSample(
- "Autofill.WalletAddresses.AddedOrRemoved",
+ "Autofill.WalletAddresses2.AddedOrRemoved",
/*bucket=*/added + removed,
/*count=*/1);
}
void ExpectNoHistogramsForAddressesDiff() {
- histogram_tester_.ExpectTotalCount("Autofill.WalletAddresses.Added", 0);
- histogram_tester_.ExpectTotalCount("Autofill.WalletAddresses.Removed", 0);
+ histogram_tester_.ExpectTotalCount("Autofill.WalletAddresses2.Added", 0);
+ histogram_tester_.ExpectTotalCount("Autofill.WalletAddresses2.Removed", 0);
histogram_tester_.ExpectTotalCount(
- "Autofill.WalletAddresses.AddedOrRemoved", 0);
+ "Autofill.WalletAddresses2.AddedOrRemoved", 0);
}
void ExpectCardsDiffInHistograms(int added, int removed) {
- histogram_tester_.ExpectUniqueSample("Autofill.WalletCards.Added",
+ histogram_tester_.ExpectUniqueSample("Autofill.WalletCards2.Added",
/*bucket=*/added,
/*count=*/1);
- histogram_tester_.ExpectUniqueSample("Autofill.WalletCards.Removed",
+ histogram_tester_.ExpectUniqueSample("Autofill.WalletCards2.Removed",
/*bucket=*/removed,
/*count=*/1);
- histogram_tester_.ExpectUniqueSample("Autofill.WalletCards.AddedOrRemoved",
+ histogram_tester_.ExpectUniqueSample("Autofill.WalletCards2.AddedOrRemoved",
/*bucket=*/added + removed,
/*count=*/1);
}
void ExpectNoHistogramsForCardsDiff() {
- histogram_tester_.ExpectTotalCount("Autofill.WalletCards.Added", 0);
- histogram_tester_.ExpectTotalCount("Autofill.WalletCards.Removed", 0);
- histogram_tester_.ExpectTotalCount("Autofill.WalletCards.AddedOrRemoved",
+ histogram_tester_.ExpectTotalCount("Autofill.WalletCards2.Added", 0);
+ histogram_tester_.ExpectTotalCount("Autofill.WalletCards2.Removed", 0);
+ histogram_tester_.ExpectTotalCount("Autofill.WalletCards2.AddedOrRemoved",
0);
}
+ void ExpectCountsOfWalletMetadataInDB(unsigned int cards_count,
+ unsigned int addresses_count) {
+ std::map<std::string, AutofillMetadata> cards_metadata;
+ ASSERT_TRUE(table()->GetServerCardsMetadata(&cards_metadata));
+ EXPECT_EQ(cards_count, cards_metadata.size());
+
+ std::map<std::string, AutofillMetadata> addresses_metadata;
+ ASSERT_TRUE(table()->GetServerAddressesMetadata(&addresses_metadata));
+ EXPECT_EQ(addresses_count, addresses_metadata.size());
+ }
+
EntityData SpecificsToEntity(const AutofillWalletSpecifics& specifics) {
EntityData data;
*data.specifics.mutable_autofill_wallet() = specifics;
@@ -351,21 +389,21 @@ class AutofillWalletSyncBridgeTest : public testing::Test {
};
// The following 3 tests make sure client tags stay stable.
-TEST_F(AutofillWalletSyncBridgeTest, GetClientTagForAddress) {
+TEST_P(AutofillWalletSyncBridgeTest, GetClientTagForAddress) {
AutofillWalletSpecifics specifics =
CreateAutofillWalletSpecificsForAddress(kAddr1SpecificsId);
EXPECT_EQ(bridge()->GetClientTag(SpecificsToEntity(specifics)),
kAddr1SyncTag);
}
-TEST_F(AutofillWalletSyncBridgeTest, GetClientTagForCard) {
+TEST_P(AutofillWalletSyncBridgeTest, GetClientTagForCard) {
AutofillWalletSpecifics specifics =
CreateAutofillWalletSpecificsForCard(kCard1SpecificsId);
EXPECT_EQ(bridge()->GetClientTag(SpecificsToEntity(specifics)),
kCard1SyncTag);
}
-TEST_F(AutofillWalletSyncBridgeTest, GetClientTagForCustomerData) {
+TEST_P(AutofillWalletSyncBridgeTest, GetClientTagForCustomerData) {
AutofillWalletSpecifics specifics =
CreateAutofillWalletSpecificsForPaymentsCustomerData(
kCustomerDataSyncTag);
@@ -374,28 +412,28 @@ TEST_F(AutofillWalletSyncBridgeTest, GetClientTagForCustomerData) {
}
// The following 3 tests make sure storage keys stay stable.
-TEST_F(AutofillWalletSyncBridgeTest, GetStorageKeyForAddress) {
+TEST_P(AutofillWalletSyncBridgeTest, GetStorageKeyForAddress) {
AutofillWalletSpecifics specifics1 =
CreateAutofillWalletSpecificsForAddress(kAddr1SpecificsId);
EXPECT_EQ(bridge()->GetStorageKey(SpecificsToEntity(specifics1)),
kAddr1SpecificsId);
}
-TEST_F(AutofillWalletSyncBridgeTest, GetStorageKeyForCard) {
+TEST_P(AutofillWalletSyncBridgeTest, GetStorageKeyForCard) {
AutofillWalletSpecifics specifics2 =
CreateAutofillWalletSpecificsForCard(kCard1SpecificsId);
EXPECT_EQ(bridge()->GetStorageKey(SpecificsToEntity(specifics2)),
kCard1SpecificsId);
}
-TEST_F(AutofillWalletSyncBridgeTest, GetStorageKeyForCustomerData) {
+TEST_P(AutofillWalletSyncBridgeTest, GetStorageKeyForCustomerData) {
AutofillWalletSpecifics specifics3 =
CreateAutofillWalletSpecificsForPaymentsCustomerData(kCustomerDataId);
EXPECT_EQ(bridge()->GetStorageKey(SpecificsToEntity(specifics3)),
kCustomerDataId);
}
-TEST_F(AutofillWalletSyncBridgeTest,
+TEST_P(AutofillWalletSyncBridgeTest,
GetAllDataForDebugging_ShouldReturnAllData) {
AutofillProfile address1 = test::GetServerProfile();
AutofillProfile address2 = test::GetServerProfile2();
@@ -428,7 +466,7 @@ TEST_F(AutofillWalletSyncBridgeTest,
// Tests that when a new wallet card and new wallet address are sent by the
// server, the client only keeps the new data.
-TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_NewWalletAddressAndCard) {
+TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_NewWalletAddressAndCard) {
// Create one profile and one card on the client.
AutofillProfile address1 = test::GetServerProfile();
table()->SetServerProfiles({address1});
@@ -450,15 +488,22 @@ TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_NewWalletAddressAndCard) {
EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(
- AddChange(address2.guid(), address2)));
- EXPECT_CALL(*backend(),
- NotifyOfAutofillProfileChanged(RemoveChange(address1.guid())));
+ AddChange(address2.server_id(), address2)));
+ EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(
+ RemoveChange(address1.server_id())));
EXPECT_CALL(*backend(),
- NotifyOfCreditCardChanged(AddChange(card2.guid(), card2)));
+ NotifyOfCreditCardChanged(AddChange(card2.server_id(), card2)));
EXPECT_CALL(*backend(),
- NotifyOfCreditCardChanged(RemoveChange(card1.guid())));
+ NotifyOfCreditCardChanged(RemoveChange(card1.server_id())));
StartSyncing({profile_specifics2, card_specifics2, customer_data_specifics});
+ if (IsWalletMetadataOnUSS()) {
+ // This bridge does not store metadata, i.e. billing_address_id. Strip it
+ // off so that the expectations below pass.
+ card_specifics2.mutable_masked_card()->set_billing_address_id(
+ std::string());
+ }
+
// Only the server card should be present on the client.
EXPECT_THAT(GetAllLocalData(),
UnorderedElementsAre(EqualsSpecifics(profile_specifics2),
@@ -470,7 +515,7 @@ TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_NewWalletAddressAndCard) {
// Tests that in initial sync, no metrics are recorded for new addresses and
// cards.
-TEST_F(AutofillWalletSyncBridgeTest,
+TEST_P(AutofillWalletSyncBridgeTest,
MergeSyncData_NewWalletAddressAndCardNoMetricsInitialSync) {
ResetProcessor();
ResetBridge(/*initial_sync_done=*/false);
@@ -490,6 +535,14 @@ TEST_F(AutofillWalletSyncBridgeTest,
EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
StartSyncing({profile_specifics, card_specifics, customer_data_specifics});
+ if (IsWalletMetadataOnUSS()) {
+ ExpectCountsOfWalletMetadataInDB(/*cards_count=*/0u, /*address_count=*/0u);
+
+ // This bridge does not store metadata, i.e. billing_address_id. Strip it
+ // off so that the expectations below pass.
+ card_specifics.mutable_masked_card()->set_billing_address_id(std::string());
+ }
+
EXPECT_THAT(GetAllLocalData(),
UnorderedElementsAre(EqualsSpecifics(profile_specifics),
EqualsSpecifics(card_specifics),
@@ -500,7 +553,7 @@ TEST_F(AutofillWalletSyncBridgeTest,
// Tests that when a new payments customer data is sent by the server, the
// client only keeps the new data.
-TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_NewPaymentsCustomerData) {
+TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_NewPaymentsCustomerData) {
// Create one profile, one card and one customer data entry on the client.
AutofillProfile address = test::GetServerProfile();
table()->SetServerProfiles({address});
@@ -535,7 +588,7 @@ TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_NewPaymentsCustomerData) {
// Tests that when the server sends no cards or address, the client should
// delete all it's existing data.
-TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_NoWalletAddressOrCard) {
+TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_NoWalletAddressOrCard) {
// Create one profile and one card on the client.
AutofillProfile local_profile = test::GetServerProfile();
table()->SetServerProfiles({local_profile});
@@ -544,11 +597,17 @@ TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_NoWalletAddressOrCard) {
EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(
- RemoveChange(local_profile.guid())));
+ RemoveChange(local_profile.server_id())));
EXPECT_CALL(*backend(),
- NotifyOfCreditCardChanged(RemoveChange(local_card.guid())));
+ NotifyOfCreditCardChanged(RemoveChange(local_card.server_id())));
StartSyncing({});
+ if (IsWalletMetadataOnUSS()) {
+ // This bridge should not touch the metadata; should get deleted by the
+ // metadata bridge.
+ ExpectCountsOfWalletMetadataInDB(/*cards_count=*/1u, /*address_count=*/1u);
+ }
+
EXPECT_TRUE(GetAllLocalData().empty());
// No diff metrics reported when new data is empty.
ExpectNoHistogramsForAddressesDiff();
@@ -557,7 +616,7 @@ TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_NoWalletAddressOrCard) {
// Test that when the server sends the same address and card as the client has,
// nothing changes on the client.
-TEST_F(AutofillWalletSyncBridgeTest,
+TEST_P(AutofillWalletSyncBridgeTest,
MergeSyncData_SameWalletAddressAndCardAndCustomerData) {
// Create one profile and one card on the client.
AutofillProfile profile = test::GetServerProfile();
@@ -591,7 +650,7 @@ TEST_F(AutofillWalletSyncBridgeTest,
// Tests that when there are multiple changes happening at the same time, the
// data from the server is what the client ends up with.
-TEST_F(AutofillWalletSyncBridgeTest,
+TEST_P(AutofillWalletSyncBridgeTest,
MergeSyncData_AddRemoveAndPreserveWalletAddressAndCard) {
// Create two profile and one card on the client.
AutofillProfile profile = test::GetServerProfile();
@@ -614,13 +673,21 @@ TEST_F(AutofillWalletSyncBridgeTest,
&customer_data_specifics);
EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
+ EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(
+ RemoveChange(profile2.server_id())));
EXPECT_CALL(*backend(),
- NotifyOfAutofillProfileChanged(RemoveChange(profile2.guid())));
- EXPECT_CALL(*backend(), NotifyOfCreditCardChanged(RemoveChange(card.guid())));
+ NotifyOfCreditCardChanged(RemoveChange(card.server_id())));
EXPECT_CALL(*backend(),
- NotifyOfCreditCardChanged(AddChange(card2.guid(), card2)));
+ NotifyOfCreditCardChanged(AddChange(card2.server_id(), card2)));
StartSyncing({profile_specifics, card2_specifics, customer_data_specifics});
+ if (IsWalletMetadataOnUSS()) {
+ // This bridge does not store metadata, i.e. billing_address_id. Strip it
+ // off so that the expectations below pass.
+ card2_specifics.mutable_masked_card()->set_billing_address_id(
+ std::string());
+ }
+
// Make sure that the client only has the data from the server.
EXPECT_THAT(GetAllLocalData(),
UnorderedElementsAre(EqualsSpecifics(profile_specifics),
@@ -632,7 +699,7 @@ TEST_F(AutofillWalletSyncBridgeTest,
// Test that all field values for a address sent form the server are copied on
// the address on the client.
-TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletAddressData) {
+TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletAddressData) {
// Create a profile to be synced from the server.
AutofillProfile profile = test::GetServerProfile();
AutofillWalletSpecifics profile_specifics;
@@ -686,7 +753,7 @@ TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletAddressData) {
// Test that all field values for a card sent form the server are copied on the
// card on the client.
-TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletCardData) {
+TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletCardData) {
// Create a card to be synced from the server.
CreditCard card = test::GetMaskedServerCard();
// Add this value type as it is not added by default but should be synced.
@@ -696,6 +763,13 @@ TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletCardData) {
StartSyncing({card_specifics});
+ if (IsWalletMetadataOnUSS()) {
+ // This bridge does not store metadata, i.e. billing_address_id. Strip it
+ // off so that the expectations below pass.
+ card.set_billing_address_id(std::string());
+ card_specifics.mutable_masked_card()->set_billing_address_id(std::string());
+ }
+
EXPECT_THAT(GetAllLocalData(),
UnorderedElementsAre(EqualsSpecifics(card_specifics)));
@@ -718,12 +792,14 @@ TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletCardData) {
EXPECT_FALSE(card.LastFourDigits().empty());
EXPECT_NE(0, card.expiration_month());
EXPECT_NE(0, card.expiration_year());
- EXPECT_FALSE(card.billing_address_id().empty());
+ if (!IsWalletMetadataOnUSS()) {
+ EXPECT_FALSE(card.billing_address_id().empty());
+ }
EXPECT_NE(CreditCard::CARD_TYPE_UNKNOWN, card.card_type());
EXPECT_FALSE(card.bank_name().empty());
}
-TEST_F(AutofillWalletSyncBridgeTest, LoadMetadataCalled) {
+TEST_P(AutofillWalletSyncBridgeTest, LoadMetadataCalled) {
EXPECT_TRUE(table()->UpdateSyncMetadata(syncer::AUTOFILL_WALLET_DATA, "key",
EntityMetadata()));
@@ -734,7 +810,7 @@ TEST_F(AutofillWalletSyncBridgeTest, LoadMetadataCalled) {
ResetBridge(/*initial_sync_done=*/true);
}
-TEST_F(AutofillWalletSyncBridgeTest, ApplyStopSyncChanges_ClearAllData) {
+TEST_P(AutofillWalletSyncBridgeTest, ApplyStopSyncChanges_ClearAllData) {
// Create one profile and one card on the client.
AutofillProfile local_profile = test::GetServerProfile();
table()->SetServerProfiles({local_profile});
@@ -743,21 +819,27 @@ TEST_F(AutofillWalletSyncBridgeTest, ApplyStopSyncChanges_ClearAllData) {
EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(
- RemoveChange(local_profile.guid())));
+ RemoveChange(local_profile.server_id())));
EXPECT_CALL(*backend(),
- NotifyOfCreditCardChanged(RemoveChange(local_card.guid())));
+ NotifyOfCreditCardChanged(RemoveChange(local_card.server_id())));
// Passing in a non-null metadata change list indicates to the bridge that
// sync is stopping because it was disabled.
bridge()->ApplyStopSyncChanges(
std::make_unique<syncer::InMemoryMetadataChangeList>());
+ if (IsWalletMetadataOnUSS()) {
+ // This bridge should not touch the metadata; should get deleted by the
+ // metadata bridge.
+ ExpectCountsOfWalletMetadataInDB(/*cards_count=*/1u, /*address_count=*/1u);
+ }
+
EXPECT_TRUE(GetAllLocalData().empty());
// No diff metrics reported when clearing data.
ExpectNoHistogramsForAddressesDiff();
ExpectNoHistogramsForCardsDiff();
}
-TEST_F(AutofillWalletSyncBridgeTest, ApplyStopSyncChanges_KeepData) {
+TEST_P(AutofillWalletSyncBridgeTest, ApplyStopSyncChanges_KeepData) {
// Create one profile and one card on the client.
AutofillProfile local_profile = test::GetServerProfile();
table()->SetServerProfiles({local_profile});
@@ -777,7 +859,7 @@ TEST_F(AutofillWalletSyncBridgeTest, ApplyStopSyncChanges_KeepData) {
ExpectNoHistogramsForCardsDiff();
}
-TEST_F(AutofillWalletSyncBridgeTest, NotifiesWhenActivelySyncing) {
+TEST_P(AutofillWalletSyncBridgeTest, NotifiesWhenActivelySyncing) {
testing::InSequence seq;
ResetProcessor();
@@ -802,4 +884,8 @@ TEST_F(AutofillWalletSyncBridgeTest, NotifiesWhenActivelySyncing) {
bridge()->ApplyStopSyncChanges(/*delete_metadata_change_list=*/nullptr);
}
+INSTANTIATE_TEST_CASE_P(USS,
+ AutofillWalletSyncBridgeTest,
+ ::testing::Values(false, true));
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
index 211c6f1517b..3cc21a09948 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
@@ -213,7 +213,8 @@ syncer::SyncMergeResult AutofillWalletSyncableService::MergeDataAndStartSyncing(
std::unique_ptr<syncer::SyncErrorFactory> sync_error_factory) {
DCHECK(thread_checker_.CalledOnValidThread());
sync_processor_ = std::move(sync_processor);
- syncer::SyncMergeResult result = SetSyncData(initial_sync_data);
+ syncer::SyncMergeResult result =
+ SetSyncData(initial_sync_data, /*is_initial_merge=*/true);
if (webdata_backend_)
webdata_backend_->NotifyThatSyncHasStarted(type);
return result;
@@ -239,7 +240,8 @@ syncer::SyncError AutofillWalletSyncableService::ProcessSyncChanges(
DCHECK(thread_checker_.CalledOnValidThread());
// Don't bother handling incremental updates. Wallet data changes very rarely
// and has few items. Instead, just get all the current data and save it.
- SetSyncData(sync_processor_->GetAllSyncData(syncer::AUTOFILL_WALLET_DATA));
+ SetSyncData(sync_processor_->GetAllSyncData(syncer::AUTOFILL_WALLET_DATA),
+ /*is_initial_merge=*/false);
return syncer::SyncError();
}
@@ -250,8 +252,8 @@ void AutofillWalletSyncableService::CreateForWebDataServiceAndBackend(
const std::string& app_locale) {
web_data_service->GetDBUserData()->SetUserData(
AutofillWalletSyncableServiceUserDataKey(),
- base::WrapUnique(
- new AutofillWalletSyncableService(webdata_backend, app_locale)));
+ std::make_unique<AutofillWalletSyncableService>(webdata_backend,
+ app_locale));
}
// static
@@ -340,7 +342,8 @@ void AutofillWalletSyncableService::CopyRelevantMetadataFromDisk(
}
syncer::SyncMergeResult AutofillWalletSyncableService::SetSyncData(
- const syncer::SyncDataList& data_list) {
+ const syncer::SyncDataList& data_list,
+ bool is_initial_merge) {
std::vector<CreditCard> wallet_cards;
std::vector<AutofillProfile> wallet_addresses;
std::vector<PaymentsCustomerData> customer_data;
@@ -402,20 +405,29 @@ syncer::SyncMergeResult AutofillWalletSyncableService::SetSyncData(
table->SetPaymentsCustomerData(&customer_data.front());
}
+ if (is_initial_merge && cards_diff.IsEmpty() && addresses_diff.IsEmpty()) {
+ // Skip reporting the diff on startup if there is no change. It can happen
+ // that new updates come into the directory before
+ // MergeDataAndStartSyncing() gets called; such updates should get reported.
+ // We cannot distinguish them precisely so we at least report the non-empty
+ // diffs which _must_ be caused by an update from the server.
+ should_report_diff = false;
+ }
+
if (should_report_diff) {
- UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCards.Added",
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCards2.Added",
cards_diff.items_added);
- UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCards.Removed",
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCards2.Removed",
cards_diff.items_removed);
- UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCards.AddedOrRemoved",
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCards2.AddedOrRemoved",
cards_diff.items_added + cards_diff.items_removed);
- UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddresses.Added",
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddresses2.Added",
addresses_diff.items_added);
- UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddresses.Removed",
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddresses2.Removed",
addresses_diff.items_removed);
UMA_HISTOGRAM_COUNTS_100(
- "Autofill.WalletAddresses.AddedOrRemoved",
+ "Autofill.WalletAddresses2.AddedOrRemoved",
addresses_diff.items_added + addresses_diff.items_removed);
}
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h
index 256d1a51cd0..e8c130d73ca 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h
@@ -29,6 +29,9 @@ class AutofillWalletSyncableService
: public base::SupportsUserData::Data,
public syncer::SyncableService {
public:
+ AutofillWalletSyncableService(AutofillWebDataBackend* webdata_backend,
+ const std::string& app_locale);
+
~AutofillWalletSyncableService() override;
// syncer::SyncableService implementation.
@@ -60,11 +63,6 @@ class AutofillWalletSyncableService
void InjectStartSyncFlare(
const syncer::SyncableService::StartSyncFlare& flare);
- protected:
- AutofillWalletSyncableService(
- AutofillWebDataBackend* webdata_backend,
- const std::string& app_locale);
-
private:
FRIEND_TEST_ALL_PREFIXES(AutofillWalletSyncableServiceTest,
CopyRelevantMetadataFromDisk_KeepLocalAddresses);
@@ -102,7 +100,8 @@ class AutofillWalletSyncableService
static Diff ComputeDiff(const std::vector<std::unique_ptr<Item>>& old_data,
const std::vector<Item>& new_data);
- syncer::SyncMergeResult SetSyncData(const syncer::SyncDataList& data_list);
+ syncer::SyncMergeResult SetSyncData(const syncer::SyncDataList& data_list,
+ bool is_initial_merge);
// Populates the wallet datatypes from the sync data and uses the sync data to
// link the card to its billing address.
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 796447f1a02..e69f6834bc4 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
@@ -15,6 +15,7 @@
#include "components/autofill/core/browser/webdata/autofill_change.h"
#include "components/autofill/core/browser/webdata/autofill_entry.h"
#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/form_field_data.h"
#include "components/webdata/common/web_database_backend.h"
@@ -53,6 +54,11 @@ AutofillWebDataBackendImpl::~AutofillWebDataBackendImpl() {
DCHECK(!user_data_); // Forgot to call ResetUserData?
}
+void AutofillWebDataBackendImpl::SetAutofillProfileChangedCallback(
+ base::RepeatingCallback<void(const AutofillProfileDeepChange&)> change_cb) {
+ on_autofill_profile_changed_cb_ = std::move(change_cb);
+}
+
WebDatabase* AutofillWebDataBackendImpl::GetDatabase() {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
return web_database_backend_->database();
@@ -60,8 +66,26 @@ WebDatabase* AutofillWebDataBackendImpl::GetDatabase() {
void AutofillWebDataBackendImpl::RemoveExpiredFormElements() {
web_database_backend_->ExecuteWriteTask(
- Bind(&AutofillWebDataBackendImpl::RemoveExpiredFormElementsImpl,
- this));
+ Bind(&AutofillWebDataBackendImpl::RemoveExpiredFormElementsImpl, this));
+}
+
+std::unique_ptr<WDTypedResult>
+AutofillWebDataBackendImpl::RemoveExpiredAutocompleteEntries(WebDatabase* db) {
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
+ AutofillChangeList changes;
+
+ if (AutofillTable::FromWebDatabase(db)->RemoveExpiredFormElements(&changes)) {
+ if (!changes.empty()) {
+ // Post the notifications including the list of affected keys.
+ // This is sent here so that work resulting from this notification
+ // will be done on the DB sequence, and not the UI sequence.
+ for (auto& db_observer : db_observer_list_)
+ db_observer.AutofillEntriesChanged(changes);
+ }
+ }
+
+ return std::make_unique<WDResult<size_t>>(AUTOFILL_CLEANUP_RESULT,
+ changes.size());
}
void AutofillWebDataBackendImpl::NotifyOfAutofillProfileChanged(
@@ -142,11 +166,11 @@ AutofillWebDataBackendImpl::GetFormValuesForElementName(
int limit,
WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
- std::vector<base::string16> values;
+ std::vector<AutofillEntry> entries;
AutofillTable::FromWebDatabase(db)->GetFormValuesForElementName(
- name, prefix, &values, limit);
- return std::unique_ptr<WDTypedResult>(
- new WDResult<std::vector<base::string16>>(AUTOFILL_VALUE_RESULT, values));
+ name, prefix, &entries, limit);
+ return std::make_unique<WDResult<std::vector<AutofillEntry>>>(
+ AUTOFILL_VALUE_RESULT, entries);
}
WebDatabase::State AutofillWebDataBackendImpl::RemoveFormElementsAddedBetween(
@@ -202,6 +226,13 @@ WebDatabase::State AutofillWebDataBackendImpl::AddAutofillProfile(
for (auto& db_observer : db_observer_list_)
db_observer.AutofillProfileChanged(change);
+ if (!on_autofill_profile_changed_cb_.is_null()) {
+ ui_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(on_autofill_profile_changed_cb_,
+ AutofillProfileDeepChange(
+ AutofillProfileChange::ADD, profile)));
+ }
+
return WebDatabase::COMMIT_NEEDED;
}
@@ -227,6 +258,13 @@ WebDatabase::State AutofillWebDataBackendImpl::UpdateAutofillProfile(
for (auto& db_observer : db_observer_list_)
db_observer.AutofillProfileChanged(change);
+ if (!on_autofill_profile_changed_cb_.is_null()) {
+ ui_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(on_autofill_profile_changed_cb_,
+ AutofillProfileDeepChange(
+ AutofillProfileChange::UPDATE, profile)));
+ }
+
return WebDatabase::COMMIT_NEEDED;
}
@@ -250,6 +288,13 @@ WebDatabase::State AutofillWebDataBackendImpl::RemoveAutofillProfile(
for (auto& db_observer : db_observer_list_)
db_observer.AutofillProfileChanged(change);
+ if (!on_autofill_profile_changed_cb_.is_null()) {
+ ui_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(on_autofill_profile_changed_cb_,
+ AutofillProfileDeepChange(
+ AutofillProfileChange::REMOVE, guid)));
+ }
+
return WebDatabase::COMMIT_NEEDED;
}
@@ -410,12 +455,13 @@ WebDatabase::State AutofillWebDataBackendImpl::UpdateServerCardMetadata(
const CreditCard& card,
WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
+ DCHECK_NE(CreditCard::LOCAL_CARD, card.record_type());
if (!AutofillTable::FromWebDatabase(db)->UpdateServerCardMetadata(card))
return WebDatabase::COMMIT_NOT_NEEDED;
for (auto& db_observer : db_observer_list_) {
db_observer.CreditCardChanged(
- CreditCardChange(CreditCardChange::UPDATE, card.guid(), &card));
+ CreditCardChange(CreditCardChange::UPDATE, card.server_id(), &card));
}
return WebDatabase::COMMIT_NEEDED;
@@ -425,6 +471,7 @@ WebDatabase::State AutofillWebDataBackendImpl::UpdateServerAddressMetadata(
const AutofillProfile& profile,
WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
+ DCHECK_EQ(AutofillProfile::SERVER_PROFILE, profile.record_type());
if (!AutofillTable::FromWebDatabase(db)->UpdateServerAddressMetadata(
profile)) {
return WebDatabase::COMMIT_NOT_NEEDED;
@@ -432,7 +479,7 @@ WebDatabase::State AutofillWebDataBackendImpl::UpdateServerAddressMetadata(
for (auto& db_observer : db_observer_list_) {
db_observer.AutofillProfileChanged(AutofillProfileChange(
- AutofillProfileChange::UPDATE, profile.guid(), &profile));
+ AutofillProfileChange::UPDATE, profile.server_id(), &profile));
}
return WebDatabase::COMMIT_NEEDED;
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 064d7ec2006..9b4a5a2abb6 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
@@ -55,19 +55,27 @@ class AutofillWebDataBackendImpl
const base::Closure& on_changed_callback,
const base::Callback<void(syncer::ModelType)>& on_sync_started_callback);
+ void SetAutofillProfileChangedCallback(
+ base::RepeatingCallback<void(const AutofillProfileDeepChange&)>
+ change_cb);
+
// AutofillWebDataBackend implementation.
void AddObserver(
AutofillWebDataServiceObserverOnDBSequence* observer) override;
void RemoveObserver(
AutofillWebDataServiceObserverOnDBSequence* observer) override;
WebDatabase* GetDatabase() override;
- void RemoveExpiredFormElements() override;
void NotifyOfAutofillProfileChanged(
const AutofillProfileChange& change) override;
void NotifyOfCreditCardChanged(const CreditCardChange& change) override;
void NotifyOfMultipleAutofillChanges() override;
void NotifyThatSyncHasStarted(syncer::ModelType model_type) override;
+ // TODO(crbug.com/920214): Deprecated, will be removed when
+ // autocomplete retention policy shipped. Replaced by
+ // RemoveExpiredAutocompleteEntries.
+ void RemoveExpiredFormElements() override;
+
// Returns a SupportsUserData object that may be used to store data accessible
// from the DB sequence. Should be called only from the DB sequence, and will
// be destroyed on the DB sequence soon after ShutdownOnUISequence() is
@@ -88,6 +96,12 @@ class AutofillWebDataBackendImpl
int limit,
WebDatabase* db);
+ // Function to remove expired Autocomplete entries, which deletes them from
+ // the Sqlite table, unlinks them from Sync and cleans up the metadata.
+ // Returns the number of entries cleaned-up.
+ std::unique_ptr<WDTypedResult> RemoveExpiredAutocompleteEntries(
+ WebDatabase* db);
+
// Removes form elements recorded for Autocomplete from the database.
WebDatabase::State RemoveFormElementsAddedBetween(
const base::Time& delete_begin,
@@ -218,6 +232,9 @@ class AutofillWebDataBackendImpl
// by this object. Is created on first call to |GetDBUserData()|.
std::unique_ptr<SupportsUserDataAggregatable> user_data_;
+ // TODO(crbug.com/920214): Deprecated, will be removed when
+ // autocomplete retention policy shipped. Replaced by
+ // RemoveExpiredAutocompleteEntries.
WebDatabase::State RemoveExpiredFormElementsImpl(WebDatabase* db);
base::ObserverList<AutofillWebDataServiceObserverOnDBSequence>::Unchecked
@@ -230,6 +247,9 @@ class AutofillWebDataBackendImpl
base::Closure on_changed_callback_;
base::Callback<void(syncer::ModelType)> on_sync_started_callback_;
+ base::RepeatingCallback<void(const AutofillProfileDeepChange&)>
+ on_autofill_profile_changed_cb_;
+
DISALLOW_COPY_AND_ASSIGN(AutofillWebDataBackendImpl);
};
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 dd40364ed89..ebb033556c9 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc
@@ -107,6 +107,11 @@ void AutofillWebDataService::AddAutofillProfile(
autofill_backend_, profile));
}
+void AutofillWebDataService::SetAutofillProfileChangedCallback(
+ base::RepeatingCallback<void(const AutofillProfileDeepChange&)> change_cb) {
+ autofill_backend_->SetAutofillProfileChangedCallback(std::move(change_cb));
+}
+
void AutofillWebDataService::UpdateAutofillProfile(
const AutofillProfile& profile) {
wdbs_->ScheduleDBTask(FROM_HERE,
@@ -315,6 +320,16 @@ base::SingleThreadTaskRunner* AutofillWebDataService::GetDBTaskRunner() {
return db_task_runner_.get();
}
+WebDataServiceBase::Handle
+AutofillWebDataService::RemoveExpiredAutocompleteEntries(
+ WebDataServiceConsumer* consumer) {
+ return wdbs_->ScheduleDBTaskWithResult(
+ FROM_HERE,
+ Bind(&AutofillWebDataBackendImpl::RemoveExpiredAutocompleteEntries,
+ autofill_backend_),
+ consumer);
+}
+
AutofillWebDataService::~AutofillWebDataService() {
}
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 a1db37c055a..f25b3b0cf35 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h
@@ -12,6 +12,7 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/supports_user_data.h"
+#include "components/autofill/core/browser/webdata/autofill_change.h"
#include "components/autofill/core/browser/webdata/autofill_webdata.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/sync/base/model_type.h"
@@ -83,6 +84,10 @@ class AutofillWebDataService : public AutofillWebData,
void UpdateAutofillEntries(
const std::vector<AutofillEntry>& autofill_entries) override;
+ void SetAutofillProfileChangedCallback(
+ base::RepeatingCallback<void(const AutofillProfileDeepChange&)>
+ change_cb);
+
// Credit cards.
void AddCreditCard(const CreditCard& credit_card) override;
void UpdateCreditCard(const CreditCard& credit_card) override;
@@ -137,6 +142,11 @@ class AutofillWebDataService : public AutofillWebData,
// sequence.
base::SingleThreadTaskRunner* GetDBTaskRunner();
+ // Triggers an Autocomplete retention policy run which will cleanup data that
+ // hasn't been used since over the retention threshold.
+ virtual WebDataServiceBase::Handle RemoveExpiredAutocompleteEntries(
+ WebDataServiceConsumer* consumer);
+
protected:
~AutofillWebDataService() override;
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 94805a9a999..7477ce7781b 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
@@ -37,6 +37,8 @@ class AutofillWebDataServiceObserverOnUISequence {
// Sync.
virtual void AutofillMultipleChanged() {}
+ virtual void AutofillProfileChanged(const AutofillProfileChange& change) {}
+
// Called on UI sequence when sync has started for |model_type|.
virtual void SyncStarted(syncer::ModelType /* model_type */) {}
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 97f8650618b..f1d6e76fcc9 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
@@ -43,6 +43,7 @@ using base::TimeDelta;
using base::WaitableEvent;
using testing::_;
using testing::DoDefault;
+using testing::ElementsAre;
using testing::ElementsAreArray;
namespace {
@@ -106,7 +107,7 @@ class WebDataServiceTest : public testing::Test {
base::CreateSingleThreadTaskRunnerWithTraits({base::MayBlock()});
wdbs_ = new WebDatabaseService(path, base::ThreadTaskRunnerHandle::Get(),
db_task_runner);
- wdbs_->AddTable(base::WrapUnique(new AutofillTable));
+ wdbs_->AddTable(std::make_unique<AutofillTable>());
wdbs_->LoadDatabase();
wds_ = new AutofillWebDataService(
@@ -204,7 +205,7 @@ TEST_F(WebDataServiceAutofillTest, FormFillAdd) {
// The event will be signaled when the mock observer is notified.
done_event_.TimedWait(test_timeout_);
- AutofillWebDataServiceConsumer<std::vector<base::string16>> consumer;
+ AutofillWebDataServiceConsumer<std::vector<AutofillEntry>> consumer;
WebDataServiceBase::Handle handle;
static const int limit = 10;
handle = wds_->GetFormValuesForElementName(
@@ -212,7 +213,7 @@ TEST_F(WebDataServiceAutofillTest, FormFillAdd) {
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(handle, consumer.handle());
ASSERT_EQ(1U, consumer.result().size());
- EXPECT_EQ(value1_, consumer.result()[0]);
+ EXPECT_EQ(value1_, consumer.result()[0].key().value());
}
TEST_F(WebDataServiceAutofillTest, FormFillRemoveOne) {
diff --git a/chromium/components/autofill/core/common/BUILD.gn b/chromium/components/autofill/core/common/BUILD.gn
index 8c39eef21f5..0ff74d6c22e 100644
--- a/chromium/components/autofill/core/common/BUILD.gn
+++ b/chromium/components/autofill/core/common/BUILD.gn
@@ -25,6 +25,7 @@ jumbo_static_library("common") {
"autofill_switches.h",
"autofill_util.cc",
"autofill_util.h",
+ "button_title_type.h",
"filling_status.h",
"form_data.cc",
"form_data.h",
diff --git a/chromium/components/autofill/core/common/OWNERS b/chromium/components/autofill/core/common/OWNERS
index c5e2808f24c..1b519b8281f 100644
--- a/chromium/components/autofill/core/common/OWNERS
+++ b/chromium/components/autofill/core/common/OWNERS
@@ -1,4 +1,3 @@
per-file *password*=dvadym@chromium.org
per-file *password*=kolos@chromium.org
-per-file *password*=vabr@chromium.org
per-file *password*=vasilii@chromium.org
diff --git a/chromium/components/autofill/core/common/autofill_constants.cc b/chromium/components/autofill/core/common/autofill_constants.cc
index 53a8b465f1b..e1ebeb1822d 100644
--- a/chromium/components/autofill/core/common/autofill_constants.cc
+++ b/chromium/components/autofill/core/common/autofill_constants.cc
@@ -9,13 +9,6 @@
namespace autofill {
-const char kHelpURL[] =
-#if defined(OS_CHROMEOS)
- "https://support.google.com/chromebook/?p=settings_autofill";
-#else
- "https://support.google.com/chrome/?p=settings_autofill";
-#endif
-
const char kSettingsOrigin[] = "Chrome settings";
size_t MinRequiredFieldsForHeuristics() {
diff --git a/chromium/components/autofill/core/common/autofill_constants.h b/chromium/components/autofill/core/common/autofill_constants.h
index 2ab64b61059..f5c341618aa 100644
--- a/chromium/components/autofill/core/common/autofill_constants.h
+++ b/chromium/components/autofill/core/common/autofill_constants.h
@@ -7,12 +7,11 @@
#ifndef COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_CONSTANTS_H_
#define COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_CONSTANTS_H_
-#include <stddef.h> // For size_t
+#include <stddef.h> // For size_t
-namespace autofill {
+#include "base/time/time.h"
-// Help URL for the Autofill dialog.
-extern const char kHelpURL[];
+namespace autofill {
// The origin of an AutofillDataModel created or modified in the settings page.
extern const char kSettingsOrigin[];
@@ -45,6 +44,16 @@ enum ShowPasswordSuggestionsOptions {
// its own credit card save policy.
const int kMaxStrikesToPreventPoppingUpOfferToSavePrompt = 3;
+// Constants for the soft/hard deletion of Autofill data.
+constexpr base::TimeDelta kDisusedDataModelTimeDelta =
+ base::TimeDelta::FromDays(180);
+constexpr base::TimeDelta kDisusedDataModelDeletionTimeDelta =
+ base::TimeDelta::FromDays(395);
+
+// The period after which autocomplete entries should be cleaned-up in days.
+// Equivalent to roughly 14 months.
+const int64_t kAutocompleteRetentionPolicyPeriodInDays = 14 * 31;
+
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_CONSTANTS_H_
diff --git a/chromium/components/autofill/core/common/autofill_features.cc b/chromium/components/autofill/core/common/autofill_features.cc
index ac8f821927a..fbe039a1880 100644
--- a/chromium/components/autofill/core/common/autofill_features.cc
+++ b/chromium/components/autofill/core/common/autofill_features.cc
@@ -16,11 +16,14 @@
#include "components/autofill/core/common/autofill_switches.h"
#include "components/prefs/pref_service.h"
#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/ui_base_features.h"
namespace autofill {
namespace features {
+// Controls whether the Autocomplete Retention Policy is being enforced or not.
+const base::Feature kAutocompleteRetentionPolicyEnabled{
+ "AutocompleteRetentionPolicyEnabled", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Controls whether autofill activates on non-HTTP(S) pages. Useful for
// automated with data URLS in cases where it's too difficult to use the
// embedded test server. Generally avoid using.
@@ -113,22 +116,25 @@ const base::Feature kAutofillEnforceMinRequiredFieldsForHeuristics{
// crowd-sourced field type predictions are queried for a form.
const base::Feature kAutofillEnforceMinRequiredFieldsForQuery{
"AutofillEnforceMinRequiredFieldsForQuery",
- base::FEATURE_ENABLED_BY_DEFAULT};
+ base::FEATURE_DISABLED_BY_DEFAULT};
// Controls whether or not a minimum number of fields is required before
// field type votes are uploaded to the crowd-sourcing server.
const base::Feature kAutofillEnforceMinRequiredFieldsForUpload{
"AutofillEnforceMinRequiredFieldsForUpload",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
-const base::Feature kAutofillExpandedPopupViews{
- "AutofillExpandedPopupViews", base::FEATURE_ENABLED_BY_DEFAULT};
+ base::FEATURE_DISABLED_BY_DEFAULT};
// When enabled, gets payment identity from sync service instead of
// identity manager.
const base::Feature kAutofillGetPaymentsIdentityFromSync{
"AutofillGetPaymentsIdentityFromSync", base::FEATURE_DISABLED_BY_DEFAULT};
+// When enabled, a credit card form that is hidden after receiving input can
+// import the card.
+const base::Feature kAutofillImportNonFocusableCreditCardForms{
+ "AutofillImportNonFocusableCreditCardForms",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// When enabled, autofill suggestions are displayed in the keyboard accessory
// instead of the regular popup.
const base::Feature kAutofillKeyboardAccessory{
@@ -160,16 +166,6 @@ const base::Feature kAutofillPreferServerNamePredictions{
const base::Feature kAutofillPrefilledFields{"AutofillPrefilledFields",
base::FEATURE_ENABLED_BY_DEFAULT};
-const base::Feature kAutofillRationalizeFieldTypePredictions{
- "AutofillRationalizeFieldTypePredictions",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
-// Controls whether Autofill should rationalize repeated server type
-// predictions.
-const base::Feature kAutofillRationalizeRepeatedServerPredictions{
- "AutofillRationalizeRepeatedServerPredictions",
- base::FEATURE_ENABLED_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.
@@ -200,7 +196,7 @@ const base::Feature kAutofillSaveCardImprovedUserConsent{
// When enabled, a sign in promo will show up right after the user
// saves a card locally. This also introduces a "Manage Cards" bubble.
const base::Feature kAutofillSaveCardSignInAfterLocalSave{
- "AutofillSaveCardSignInAfterLocalSave", base::FEATURE_DISABLED_BY_DEFAULT};
+ "AutofillSaveCardSignInAfterLocalSave", base::FEATURE_ENABLED_BY_DEFAULT};
// Controls whether offering to save cards will consider data from the Autofill
// strike database.
@@ -208,6 +204,12 @@ const base::Feature kAutofillSaveCreditCardUsesStrikeSystem{
"AutofillSaveCreditCardUsesStrikeSystem",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Controls whether offering to save cards will consider data from the Autofill
+// strike database (new version).
+const base::Feature kAutofillSaveCreditCardUsesStrikeSystemV2{
+ "AutofillSaveCreditCardUsesStrikeSystemV2",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Controls whether experiment ids should be sent through
// Google Payments RPCs or not.
const base::Feature kAutofillSendExperimentIdsInPaymentsRPCs{
@@ -230,6 +232,11 @@ const base::Feature kAutofillSendOnlyCountryInGetUploadDetails{
const base::Feature kAutofillServerCommunication{
"AutofillServerCommunication", base::FEATURE_ENABLED_BY_DEFAULT};
+// Controls whether the payments settings page should list the credit cards
+// split by type: Local of from Account.
+const base::Feature kAutofillSettingsCardTypeSplit{
+ "AutofillSettingsCardTypeSplit", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Controls whether autofill suggestions are filtered by field values previously
// filled by website.
const base::Feature kAutofillShowAllSuggestionsOnPrefilledForms{
@@ -258,6 +265,9 @@ const base::Feature kAutofillSuggestInvalidProfileData{
const base::Feature kAutofillSuppressDisusedAddresses{
"AutofillSuppressDisusedAddresses", base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kAutofillProfileClientValidation{
+ "AutofillProfileClientValidation", base::FEATURE_DISABLED_BY_DEFAULT};
+
const base::Feature kAutofillSuppressDisusedCreditCards{
"AutofillSuppressDisusedCreditCards", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -294,15 +304,9 @@ const base::Feature kAutofillUpstreamEditableExpirationDate{
"AutofillUpstreamEditableExpirationDate",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Controls whether the credit card upload bubble shows the Google Pay logo and
-// a shorter "Save card?" header message on mobile.
-const base::Feature kAutofillUpstreamUseGooglePayBrandingOnMobile{
- "AutofillUpstreamUseGooglePayOnAndroidBranding",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// Controls whether to use the API or use the legacy server.
-extern const base::Feature kAutofillUseApi{"AutofillUseApi",
- base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kAutofillUseApi{"AutofillUseApi",
+ base::FEATURE_DISABLED_BY_DEFAULT};
// Controls whether the PaymentsCustomerData is used to make requests to
// Google Payments.
@@ -319,10 +323,6 @@ const base::Feature kAutomaticPasswordGeneration = {
"AutomaticPasswordGeneration", base::FEATURE_ENABLED_BY_DEFAULT};
#endif
-// Controls whether or not the autofill UI triggers on a single click.
-const base::Feature kSingleClickAutofill{"SingleClickAutofill",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
const char kAutofillCreditCardLocalCardMigrationParameterName[] = "variant";
const char kAutofillCreditCardLocalCardMigrationParameterWithoutSettingsPage[] =
@@ -386,15 +386,6 @@ bool IsAutofillManualFallbackEnabled() {
return base::FeatureList::IsEnabled(kAutofillManualFallbackPhaseTwo);
}
-bool ShouldUseNativeViews() {
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
- return base::FeatureList::IsEnabled(kAutofillExpandedPopupViews) ||
- base::FeatureList::IsEnabled(::features::kExperimentalUi);
-#else
- return false;
-#endif
-}
-
bool IsAutofillSaveCardDialogUnlabeledExpirationDateEnabled() {
return base::FeatureList::IsEnabled(
kAutofillSaveCardDialogUnlabeledExpirationDate);
diff --git a/chromium/components/autofill/core/common/autofill_features.h b/chromium/components/autofill/core/common/autofill_features.h
index 4cf32f6c674..01e901d9043 100644
--- a/chromium/components/autofill/core/common/autofill_features.h
+++ b/chromium/components/autofill/core/common/autofill_features.h
@@ -21,6 +21,7 @@ namespace autofill {
namespace features {
// All features in alphabetical order.
+extern const base::Feature kAutocompleteRetentionPolicyEnabled;
extern const base::Feature kAutofillAllowNonHttpActivation;
extern const base::Feature kAutofillAddressNormalizer;
extern const base::Feature kAutofillAlwaysFillAddresses;
@@ -41,8 +42,8 @@ extern const base::Feature kAutofillEnableIFrameSupportOniOS;
extern const base::Feature kAutofillEnforceMinRequiredFieldsForHeuristics;
extern const base::Feature kAutofillEnforceMinRequiredFieldsForQuery;
extern const base::Feature kAutofillEnforceMinRequiredFieldsForUpload;
-extern const base::Feature kAutofillExpandedPopupViews;
extern const base::Feature kAutofillGetPaymentsIdentityFromSync;
+extern const base::Feature kAutofillImportNonFocusableCreditCardForms;
extern const base::Feature kAutofillKeyboardAccessory;
extern const base::Feature kAutofillLocalCardMigrationShowFeedback;
extern const base::Feature kAutofillManualFallback;
@@ -52,18 +53,18 @@ extern const base::Feature kAutofillPreferServerNamePredictions;
extern const base::Feature kAutofillNoLocalSaveOnUploadSuccess;
extern const base::Feature kAutofillOverrideWithRaterConsensus;
extern const base::Feature kAutofillPrefilledFields;
-extern const base::Feature kAutofillRationalizeFieldTypePredictions;
-extern const base::Feature kAutofillRationalizeRepeatedServerPredictions;
extern const base::Feature kAutofillRestrictUnownedFieldsToFormlessCheckout;
extern const base::Feature kAutofillRichMetadataQueries;
extern const base::Feature kAutofillSaveCardDialogUnlabeledExpirationDate;
extern const base::Feature kAutofillSaveCardImprovedUserConsent;
extern const base::Feature kAutofillSaveCardSignInAfterLocalSave;
extern const base::Feature kAutofillSaveCreditCardUsesStrikeSystem;
+extern const base::Feature kAutofillSaveCreditCardUsesStrikeSystemV2;
extern const base::Feature kAutofillSaveOnProbablySubmitted;
extern const base::Feature kAutofillSendExperimentIdsInPaymentsRPCs;
extern const base::Feature kAutofillSendOnlyCountryInGetUploadDetails;
extern const base::Feature kAutofillServerCommunication;
+extern const base::Feature kAutofillSettingsCardTypeSplit;
extern const base::Feature kAutofillShowAllSuggestionsOnPrefilledForms;
extern const base::Feature kAutofillShowAutocompleteConsoleWarnings;
extern const base::Feature kAutofillShowTypePredictions;
@@ -82,9 +83,9 @@ extern const base::Feature kAutofillUpstreamEditableCardholderName;
extern const base::Feature kAutofillUpstreamEditableExpirationDate;
extern const base::Feature kAutofillUpstreamUseGooglePayBrandingOnMobile;
extern const base::Feature kAutofillUseApi;
+extern const base::Feature kAutofillProfileClientValidation;
extern const base::Feature kAutofillUsePaymentsCustomerData;
extern const base::Feature kAutomaticPasswordGeneration;
-extern const base::Feature kSingleClickAutofill;
extern const char kAutofillCreditCardLastUsedDateShowExpirationDateKey[];
extern const char kAutofillLocalCardMigrationCloseButtonDelay[];
extern const char kAutofillCreditCardLocalCardMigrationParameterName[];
@@ -150,11 +151,6 @@ bool IsPasswordManualFallbackEnabled();
// enabled.
bool IsAutofillManualFallbackEnabled();
-// Returns true if the native Views implementation of the Desktop dropdown
-// should be used. This will also be true if the kExperimentalUi flag is true,
-// which forces a bunch of forthcoming UI changes on.
-bool ShouldUseNativeViews();
-
// Returns true if expiration dates on the save card dialog should be
// unlabeled, i.e. not preceded by "Exp."
bool IsAutofillSaveCardDialogUnlabeledExpirationDateEnabled();
diff --git a/chromium/components/autofill/core/common/autofill_l10n_util.cc b/chromium/components/autofill/core/common/autofill_l10n_util.cc
index 9ab031f12fb..f22057abae5 100644
--- a/chromium/components/autofill/core/common/autofill_l10n_util.cc
+++ b/chromium/components/autofill/core/common/autofill_l10n_util.cc
@@ -31,7 +31,7 @@ std::unique_ptr<icu::Collator> GetCollatorForLocale(const icu::Locale& locale) {
<< locale_name;
// Attempt to load the English locale.
- collator = base::WrapUnique(
+ collator.reset(
icu::Collator::createInstance(icu::Locale::getEnglish(), ignored));
if (!collator) {
LOG(ERROR) << "Failed to initialize the ICU Collator with the English "
diff --git a/chromium/components/autofill/core/common/autofill_prefs.cc b/chromium/components/autofill/core/common/autofill_prefs.cc
index 86ea54e241b..6e37efe25dc 100644
--- a/chromium/components/autofill/core/common/autofill_prefs.cc
+++ b/chromium/components/autofill/core/common/autofill_prefs.cc
@@ -126,6 +126,11 @@ const char kAutofillWalletImportEnabled[] = "autofill.wallet_import_enabled";
const char kAutofillWalletImportStorageCheckboxState[] =
"autofill.wallet_import_storage_checkbox_state";
+// Integer that is set to the last major version where the Autocomplete
+// retention policy was run.
+const char kAutocompleteLastVersionRetentionPolicy[] =
+ "autocomplete.retention_policy_last_version";
+
void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
// Synced prefs. Used for cross-device choices, e.g., credit card Autofill.
registry->RegisterDoublePref(
@@ -166,6 +171,8 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_NONE);
registry->RegisterIntegerPref(
prefs::kAutofillLastVersionDisusedCreditCardsDeleted, 0);
+ registry->RegisterIntegerPref(prefs::kAutocompleteLastVersionRetentionPolicy,
+ 0);
registry->RegisterBooleanPref(
prefs::kAutofillMigrateLocalCardsCancelledPrompt, false);
registry->RegisterBooleanPref(prefs::kAutofillOrphanRowsRemoved, false);
diff --git a/chromium/components/autofill/core/common/autofill_prefs.h b/chromium/components/autofill/core/common/autofill_prefs.h
index bc4ff4790fe..47bd73a7e0f 100644
--- a/chromium/components/autofill/core/common/autofill_prefs.h
+++ b/chromium/components/autofill/core/common/autofill_prefs.h
@@ -41,6 +41,7 @@ extern const char kAutofillUploadEvents[];
extern const char kAutofillUploadEventsLastResetTimestamp[];
extern const char kAutofillWalletImportEnabled[];
extern const char kAutofillWalletImportStorageCheckboxState[];
+extern const char kAutocompleteLastVersionRetentionPolicy[];
namespace sync_transport_opt_in {
enum Flags {
diff --git a/chromium/components/autofill/core/common/autofill_prefs_unittest.cc b/chromium/components/autofill/core/common/autofill_prefs_unittest.cc
index 09fd4d7ea05..1a9e4e0558e 100644
--- a/chromium/components/autofill/core/common/autofill_prefs_unittest.cc
+++ b/chromium/components/autofill/core/common/autofill_prefs_unittest.cc
@@ -6,6 +6,8 @@
#include <memory>
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/pref_service_factory.h"
@@ -176,5 +178,25 @@ TEST_F(AutofillPrefsTest, WalletSyncTransportPref_Clear) {
->DictEmpty());
}
+// Tests that the account id hash that we generate can be written and read from
+// JSON properly.
+TEST_F(AutofillPrefsTest, WalletSyncTransportPref_CanBeSetAndReadFromJSON) {
+ const std::string account1 = "account1";
+
+ // Set the opt-in for the first account.
+ SetUserOptedInWalletSyncTransport(pref_service(), account1, true);
+ EXPECT_FALSE(pref_service()
+ ->GetDictionary(prefs::kAutofillSyncTransportOptIn)
+ ->DictEmpty());
+
+ const base::DictionaryValue* dictionary =
+ pref_service()->GetDictionary(prefs::kAutofillSyncTransportOptIn);
+
+ std::string output_js;
+ EXPECT_TRUE(base::JSONWriter::Write(*dictionary, &output_js));
+ EXPECT_TRUE(dictionary->Equals(
+ base::DictionaryValue::From(base::JSONReader::Read(output_js)).get()));
+}
+
} // namespace prefs
-} // namespace autofill \ No newline at end of file
+} // namespace autofill
diff --git a/chromium/components/autofill/core/common/autofill_switches.cc b/chromium/components/autofill/core/common/autofill_switches.cc
index c753a2e3dfd..4bb9f632105 100644
--- a/chromium/components/autofill/core/common/autofill_switches.cc
+++ b/chromium/components/autofill/core/common/autofill_switches.cc
@@ -19,7 +19,7 @@ const char kAutofillServerURL[] = "autofill-server-url";
// The randomized encoding type to use when sending metadata uploads. The
// value of the parameter must be one of the valid integer values of the
// AutofillRandomizedValue_EncodingType enum.
-extern const char kAutofillMetadataUploadEncoding[] =
+const char kAutofillMetadataUploadEncoding[] =
"autofill-metadata-upload-encoding";
// Force hiding the local save checkbox in the autofill dialog box for getting
diff --git a/chromium/components/autofill/core/common/button_title_type.h b/chromium/components/autofill/core/common/button_title_type.h
new file mode 100644
index 00000000000..bf3696d5807
--- /dev/null
+++ b/chromium/components/autofill/core/common/button_title_type.h
@@ -0,0 +1,26 @@
+// 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_CORE_COMMON_BUTTON_TITLE_TYPE_H_
+#define COMPONENTS_AUTOFILL_CORE_COMMON_BUTTON_TITLE_TYPE_H_
+
+namespace autofill {
+
+// Describes how a form button is implemented in HTML source. Should be
+// synced with |ButtonTitleType| in
+// components/autofill/core/browser/proto/server.proto.
+enum ButtonTitleType {
+ NONE = 0,
+ BUTTON_ELEMENT_SUBMIT_TYPE = 1, // <button type='submit'>
+ BUTTON_ELEMENT_BUTTON_TYPE = 2, // <button type='button'>
+ INPUT_ELEMENT_SUBMIT_TYPE = 3, // <input type='submit'>
+ INPUT_ELEMENT_BUTTON_TYPE = 4, // <input type='button'>
+ HYPERLINK = 5, // e.g. <a class='button'>
+ DIV = 6, // e.g. <div id='submit'>
+ SPAN = 7 // e.g. <span name='btn'>
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_COMMON_FORM_SUBMISSION_SOURCE_H_
diff --git a/chromium/components/autofill/core/common/form_data.cc b/chromium/components/autofill/core/common/form_data.cc
index f0f11cf33a5..06c2327da2c 100644
--- a/chromium/components/autofill/core/common/form_data.cc
+++ b/chromium/components/autofill/core/common/form_data.cc
@@ -72,7 +72,7 @@ FormData::FormData() : is_form_tag(true), is_formless_checkout(false) {}
FormData::FormData(const FormData& data)
: name(data.name),
- button_title(data.button_title),
+ button_titles(data.button_titles),
origin(data.origin),
action(data.action),
main_frame_origin(data.main_frame_origin),
diff --git a/chromium/components/autofill/core/common/form_data.h b/chromium/components/autofill/core/common/form_data.h
index fc2afba536f..66aff9021fe 100644
--- a/chromium/components/autofill/core/common/form_data.h
+++ b/chromium/components/autofill/core/common/form_data.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/strings/string16.h"
+#include "components/autofill/core/common/button_title_type.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/submission_indicator_event.h"
#include "url/gurl.h"
@@ -16,6 +17,13 @@
namespace autofill {
+// Pair of a button title (e.g. "Register") and its type (e.g.
+// INPUT_ELEMENT_SUBMIT_TYPE).
+using ButtonTitleInfo = std::pair<base::string16, ButtonTitleType>;
+
+// List of button titles of a given form.
+using ButtonTitleList = std::vector<ButtonTitleInfo>;
+
// Holds information about a form to be filled and/or submitted.
struct FormData {
static constexpr uint32_t kNotSetFormRendererId =
@@ -56,8 +64,8 @@ struct FormData {
// form signatures.
// TODO(crbug/896689): remove this and use attributes/unique_id instead.
base::string16 name;
- // The form submission button's title.
- base::string16 button_title;
+ // Titles of form's buttons.
+ ButtonTitleList button_titles;
// The URL (minus query parameters) containing the form.
GURL origin;
// The action target of the form.
diff --git a/chromium/components/autofill/core/common/password_form.cc b/chromium/components/autofill/core/common/password_form.cc
index a720d677b3b..66eae10cc37 100644
--- a/chromium/components/autofill/core/common/password_form.cc
+++ b/chromium/components/autofill/core/common/password_form.cc
@@ -37,6 +37,8 @@ void PasswordFormToJSON(const PasswordForm& form,
target->SetString("username_value", form.username_value);
target->SetString("password_element", form.password_element);
target->SetString("password_value", form.password_value);
+ target->SetInteger("password_element_renderer_id",
+ form.password_element_renderer_id);
target->SetString("new_password_element", form.new_password_element);
target->SetInteger("password_element_renderer_id",
form.password_element_renderer_id);
@@ -45,6 +47,8 @@ void PasswordFormToJSON(const PasswordForm& form,
form.new_password_marked_by_site);
target->SetString("confirmation_password_element",
form.confirmation_password_element);
+ target->SetInteger("confirmation_password_element_renderer_id",
+ form.confirmation_password_element_renderer_id);
target->SetString("other_possible_usernames",
ValueElementVectorToString(form.other_possible_usernames));
target->SetString("all_possible_passwords",
@@ -71,9 +75,10 @@ void PasswordFormToJSON(const PasswordForm& form,
std::ostringstream submission_event_string_stream;
submission_event_string_stream << form.submission_event;
target->SetString("submission_event", submission_event_string_stream.str());
- target->SetBoolean("only_for_fallback_saving", form.only_for_fallback_saving);
+ target->SetBoolean("only_for_fallback", form.only_for_fallback);
target->SetBoolean("is_gaia_with_skip_save_password_form",
form.is_gaia_with_skip_save_password_form);
+ target->SetBoolean("is_new_password_reliable", form.is_new_password_reliable);
}
} // namespace
@@ -93,7 +98,7 @@ PasswordForm::PasswordForm()
is_public_suffix_match(false),
is_affiliation_based_match(false),
submission_event(SubmissionIndicatorEvent::NONE),
- only_for_fallback_saving(false),
+ only_for_fallback(false),
is_gaia_with_skip_save_password_form(false) {}
PasswordForm::PasswordForm(const PasswordForm& other) = default;
@@ -114,6 +119,12 @@ bool PasswordForm::IsPossibleChangePasswordFormWithoutUsername() const {
return IsPossibleChangePasswordForm() && username_element.empty();
}
+bool PasswordForm::HasPasswordElement() const {
+ return has_renderer_ids ? password_element_renderer_id !=
+ FormFieldData::kNotSetFormControlRendererId
+ : !password_element.empty();
+}
+
bool PasswordForm::operator==(const PasswordForm& form) const {
return scheme == form.scheme && signon_realm == form.signon_realm &&
origin == form.origin && action == form.action &&
@@ -130,7 +141,12 @@ bool PasswordForm::operator==(const PasswordForm& form) const {
password_element_renderer_id == form.password_element_renderer_id &&
password_value == form.password_value &&
new_password_element == form.new_password_element &&
+ confirmation_password_element_renderer_id ==
+ form.confirmation_password_element_renderer_id &&
new_password_marked_by_site == form.new_password_marked_by_site &&
+ confirmation_password_element == form.confirmation_password_element &&
+ confirmation_password_element_renderer_id ==
+ form.confirmation_password_element_renderer_id &&
new_password_value == form.new_password_value &&
preferred == form.preferred && date_created == form.date_created &&
date_synced == form.date_synced &&
@@ -151,9 +167,10 @@ bool PasswordForm::operator==(const PasswordForm& form) const {
app_display_name == form.app_display_name &&
app_icon_url == form.app_icon_url &&
submission_event == form.submission_event &&
- only_for_fallback_saving == form.only_for_fallback_saving &&
+ only_for_fallback == form.only_for_fallback &&
is_gaia_with_skip_save_password_form ==
- form.is_gaia_with_skip_save_password_form;
+ form.is_gaia_with_skip_save_password_form &&
+ is_new_password_reliable == form.is_new_password_reliable;
}
bool PasswordForm::operator!=(const PasswordForm& form) const {
diff --git a/chromium/components/autofill/core/common/password_form.h b/chromium/components/autofill/core/common/password_form.h
index f5d70421922..fc55fa533ce 100644
--- a/chromium/components/autofill/core/common/password_form.h
+++ b/chromium/components/autofill/core/common/password_form.h
@@ -200,10 +200,20 @@ struct PasswordForm {
// element corresponding to the new password. Optional, and not persisted.
base::string16 new_password_element;
+ // The renderer id of the new password input element. It is set during the new
+ // form parsing and not persisted.
+ uint32_t new_password_element_renderer_id =
+ FormFieldData::kNotSetFormControlRendererId;
+
// The confirmation password element. Optional, only set on form parsing, and
// not persisted.
base::string16 confirmation_password_element;
+ // The renderer id of the confirmation password input element. It is set
+ // during the new form parsing and not persisted.
+ uint32_t confirmation_password_element_renderer_id =
+ FormFieldData::kNotSetFormControlRendererId;
+
// The new password. Optional, and not persisted.
base::string16 new_password_value;
@@ -302,13 +312,19 @@ struct PasswordForm {
// out only for submitted forms.
SubmissionIndicatorEvent submission_event;
- // True iff heuristics declined this form for saving (e.g. only credit card
- // fields were found). But this form can be saved only with the fallback.
- bool only_for_fallback_saving;
+ // True iff heuristics declined this form for normal saving or filling (e.g.
+ // only credit card fields were found). But this form can be saved or filled
+ // only with the fallback.
+ bool only_for_fallback;
// True iff this is Gaia form which should be skipped on saving.
bool is_gaia_with_skip_save_password_form;
+ // True iff the new password field was found with server hints or autocomplete
+ // attributes. Only set on form parsing for filling, and not persisted. Used
+ // as signal for password generation eligibility.
+ bool is_new_password_reliable = false;
+
// 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;
@@ -318,6 +334,9 @@ struct PasswordForm {
// include signup forms.
bool IsPossibleChangePasswordFormWithoutUsername() const;
+ // Returns true if current password element is set.
+ bool HasPasswordElement() const;
+
// Equality operators for testing.
bool operator==(const PasswordForm& form) const;
bool operator!=(const PasswordForm& form) const;
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 ae72606e31e..42b65b4c889 100644
--- a/chromium/components/autofill/core/common/password_form_fill_data.cc
+++ b/chromium/components/autofill/core/common/password_form_fill_data.cc
@@ -29,22 +29,30 @@ void InitPasswordFormFillData(
// |username_field| and |password_field| because they are currently not used
// by the password autocomplete code.
FormFieldData username_field;
- username_field.name = form_on_page.username_element;
username_field.value = preferred_match->username_value;
- username_field.unique_renderer_id = form_on_page.username_element_renderer_id;
- result->username_may_use_prefilled_placeholder =
- form_on_page.username_may_use_prefilled_placeholder;
FormFieldData password_field;
- password_field.name = form_on_page.password_element;
password_field.value = preferred_match->password_value;
- password_field.unique_renderer_id = form_on_page.password_element_renderer_id;
- password_field.form_control_type = "password";
+ if (!form_on_page.only_for_fallback) {
+ // Fill fields identifying information only for non-fallback case. In
+ // fallback case, a fill popup is shown on clicking on each password
+ // field so no need in any field identifiers.
+ username_field.name = form_on_page.username_element;
+ username_field.unique_renderer_id =
+ form_on_page.username_element_renderer_id;
+ result->username_may_use_prefilled_placeholder =
+ form_on_page.username_may_use_prefilled_placeholder;
-// On iOS, use the unique_id field to refer to elements.
+ password_field.name = form_on_page.password_element;
+ password_field.unique_renderer_id =
+ form_on_page.password_element_renderer_id;
+ password_field.form_control_type = "password";
+
+ // On iOS, use the unique_id field to refer to elements.
#if defined(OS_IOS)
- username_field.unique_id = form_on_page.username_element;
- password_field.unique_id = form_on_page.password_element;
+ username_field.unique_id = form_on_page.username_element;
+ password_field.unique_id = form_on_page.password_element;
#endif
+ }
// Fill basic form data.
result->form_renderer_id = form_on_page.form_data.unique_renderer_id;
@@ -73,12 +81,16 @@ void InitPasswordFormFillData(
}
}
-PasswordFormFillData ClearPasswordValues(const PasswordFormFillData& data) {
+PasswordFormFillData MaybeClearPasswordValues(
+ const PasswordFormFillData& data) {
// In case when there is a username on a page (for example in a hidden field),
// credentials from |additional_logins| could be used for filling on load. So
// in case of filling on load nor |password_field| nor |additional_logins|
// can't be cleared
- if (!data.wait_for_username)
+ bool is_fallback =
+ data.has_renderer_ids && data.password_field.unique_renderer_id ==
+ FormFieldData::kNotSetFormControlRendererId;
+ if (!data.wait_for_username && !is_fallback)
return data;
PasswordFormFillData result(data);
result.password_field.value.clear();
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 5db0c17b244..cbb47f8971a 100644
--- a/chromium/components/autofill/core/common/password_form_fill_data.h
+++ b/chromium/components/autofill/core/common/password_form_fill_data.h
@@ -91,9 +91,9 @@ void InitPasswordFormFillData(
bool wait_for_username_before_autofill,
PasswordFormFillData* result);
-// Renderer needs to have only a password that should be autofilled, all other
-// passwords might be safety erased.
-PasswordFormFillData ClearPasswordValues(const PasswordFormFillData& data);
+// If |data.wait_for_username| is set, the renderer does not need to receive
+// passwords, yet, and this function clears the password values from |data|.
+PasswordFormFillData MaybeClearPasswordValues(const PasswordFormFillData& data);
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/password_form_generation_data.h b/chromium/components/autofill/core/common/password_form_generation_data.h
index f14d2953821..40fb1977be2 100644
--- a/chromium/components/autofill/core/common/password_form_generation_data.h
+++ b/chromium/components/autofill/core/common/password_form_generation_data.h
@@ -9,7 +9,9 @@
#include "base/optional.h"
#include "base/strings/string16.h"
+#include "build/build_config.h"
#include "components/autofill/core/common/form_field_data.h"
+#include "components/autofill/core/common/password_form.h"
#include "components/autofill/core/common/signatures_util.h"
#include "url/gurl.h"
@@ -37,6 +39,23 @@ struct PasswordFormGenerationData {
base::Optional<FieldSignature> confirmation_field_signature;
};
+// Structure used for sending information from browser to renderer about on
+// which fields password should be generated.
+// TODO(https://crbug.com/866444): Remove old PasswordFormGenerationData and
+// rename to PasswordFormGenerationData when the old parser is gone.
+struct NewPasswordFormGenerationData {
+#if defined(OS_IOS)
+ base::string16 form_name;
+ base::string16 new_password_element;
+ base::string16 confirmation_password_element;
+#else
+ uint32_t new_password_renderer_id =
+ FormFieldData::kNotSetFormControlRendererId;
+ uint32_t confirmation_password_renderer_id =
+ FormFieldData::kNotSetFormControlRendererId;
+#endif
+};
+
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_COMMON_PASSWORD_FORM_GENERATION_DATA_H_
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 5c7cb4e96b1..de254813971 100644
--- a/chromium/components/autofill/core/common/save_password_progress_logger.cc
+++ b/chromium/components/autofill/core/common/save_password_progress_logger.cc
@@ -82,9 +82,18 @@ void SavePasswordProgressLogger::LogPasswordForm(
}
log.SetString(GetStringFromID(STRING_NEW_PASSWORD_ELEMENT),
ScrubElementID(form.new_password_element));
+ if (form.has_renderer_ids) {
+ log.SetString(GetStringFromID(STRING_NEW_PASSWORD_ELEMENT_RENDERER_ID),
+ UintToString(form.new_password_element_renderer_id));
+ }
if (!form.confirmation_password_element.empty()) {
log.SetString(GetStringFromID(STRING_CONFIRMATION_PASSWORD_ELEMENT),
ScrubElementID(form.confirmation_password_element));
+ if (form.has_renderer_ids) {
+ log.SetString(
+ GetStringFromID(STRING_CONFIRMATION_PASSWORD_ELEMENT_RENDERER_ID),
+ UintToString(form.confirmation_password_element_renderer_id));
+ }
}
log.SetBoolean(GetStringFromID(STRING_PASSWORD_GENERATED),
form.type == PasswordForm::TYPE_GENERATED);
@@ -208,8 +217,13 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "Password element renderer id";
case SavePasswordProgressLogger::STRING_NEW_PASSWORD_ELEMENT:
return "New password element";
+ case SavePasswordProgressLogger::STRING_NEW_PASSWORD_ELEMENT_RENDERER_ID:
+ return "New password element renderer id";
case SavePasswordProgressLogger::STRING_CONFIRMATION_PASSWORD_ELEMENT:
return "Confirmation password element";
+ case SavePasswordProgressLogger::
+ STRING_CONFIRMATION_PASSWORD_ELEMENT_RENDERER_ID:
+ return "Confirmation password element renderer id";
case SavePasswordProgressLogger::STRING_PASSWORD_GENERATED:
return "Password generated";
case SavePasswordProgressLogger::STRING_TIMES_USED:
@@ -291,7 +305,7 @@ std::string SavePasswordProgressLogger::GetStringFromID(
case SavePasswordProgressLogger::STRING_ON_ASK_USER_OR_SAVE_PASSWORD:
return "PasswordManager::AskUserOrSavePassword";
case SavePasswordProgressLogger::STRING_CAN_PROVISIONAL_MANAGER_SAVE_METHOD:
- return "PasswordManager::CanProvisionalManagerSave";
+ return "PasswordManager::IsAutomaticSavePromptAvailable";
case SavePasswordProgressLogger::STRING_NO_PROVISIONAL_SAVE_MANAGER:
return "No provisional save manager";
case SavePasswordProgressLogger::STRING_NUMBER_OF_VISIBLE_FORMS:
@@ -446,6 +460,16 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "Form parsing input";
case STRING_FORM_PARSING_OUTPUT:
return "Form parsing output";
+ case STRING_FAILED_TO_FILL_INTO_IFRAME:
+ return "Failed to fill: Form is in iframe on a non-PSL-matching security "
+ "origin";
+ case STRING_FAILED_TO_FILL_NO_AUTOCOMPLETEABLE_ELEMENT:
+ return "Failed to fill: No autocompleteable element found";
+ case STRING_FAILED_TO_FILL_PREFILLED_USERNAME:
+ return "Failed to fill: Username field was prefilled, but no credential "
+ "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_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 40775e06328..404e5c2473d 100644
--- a/chromium/components/autofill/core/common/save_password_progress_logger.h
+++ b/chromium/components/autofill/core/common/save_password_progress_logger.h
@@ -50,7 +50,9 @@ class SavePasswordProgressLogger {
STRING_PASSWORD_ELEMENT,
STRING_PASSWORD_ELEMENT_RENDERER_ID,
STRING_NEW_PASSWORD_ELEMENT,
+ STRING_NEW_PASSWORD_ELEMENT_RENDERER_ID,
STRING_CONFIRMATION_PASSWORD_ELEMENT,
+ STRING_CONFIRMATION_PASSWORD_ELEMENT_RENDERER_ID,
STRING_PASSWORD_GENERATED,
STRING_TIMES_USED,
STRING_PSL_MATCH,
@@ -166,6 +168,10 @@ class SavePasswordProgressLogger {
STRING_IS_FORM_TAG,
STRING_FORM_PARSING_INPUT,
STRING_FORM_PARSING_OUTPUT,
+ STRING_FAILED_TO_FILL_INTO_IFRAME,
+ STRING_FAILED_TO_FILL_NO_AUTOCOMPLETEABLE_ELEMENT,
+ STRING_FAILED_TO_FILL_PREFILLED_USERNAME,
+ STRING_FAILED_TO_FILL_FOUND_NO_PASSWORD_FOR_USERNAME,
STRING_INVALID, // Represents a string returned in a case of an error.
STRING_MAX = STRING_INVALID
};
diff --git a/chromium/components/autofill/ios/browser/BUILD.gn b/chromium/components/autofill/ios/browser/BUILD.gn
index c17fc305885..3a5e25be0d6 100644
--- a/chromium/components/autofill/ios/browser/BUILD.gn
+++ b/chromium/components/autofill/ios/browser/BUILD.gn
@@ -67,6 +67,7 @@ source_set("test_support") {
"//base",
"//base/test:test_support",
"//components/autofill/core/browser",
+ "//components/leveldb_proto:leveldb_proto",
"//ios/web/public",
]
}
diff --git a/chromium/components/autofill/ios/browser/autofill_agent.mm b/chromium/components/autofill/ios/browser/autofill_agent.mm
index 40a51344cdf..eb8bf0dd088 100644
--- a/chromium/components/autofill/ios/browser/autofill_agent.mm
+++ b/chromium/components/autofill/ios/browser/autofill_agent.mm
@@ -231,8 +231,7 @@ autofillManagerFromWebState:(web::WebState*)webState
DCHECK_EQ(1U, forms.size());
autofill::FormData form = forms[0];
autofillManager->OnFormSubmitted(form, false,
- autofill::SubmissionSource::FORM_SUBMISSION,
- base::TimeTicks::Now());
+ autofill::SubmissionSource::FORM_SUBMISSION);
autofill::KeyboardAccessoryMetricsLogger::OnFormSubmitted();
}
diff --git a/chromium/components/autofill/ios/browser/autofill_driver_ios.h b/chromium/components/autofill/ios/browser/autofill_driver_ios.h
index 75ec90b29c5..2624127f010 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios.h
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios.h
@@ -54,7 +54,6 @@ class AutofillDriverIOS : public AutofillDriver {
void RendererShouldClearPreviewedForm() override;
void RendererShouldAcceptDataListSuggestion(
const base::string16& value) override;
- void DidInteractWithCreditCardForm() override;
AutofillManager* autofill_manager() { return &autofill_manager_; }
diff --git a/chromium/components/autofill/ios/browser/autofill_driver_ios.mm b/chromium/components/autofill/ios/browser/autofill_driver_ios.mm
index 94da426d9af..bba0e29ee9a 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios.mm
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios.mm
@@ -116,12 +116,6 @@ void AutofillDriverIOS::RendererShouldAcceptDataListSuggestion(
const base::string16& value) {
}
-void AutofillDriverIOS::DidInteractWithCreditCardForm() {
- if (!web::IsOriginSecure(web_state_->GetLastCommittedURL())) {
- autofill_manager_.client()->DidInteractWithNonsecureCreditCardInput();
- }
-}
-
void AutofillDriverIOS::RendererShouldClearFilledSection() {}
void AutofillDriverIOS::RendererShouldClearPreviewedForm() {
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 39903370245..56a6630190e 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.h
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.h
@@ -34,18 +34,19 @@ class AutofillDriverIOSWebFrameFactory
AutofillManager::AutofillDownloadManagerState enable_download_manager);
~AutofillDriverIOSWebFrameFactory() override;
- // Returns a AutofillDriverIOSFromWebFrame for |web_frame|, creating it if
- // needed.
- AutofillDriverIOSWebFrame* AutofillDriverIOSFromWebFrame(
- web::WebFrame* web_frame);
-
- private:
AutofillDriverIOSWebFrameFactory(
web::WebState* web_state,
AutofillClient* client,
id<AutofillDriverIOSBridge> bridge,
const std::string& app_locale,
AutofillManager::AutofillDownloadManagerState enable_download_manager);
+
+ // Returns a AutofillDriverIOSFromWebFrame for |web_frame|, creating it if
+ // needed.
+ AutofillDriverIOSWebFrame* AutofillDriverIOSFromWebFrame(
+ web::WebFrame* web_frame);
+
+ private:
web::WebState* web_state_ = nullptr;
AutofillClient* client_ = nullptr;
id<AutofillDriverIOSBridge> bridge_ = nil;
@@ -96,7 +97,6 @@ class AutofillDriverIOSWebFrame
AutofillDriverIOS* driver() { return driver_.get(); }
scoped_refptr<AutofillDriverIOSRefCountable> GetRetainableDriver();
- private:
AutofillDriverIOSWebFrame(
web::WebState* web_state,
web::WebFrame* web_frame,
diff --git a/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.mm b/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.mm
index c924b11f8ce..2c4988db611 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.mm
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.mm
@@ -20,8 +20,8 @@ void AutofillDriverIOSWebFrameFactory::CreateForWebStateAndDelegate(
web_state->SetUserData(
UserDataKey(),
- base::WrapUnique(new AutofillDriverIOSWebFrameFactory(
- web_state, client, bridge, app_locale, enable_download_manager)));
+ std::make_unique<AutofillDriverIOSWebFrameFactory>(
+ web_state, client, bridge, app_locale, enable_download_manager));
}
AutofillDriverIOSWebFrameFactory::AutofillDriverIOSWebFrameFactory(
@@ -59,9 +59,9 @@ void AutofillDriverIOSWebFrame::CreateForWebFrameAndDelegate(
return;
web_frame->SetUserData(UserDataKey(),
- base::WrapUnique(new AutofillDriverIOSWebFrame(
+ std::make_unique<AutofillDriverIOSWebFrame>(
web_state, web_frame, client, bridge, app_locale,
- enable_download_manager)));
+ enable_download_manager));
}
AutofillDriverIOSRefCountable::AutofillDriverIOSRefCountable(
diff --git a/chromium/components/autofill/ios/browser/autofill_driver_ios_webstate.h b/chromium/components/autofill/ios/browser/autofill_driver_ios_webstate.h
index d6fc06948b4..7e3dabd4c62 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios_webstate.h
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios_webstate.h
@@ -28,7 +28,6 @@ class AutofillDriverIOSWebState
~AutofillDriverIOSWebState() override;
- protected:
AutofillDriverIOSWebState(
web::WebState* web_state,
AutofillClient* client,
diff --git a/chromium/components/autofill/ios/browser/autofill_driver_ios_webstate.mm b/chromium/components/autofill/ios/browser/autofill_driver_ios_webstate.mm
index d69d3b5fd14..0237ae17128 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios_webstate.mm
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios_webstate.mm
@@ -24,8 +24,8 @@ void AutofillDriverIOSWebState::CreateForWebStateAndDelegate(
web_state->SetUserData(
UserDataKey(),
- base::WrapUnique(new AutofillDriverIOSWebState(
- web_state, client, bridge, app_locale, enable_download_manager)));
+ std::make_unique<AutofillDriverIOSWebState>(
+ web_state, client, bridge, app_locale, enable_download_manager));
}
AutofillDriverIOSWebState::AutofillDriverIOSWebState(
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 cb879636101..4089ada1978 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
@@ -24,7 +24,7 @@
- (void)receivedUploadCardResponse;
-- (void)ccsmStrikeChangeComplete;
+- (void)strikeChangeComplete;
@end
@@ -46,7 +46,7 @@ class CreditCardSaveManagerTestObserverBridge
void OnReceivedGetUploadDetailsResponse() override;
void OnSentUploadCardRequest() override;
void OnReceivedUploadCardResponse() override;
- void OnCCSMStrikeChangeComplete() override;
+ void OnStrikeChangeComplete() override;
private:
__weak id<CreditCardSaveManagerTestObserver> observer_ = nil;
diff --git a/chromium/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.mm b/chromium/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.mm
index f615e04ff27..bbb0c41f08c 100644
--- a/chromium/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.mm
+++ b/chromium/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.mm
@@ -43,8 +43,8 @@ void CreditCardSaveManagerTestObserverBridge::OnReceivedUploadCardResponse() {
[observer_ receivedUploadCardResponse];
}
-void CreditCardSaveManagerTestObserverBridge::OnCCSMStrikeChangeComplete() {
- [observer_ ccsmStrikeChangeComplete];
+void CreditCardSaveManagerTestObserverBridge::OnStrikeChangeComplete() {
+ [observer_ strikeChangeComplete];
}
} // namespace autofill
diff --git a/chromium/components/autofill/ios/form_util/form_activity_tab_helper.mm b/chromium/components/autofill/ios/form_util/form_activity_tab_helper.mm
index fd595e57bbe..ed04da751eb 100644
--- a/chromium/components/autofill/ios/form_util/form_activity_tab_helper.mm
+++ b/chromium/components/autofill/ios/form_util/form_activity_tab_helper.mm
@@ -16,8 +16,6 @@
#error "This file requires ARC support."
#endif
-DEFINE_WEB_STATE_USER_DATA_KEY(autofill::FormActivityTabHelper);
-
namespace autofill {
namespace {
diff --git a/chromium/components/autofill/ios/form_util/resources/form_handlers.js b/chromium/components/autofill/ios/form_util/resources/form_handlers.js
index 8963d6bf4fc..940b256a480 100644
--- a/chromium/components/autofill/ios/form_util/resources/form_handlers.js
+++ b/chromium/components/autofill/ios/form_util/resources/form_handlers.js
@@ -94,9 +94,13 @@ function getFullyQualifiedUrl_(originalURL) {
*/
function formActivity_(evt) {
var target = evt.target;
+ if (!['FORM', 'INPUT', 'OPTION', 'SELECT', 'TEXTAREA'].includes(
+ target.tagName)) {
+ return;
+ }
var value = target.value || '';
var fieldType = target.type || '';
- if (evt.type != 'blur') {
+ if (evt.type !== 'blur') {
lastFocusedElement_ = document.activeElement;
}
if (['change', 'input'].includes(evt.type) &&
@@ -122,6 +126,10 @@ function formActivity_(evt) {
*/
function submitHandler_(evt) {
if (evt['defaultPrevented']) return;
+ if (evt.target.tagName !== 'FORM') {
+ return;
+ }
+
formSubmitted_(evt.target);
}
@@ -225,7 +233,7 @@ __gCrWeb.formHandlers['trackFormMutations'] = function(delay) {
addedElements, [].slice.call(node.getElementsByTagName('*')));
}
var form_changed = addedElements.find(function(element) {
- return element.tagName.match(/(FORM|INPUT|SELECT|OPTION)/);
+ return element.tagName.match(/(FORM|INPUT|SELECT|OPTION|TEXTAREA)/);
});
if (form_changed) {
var msg = {